Line data Source code
1 : /* Floating point range operators.
2 : Copyright (C) 2022-2026 Free Software Foundation, Inc.
3 : Contributed by Aldy Hernandez <aldyh@redhat.com>.
4 :
5 : This file is part of GCC.
6 :
7 : GCC is free software; you can redistribute it and/or modify
8 : it under the terms of the GNU General Public License as published by
9 : the Free Software Foundation; either version 3, or (at your option)
10 : any later version.
11 :
12 : GCC is distributed in the hope that it will be useful,
13 : but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : GNU General Public License for more details.
16 :
17 : You should have received a copy of the GNU General Public License
18 : along with GCC; see the file COPYING3. If not see
19 : <http://www.gnu.org/licenses/>. */
20 :
21 : #include "config.h"
22 : #include "system.h"
23 : #include "coretypes.h"
24 : #include "backend.h"
25 : #include "insn-codes.h"
26 : #include "rtl.h"
27 : #include "tree.h"
28 : #include "gimple.h"
29 : #include "cfghooks.h"
30 : #include "tree-pass.h"
31 : #include "ssa.h"
32 : #include "optabs-tree.h"
33 : #include "gimple-pretty-print.h"
34 : #include "diagnostic-core.h"
35 : #include "flags.h"
36 : #include "fold-const.h"
37 : #include "stor-layout.h"
38 : #include "calls.h"
39 : #include "cfganal.h"
40 : #include "gimple-iterator.h"
41 : #include "gimple-fold.h"
42 : #include "tree-eh.h"
43 : #include "gimple-walk.h"
44 : #include "tree-cfg.h"
45 : #include "wide-int.h"
46 : #include "value-relation.h"
47 : #include "range-op.h"
48 : #include "range-op-mixed.h"
49 :
50 : // Default definitions for floating point operators.
51 :
52 : bool
53 5690629 : range_operator::fold_range (frange &r, tree type,
54 : const frange &op1, const frange &op2,
55 : relation_trio trio) const
56 : {
57 5690629 : if (empty_range_varying (r, type, op1, op2))
58 6391 : return true;
59 5684238 : if (op1.known_isnan () || op2.known_isnan ())
60 : {
61 7395 : r.set_nan (type);
62 7395 : return true;
63 : }
64 :
65 5676843 : rv_fold (r, type,
66 : op1.lower_bound (), op1.upper_bound (),
67 : op2.lower_bound (), op2.upper_bound (), trio.op1_op2 ());
68 :
69 5676843 : if (r.known_isnan ())
70 : return true;
71 9124332 : if (op1.maybe_isnan () || op2.maybe_isnan ())
72 4126657 : r.update_nan ();
73 :
74 : // If the result has overflowed and flag_trapping_math, folding this
75 : // operation could elide an overflow or division by zero exception.
76 : // Avoid returning a singleton +-INF, to keep the propagators (DOM
77 : // and substitute_and_fold_engine) from folding. See PR107608.
78 5676152 : if (flag_trapping_math
79 26629837 : && MODE_HAS_INFINITIES (TYPE_MODE (type))
80 10914976 : && r.known_isinf () && !op1.known_isinf () && !op2.known_isinf ())
81 : {
82 1611 : REAL_VALUE_TYPE inf = r.lower_bound ();
83 1611 : if (real_isneg (&inf))
84 : {
85 96 : REAL_VALUE_TYPE min = real_min_representable (type);
86 96 : r.set (type, inf, min);
87 : }
88 : else
89 : {
90 1515 : REAL_VALUE_TYPE max = real_max_representable (type);
91 1515 : r.set (type, max, inf);
92 : }
93 : }
94 :
95 5676152 : r.flush_denormals_to_zero ();
96 :
97 5676152 : return true;
98 : }
99 :
100 : // For a given operation, fold two sets of ranges into [lb, ub].
101 : // MAYBE_NAN is set to TRUE if, in addition to any result in LB or
102 : // UB, the final range has the possibility of a NAN.
103 : void
104 504146 : range_operator::rv_fold (frange &r, tree type,
105 : const REAL_VALUE_TYPE &,
106 : const REAL_VALUE_TYPE &,
107 : const REAL_VALUE_TYPE &,
108 : const REAL_VALUE_TYPE &, relation_kind) const
109 : {
110 504146 : r.set (type, dconstninf, dconstinf, nan_state (true));
111 504146 : }
112 :
113 : bool
114 101745 : range_operator::fold_range (irange &r ATTRIBUTE_UNUSED,
115 : tree type ATTRIBUTE_UNUSED,
116 : const frange &lh ATTRIBUTE_UNUSED,
117 : const irange &rh ATTRIBUTE_UNUSED,
118 : relation_trio) const
119 : {
120 101745 : return false;
121 : }
122 :
123 : bool
124 0 : range_operator::fold_range (irange &r ATTRIBUTE_UNUSED,
125 : tree type ATTRIBUTE_UNUSED,
126 : const frange &lh ATTRIBUTE_UNUSED,
127 : const frange &rh ATTRIBUTE_UNUSED,
128 : relation_trio) const
129 : {
130 0 : return false;
131 : }
132 :
133 : bool
134 0 : range_operator::fold_range (frange &r ATTRIBUTE_UNUSED,
135 : tree type ATTRIBUTE_UNUSED,
136 : const irange &lh ATTRIBUTE_UNUSED,
137 : const irange &rh ATTRIBUTE_UNUSED,
138 : relation_trio) const
139 : {
140 0 : return false;
141 : }
142 :
143 : bool
144 676 : range_operator::op1_range (frange &r ATTRIBUTE_UNUSED,
145 : tree type ATTRIBUTE_UNUSED,
146 : const frange &lhs ATTRIBUTE_UNUSED,
147 : const frange &op2 ATTRIBUTE_UNUSED,
148 : relation_trio) const
149 : {
150 676 : return false;
151 : }
152 :
153 : bool
154 6074 : range_operator::op1_range (frange &r ATTRIBUTE_UNUSED,
155 : tree type ATTRIBUTE_UNUSED,
156 : const irange &lhs ATTRIBUTE_UNUSED,
157 : const frange &op2 ATTRIBUTE_UNUSED,
158 : relation_trio) const
159 : {
160 6074 : return false;
161 : }
162 :
163 : bool
164 2407 : range_operator::op2_range (frange &r ATTRIBUTE_UNUSED,
165 : tree type ATTRIBUTE_UNUSED,
166 : const frange &lhs ATTRIBUTE_UNUSED,
167 : const frange &op1 ATTRIBUTE_UNUSED,
168 : relation_trio) const
169 : {
170 2407 : return false;
171 : }
172 :
173 : bool
174 0 : range_operator::op2_range (frange &r ATTRIBUTE_UNUSED,
175 : tree type ATTRIBUTE_UNUSED,
176 : const irange &lhs ATTRIBUTE_UNUSED,
177 : const frange &op1 ATTRIBUTE_UNUSED,
178 : relation_trio) const
179 : {
180 0 : return false;
181 : }
182 :
183 : relation_kind
184 5702403 : range_operator::lhs_op1_relation (const frange &lhs ATTRIBUTE_UNUSED,
185 : const frange &op1 ATTRIBUTE_UNUSED,
186 : const frange &op2 ATTRIBUTE_UNUSED,
187 : relation_kind) const
188 : {
189 5702403 : return VREL_VARYING;
190 : }
191 :
192 : relation_kind
193 1022092 : range_operator::lhs_op1_relation (const irange &lhs ATTRIBUTE_UNUSED,
194 : const frange &op1 ATTRIBUTE_UNUSED,
195 : const frange &op2 ATTRIBUTE_UNUSED,
196 : relation_kind) const
197 : {
198 1022092 : return VREL_VARYING;
199 : }
200 :
201 : relation_kind
202 169229 : range_operator::lhs_op2_relation (const irange &lhs ATTRIBUTE_UNUSED,
203 : const frange &op1 ATTRIBUTE_UNUSED,
204 : const frange &op2 ATTRIBUTE_UNUSED,
205 : relation_kind) const
206 : {
207 169229 : return VREL_VARYING;
208 : }
209 :
210 : relation_kind
211 3613318 : range_operator::lhs_op2_relation (const frange &lhs ATTRIBUTE_UNUSED,
212 : const frange &op1 ATTRIBUTE_UNUSED,
213 : const frange &op2 ATTRIBUTE_UNUSED,
214 : relation_kind) const
215 : {
216 3613318 : return VREL_VARYING;
217 : }
218 :
219 : relation_kind
220 353664 : range_operator::op1_op2_relation (const irange &,
221 : const frange &,
222 : const frange &) const
223 : {
224 353664 : return VREL_VARYING;
225 : }
226 :
227 :
228 : relation_kind
229 599715 : range_operator::op1_op2_relation (const frange &,
230 : const frange &,
231 : const frange &) const
232 : {
233 599715 : return VREL_VARYING;
234 : }
235 :
236 : // Return TRUE if OP1 and OP2 may be a NAN.
237 :
238 : static inline bool
239 3561772 : maybe_isnan (const frange &op1, const frange &op2)
240 : {
241 6203225 : return op1.maybe_isnan () || op2.maybe_isnan ();
242 : }
243 :
244 : // Floating point version of relop_early_resolve that takes NANs into
245 : // account.
246 : //
247 : // For relation opcodes, first try to see if the supplied relation
248 : // forces a true or false result, and return that.
249 : // Then check for undefined operands. If none of this applies,
250 : // return false.
251 : //
252 : // TRIO are the relations between operands as they appear in the IL.
253 : // MY_REL is the relation that corresponds to the operator being
254 : // folded. For example, when attempting to fold x_3 == y_5, MY_REL is
255 : // VREL_EQ, and if the statement is dominated by x_3 > y_5, then
256 : // TRIO.op1_op2() is VREL_GT.
257 :
258 : static inline bool
259 2070040 : frelop_early_resolve (irange &r, tree type,
260 : const frange &op1, const frange &op2,
261 : relation_trio trio, relation_kind my_rel)
262 : {
263 2070040 : relation_kind rel = trio.op1_op2 ();
264 :
265 : // If known relation is a complete subset of this relation, always
266 : // return true. However, avoid doing this when NAN is a possibility
267 : // as we'll incorrectly fold conditions:
268 : //
269 : // if (x_3 >= y_5)
270 : // ;
271 : // else
272 : // ;; With NANs the relation here is basically VREL_UNLT, so we
273 : // ;; can't fold the following:
274 : // if (x_3 < y_5)
275 2070040 : if (!maybe_isnan (op1, op2) && relation_union (rel, my_rel) == my_rel)
276 : {
277 1936 : r = range_true (type);
278 1936 : return true;
279 : }
280 :
281 : // If known relation has no subset of this relation, always false.
282 2068104 : if (relation_intersect (rel, my_rel) == VREL_UNDEFINED)
283 : {
284 1044 : r = range_false (type);
285 1044 : return true;
286 : }
287 :
288 : // If either operand is undefined, return VARYING.
289 2067060 : if (empty_range_varying (r, type, op1, op2))
290 3086 : return true;
291 :
292 : return false;
293 : }
294 :
295 : // Set VALUE to its next real value, or INF if the operation overflows.
296 :
297 : void
298 3405831 : frange_nextafter (enum machine_mode mode,
299 : REAL_VALUE_TYPE &value,
300 : const REAL_VALUE_TYPE &inf)
301 : {
302 23840817 : if (MODE_COMPOSITE_P (mode)
303 0 : && (real_isdenormal (&value, mode) || real_iszero (&value)))
304 : {
305 : // IBM extended denormals only have DFmode precision.
306 0 : REAL_VALUE_TYPE tmp, tmp2;
307 0 : real_convert (&tmp2, DFmode, &value);
308 0 : real_nextafter (&tmp, REAL_MODE_FORMAT (DFmode), &tmp2, &inf);
309 0 : real_convert (&value, mode, &tmp);
310 : }
311 : else
312 : {
313 3405831 : REAL_VALUE_TYPE tmp;
314 3405831 : real_nextafter (&tmp, REAL_MODE_FORMAT (mode), &value, &inf);
315 3405831 : value = tmp;
316 : }
317 3405831 : }
318 :
319 : // Like real_arithmetic, but round the result to INF if the operation
320 : // produced inexact results.
321 : //
322 : // ?? There is still one problematic case, i387. With
323 : // -fexcess-precision=standard we perform most SF/DFmode arithmetic in
324 : // XFmode (long_double_type_node), so that case is OK. But without
325 : // -mfpmath=sse, all the SF/DFmode computations are in XFmode
326 : // precision (64-bit mantissa) and only occasionally rounded to
327 : // SF/DFmode (when storing into memory from the 387 stack). Maybe
328 : // this is ok as well though it is just occasionally more precise. ??
329 :
330 : void
331 15100239 : frange_arithmetic (enum tree_code code, tree type,
332 : REAL_VALUE_TYPE &result,
333 : const REAL_VALUE_TYPE &op1,
334 : const REAL_VALUE_TYPE &op2,
335 : const REAL_VALUE_TYPE &inf)
336 : {
337 15100239 : REAL_VALUE_TYPE value;
338 15100239 : enum machine_mode mode = TYPE_MODE (type);
339 105701673 : bool mode_composite = MODE_COMPOSITE_P (mode);
340 :
341 15100239 : bool inexact = real_arithmetic (&value, code, &op1, &op2);
342 15100239 : real_convert (&result, mode, &value);
343 :
344 : /* When rounding towards negative infinity, x + (-x) and
345 : x - x is -0 rather than +0 real_arithmetic computes.
346 : So, when we are looking for lower bound (inf is negative),
347 : use -0 rather than +0. */
348 15100239 : if (flag_rounding_math
349 16568 : && (code == PLUS_EXPR || code == MINUS_EXPR)
350 4868 : && !inexact
351 4868 : && real_iszero (&result)
352 66 : && !real_isneg (&result)
353 15100305 : && real_isneg (&inf))
354 : {
355 36 : REAL_VALUE_TYPE op2a = op2;
356 36 : if (code == PLUS_EXPR)
357 30 : op2a.sign ^= 1;
358 36 : if (real_isneg (&op1) == real_isneg (&op2a) && real_equal (&op1, &op2a))
359 36 : result.sign = 1;
360 : }
361 :
362 : // Be extra careful if there may be discrepancies between the
363 : // compile and runtime results.
364 15100239 : bool round = false;
365 15100239 : if (mode_composite)
366 : round = true;
367 : else
368 : {
369 15100239 : bool low = real_isneg (&inf);
370 15100239 : round = (low ? !real_less (&result, &value)
371 7550183 : : !real_less (&value, &result));
372 15100239 : if (real_isinf (&result, !low)
373 1527322 : && !real_isinf (&value)
374 15490309 : && !flag_rounding_math)
375 : {
376 : // Use just [+INF, +INF] rather than [MAX, +INF]
377 : // even if value is larger than MAX and rounds to
378 : // nearest to +INF. Similarly just [-INF, -INF]
379 : // rather than [-INF, +MAX] even if value is smaller
380 : // than -MAX and rounds to nearest to -INF.
381 : // Unless INEXACT is true, in that case we need some
382 : // extra buffer.
383 388169 : if (!inexact)
384 : round = false;
385 : else
386 : {
387 56702 : REAL_VALUE_TYPE tmp = result, tmp2;
388 56702 : frange_nextafter (mode, tmp, inf);
389 : // TMP is at this point the maximum representable
390 : // number.
391 56702 : real_arithmetic (&tmp2, MINUS_EXPR, &value, &tmp);
392 56702 : if (real_isneg (&tmp2) != low
393 56702 : && (REAL_EXP (&tmp2) - REAL_EXP (&tmp)
394 56702 : >= 2 - REAL_MODE_FORMAT (mode)->p))
395 56701 : round = false;
396 : }
397 : }
398 : }
399 14768772 : if (round && (inexact || !real_identical (&result, &value)))
400 : {
401 1228032 : if (mode_composite
402 1228032 : && (real_isdenormal (&result, mode) || real_iszero (&result)))
403 : {
404 : // IBM extended denormals only have DFmode precision.
405 0 : REAL_VALUE_TYPE tmp, tmp2;
406 0 : real_convert (&tmp2, DFmode, &value);
407 0 : real_nextafter (&tmp, REAL_MODE_FORMAT (DFmode), &tmp2, &inf);
408 0 : real_convert (&result, mode, &tmp);
409 : }
410 : else
411 1228032 : frange_nextafter (mode, result, inf);
412 : }
413 15100239 : if (mode_composite)
414 0 : switch (code)
415 : {
416 0 : case PLUS_EXPR:
417 0 : case MINUS_EXPR:
418 : // ibm-ldouble-format documents 1ulp for + and -.
419 0 : frange_nextafter (mode, result, inf);
420 0 : break;
421 0 : case MULT_EXPR:
422 : // ibm-ldouble-format documents 2ulps for *.
423 0 : frange_nextafter (mode, result, inf);
424 0 : frange_nextafter (mode, result, inf);
425 0 : break;
426 0 : case RDIV_EXPR:
427 : // ibm-ldouble-format documents 3ulps for /.
428 0 : frange_nextafter (mode, result, inf);
429 0 : frange_nextafter (mode, result, inf);
430 0 : frange_nextafter (mode, result, inf);
431 0 : break;
432 : default:
433 : break;
434 : }
435 15100239 : }
436 :
437 : // Crop R to [-INF, MAX] where MAX is the maximum representable number
438 : // for TYPE.
439 :
440 : static inline void
441 171300 : frange_drop_inf (frange &r, tree type)
442 : {
443 171300 : REAL_VALUE_TYPE max = real_max_representable (type);
444 171300 : frange tmp (type, r.lower_bound (), max);
445 171300 : r.intersect (tmp);
446 171300 : }
447 :
448 : // Crop R to [MIN, +INF] where MIN is the minimum representable number
449 : // for TYPE.
450 :
451 : static inline void
452 90645 : frange_drop_ninf (frange &r, tree type)
453 : {
454 90645 : REAL_VALUE_TYPE min = real_min_representable (type);
455 90645 : frange tmp (type, min, r.upper_bound ());
456 90645 : r.intersect (tmp);
457 90645 : }
458 :
459 : // Crop R to [MIN, MAX] where MAX is the maximum representable number
460 : // for TYPE and MIN the minimum representable number for TYPE.
461 :
462 : static inline void
463 1303823 : frange_drop_infs (frange &r, tree type)
464 : {
465 1303823 : REAL_VALUE_TYPE max = real_max_representable (type);
466 1303823 : REAL_VALUE_TYPE min = real_min_representable (type);
467 1303823 : frange tmp (type, min, max);
468 1303823 : r.intersect (tmp);
469 1303823 : }
470 :
471 : // If zero is in R, make sure both -0.0 and +0.0 are in the range.
472 :
473 : static inline void
474 906976 : frange_add_zeros (frange &r, tree type)
475 : {
476 906976 : if (r.undefined_p () || r.known_isnan ())
477 : return;
478 :
479 906976 : if (HONOR_SIGNED_ZEROS (type)
480 906976 : && (real_iszero (&r.lower_bound ()) || real_iszero (&r.upper_bound ())))
481 : {
482 158548 : frange zero;
483 158548 : zero.set_zero (type);
484 158548 : r.union_ (zero);
485 158548 : }
486 : }
487 :
488 : // Build a range that is <= VAL and store it in R. Return TRUE if
489 : // further changes may be needed for R, or FALSE if R is in its final
490 : // form.
491 :
492 : static bool
493 253060 : build_le (frange &r, tree type, const frange &val)
494 : {
495 253060 : gcc_checking_assert (!val.known_isnan ());
496 :
497 253060 : REAL_VALUE_TYPE ninf = frange_val_min (type);
498 253060 : r.set (type, ninf, val.upper_bound ());
499 :
500 : // Add both zeros if there's the possibility of zero equality.
501 253060 : frange_add_zeros (r, type);
502 :
503 253060 : return true;
504 : }
505 :
506 : // Build a range that is < VAL and store it in R. Return TRUE if
507 : // further changes may be needed for R, or FALSE if R is in its final
508 : // form.
509 :
510 : static bool
511 300779 : build_lt (frange &r, tree type, const frange &val)
512 : {
513 300779 : gcc_checking_assert (!val.known_isnan ());
514 :
515 : // < -INF is outside the range.
516 300779 : if (real_isinf (&val.upper_bound (), 1))
517 : {
518 1460 : if (HONOR_NANS (type))
519 1460 : r.set_nan (type);
520 : else
521 0 : r.set_undefined ();
522 1460 : return false;
523 : }
524 :
525 299319 : REAL_VALUE_TYPE ninf = frange_val_min (type);
526 299319 : REAL_VALUE_TYPE prev = val.upper_bound ();
527 299319 : machine_mode mode = TYPE_MODE (type);
528 : // Default to the conservatively correct closed ranges for
529 : // MODE_COMPOSITE_P, otherwise use nextafter. Note that for
530 : // !HONOR_INFINITIES, nextafter will yield -INF, but frange::set()
531 : // will crop the range appropriately.
532 2095233 : if (!MODE_COMPOSITE_P (mode))
533 299319 : frange_nextafter (mode, prev, ninf);
534 299319 : r.set (type, ninf, prev);
535 299319 : return true;
536 : }
537 :
538 : // Build a range that is >= VAL and store it in R. Return TRUE if
539 : // further changes may be needed for R, or FALSE if R is in its final
540 : // form.
541 :
542 : static bool
543 380824 : build_ge (frange &r, tree type, const frange &val)
544 : {
545 380824 : gcc_checking_assert (!val.known_isnan ());
546 :
547 380824 : REAL_VALUE_TYPE inf = frange_val_max (type);
548 380824 : r.set (type, val.lower_bound (), inf);
549 :
550 : // Add both zeros if there's the possibility of zero equality.
551 380824 : frange_add_zeros (r, type);
552 :
553 380824 : return true;
554 : }
555 :
556 : // Build a range that is > VAL and store it in R. Return TRUE if
557 : // further changes may be needed for R, or FALSE if R is in its final
558 : // form.
559 :
560 : static bool
561 201556 : build_gt (frange &r, tree type, const frange &val)
562 : {
563 201556 : gcc_checking_assert (!val.known_isnan ());
564 :
565 : // > +INF is outside the range.
566 201556 : if (real_isinf (&val.lower_bound (), 0))
567 : {
568 3239 : if (HONOR_NANS (type))
569 3239 : r.set_nan (type);
570 : else
571 0 : r.set_undefined ();
572 3239 : return false;
573 : }
574 :
575 198317 : REAL_VALUE_TYPE inf = frange_val_max (type);
576 198317 : REAL_VALUE_TYPE next = val.lower_bound ();
577 198317 : machine_mode mode = TYPE_MODE (type);
578 : // Default to the conservatively correct closed ranges for
579 : // MODE_COMPOSITE_P, otherwise use nextafter. Note that for
580 : // !HONOR_INFINITIES, nextafter will yield +INF, but frange::set()
581 : // will crop the range appropriately.
582 1388219 : if (!MODE_COMPOSITE_P (mode))
583 198317 : frange_nextafter (mode, next, inf);
584 198317 : r.set (type, next, inf);
585 198317 : return true;
586 : }
587 :
588 :
589 : bool
590 55170 : operator_identity::fold_range (frange &r, tree, const frange &op1,
591 : const frange &, relation_trio) const
592 : {
593 55170 : r = op1;
594 55170 : return true;
595 : }
596 :
597 : bool
598 17024 : operator_identity::op1_range (frange &r, tree, const frange &lhs,
599 : const frange &, relation_trio) const
600 : {
601 17024 : r = lhs;
602 17024 : return true;
603 : }
604 :
605 : bool
606 1118 : operator_cst::fold_range (frange &r, tree, const frange &op1,
607 : const frange &, relation_trio) const
608 : {
609 1118 : r = op1;
610 1118 : return true;
611 : }
612 :
613 : bool
614 25564 : operator_equal::op2_range (frange &r, tree type,
615 : const irange &lhs, const frange &op1,
616 : relation_trio rel) const
617 : {
618 25564 : return op1_range (r, type, lhs, op1, rel.swap_op1_op2 ());
619 : }
620 :
621 : bool
622 175755 : operator_equal::fold_range (irange &r, tree type,
623 : const frange &op1, const frange &op2,
624 : relation_trio rel) const
625 : {
626 175755 : if (frelop_early_resolve (r, type, op1, op2, rel, VREL_EQ))
627 : return true;
628 :
629 173392 : if (op1.known_isnan () || op2.known_isnan ())
630 525 : r = range_false (type);
631 : // We can be sure the values are always equal or not if both ranges
632 : // consist of a single value, and then compare them.
633 172867 : else if (op1.singleton_p () && op2.singleton_p ())
634 : {
635 458 : if (op1 == op2)
636 110 : r = range_true (type);
637 : // If one operand is -0.0 and other 0.0, they are still equal.
638 348 : else if (real_iszero (&op1.lower_bound ())
639 348 : && real_iszero (&op2.lower_bound ()))
640 29 : r = range_true (type);
641 : else
642 319 : r = range_false (type);
643 : }
644 172409 : else if (real_iszero (&op1.lower_bound ())
645 5788 : && real_iszero (&op1.upper_bound ())
646 735 : && real_iszero (&op2.lower_bound ())
647 309 : && real_iszero (&op2.upper_bound ())
648 172718 : && !maybe_isnan (op1, op2))
649 : // [-0.0, 0.0] == [-0.0, 0.0] or similar.
650 166 : r = range_true (type);
651 : else
652 : {
653 : // If ranges do not intersect, we know the range is not equal,
654 : // otherwise we don't know anything for sure.
655 172243 : frange tmp = op1;
656 172243 : tmp.intersect (op2);
657 172243 : if (tmp.undefined_p ())
658 : {
659 : // If one range is [whatever, -0.0] and another
660 : // [0.0, whatever2], we don't know anything either,
661 : // because -0.0 == 0.0.
662 612 : if ((real_iszero (&op1.upper_bound ())
663 59 : && real_iszero (&op2.lower_bound ()))
664 615 : || (real_iszero (&op1.lower_bound ())
665 37 : && real_iszero (&op2.upper_bound ())))
666 56 : r = range_true_and_false (type);
667 : else
668 556 : r = range_false (type);
669 : }
670 : else
671 171631 : r = range_true_and_false (type);
672 172243 : }
673 : return true;
674 : }
675 :
676 : bool
677 135273 : operator_equal::op1_range (frange &r, tree type,
678 : const irange &lhs,
679 : const frange &op2,
680 : relation_trio trio) const
681 : {
682 135273 : relation_kind rel = trio.op1_op2 ();
683 135273 : switch (get_bool_state (r, lhs, type))
684 : {
685 37875 : case BRS_TRUE:
686 : // The TRUE side of x == NAN is unreachable.
687 37875 : if (op2.known_isnan ())
688 0 : r.set_undefined ();
689 : else
690 : {
691 : // If it's true, the result is the same as OP2.
692 37875 : r = op2;
693 : // Add both zeros if there's the possibility of zero equality.
694 37875 : frange_add_zeros (r, type);
695 : // The TRUE side of op1 == op2 implies op1 is !NAN.
696 37875 : r.clear_nan ();
697 : }
698 : break;
699 :
700 95640 : case BRS_FALSE:
701 : // The FALSE side of op1 == op1 implies op1 is a NAN.
702 95640 : if (rel == VREL_EQ)
703 2217 : r.set_nan (type);
704 : // On the FALSE side of x == NAN, we know nothing about x.
705 93423 : else if (op2.known_isnan ())
706 0 : r.set_varying (type);
707 : // If the result is false, the only time we know anything is
708 : // if OP2 is a constant.
709 93423 : else if (op2.singleton_p ()
710 102470 : || (!op2.maybe_isnan () && op2.zero_p ()))
711 : {
712 61110 : REAL_VALUE_TYPE tmp = op2.lower_bound ();
713 61110 : r.set (type, tmp, tmp, VR_ANTI_RANGE);
714 : }
715 : else
716 32313 : r.set_varying (type);
717 : break;
718 :
719 : default:
720 : break;
721 : }
722 135273 : return true;
723 : }
724 :
725 : // Check if the LHS range indicates a relation between OP1 and OP2.
726 :
727 : relation_kind
728 133860 : operator_equal::op1_op2_relation (const irange &lhs, const frange &,
729 : const frange &) const
730 : {
731 133860 : if (lhs.undefined_p ())
732 : return VREL_UNDEFINED;
733 :
734 : // FALSE = op1 == op2 indicates NE_EXPR.
735 133860 : if (lhs.zero_p ())
736 : return VREL_NE;
737 :
738 : // TRUE = op1 == op2 indicates EQ_EXPR.
739 70099 : if (!contains_zero_p (lhs))
740 68525 : return VREL_EQ;
741 : return VREL_VARYING;
742 : }
743 :
744 : bool
745 850320 : operator_not_equal::fold_range (irange &r, tree type,
746 : const frange &op1, const frange &op2,
747 : relation_trio trio) const
748 : {
749 850320 : relation_kind rel = trio.op1_op2 ();
750 :
751 : // VREL_NE & NE_EXPR is always true, even with NANs.
752 850320 : if (rel == VREL_NE)
753 : {
754 26 : r = range_true (type);
755 26 : return true;
756 : }
757 850294 : if (rel == VREL_EQ && maybe_isnan (op1, op2))
758 : {
759 : // Avoid frelop_early_resolve() below as it could fold to FALSE
760 : // without regards to NANs. This would be incorrect if trying
761 : // to fold x_5 != x_5 without prior knowledge of NANs.
762 : // Still, if either operand is undefined, return VARYING.
763 27072 : if (empty_range_varying (r, type, op1, op2))
764 5 : return true;
765 : }
766 823222 : else if (frelop_early_resolve (r, type, op1, op2, trio, VREL_NE))
767 : return true;
768 :
769 : // x != NAN is always TRUE.
770 848862 : if (op1.known_isnan () || op2.known_isnan ())
771 1271 : r = range_true (type);
772 : // We can be sure the values are always equal or not if both ranges
773 : // consist of a single value, and then compare them.
774 847591 : else if (op1.singleton_p () && op2.singleton_p ())
775 : {
776 1024 : if (op1 == op2)
777 677 : r = range_false (type);
778 : // If one operand is -0.0 and other 0.0, they are still equal.
779 347 : else if (real_iszero (&op1.lower_bound ())
780 347 : && real_iszero (&op2.lower_bound ()))
781 0 : r = range_false (type);
782 : else
783 347 : r = range_true (type);
784 : }
785 846567 : else if (real_iszero (&op1.lower_bound ())
786 7102 : && real_iszero (&op1.upper_bound ())
787 367 : && real_iszero (&op2.lower_bound ())
788 188 : && real_iszero (&op2.upper_bound ())
789 846755 : && !maybe_isnan (op1, op2))
790 : // [-0.0, 0.0] != [-0.0, 0.0] or similar.
791 100 : r = range_false (type);
792 : else
793 : {
794 : // If ranges do not intersect, we know the range is not equal,
795 : // otherwise we don't know anything for sure.
796 846467 : frange tmp = op1;
797 846467 : tmp.intersect (op2);
798 846467 : if (tmp.undefined_p ())
799 : {
800 : // If one range is [whatever, -0.0] and another
801 : // [0.0, whatever2], we don't know anything either,
802 : // because -0.0 == 0.0.
803 542 : if ((real_iszero (&op1.upper_bound ())
804 5 : && real_iszero (&op2.lower_bound ()))
805 547 : || (real_iszero (&op1.lower_bound ())
806 10 : && real_iszero (&op2.upper_bound ())))
807 0 : r = range_true_and_false (type);
808 : else
809 542 : r = range_true (type);
810 : }
811 : else
812 845925 : r = range_true_and_false (type);
813 846467 : }
814 : return true;
815 : }
816 :
817 : bool
818 284006 : operator_not_equal::op1_range (frange &r, tree type,
819 : const irange &lhs,
820 : const frange &op2,
821 : relation_trio trio) const
822 : {
823 284006 : relation_kind rel = trio.op1_op2 ();
824 284006 : switch (get_bool_state (r, lhs, type))
825 : {
826 47050 : case BRS_TRUE:
827 : // If the result is true, the only time we know anything is if
828 : // OP2 is a constant.
829 47050 : if (op2.singleton_p ())
830 : {
831 : // This is correct even if op1 is NAN, because the following
832 : // range would be ~[tmp, tmp] with the NAN property set to
833 : // maybe (VARYING).
834 22987 : REAL_VALUE_TYPE tmp = op2.lower_bound ();
835 22987 : r.set (type, tmp, tmp, VR_ANTI_RANGE);
836 : }
837 : // The TRUE side of op1 != op1 implies op1 is NAN.
838 24063 : else if (rel == VREL_EQ)
839 5907 : r.set_nan (type);
840 : else
841 18156 : r.set_varying (type);
842 : break;
843 :
844 235374 : case BRS_FALSE:
845 : // The FALSE side of x != NAN is impossible.
846 235374 : if (op2.known_isnan ())
847 170 : r.set_undefined ();
848 : else
849 : {
850 : // If it's false, the result is the same as OP2.
851 235204 : r = op2;
852 : // Add both zeros if there's the possibility of zero equality.
853 235204 : frange_add_zeros (r, type);
854 : // The FALSE side of op1 != op2 implies op1 is !NAN.
855 235204 : r.clear_nan ();
856 : }
857 : break;
858 :
859 : default:
860 : break;
861 : }
862 284006 : return true;
863 : }
864 :
865 : bool
866 183217 : operator_not_equal::op2_range (frange &r, tree type,
867 : const irange &lhs,
868 : const frange &op1,
869 : relation_trio trio) const
870 : {
871 183217 : return op1_range (r, type, lhs, op1, trio);
872 : }
873 :
874 : // Check if the LHS range indicates a relation between OP1 and OP2.
875 :
876 : relation_kind
877 634821 : operator_not_equal::op1_op2_relation (const irange &lhs, const frange &,
878 : const frange &) const
879 : {
880 634821 : if (lhs.undefined_p ())
881 : return VREL_UNDEFINED;
882 :
883 : // FALSE = op1 != op2 indicates EQ_EXPR.
884 634821 : if (lhs.zero_p ())
885 : return VREL_EQ;
886 :
887 : // TRUE = op1 != op2 indicates NE_EXPR.
888 118000 : if (!contains_zero_p (lhs))
889 116445 : return VREL_NE;
890 : return VREL_VARYING;
891 : }
892 :
893 : bool
894 269758 : operator_lt::fold_range (irange &r, tree type,
895 : const frange &op1, const frange &op2,
896 : relation_trio trio) const
897 : {
898 269758 : if (frelop_early_resolve (r, type, op1, op2, trio, VREL_LT))
899 : return true;
900 :
901 269217 : if (op1.known_isnan ()
902 268824 : || op2.known_isnan ()
903 537787 : || !real_less (&op1.lower_bound (), &op2.upper_bound ()))
904 2641 : r = range_false (type);
905 266576 : else if (!maybe_isnan (op1, op2)
906 266576 : && real_less (&op1.upper_bound (), &op2.lower_bound ()))
907 1087 : r = range_true (type);
908 : else
909 265489 : r = range_true_and_false (type);
910 : return true;
911 : }
912 :
913 : bool
914 424477 : operator_lt::op1_range (frange &r,
915 : tree type,
916 : const irange &lhs,
917 : const frange &op2,
918 : relation_trio) const
919 : {
920 424477 : switch (get_bool_state (r, lhs, type))
921 : {
922 143949 : case BRS_TRUE:
923 : // The TRUE side of x < NAN is unreachable.
924 143949 : if (op2.known_isnan ())
925 68 : r.set_undefined ();
926 143881 : else if (op2.undefined_p ())
927 : return false;
928 143881 : else if (build_lt (r, type, op2))
929 : {
930 143881 : r.clear_nan ();
931 : // x < y implies x is not +INF.
932 143881 : frange_drop_inf (r, type);
933 : }
934 : break;
935 :
936 279954 : case BRS_FALSE:
937 : // On the FALSE side of x < NAN, we know nothing about x.
938 530639 : if (op2.maybe_isnan ())
939 29269 : r.set_varying (type);
940 : else
941 250685 : build_ge (r, type, op2);
942 : break;
943 :
944 : default:
945 : break;
946 : }
947 : return true;
948 : }
949 :
950 : bool
951 63804 : operator_lt::op2_range (frange &r,
952 : tree type,
953 : const irange &lhs,
954 : const frange &op1,
955 : relation_trio) const
956 : {
957 63804 : switch (get_bool_state (r, lhs, type))
958 : {
959 25809 : case BRS_TRUE:
960 : // The TRUE side of NAN < x is unreachable.
961 25809 : if (op1.known_isnan ())
962 22 : r.set_undefined ();
963 25787 : else if (op1.undefined_p ())
964 : return false;
965 25787 : else if (build_gt (r, type, op1))
966 : {
967 25787 : r.clear_nan ();
968 : // x < y implies y is not -INF.
969 25787 : frange_drop_ninf (r, type);
970 : }
971 : break;
972 :
973 37610 : case BRS_FALSE:
974 : // On the FALSE side of NAN < x, we know nothing about x.
975 41318 : if (op1.maybe_isnan ())
976 33902 : r.set_varying (type);
977 : else
978 3708 : build_le (r, type, op1);
979 : break;
980 :
981 : default:
982 : break;
983 : }
984 : return true;
985 : }
986 :
987 :
988 : // Check if the LHS range indicates a relation between OP1 and OP2.
989 :
990 : relation_kind
991 244525 : operator_lt::op1_op2_relation (const irange &lhs, const frange &,
992 : const frange &) const
993 : {
994 244525 : if (lhs.undefined_p ())
995 : return VREL_UNDEFINED;
996 :
997 : // FALSE = op1 < op2 indicates GE_EXPR.
998 244525 : if (lhs.zero_p ())
999 : return VREL_GE;
1000 :
1001 : // TRUE = op1 < op2 indicates LT_EXPR.
1002 112202 : if (!contains_zero_p (lhs))
1003 111462 : return VREL_LT;
1004 : return VREL_VARYING;
1005 : }
1006 :
1007 : bool
1008 271508 : operator_le::fold_range (irange &r, tree type,
1009 : const frange &op1, const frange &op2,
1010 : relation_trio rel) const
1011 : {
1012 271508 : if (frelop_early_resolve (r, type, op1, op2, rel, VREL_LE))
1013 : return true;
1014 :
1015 270919 : if (op1.known_isnan ()
1016 269917 : || op2.known_isnan ()
1017 540794 : || !real_compare (LE_EXPR, &op1.lower_bound (), &op2.upper_bound ()))
1018 2463 : r = range_false (type);
1019 268456 : else if (!maybe_isnan (op1, op2)
1020 268456 : && real_compare (LE_EXPR, &op1.upper_bound (), &op2.lower_bound ()))
1021 776 : r = range_true (type);
1022 : else
1023 267680 : r = range_true_and_false (type);
1024 : return true;
1025 : }
1026 :
1027 : bool
1028 98104 : operator_le::op1_range (frange &r,
1029 : tree type,
1030 : const irange &lhs,
1031 : const frange &op2,
1032 : relation_trio) const
1033 : {
1034 98104 : switch (get_bool_state (r, lhs, type))
1035 : {
1036 67703 : case BRS_TRUE:
1037 : // The TRUE side of x <= NAN is unreachable.
1038 67703 : if (op2.known_isnan ())
1039 0 : r.set_undefined ();
1040 67703 : else if (op2.undefined_p ())
1041 : return false;
1042 67703 : else if (build_le (r, type, op2))
1043 67703 : r.clear_nan ();
1044 : break;
1045 :
1046 30068 : case BRS_FALSE:
1047 : // On the FALSE side of x <= NAN, we know nothing about x.
1048 55393 : if (op2.maybe_isnan ())
1049 4743 : r.set_varying (type);
1050 : else
1051 25325 : build_gt (r, type, op2);
1052 : break;
1053 :
1054 : default:
1055 : break;
1056 : }
1057 : return true;
1058 : }
1059 :
1060 : bool
1061 14995 : operator_le::op2_range (frange &r,
1062 : tree type,
1063 : const irange &lhs,
1064 : const frange &op1,
1065 : relation_trio) const
1066 : {
1067 14995 : switch (get_bool_state (r, lhs, type))
1068 : {
1069 4088 : case BRS_TRUE:
1070 : // The TRUE side of NAN <= x is unreachable.
1071 4088 : if (op1.known_isnan ())
1072 0 : r.set_undefined ();
1073 4088 : else if (op1.undefined_p ())
1074 : return false;
1075 4088 : else if (build_ge (r, type, op1))
1076 4088 : r.clear_nan ();
1077 : break;
1078 :
1079 10610 : case BRS_FALSE:
1080 : // On the FALSE side of NAN <= x, we know nothing about x.
1081 11452 : if (op1.maybe_isnan ())
1082 9768 : r.set_varying (type);
1083 842 : else if (op1.undefined_p ())
1084 : return false;
1085 : else
1086 842 : build_lt (r, type, op1);
1087 : break;
1088 :
1089 : default:
1090 : break;
1091 : }
1092 : return true;
1093 : }
1094 :
1095 : // Check if the LHS range indicates a relation between OP1 and OP2.
1096 :
1097 : relation_kind
1098 60969 : operator_le::op1_op2_relation (const irange &lhs, const frange &,
1099 : const frange &) const
1100 : {
1101 60969 : if (lhs.undefined_p ())
1102 : return VREL_UNDEFINED;
1103 :
1104 : // FALSE = op1 <= op2 indicates GT_EXPR.
1105 60969 : if (lhs.zero_p ())
1106 : return VREL_GT;
1107 :
1108 : // TRUE = op1 <= op2 indicates LE_EXPR.
1109 30729 : if (!contains_zero_p (lhs))
1110 30131 : return VREL_LE;
1111 : return VREL_VARYING;
1112 : }
1113 :
1114 : bool
1115 260996 : operator_gt::fold_range (irange &r, tree type,
1116 : const frange &op1, const frange &op2,
1117 : relation_trio trio) const
1118 : {
1119 260996 : if (frelop_early_resolve (r, type, op1, op2, trio, VREL_GT))
1120 : return true;
1121 :
1122 260227 : if (op1.known_isnan ()
1123 259884 : || op2.known_isnan ()
1124 519787 : || !real_compare (GT_EXPR, &op1.upper_bound (), &op2.lower_bound ()))
1125 3940 : r = range_false (type);
1126 256287 : else if (!maybe_isnan (op1, op2)
1127 256287 : && real_compare (GT_EXPR, &op1.lower_bound (), &op2.upper_bound ()))
1128 689 : r = range_true (type);
1129 : else
1130 255598 : r = range_true_and_false (type);
1131 : return true;
1132 : }
1133 :
1134 : bool
1135 168763 : operator_gt::op1_range (frange &r,
1136 : tree type,
1137 : const irange &lhs,
1138 : const frange &op2,
1139 : relation_trio) const
1140 : {
1141 168763 : switch (get_bool_state (r, lhs, type))
1142 : {
1143 64886 : case BRS_TRUE:
1144 : // The TRUE side of x > NAN is unreachable.
1145 64886 : if (op2.known_isnan ())
1146 28 : r.set_undefined ();
1147 64858 : else if (op2.undefined_p ())
1148 : return false;
1149 64858 : else if (build_gt (r, type, op2))
1150 : {
1151 64858 : r.clear_nan ();
1152 : // x > y implies x is not -INF.
1153 64858 : frange_drop_ninf (r, type);
1154 : }
1155 : break;
1156 :
1157 103136 : case BRS_FALSE:
1158 : // On the FALSE side of x > NAN, we know nothing about x.
1159 177543 : if (op2.maybe_isnan ())
1160 28729 : r.set_varying (type);
1161 74407 : else if (op2.undefined_p ())
1162 : return false;
1163 : else
1164 74407 : build_le (r, type, op2);
1165 : break;
1166 :
1167 : default:
1168 : break;
1169 : }
1170 : return true;
1171 : }
1172 :
1173 : bool
1174 69995 : operator_gt::op2_range (frange &r,
1175 : tree type,
1176 : const irange &lhs,
1177 : const frange &op1,
1178 : relation_trio) const
1179 : {
1180 69995 : switch (get_bool_state (r, lhs, type))
1181 : {
1182 27441 : case BRS_TRUE:
1183 : // The TRUE side of NAN > x is unreachable.
1184 27441 : if (op1.known_isnan ())
1185 22 : r.set_undefined ();
1186 27419 : else if (op1.undefined_p ())
1187 : return false;
1188 27419 : else if (build_lt (r, type, op1))
1189 : {
1190 27419 : r.clear_nan ();
1191 : // x > y implies y is not +INF.
1192 27419 : frange_drop_inf (r, type);
1193 : }
1194 : break;
1195 :
1196 42147 : case BRS_FALSE:
1197 : // On The FALSE side of NAN > x, we know nothing about x.
1198 45527 : if (op1.maybe_isnan ())
1199 38767 : r.set_varying (type);
1200 3380 : else if (op1.undefined_p ())
1201 : return false;
1202 : else
1203 3380 : build_ge (r, type, op1);
1204 : break;
1205 :
1206 : default:
1207 : break;
1208 : }
1209 : return true;
1210 : }
1211 :
1212 : // Check if the LHS range indicates a relation between OP1 and OP2.
1213 :
1214 : relation_kind
1215 266577 : operator_gt::op1_op2_relation (const irange &lhs, const frange &,
1216 : const frange &) const
1217 : {
1218 266577 : if (lhs.undefined_p ())
1219 : return VREL_UNDEFINED;
1220 :
1221 : // FALSE = op1 > op2 indicates LE_EXPR.
1222 266577 : if (lhs.zero_p ())
1223 : return VREL_LE;
1224 :
1225 : // TRUE = op1 > op2 indicates GT_EXPR.
1226 119629 : if (!contains_zero_p (lhs))
1227 118779 : return VREL_GT;
1228 : return VREL_VARYING;
1229 : }
1230 :
1231 : bool
1232 268801 : operator_ge::fold_range (irange &r, tree type,
1233 : const frange &op1, const frange &op2,
1234 : relation_trio rel) const
1235 : {
1236 268801 : if (frelop_early_resolve (r, type, op1, op2, rel, VREL_GE))
1237 : return true;
1238 :
1239 268424 : if (op1.known_isnan ()
1240 267608 : || op2.known_isnan ()
1241 535988 : || !real_compare (GE_EXPR, &op1.upper_bound (), &op2.lower_bound ()))
1242 1503 : r = range_false (type);
1243 266921 : else if (!maybe_isnan (op1, op2)
1244 266921 : && real_compare (GE_EXPR, &op1.lower_bound (), &op2.upper_bound ()))
1245 2457 : r = range_true (type);
1246 : else
1247 264464 : r = range_true_and_false (type);
1248 : return true;
1249 : }
1250 :
1251 : bool
1252 108130 : operator_ge::op1_range (frange &r,
1253 : tree type,
1254 : const irange &lhs,
1255 : const frange &op2,
1256 : relation_trio) const
1257 : {
1258 108130 : switch (get_bool_state (r, lhs, type))
1259 : {
1260 60009 : case BRS_TRUE:
1261 : // The TRUE side of x >= NAN is unreachable.
1262 60009 : if (op2.known_isnan ())
1263 0 : r.set_undefined ();
1264 60009 : else if (op2.undefined_p ())
1265 : return false;
1266 60009 : else if (build_ge (r, type, op2))
1267 60009 : r.clear_nan ();
1268 : break;
1269 :
1270 47824 : case BRS_FALSE:
1271 : // On the FALSE side of x >= NAN, we know nothing about x.
1272 88865 : if (op2.maybe_isnan ())
1273 6783 : r.set_varying (type);
1274 41041 : else if (op2.undefined_p ())
1275 : return false;
1276 : else
1277 41041 : build_lt (r, type, op2);
1278 : break;
1279 :
1280 : default:
1281 : break;
1282 : }
1283 : return true;
1284 : }
1285 :
1286 : bool
1287 13488 : operator_ge::op2_range (frange &r, tree type,
1288 : const irange &lhs,
1289 : const frange &op1,
1290 : relation_trio) const
1291 : {
1292 13488 : switch (get_bool_state (r, lhs, type))
1293 : {
1294 5497 : case BRS_TRUE:
1295 : // The TRUE side of NAN >= x is unreachable.
1296 5497 : if (op1.known_isnan ())
1297 0 : r.set_undefined ();
1298 5497 : else if (op1.undefined_p ())
1299 : return false;
1300 5497 : else if (build_le (r, type, op1))
1301 5497 : r.clear_nan ();
1302 : break;
1303 :
1304 7730 : case BRS_FALSE:
1305 : // On the FALSE side of NAN >= x, we know nothing about x.
1306 8499 : if (op1.maybe_isnan ())
1307 6961 : r.set_varying (type);
1308 769 : else if (op1.undefined_p ())
1309 : return false;
1310 : else
1311 769 : build_gt (r, type, op1);
1312 : break;
1313 :
1314 : default:
1315 : break;
1316 : }
1317 : return true;
1318 : }
1319 :
1320 : // Check if the LHS range indicates a relation between OP1 and OP2.
1321 :
1322 : relation_kind
1323 58419 : operator_ge::op1_op2_relation (const irange &lhs, const frange &,
1324 : const frange &) const
1325 : {
1326 58419 : if (lhs.undefined_p ())
1327 : return VREL_UNDEFINED;
1328 :
1329 : // FALSE = op1 >= op2 indicates LT_EXPR.
1330 58419 : if (lhs.zero_p ())
1331 : return VREL_LT;
1332 :
1333 : // TRUE = op1 >= op2 indicates GE_EXPR.
1334 30518 : if (!contains_zero_p (lhs))
1335 29992 : return VREL_GE;
1336 : return VREL_VARYING;
1337 : }
1338 :
1339 : // UNORDERED_EXPR comparison.
1340 :
1341 : class foperator_unordered : public range_operator
1342 : {
1343 : using range_operator::fold_range;
1344 : using range_operator::op1_range;
1345 : using range_operator::op2_range;
1346 : public:
1347 : bool fold_range (irange &r, tree type,
1348 : const frange &op1, const frange &op2,
1349 : relation_trio = TRIO_VARYING) const final override;
1350 : bool op1_range (frange &r, tree type,
1351 : const irange &lhs, const frange &op2,
1352 : relation_trio = TRIO_VARYING) const final override;
1353 56399 : bool op2_range (frange &r, tree type,
1354 : const irange &lhs, const frange &op1,
1355 : relation_trio rel = TRIO_VARYING) const final override
1356 : {
1357 56399 : return op1_range (r, type, lhs, op1, rel.swap_op1_op2 ());
1358 : }
1359 : };
1360 : static const foperator_unordered fop_unordered;
1361 :
1362 : bool
1363 54985 : foperator_unordered::fold_range (irange &r, tree type,
1364 : const frange &op1, const frange &op2,
1365 : relation_trio) const
1366 : {
1367 : // UNORDERED is TRUE if either operand is a NAN.
1368 54985 : if (op1.known_isnan () || op2.known_isnan ())
1369 115 : r = range_true (type);
1370 : // UNORDERED is FALSE if neither operand is a NAN.
1371 57322 : else if (!op1.maybe_isnan () && !op2.maybe_isnan ())
1372 1228 : r = range_false (type);
1373 : else
1374 53642 : r = range_true_and_false (type);
1375 54985 : return true;
1376 : }
1377 :
1378 : bool
1379 103067 : foperator_unordered::op1_range (frange &r, tree type,
1380 : const irange &lhs,
1381 : const frange &op2,
1382 : relation_trio trio) const
1383 : {
1384 103067 : relation_kind rel = trio.op1_op2 ();
1385 103067 : switch (get_bool_state (r, lhs, type))
1386 : {
1387 37802 : case BRS_TRUE:
1388 : // Since at least one operand must be NAN, if one of them is
1389 : // not, the other must be.
1390 37802 : if (rel == VREL_EQ || !op2.maybe_isnan ())
1391 9589 : r.set_nan (type);
1392 : else
1393 28213 : r.set_varying (type);
1394 : break;
1395 :
1396 57422 : case BRS_FALSE:
1397 : // A false UNORDERED means both operands are !NAN, so it's
1398 : // impossible for op2 to be a NAN.
1399 57422 : if (op2.known_isnan ())
1400 0 : r.set_undefined ();
1401 : else
1402 : {
1403 57422 : r.set_varying (type);
1404 57422 : r.clear_nan ();
1405 : }
1406 : break;
1407 :
1408 : default:
1409 : break;
1410 : }
1411 103067 : return true;
1412 : }
1413 :
1414 : // ORDERED_EXPR comparison.
1415 :
1416 : class foperator_ordered : public range_operator
1417 : {
1418 : using range_operator::fold_range;
1419 : using range_operator::op1_range;
1420 : using range_operator::op2_range;
1421 : public:
1422 : bool fold_range (irange &r, tree type,
1423 : const frange &op1, const frange &op2,
1424 : relation_trio = TRIO_VARYING) const final override;
1425 : bool op1_range (frange &r, tree type,
1426 : const irange &lhs, const frange &op2,
1427 : relation_trio = TRIO_VARYING) const final override;
1428 30034 : bool op2_range (frange &r, tree type,
1429 : const irange &lhs, const frange &op1,
1430 : relation_trio rel = TRIO_VARYING) const final override
1431 : {
1432 30034 : return op1_range (r, type, lhs, op1, rel.swap_op1_op2 ());
1433 : }
1434 : };
1435 : static const foperator_ordered fop_ordered;
1436 :
1437 : bool
1438 32814 : foperator_ordered::fold_range (irange &r, tree type,
1439 : const frange &op1, const frange &op2,
1440 : relation_trio) const
1441 : {
1442 32814 : if (op1.known_isnan () || op2.known_isnan ())
1443 360 : r = range_false (type);
1444 35368 : else if (!op1.maybe_isnan () && !op2.maybe_isnan ())
1445 1450 : r = range_true (type);
1446 : else
1447 31004 : r = range_true_and_false (type);
1448 32814 : return true;
1449 : }
1450 :
1451 : bool
1452 63925 : foperator_ordered::op1_range (frange &r, tree type,
1453 : const irange &lhs,
1454 : const frange &op2,
1455 : relation_trio trio) const
1456 : {
1457 63925 : relation_kind rel = trio.op1_op2 ();
1458 63925 : switch (get_bool_state (r, lhs, type))
1459 : {
1460 57316 : case BRS_TRUE:
1461 : // The TRUE side of ORDERED means both operands are !NAN, so
1462 : // it's impossible for op2 to be a NAN.
1463 57316 : if (op2.known_isnan ())
1464 10 : r.set_undefined ();
1465 : else
1466 : {
1467 57306 : r.set_varying (type);
1468 57306 : r.clear_nan ();
1469 : }
1470 : break;
1471 :
1472 4626 : case BRS_FALSE:
1473 : // The FALSE side of op1 ORDERED op1 implies op1 is NAN.
1474 4626 : if (rel == VREL_EQ)
1475 2111 : r.set_nan (type);
1476 : else
1477 2515 : r.set_varying (type);
1478 : break;
1479 :
1480 : default:
1481 : break;
1482 : }
1483 63925 : return true;
1484 : }
1485 :
1486 : bool
1487 241330 : operator_negate::fold_range (frange &r, tree type,
1488 : const frange &op1, const frange &op2,
1489 : relation_trio) const
1490 : {
1491 241330 : if (empty_range_varying (r, type, op1, op2))
1492 426 : return true;
1493 240904 : if (op1.known_isnan ())
1494 : {
1495 398 : bool sign;
1496 398 : if (op1.nan_signbit_p (sign))
1497 38 : r.set_nan (type, !sign);
1498 : else
1499 360 : r.set_nan (type);
1500 398 : return true;
1501 : }
1502 :
1503 240506 : REAL_VALUE_TYPE lh_lb = op1.lower_bound ();
1504 240506 : REAL_VALUE_TYPE lh_ub = op1.upper_bound ();
1505 240506 : lh_lb = real_value_negate (&lh_lb);
1506 240506 : lh_ub = real_value_negate (&lh_ub);
1507 240506 : r.set (type, lh_ub, lh_lb);
1508 430184 : if (op1.maybe_isnan ())
1509 : {
1510 50832 : bool sign;
1511 50832 : if (op1.nan_signbit_p (sign))
1512 2372 : r.update_nan (!sign);
1513 : else
1514 48460 : r.update_nan ();
1515 : }
1516 : else
1517 189674 : r.clear_nan ();
1518 : return true;
1519 : }
1520 :
1521 : bool
1522 3130 : operator_negate::op1_range (frange &r, tree type,
1523 : const frange &lhs, const frange &op2,
1524 : relation_trio rel) const
1525 : {
1526 3130 : return fold_range (r, type, lhs, op2, rel);
1527 : }
1528 :
1529 : bool
1530 558015 : operator_abs::fold_range (frange &r, tree type,
1531 : const frange &op1, const frange &op2,
1532 : relation_trio) const
1533 : {
1534 558015 : if (empty_range_varying (r, type, op1, op2))
1535 113 : return true;
1536 557902 : if (op1.known_isnan ())
1537 : {
1538 588 : r.set_nan (type, /*sign=*/false);
1539 588 : return true;
1540 : }
1541 :
1542 557314 : const REAL_VALUE_TYPE lh_lb = op1.lower_bound ();
1543 557314 : const REAL_VALUE_TYPE lh_ub = op1.upper_bound ();
1544 : // Handle the easy case where everything is positive.
1545 557314 : if (real_compare (GE_EXPR, &lh_lb, &dconst0)
1546 159761 : && !real_iszero (&lh_lb, /*sign=*/true)
1547 714507 : && !op1.maybe_isnan (/*sign=*/true))
1548 : {
1549 156828 : r = op1;
1550 156828 : return true;
1551 : }
1552 :
1553 400486 : REAL_VALUE_TYPE min = real_value_abs (&lh_lb);
1554 400486 : REAL_VALUE_TYPE max = real_value_abs (&lh_ub);
1555 : // If the range contains zero then we know that the minimum value in the
1556 : // range will be zero.
1557 400486 : if (real_compare (LE_EXPR, &lh_lb, &dconst0)
1558 400486 : && real_compare (GE_EXPR, &lh_ub, &dconst0))
1559 : {
1560 399617 : if (real_compare (GT_EXPR, &min, &max))
1561 4791 : max = min;
1562 399617 : min = dconst0;
1563 : }
1564 : else
1565 : {
1566 : // If the range was reversed, swap MIN and MAX.
1567 869 : if (real_compare (GT_EXPR, &min, &max))
1568 790 : std::swap (min, max);
1569 : }
1570 :
1571 400486 : r.set (type, min, max);
1572 425704 : if (op1.maybe_isnan ())
1573 376431 : r.update_nan (/*sign=*/false);
1574 : else
1575 24055 : r.clear_nan ();
1576 : return true;
1577 : }
1578 :
1579 : bool
1580 320737 : operator_abs::op1_range (frange &r, tree type,
1581 : const frange &lhs, const frange &op2,
1582 : relation_trio) const
1583 : {
1584 320737 : if (empty_range_varying (r, type, lhs, op2))
1585 0 : return true;
1586 320737 : if (lhs.known_isnan ())
1587 : {
1588 2805 : r.set_nan (type);
1589 2805 : return true;
1590 : }
1591 :
1592 : // Start with the positives because negatives are an impossible result.
1593 317932 : frange positives (type, dconst0, frange_val_max (type));
1594 317932 : positives.update_nan (/*sign=*/false);
1595 317932 : positives.intersect (lhs);
1596 317932 : r = positives;
1597 : // Add -NAN if relevant.
1598 480752 : if (r.maybe_isnan ())
1599 : {
1600 155052 : frange neg_nan;
1601 155052 : neg_nan.set_nan (type, true);
1602 155052 : r.union_ (neg_nan);
1603 155052 : }
1604 317932 : if (r.known_isnan () || r.undefined_p ())
1605 : return true;
1606 : // Then add the negative of each pair:
1607 : // ABS(op1) = [5,20] would yield op1 => [-20,-5][5,20].
1608 317860 : frange negatives (type, real_value_negate (&positives.upper_bound ()),
1609 317860 : real_value_negate (&positives.lower_bound ()));
1610 317860 : negatives.clear_nan ();
1611 317860 : r.union_ (negatives);
1612 317860 : return true;
1613 635792 : }
1614 :
1615 : class foperator_unordered_lt : public range_operator
1616 : {
1617 : using range_operator::fold_range;
1618 : using range_operator::op1_range;
1619 : using range_operator::op2_range;
1620 : public:
1621 11060 : bool fold_range (irange &r, tree type,
1622 : const frange &op1, const frange &op2,
1623 : relation_trio trio = TRIO_VARYING) const final override
1624 : {
1625 11060 : if (op1.known_isnan () || op2.known_isnan ())
1626 : {
1627 33 : r = range_true (type);
1628 33 : return true;
1629 : }
1630 11027 : frange op1_no_nan = op1;
1631 11027 : frange op2_no_nan = op2;
1632 13632 : if (op1.maybe_isnan ())
1633 8406 : op1_no_nan.clear_nan ();
1634 18488 : if (op2.maybe_isnan ())
1635 3566 : op2_no_nan.clear_nan ();
1636 11027 : if (!range_op_handler (LT_EXPR).fold_range (r, type, op1_no_nan,
1637 : op2_no_nan, trio))
1638 : return false;
1639 : // The result is the same as the ordered version when the
1640 : // comparison is true or when the operands cannot be NANs.
1641 11027 : if (!maybe_isnan (op1, op2) || r == range_true (type))
1642 : return true;
1643 : else
1644 : {
1645 8302 : r = range_true_and_false (type);
1646 8302 : return true;
1647 : }
1648 11027 : }
1649 : bool op1_range (frange &r, tree type,
1650 : const irange &lhs,
1651 : const frange &op2,
1652 : relation_trio trio) const final override;
1653 : bool op2_range (frange &r, tree type,
1654 : const irange &lhs,
1655 : const frange &op1,
1656 : relation_trio trio) const final override;
1657 : };
1658 : static const foperator_unordered_lt fop_unordered_lt;
1659 :
1660 : bool
1661 3586 : foperator_unordered_lt::op1_range (frange &r, tree type,
1662 : const irange &lhs,
1663 : const frange &op2,
1664 : relation_trio) const
1665 : {
1666 3586 : switch (get_bool_state (r, lhs, type))
1667 : {
1668 1722 : case BRS_TRUE:
1669 3388 : if (op2.maybe_isnan ())
1670 56 : r.set_varying (type);
1671 1666 : else if (op2.undefined_p ())
1672 : return false;
1673 : else
1674 1666 : build_lt (r, type, op2);
1675 : break;
1676 :
1677 1236 : case BRS_FALSE:
1678 : // A false UNORDERED_LT means both operands are !NAN, so it's
1679 : // impossible for op2 to be a NAN.
1680 1236 : if (op2.known_isnan ())
1681 0 : r.set_undefined ();
1682 1236 : else if (op2.undefined_p ())
1683 : return false;
1684 1236 : else if (build_ge (r, type, op2))
1685 1236 : r.clear_nan ();
1686 : break;
1687 :
1688 : default:
1689 : break;
1690 : }
1691 : return true;
1692 : }
1693 :
1694 : bool
1695 684 : foperator_unordered_lt::op2_range (frange &r, tree type,
1696 : const irange &lhs,
1697 : const frange &op1,
1698 : relation_trio) const
1699 : {
1700 684 : switch (get_bool_state (r, lhs, type))
1701 : {
1702 56 : case BRS_TRUE:
1703 56 : if (op1.maybe_isnan ())
1704 56 : r.set_varying (type);
1705 0 : else if (op1.undefined_p ())
1706 : return false;
1707 : else
1708 0 : build_gt (r, type, op1);
1709 : break;
1710 :
1711 0 : case BRS_FALSE:
1712 : // A false UNORDERED_LT means both operands are !NAN, so it's
1713 : // impossible for op1 to be a NAN.
1714 0 : if (op1.known_isnan ())
1715 0 : r.set_undefined ();
1716 0 : else if (op1.undefined_p ())
1717 : return false;
1718 0 : else if (build_le (r, type, op1))
1719 0 : r.clear_nan ();
1720 : break;
1721 :
1722 : default:
1723 : break;
1724 : }
1725 : return true;
1726 : }
1727 :
1728 : class foperator_unordered_le : public range_operator
1729 : {
1730 : using range_operator::fold_range;
1731 : using range_operator::op1_range;
1732 : using range_operator::op2_range;
1733 : public:
1734 180058 : bool fold_range (irange &r, tree type,
1735 : const frange &op1, const frange &op2,
1736 : relation_trio trio = TRIO_VARYING) const final override
1737 : {
1738 180058 : if (op1.known_isnan () || op2.known_isnan ())
1739 : {
1740 98 : r = range_true (type);
1741 98 : return true;
1742 : }
1743 179960 : frange op1_no_nan = op1;
1744 179960 : frange op2_no_nan = op2;
1745 206042 : if (op1.maybe_isnan ())
1746 153852 : op1_no_nan.clear_nan ();
1747 352735 : if (op2.maybe_isnan ())
1748 7179 : op2_no_nan.clear_nan ();
1749 179960 : if (!range_op_handler (LE_EXPR).fold_range (r, type, op1_no_nan,
1750 : op2_no_nan, trio))
1751 : return false;
1752 : // The result is the same as the ordered version when the
1753 : // comparison is true or when the operands cannot be NANs.
1754 179960 : if (!maybe_isnan (op1, op2) || r == range_true (type))
1755 : return true;
1756 : else
1757 : {
1758 155616 : r = range_true_and_false (type);
1759 155616 : return true;
1760 : }
1761 179960 : }
1762 : bool op1_range (frange &r, tree type,
1763 : const irange &lhs, const frange &op2,
1764 : relation_trio = TRIO_VARYING) const final override;
1765 : bool op2_range (frange &r, tree type,
1766 : const irange &lhs, const frange &op1,
1767 : relation_trio = TRIO_VARYING) const final override;
1768 : };
1769 : static const foperator_unordered_le fop_unordered_le;
1770 :
1771 : bool
1772 167157 : foperator_unordered_le::op1_range (frange &r, tree type,
1773 : const irange &lhs, const frange &op2,
1774 : relation_trio) const
1775 : {
1776 167157 : switch (get_bool_state (r, lhs, type))
1777 : {
1778 92205 : case BRS_TRUE:
1779 179293 : if (op2.maybe_isnan ())
1780 5117 : r.set_varying (type);
1781 87088 : else if (op2.undefined_p ())
1782 : return false;
1783 : else
1784 87088 : build_le (r, type, op2);
1785 : break;
1786 :
1787 74310 : case BRS_FALSE:
1788 : // A false UNORDERED_LE means both operands are !NAN, so it's
1789 : // impossible for op2 to be a NAN.
1790 74310 : if (op2.known_isnan ())
1791 0 : r.set_undefined ();
1792 74310 : else if (build_gt (r, type, op2))
1793 74308 : r.clear_nan ();
1794 : break;
1795 :
1796 : default:
1797 : break;
1798 : }
1799 : return true;
1800 : }
1801 :
1802 : bool
1803 14098 : foperator_unordered_le::op2_range (frange &r,
1804 : tree type,
1805 : const irange &lhs,
1806 : const frange &op1,
1807 : relation_trio) const
1808 : {
1809 14098 : switch (get_bool_state (r, lhs, type))
1810 : {
1811 9851 : case BRS_TRUE:
1812 14857 : if (op1.maybe_isnan ())
1813 4845 : r.set_varying (type);
1814 5006 : else if (op1.undefined_p ())
1815 : return false;
1816 : else
1817 5006 : build_ge (r, type, op1);
1818 : break;
1819 :
1820 3605 : case BRS_FALSE:
1821 : // A false UNORDERED_LE means both operands are !NAN, so it's
1822 : // impossible for op1 to be a NAN.
1823 3605 : if (op1.known_isnan ())
1824 0 : r.set_undefined ();
1825 3605 : else if (op1.undefined_p ())
1826 : return false;
1827 3605 : else if (build_lt (r, type, op1))
1828 3605 : r.clear_nan ();
1829 : break;
1830 :
1831 : default:
1832 : break;
1833 : }
1834 : return true;
1835 : }
1836 :
1837 : class foperator_unordered_gt : public range_operator
1838 : {
1839 : using range_operator::fold_range;
1840 : using range_operator::op1_range;
1841 : using range_operator::op2_range;
1842 : public:
1843 35422 : bool fold_range (irange &r, tree type,
1844 : const frange &op1, const frange &op2,
1845 : relation_trio trio = TRIO_VARYING) const final override
1846 : {
1847 35422 : if (op1.known_isnan () || op2.known_isnan ())
1848 : {
1849 157 : r = range_true (type);
1850 157 : return true;
1851 : }
1852 35265 : frange op1_no_nan = op1;
1853 35265 : frange op2_no_nan = op2;
1854 38712 : if (op1.maybe_isnan ())
1855 31799 : op1_no_nan.clear_nan ();
1856 66872 : if (op2.maybe_isnan ())
1857 3658 : op2_no_nan.clear_nan ();
1858 35265 : if (!range_op_handler (GT_EXPR).fold_range (r, type, op1_no_nan,
1859 : op2_no_nan, trio))
1860 : return false;
1861 : // The result is the same as the ordered version when the
1862 : // comparison is true or when the operands cannot be NANs.
1863 35265 : if (!maybe_isnan (op1, op2) || r == range_true (type))
1864 : return true;
1865 : else
1866 : {
1867 31692 : r = range_true_and_false (type);
1868 31692 : return true;
1869 : }
1870 35265 : }
1871 : bool op1_range (frange &r, tree type,
1872 : const irange &lhs, const frange &op2,
1873 : relation_trio = TRIO_VARYING) const final override;
1874 : bool op2_range (frange &r, tree type,
1875 : const irange &lhs, const frange &op1,
1876 : relation_trio = TRIO_VARYING) const final override;
1877 : };
1878 : static const foperator_unordered_gt fop_unordered_gt;
1879 :
1880 : bool
1881 16076 : foperator_unordered_gt::op1_range (frange &r,
1882 : tree type,
1883 : const irange &lhs,
1884 : const frange &op2,
1885 : relation_trio) const
1886 : {
1887 16076 : switch (get_bool_state (r, lhs, type))
1888 : {
1889 5195 : case BRS_TRUE:
1890 10314 : if (op2.maybe_isnan ())
1891 76 : r.set_varying (type);
1892 5119 : else if (op2.undefined_p ())
1893 : return false;
1894 : else
1895 5119 : build_gt (r, type, op2);
1896 : break;
1897 :
1898 10283 : case BRS_FALSE:
1899 : // A false UNORDERED_GT means both operands are !NAN, so it's
1900 : // impossible for op2 to be a NAN.
1901 10283 : if (op2.known_isnan ())
1902 0 : r.set_undefined ();
1903 10283 : else if (op2.undefined_p ())
1904 : return false;
1905 10283 : else if (build_le (r, type, op2))
1906 10283 : r.clear_nan ();
1907 : break;
1908 :
1909 : default:
1910 : break;
1911 : }
1912 : return true;
1913 : }
1914 :
1915 : bool
1916 674 : foperator_unordered_gt::op2_range (frange &r,
1917 : tree type,
1918 : const irange &lhs,
1919 : const frange &op1,
1920 : relation_trio) const
1921 : {
1922 674 : switch (get_bool_state (r, lhs, type))
1923 : {
1924 76 : case BRS_TRUE:
1925 76 : if (op1.maybe_isnan ())
1926 76 : r.set_varying (type);
1927 0 : else if (op1.undefined_p ())
1928 : return false;
1929 : else
1930 0 : build_lt (r, type, op1);
1931 : break;
1932 :
1933 0 : case BRS_FALSE:
1934 : // A false UNORDERED_GT means both operands are !NAN, so it's
1935 : // impossible for op1 to be a NAN.
1936 0 : if (op1.known_isnan ())
1937 0 : r.set_undefined ();
1938 0 : else if (op1.undefined_p ())
1939 : return false;
1940 0 : else if (build_ge (r, type, op1))
1941 0 : r.clear_nan ();
1942 : break;
1943 :
1944 : default:
1945 : break;
1946 : }
1947 : return true;
1948 : }
1949 :
1950 : class foperator_unordered_ge : public range_operator
1951 : {
1952 : using range_operator::fold_range;
1953 : using range_operator::op1_range;
1954 : using range_operator::op2_range;
1955 : public:
1956 173308 : bool fold_range (irange &r, tree type,
1957 : const frange &op1, const frange &op2,
1958 : relation_trio trio = TRIO_VARYING) const final override
1959 : {
1960 173308 : if (op1.known_isnan () || op2.known_isnan ())
1961 : {
1962 47 : r = range_true (type);
1963 47 : return true;
1964 : }
1965 173261 : frange op1_no_nan = op1;
1966 173261 : frange op2_no_nan = op2;
1967 186761 : if (op1.maybe_isnan ())
1968 159700 : op1_no_nan.clear_nan ();
1969 339433 : if (op2.maybe_isnan ())
1970 7083 : op2_no_nan.clear_nan ();
1971 173261 : if (!range_op_handler (GE_EXPR).fold_range (r, type, op1_no_nan,
1972 : op2_no_nan, trio))
1973 : return false;
1974 : // The result is the same as the ordered version when the
1975 : // comparison is true or when the operands cannot be NANs.
1976 173261 : if (!maybe_isnan (op1, op2) || r == range_true (type))
1977 : return true;
1978 : else
1979 : {
1980 159840 : r = range_true_and_false (type);
1981 159840 : return true;
1982 : }
1983 173261 : }
1984 : bool op1_range (frange &r, tree type,
1985 : const irange &lhs, const frange &op2,
1986 : relation_trio = TRIO_VARYING) const final override;
1987 : bool op2_range (frange &r, tree type,
1988 : const irange &lhs, const frange &op1,
1989 : relation_trio = TRIO_VARYING) const final override;
1990 : };
1991 : static const foperator_unordered_ge fop_unordered_ge;
1992 :
1993 : bool
1994 144094 : foperator_unordered_ge::op1_range (frange &r,
1995 : tree type,
1996 : const irange &lhs,
1997 : const frange &op2,
1998 : relation_trio) const
1999 : {
2000 144094 : switch (get_bool_state (r, lhs, type))
2001 : {
2002 61065 : case BRS_TRUE:
2003 117485 : if (op2.maybe_isnan ())
2004 4645 : r.set_varying (type);
2005 56420 : else if (op2.undefined_p ())
2006 : return false;
2007 : else
2008 56420 : build_ge (r, type, op2);
2009 : break;
2010 :
2011 82325 : case BRS_FALSE:
2012 : // A false UNORDERED_GE means both operands are !NAN, so it's
2013 : // impossible for op2 to be a NAN.
2014 82325 : if (op2.known_isnan ())
2015 0 : r.set_undefined ();
2016 82325 : else if (op2.undefined_p ())
2017 : return false;
2018 82325 : else if (build_lt (r, type, op2))
2019 82321 : r.clear_nan ();
2020 : break;
2021 :
2022 : default:
2023 : break;
2024 : }
2025 : return true;
2026 : }
2027 :
2028 : bool
2029 14833 : foperator_unordered_ge::op2_range (frange &r, tree type,
2030 : const irange &lhs,
2031 : const frange &op1,
2032 : relation_trio) const
2033 : {
2034 14833 : switch (get_bool_state (r, lhs, type))
2035 : {
2036 8861 : case BRS_TRUE:
2037 13235 : if (op1.maybe_isnan ())
2038 4487 : r.set_varying (type);
2039 4374 : else if (op1.undefined_p ())
2040 : return false;
2041 : else
2042 4374 : build_le (r, type, op1);
2043 : break;
2044 :
2045 5388 : case BRS_FALSE:
2046 : // A false UNORDERED_GE means both operands are !NAN, so it's
2047 : // impossible for op1 to be a NAN.
2048 5388 : if (op1.known_isnan ())
2049 0 : r.set_undefined ();
2050 5388 : else if (op1.undefined_p ())
2051 : return false;
2052 5388 : else if (build_gt (r, type, op1))
2053 5388 : r.clear_nan ();
2054 : break;
2055 :
2056 : default:
2057 : break;
2058 : }
2059 : return true;
2060 : }
2061 :
2062 : class foperator_unordered_equal : public range_operator
2063 : {
2064 : using range_operator::fold_range;
2065 : using range_operator::op1_range;
2066 : using range_operator::op2_range;
2067 : public:
2068 3611 : bool fold_range (irange &r, tree type,
2069 : const frange &op1, const frange &op2,
2070 : relation_trio trio = TRIO_VARYING) const final override
2071 : {
2072 3611 : if (op1.known_isnan () || op2.known_isnan ())
2073 : {
2074 0 : r = range_true (type);
2075 0 : return true;
2076 : }
2077 3611 : frange op1_no_nan = op1;
2078 3611 : frange op2_no_nan = op2;
2079 3931 : if (op1.maybe_isnan ())
2080 3291 : op1_no_nan.clear_nan ();
2081 4032 : if (op2.maybe_isnan ())
2082 3190 : op2_no_nan.clear_nan ();
2083 3611 : if (!range_op_handler (EQ_EXPR).fold_range (r, type, op1_no_nan,
2084 : op2_no_nan, trio))
2085 : return false;
2086 : // The result is the same as the ordered version when the
2087 : // comparison is true or when the operands cannot be NANs.
2088 3611 : if (!maybe_isnan (op1, op2) || r == range_true (type))
2089 : return true;
2090 : else
2091 : {
2092 3290 : r = range_true_and_false (type);
2093 3290 : return true;
2094 : }
2095 3611 : }
2096 : bool op1_range (frange &r, tree type,
2097 : const irange &lhs, const frange &op2,
2098 : relation_trio = TRIO_VARYING) const final override;
2099 628 : bool op2_range (frange &r, tree type,
2100 : const irange &lhs, const frange &op1,
2101 : relation_trio rel = TRIO_VARYING) const final override
2102 : {
2103 628 : return op1_range (r, type, lhs, op1, rel.swap_op1_op2 ());
2104 : }
2105 : };
2106 : static const foperator_unordered_equal fop_unordered_equal;
2107 :
2108 : bool
2109 1259 : foperator_unordered_equal::op1_range (frange &r, tree type,
2110 : const irange &lhs,
2111 : const frange &op2,
2112 : relation_trio) const
2113 : {
2114 1259 : switch (get_bool_state (r, lhs, type))
2115 : {
2116 3 : case BRS_TRUE:
2117 : // If it's true, the result is the same as OP2 plus a NAN.
2118 3 : r = op2;
2119 : // Add both zeros if there's the possibility of zero equality.
2120 3 : frange_add_zeros (r, type);
2121 : // Add the possibility of a NAN.
2122 3 : r.update_nan ();
2123 3 : break;
2124 :
2125 0 : case BRS_FALSE:
2126 : // A false UNORDERED_EQ means both operands are !NAN, so it's
2127 : // impossible for op2 to be a NAN.
2128 0 : if (op2.known_isnan ())
2129 0 : r.set_undefined ();
2130 : else
2131 : {
2132 : // The false side indicates !NAN and not equal. We can at least
2133 : // represent !NAN.
2134 0 : r.set_varying (type);
2135 0 : r.clear_nan ();
2136 : }
2137 : break;
2138 :
2139 : default:
2140 : break;
2141 : }
2142 1259 : return true;
2143 : }
2144 :
2145 : class foperator_ltgt : public range_operator
2146 : {
2147 : using range_operator::fold_range;
2148 : using range_operator::op1_range;
2149 : using range_operator::op2_range;
2150 : public:
2151 2136 : bool fold_range (irange &r, tree type,
2152 : const frange &op1, const frange &op2,
2153 : relation_trio trio = TRIO_VARYING) const final override
2154 : {
2155 2136 : if (op1.known_isnan () || op2.known_isnan ())
2156 : {
2157 2 : r = range_false (type);
2158 2 : return true;
2159 : }
2160 2134 : frange op1_no_nan = op1;
2161 2134 : frange op2_no_nan = op2;
2162 2454 : if (op1.maybe_isnan ())
2163 1798 : op1_no_nan.clear_nan ();
2164 2454 : if (op2.maybe_isnan ())
2165 1798 : op2_no_nan.clear_nan ();
2166 2134 : if (!range_op_handler (NE_EXPR).fold_range (r, type, op1_no_nan,
2167 : op2_no_nan, trio))
2168 : return false;
2169 : // The result is the same as the ordered version when the
2170 : // comparison is true or when the operands cannot be NANs.
2171 2134 : if (!maybe_isnan (op1, op2) || r == range_false (type))
2172 : return true;
2173 : else
2174 : {
2175 1798 : r = range_true_and_false (type);
2176 1798 : return true;
2177 : }
2178 2134 : }
2179 : bool op1_range (frange &r, tree type,
2180 : const irange &lhs, const frange &op2,
2181 : relation_trio = TRIO_VARYING) const final override;
2182 792 : bool op2_range (frange &r, tree type,
2183 : const irange &lhs, const frange &op1,
2184 : relation_trio rel = TRIO_VARYING) const final override
2185 : {
2186 792 : return op1_range (r, type, lhs, op1, rel.swap_op1_op2 ());
2187 : }
2188 : };
2189 : static const foperator_ltgt fop_ltgt;
2190 :
2191 : bool
2192 1574 : foperator_ltgt::op1_range (frange &r, tree type,
2193 : const irange &lhs,
2194 : const frange &op2,
2195 : relation_trio) const
2196 : {
2197 1574 : switch (get_bool_state (r, lhs, type))
2198 : {
2199 0 : case BRS_TRUE:
2200 : // A true LTGT means both operands are !NAN, so it's
2201 : // impossible for op2 to be a NAN.
2202 0 : if (op2.known_isnan ())
2203 0 : r.set_undefined ();
2204 : else
2205 : {
2206 : // The true side indicates !NAN and not equal. We can at least
2207 : // represent !NAN.
2208 0 : r.set_varying (type);
2209 0 : r.clear_nan ();
2210 : }
2211 : break;
2212 :
2213 10 : case BRS_FALSE:
2214 : // If it's false, the result is the same as OP2 plus a NAN.
2215 10 : r = op2;
2216 : // Add both zeros if there's the possibility of zero equality.
2217 10 : frange_add_zeros (r, type);
2218 : // Add the possibility of a NAN.
2219 10 : r.update_nan ();
2220 10 : break;
2221 :
2222 : default:
2223 : break;
2224 : }
2225 1574 : return true;
2226 : }
2227 :
2228 : // Final tweaks for float binary op op1_range/op2_range.
2229 : // Return TRUE if the operation is performed and a valid range is available.
2230 :
2231 : static bool
2232 829736 : float_binary_op_range_finish (bool ret, frange &r, tree type,
2233 : const frange &lhs, bool div_op2 = false)
2234 : {
2235 829736 : if (!ret)
2236 : return false;
2237 :
2238 : // If we get a known NAN from reverse op, it means either that
2239 : // the other operand was known NAN (in that case we know nothing),
2240 : // or the reverse operation introduced a known NAN.
2241 : // Say for lhs = op1 * op2 if lhs is [-0, +0] and op2 is too,
2242 : // 0 / 0 is known NAN. Just punt in that case.
2243 : // If NANs aren't honored, we get for 0 / 0 UNDEFINED, so punt as well.
2244 : // Or if lhs is a known NAN, we also don't know anything.
2245 829736 : if (r.known_isnan () || lhs.known_isnan () || r.undefined_p ())
2246 : {
2247 6999 : r.set_varying (type);
2248 6999 : return true;
2249 : }
2250 :
2251 : // If lhs isn't NAN, then neither operand could be NAN,
2252 : // even if the reverse operation does introduce a maybe_nan.
2253 1484795 : if (!lhs.maybe_isnan ())
2254 : {
2255 662058 : r.clear_nan ();
2256 662058 : if (div_op2
2257 686350 : ? !(real_compare (LE_EXPR, &lhs.lower_bound (), &dconst0)
2258 24292 : && real_compare (GE_EXPR, &lhs.upper_bound (), &dconst0))
2259 1138286 : : !(real_isinf (&lhs.lower_bound ())
2260 507896 : || real_isinf (&lhs.upper_bound ())))
2261 : // For reverse + or - or * or op1 of /, if result is finite, then
2262 : // r must be finite too, as X + INF or X - INF or X * INF or
2263 : // INF / X is always +-INF or NAN. For op2 of /, if result is
2264 : // non-zero and not NAN, r must be finite, as X / INF is always
2265 : // 0 or NAN.
2266 488305 : frange_drop_infs (r, type);
2267 : }
2268 : // If lhs is a maybe or known NAN, the operand could be
2269 : // NAN.
2270 : else
2271 160679 : r.update_nan ();
2272 : return true;
2273 : }
2274 :
2275 : // True if [lb, ub] is [+-0, +-0].
2276 : static bool
2277 5042348 : zero_p (const REAL_VALUE_TYPE &lb, const REAL_VALUE_TYPE &ub)
2278 : {
2279 5042348 : return real_iszero (&lb) && real_iszero (&ub);
2280 : }
2281 :
2282 : // True if +0 or -0 is in [lb, ub] range.
2283 : static bool
2284 4099105 : contains_zero_p (const REAL_VALUE_TYPE &lb, const REAL_VALUE_TYPE &ub)
2285 : {
2286 4099105 : return (real_compare (LE_EXPR, &lb, &dconst0)
2287 4099105 : && real_compare (GE_EXPR, &ub, &dconst0));
2288 : }
2289 :
2290 : // True if [lb, ub] is [-INF, -INF] or [+INF, +INF].
2291 : static bool
2292 2834669 : singleton_inf_p (const REAL_VALUE_TYPE &lb, const REAL_VALUE_TYPE &ub)
2293 : {
2294 2834669 : return real_isinf (&lb) && real_isinf (&ub, real_isneg (&lb));
2295 : }
2296 :
2297 : // Return -1 if binary op result must have sign bit set,
2298 : // 1 if binary op result must have sign bit clear,
2299 : // 0 otherwise.
2300 : // Sign bit of binary op result is exclusive or of the
2301 : // operand's sign bits.
2302 : static int
2303 1272840 : signbit_known_p (const REAL_VALUE_TYPE &lh_lb, const REAL_VALUE_TYPE &lh_ub,
2304 : const REAL_VALUE_TYPE &rh_lb, const REAL_VALUE_TYPE &rh_ub)
2305 : {
2306 1272840 : if (real_isneg (&lh_lb) == real_isneg (&lh_ub)
2307 1272840 : && real_isneg (&rh_lb) == real_isneg (&rh_ub))
2308 : {
2309 111990 : if (real_isneg (&lh_lb) == real_isneg (&rh_ub))
2310 : return 1;
2311 : else
2312 6555 : return -1;
2313 : }
2314 : return 0;
2315 : }
2316 :
2317 : // Set [lb, ub] to [-0, -0], [-0, +0] or [+0, +0] depending on
2318 : // signbit_known.
2319 : static void
2320 6210 : zero_range (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub, int signbit_known)
2321 : {
2322 6210 : ub = lb = dconst0;
2323 6210 : if (signbit_known <= 0)
2324 6064 : lb = dconstm0;
2325 6064 : if (signbit_known < 0)
2326 44 : ub = lb;
2327 6210 : }
2328 :
2329 : // Set [lb, ub] to [-INF, -INF], [-INF, +INF] or [+INF, +INF] depending on
2330 : // signbit_known.
2331 : static void
2332 4321 : inf_range (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub, int signbit_known)
2333 : {
2334 4321 : if (signbit_known > 0)
2335 952 : ub = lb = dconstinf;
2336 3369 : else if (signbit_known < 0)
2337 96 : ub = lb = dconstninf;
2338 : else
2339 : {
2340 3273 : lb = dconstninf;
2341 3273 : ub = dconstinf;
2342 : }
2343 4321 : }
2344 :
2345 : // Set [lb, ub] to [-INF, -0], [-INF, +INF] or [+0, +INF] depending on
2346 : // signbit_known.
2347 : static void
2348 925108 : zero_to_inf_range (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub, int signbit_known)
2349 : {
2350 925108 : if (signbit_known > 0)
2351 : {
2352 10290 : lb = dconst0;
2353 10290 : ub = dconstinf;
2354 : }
2355 914818 : else if (signbit_known < 0)
2356 : {
2357 222 : lb = dconstninf;
2358 222 : ub = dconstm0;
2359 : }
2360 : else
2361 : {
2362 914596 : lb = dconstninf;
2363 914596 : ub = dconstinf;
2364 : }
2365 925108 : }
2366 :
2367 : /* Extend the LHS range by 1ulp in each direction. For op1_range
2368 : or op2_range of binary operations just computing the inverse
2369 : operation on ranges isn't sufficient. Consider e.g.
2370 : [1., 1.] = op1 + [1., 1.]. op1's range is not [0., 0.], but
2371 : [-0x1.0p-54, 0x1.0p-53] (when not -frounding-math), any value for
2372 : which adding 1. to it results in 1. after rounding to nearest.
2373 : So, for op1_range/op2_range extend the lhs range by 1ulp (or 0.5ulp)
2374 : in each direction. See PR109008 for more details. */
2375 :
2376 : static frange
2377 809739 : float_widen_lhs_range (tree type, const frange &lhs)
2378 : {
2379 809739 : frange ret = lhs;
2380 809739 : if (lhs.known_isnan ())
2381 : return ret;
2382 802741 : REAL_VALUE_TYPE lb = lhs.lower_bound ();
2383 802741 : REAL_VALUE_TYPE ub = lhs.upper_bound ();
2384 802741 : if (real_isfinite (&lb))
2385 : {
2386 622073 : frange_nextafter (TYPE_MODE (type), lb, dconstninf);
2387 622073 : if (real_isinf (&lb))
2388 : {
2389 : /* For -DBL_MAX, instead of -Inf use
2390 : nexttoward (-DBL_MAX, -LDBL_MAX) in a hypothetical
2391 : wider type with the same mantissa precision but larger
2392 : exponent range; it is outside of range of double values,
2393 : but makes it clear it is just one ulp larger rather than
2394 : infinite amount larger. */
2395 55299 : lb = dconstm1;
2396 221196 : SET_REAL_EXP (&lb, FLOAT_MODE_FORMAT (TYPE_MODE (type))->emax + 1);
2397 : }
2398 4354511 : if (!flag_rounding_math && !MODE_COMPOSITE_P (TYPE_MODE (type)))
2399 : {
2400 : /* If not -frounding-math nor IBM double double, actually widen
2401 : just by 0.5ulp rather than 1ulp. */
2402 622073 : REAL_VALUE_TYPE tem;
2403 622073 : real_arithmetic (&tem, PLUS_EXPR, &lhs.lower_bound (), &lb);
2404 622073 : real_arithmetic (&lb, RDIV_EXPR, &tem, &dconst2);
2405 : }
2406 : }
2407 802741 : if (real_isfinite (&ub))
2408 : {
2409 552250 : frange_nextafter (TYPE_MODE (type), ub, dconstinf);
2410 552250 : if (real_isinf (&ub))
2411 : {
2412 : /* For DBL_MAX similarly. */
2413 55884 : ub = dconst1;
2414 223536 : SET_REAL_EXP (&ub, FLOAT_MODE_FORMAT (TYPE_MODE (type))->emax + 1);
2415 : }
2416 3865750 : if (!flag_rounding_math && !MODE_COMPOSITE_P (TYPE_MODE (type)))
2417 : {
2418 : /* If not -frounding-math nor IBM double double, actually widen
2419 : just by 0.5ulp rather than 1ulp. */
2420 552250 : REAL_VALUE_TYPE tem;
2421 552250 : real_arithmetic (&tem, PLUS_EXPR, &lhs.upper_bound (), &ub);
2422 552250 : real_arithmetic (&ub, RDIV_EXPR, &tem, &dconst2);
2423 : }
2424 : }
2425 : /* Temporarily disable -ffinite-math-only, so that frange::set doesn't
2426 : reduce the range back to real_min_representable (type) as lower bound
2427 : or real_max_representable (type) as upper bound. */
2428 802741 : bool save_flag_finite_math_only = flag_finite_math_only;
2429 802741 : flag_finite_math_only = false;
2430 802741 : ret.set (type, lb, ub, lhs.get_nan_state ());
2431 802741 : flag_finite_math_only = save_flag_finite_math_only;
2432 802741 : return ret;
2433 : }
2434 :
2435 : bool
2436 165948 : operator_plus::op1_range (frange &r, tree type, const frange &lhs,
2437 : const frange &op2, relation_trio) const
2438 : {
2439 165948 : if (lhs.undefined_p ())
2440 : return false;
2441 165948 : range_op_handler minus (MINUS_EXPR);
2442 165948 : if (!minus)
2443 : return false;
2444 165948 : frange wlhs = float_widen_lhs_range (type, lhs);
2445 165948 : return float_binary_op_range_finish (minus.fold_range (r, type, wlhs, op2),
2446 : r, type, wlhs);
2447 165948 : }
2448 :
2449 : bool
2450 71428 : operator_plus::op2_range (frange &r, tree type,
2451 : const frange &lhs, const frange &op1,
2452 : relation_trio) const
2453 : {
2454 71428 : return op1_range (r, type, lhs, op1);
2455 : }
2456 :
2457 : void
2458 2453616 : operator_plus::rv_fold (frange &r, tree type,
2459 : const REAL_VALUE_TYPE &lh_lb,
2460 : const REAL_VALUE_TYPE &lh_ub,
2461 : const REAL_VALUE_TYPE &rh_lb,
2462 : const REAL_VALUE_TYPE &rh_ub,
2463 : relation_kind) const
2464 : {
2465 2453616 : REAL_VALUE_TYPE lb, ub;
2466 2453616 : bool maybe_nan = false;
2467 :
2468 2453616 : frange_arithmetic (PLUS_EXPR, type, lb, lh_lb, rh_lb, dconstninf);
2469 2453616 : frange_arithmetic (PLUS_EXPR, type, ub, lh_ub, rh_ub, dconstinf);
2470 :
2471 : // [-INF] + [+INF] = NAN
2472 2453616 : if (real_isinf (&lh_lb, true) && real_isinf (&rh_ub, false))
2473 : maybe_nan = true;
2474 : // [+INF] + [-INF] = NAN
2475 792221 : else if (real_isinf (&lh_ub, false) && real_isinf (&rh_lb, true))
2476 : maybe_nan = true;
2477 :
2478 : // Handle possible NANs by saturating to the appropriate INF if only
2479 : // one end is a NAN. If both ends are a NAN, just return a NAN.
2480 2453616 : bool lb_nan = real_isnan (&lb);
2481 2453616 : bool ub_nan = real_isnan (&ub);
2482 2453616 : if (lb_nan && ub_nan)
2483 : {
2484 0 : r.set_nan (type);
2485 0 : return;
2486 : }
2487 2453616 : if (lb_nan)
2488 374 : lb = dconstninf;
2489 2453242 : else if (ub_nan)
2490 0 : ub = dconstinf;
2491 2453616 : r.set (type, lb, ub, nan_state (maybe_nan));
2492 : }
2493 :
2494 :
2495 : bool
2496 83639 : operator_minus::op1_range (frange &r, tree type,
2497 : const frange &lhs, const frange &op2,
2498 : relation_trio) const
2499 : {
2500 83639 : if (lhs.undefined_p ())
2501 : return false;
2502 83639 : frange wlhs = float_widen_lhs_range (type, lhs);
2503 83639 : return float_binary_op_range_finish (
2504 167278 : range_op_handler (PLUS_EXPR).fold_range (r, type, wlhs, op2),
2505 : r, type, wlhs);
2506 83639 : }
2507 :
2508 : bool
2509 132097 : operator_minus::op2_range (frange &r, tree type,
2510 : const frange &lhs, const frange &op1,
2511 : relation_trio) const
2512 : {
2513 132097 : if (lhs.undefined_p ())
2514 : return false;
2515 132097 : frange wlhs = float_widen_lhs_range (type, lhs);
2516 132097 : return float_binary_op_range_finish (fold_range (r, type, op1, wlhs),
2517 : r, type, wlhs);
2518 132097 : }
2519 :
2520 : void
2521 908859 : operator_minus::rv_fold (frange &r, tree type,
2522 : const REAL_VALUE_TYPE &lh_lb,
2523 : const REAL_VALUE_TYPE &lh_ub,
2524 : const REAL_VALUE_TYPE &rh_lb,
2525 : const REAL_VALUE_TYPE &rh_ub,
2526 : relation_kind) const
2527 : {
2528 908859 : REAL_VALUE_TYPE lb, ub;
2529 908859 : bool maybe_nan = false;
2530 :
2531 908859 : frange_arithmetic (MINUS_EXPR, type, lb, lh_lb, rh_ub, dconstninf);
2532 908859 : frange_arithmetic (MINUS_EXPR, type, ub, lh_ub, rh_lb, dconstinf);
2533 :
2534 : // [+INF] - [+INF] = NAN
2535 908859 : if (real_isinf (&lh_ub, false) && real_isinf (&rh_ub, false))
2536 : maybe_nan = true;
2537 : // [-INF] - [-INF] = NAN
2538 626249 : else if (real_isinf (&lh_lb, true) && real_isinf (&rh_lb, true))
2539 : maybe_nan = true;
2540 :
2541 : // Handle possible NANs by saturating to the appropriate INF if only
2542 : // one end is a NAN. If both ends are a NAN, just return a NAN.
2543 908859 : bool lb_nan = real_isnan (&lb);
2544 908859 : bool ub_nan = real_isnan (&ub);
2545 908859 : if (lb_nan && ub_nan)
2546 : {
2547 0 : r.set_nan (type);
2548 0 : return;
2549 : }
2550 908859 : if (lb_nan)
2551 186 : lb = dconstninf;
2552 908673 : else if (ub_nan)
2553 312 : ub = dconstinf;
2554 908859 : r.set (type, lb, ub, nan_state (maybe_nan));
2555 : }
2556 :
2557 :
2558 : // Given CP[0] to CP[3] floating point values rounded to -INF,
2559 : // set LB to the smallest of them (treating -0 as smaller to +0).
2560 : // Given CP[4] to CP[7] floating point values rounded to +INF,
2561 : // set UB to the largest of them (treating -0 as smaller to +0).
2562 :
2563 : static void
2564 1065344 : find_range (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub,
2565 : const REAL_VALUE_TYPE (&cp)[8])
2566 : {
2567 1065344 : lb = cp[0];
2568 1065344 : ub = cp[4];
2569 4261376 : for (int i = 1; i < 4; ++i)
2570 : {
2571 3196032 : if (real_less (&cp[i], &lb)
2572 3196032 : || (real_iszero (&lb) && real_isnegzero (&cp[i])))
2573 356507 : lb = cp[i];
2574 3196032 : if (real_less (&ub, &cp[i + 4])
2575 3196032 : || (real_isnegzero (&ub) && real_iszero (&cp[i + 4])))
2576 1003236 : ub = cp[i + 4];
2577 : }
2578 1065344 : }
2579 :
2580 :
2581 : bool
2582 329195 : operator_mult::op1_range (frange &r, tree type,
2583 : const frange &lhs, const frange &op2,
2584 : relation_trio) const
2585 : {
2586 329195 : if (lhs.undefined_p ())
2587 : return false;
2588 329195 : range_op_handler rdiv (RDIV_EXPR);
2589 329195 : if (!rdiv)
2590 : return false;
2591 329195 : frange wlhs = float_widen_lhs_range (type, lhs);
2592 329195 : bool ret = rdiv.fold_range (r, type, wlhs, op2);
2593 329195 : if (ret == false)
2594 : return false;
2595 329195 : if (wlhs.known_isnan () || op2.known_isnan () || op2.undefined_p ())
2596 16 : return float_binary_op_range_finish (ret, r, type, wlhs);
2597 329179 : const REAL_VALUE_TYPE &lhs_lb = wlhs.lower_bound ();
2598 329179 : const REAL_VALUE_TYPE &lhs_ub = wlhs.upper_bound ();
2599 329179 : const REAL_VALUE_TYPE &op2_lb = op2.lower_bound ();
2600 329179 : const REAL_VALUE_TYPE &op2_ub = op2.upper_bound ();
2601 610329 : if ((contains_zero_p (lhs_lb, lhs_ub) && contains_zero_p (op2_lb, op2_ub))
2602 476381 : || ((real_isinf (&lhs_lb) || real_isinf (&lhs_ub))
2603 39350 : && (real_isinf (&op2_lb) || real_isinf (&op2_ub))))
2604 : {
2605 : // If both lhs and op2 could be zeros or both could be infinities,
2606 : // we don't know anything about op1 except maybe for the sign
2607 : // and perhaps if it can be NAN or not.
2608 140962 : REAL_VALUE_TYPE lb, ub;
2609 140962 : int signbit_known = signbit_known_p (lhs_lb, lhs_ub, op2_lb, op2_ub);
2610 140962 : zero_to_inf_range (lb, ub, signbit_known);
2611 140962 : r.set (type, lb, ub);
2612 : }
2613 : // Otherwise, if op2 is a singleton INF and lhs doesn't include INF,
2614 : // or if lhs must be zero and op2 doesn't include zero, it would be
2615 : // UNDEFINED, while rdiv.fold_range computes a zero or singleton INF
2616 : // range. Those are supersets of UNDEFINED, so let's keep that way.
2617 329179 : return float_binary_op_range_finish (ret, r, type, wlhs);
2618 329195 : }
2619 :
2620 : bool
2621 78895 : operator_mult::op2_range (frange &r, tree type,
2622 : const frange &lhs, const frange &op1,
2623 : relation_trio) const
2624 : {
2625 78895 : return op1_range (r, type, lhs, op1);
2626 : }
2627 :
2628 : void
2629 1145068 : operator_mult::rv_fold (frange &r, tree type,
2630 : const REAL_VALUE_TYPE &lh_lb,
2631 : const REAL_VALUE_TYPE &lh_ub,
2632 : const REAL_VALUE_TYPE &rh_lb,
2633 : const REAL_VALUE_TYPE &rh_ub,
2634 : relation_kind kind) const
2635 : {
2636 1145068 : bool is_square
2637 : = (kind == VREL_EQ
2638 36962 : && real_equal (&lh_lb, &rh_lb)
2639 36962 : && real_equal (&lh_ub, &rh_ub)
2640 36962 : && real_isneg (&lh_lb) == real_isneg (&rh_lb)
2641 1182030 : && real_isneg (&lh_ub) == real_isneg (&rh_ub));
2642 1108106 : REAL_VALUE_TYPE lb, ub;
2643 1836249 : bool maybe_nan = false;
2644 : // x * x never produces a new NAN and we only multiply the same
2645 : // values, so the 0 * INF problematic cases never appear there.
2646 1108106 : if (!is_square)
2647 : {
2648 : // [+-0, +-0] * [+INF,+INF] (or [-INF,-INF] or swapped is a known NAN.
2649 1113512 : if ((zero_p (lh_lb, lh_ub) && singleton_inf_p (rh_lb, rh_ub))
2650 1113506 : || (zero_p (rh_lb, rh_ub) && singleton_inf_p (lh_lb, lh_ub)))
2651 : {
2652 37 : r.set_nan (type);
2653 416925 : return;
2654 : }
2655 :
2656 : // Otherwise, if one range includes zero and the other ends with +-INF,
2657 : // it is a maybe NAN.
2658 1108069 : if ((contains_zero_p (lh_lb, lh_ub)
2659 1004700 : && (real_isinf (&rh_lb) || real_isinf (&rh_ub)))
2660 1723735 : || (contains_zero_p (rh_lb, rh_ub)
2661 201467 : && (real_isinf (&lh_lb) || real_isinf (&lh_ub))))
2662 : {
2663 416888 : maybe_nan = true;
2664 :
2665 416888 : int signbit_known = signbit_known_p (lh_lb, lh_ub, rh_lb, rh_ub);
2666 :
2667 : // If one of the ranges that includes INF is singleton
2668 : // and the other range includes zero, the resulting
2669 : // range is INF and NAN, because the 0 * INF boundary
2670 : // case will be NAN, but already nextafter (0, 1) * INF
2671 : // is INF.
2672 416888 : if (singleton_inf_p (lh_lb, lh_ub)
2673 416888 : || singleton_inf_p (rh_lb, rh_ub))
2674 : {
2675 988 : inf_range (lb, ub, signbit_known);
2676 988 : r.set (type, lb, ub, nan_state (true));
2677 988 : return;
2678 : }
2679 :
2680 : // If one of the multiplicands must be zero, the resulting
2681 : // range is +-0 and NAN.
2682 415900 : if (zero_p (lh_lb, lh_ub) || zero_p (rh_lb, rh_ub))
2683 : {
2684 5680 : zero_range (lb, ub, signbit_known);
2685 5680 : r.set (type, lb, ub, nan_state (true));
2686 5680 : return;
2687 : }
2688 :
2689 : // Otherwise one of the multiplicands could be
2690 : // [0.0, nextafter (0.0, 1.0)] and the [DBL_MAX, INF]
2691 : // or similarly with different signs. 0.0 * DBL_MAX
2692 : // is still 0.0, nextafter (0.0, 1.0) * INF is still INF,
2693 : // so if the signs are always the same or always different,
2694 : // result is [+0.0, +INF] or [-INF, -0.0], otherwise VARYING.
2695 410220 : zero_to_inf_range (lb, ub, signbit_known);
2696 410220 : r.set (type, lb, ub, nan_state (true));
2697 410220 : return;
2698 : }
2699 : }
2700 :
2701 728143 : REAL_VALUE_TYPE cp[8];
2702 : // Do a cross-product. At this point none of the multiplications
2703 : // should produce a NAN.
2704 728143 : frange_arithmetic (MULT_EXPR, type, cp[0], lh_lb, rh_lb, dconstninf);
2705 728143 : frange_arithmetic (MULT_EXPR, type, cp[4], lh_lb, rh_lb, dconstinf);
2706 728143 : if (is_square)
2707 : {
2708 : // For x * x we can just do max (lh_lb * lh_lb, lh_ub * lh_ub)
2709 : // as maximum and -0.0 as minimum if 0.0 is in the range,
2710 : // otherwise min (lh_lb * lh_lb, lh_ub * lh_ub).
2711 : // -0.0 rather than 0.0 because VREL_EQ doesn't prove that
2712 : // x and y are bitwise equal, just that they compare equal.
2713 36962 : if (contains_zero_p (lh_lb, lh_ub))
2714 : {
2715 33926 : if (real_isneg (&lh_lb) == real_isneg (&lh_ub))
2716 1155 : cp[1] = dconst0;
2717 : else
2718 32771 : cp[1] = dconstm0;
2719 : }
2720 : else
2721 3036 : cp[1] = cp[0];
2722 36962 : cp[2] = cp[0];
2723 36962 : cp[5] = cp[4];
2724 36962 : cp[6] = cp[4];
2725 : }
2726 : else
2727 : {
2728 691181 : frange_arithmetic (MULT_EXPR, type, cp[1], lh_lb, rh_ub, dconstninf);
2729 691181 : frange_arithmetic (MULT_EXPR, type, cp[5], lh_lb, rh_ub, dconstinf);
2730 691181 : frange_arithmetic (MULT_EXPR, type, cp[2], lh_ub, rh_lb, dconstninf);
2731 691181 : frange_arithmetic (MULT_EXPR, type, cp[6], lh_ub, rh_lb, dconstinf);
2732 : }
2733 728143 : frange_arithmetic (MULT_EXPR, type, cp[3], lh_ub, rh_ub, dconstninf);
2734 728143 : frange_arithmetic (MULT_EXPR, type, cp[7], lh_ub, rh_ub, dconstinf);
2735 :
2736 728143 : find_range (lb, ub, cp);
2737 :
2738 728143 : gcc_checking_assert (!real_isnan (&lb));
2739 728143 : gcc_checking_assert (!real_isnan (&ub));
2740 728143 : r.set (type, lb, ub, nan_state (maybe_nan));
2741 : }
2742 :
2743 :
2744 : class foperator_div : public range_operator
2745 : {
2746 : using range_operator::op1_range;
2747 : using range_operator::op2_range;
2748 : public:
2749 24619 : virtual bool op1_range (frange &r, tree type,
2750 : const frange &lhs,
2751 : const frange &op2,
2752 : relation_trio = TRIO_VARYING) const final override
2753 : {
2754 24619 : if (lhs.undefined_p ())
2755 : return false;
2756 24619 : frange wlhs = float_widen_lhs_range (type, lhs);
2757 24619 : bool ret = range_op_handler (MULT_EXPR).fold_range (r, type, wlhs, op2);
2758 24619 : if (!ret)
2759 : return ret;
2760 24619 : if (wlhs.known_isnan () || op2.known_isnan () || op2.undefined_p ())
2761 4 : return float_binary_op_range_finish (ret, r, type, wlhs);
2762 24615 : const REAL_VALUE_TYPE &lhs_lb = wlhs.lower_bound ();
2763 24615 : const REAL_VALUE_TYPE &lhs_ub = wlhs.upper_bound ();
2764 24615 : const REAL_VALUE_TYPE &op2_lb = op2.lower_bound ();
2765 24615 : const REAL_VALUE_TYPE &op2_ub = op2.upper_bound ();
2766 24615 : if ((contains_zero_p (lhs_lb, lhs_ub)
2767 17209 : && (real_isinf (&op2_lb) || real_isinf (&op2_ub)))
2768 31036 : || ((contains_zero_p (op2_lb, op2_ub))
2769 8186 : && (real_isinf (&lhs_lb) || real_isinf (&lhs_ub))))
2770 : {
2771 : // If both lhs could be zero and op2 infinity or vice versa,
2772 : // we don't know anything about op1 except maybe for the sign
2773 : // and perhaps if it can be NAN or not.
2774 18492 : REAL_VALUE_TYPE lb, ub;
2775 18492 : int signbit_known = signbit_known_p (lhs_lb, lhs_ub, op2_lb, op2_ub);
2776 18492 : zero_to_inf_range (lb, ub, signbit_known);
2777 18492 : r.set (type, lb, ub);
2778 : }
2779 24615 : return float_binary_op_range_finish (ret, r, type, wlhs);
2780 24619 : }
2781 41088 : virtual bool op2_range (frange &r, tree type,
2782 : const frange &lhs,
2783 : const frange &op1,
2784 : relation_trio = TRIO_VARYING) const final override
2785 : {
2786 41088 : if (lhs.undefined_p ())
2787 : return false;
2788 41088 : frange wlhs = float_widen_lhs_range (type, lhs);
2789 41088 : bool ret = fold_range (r, type, op1, wlhs);
2790 41088 : if (!ret)
2791 : return ret;
2792 41088 : if (wlhs.known_isnan () || op1.known_isnan () || op1.undefined_p ())
2793 20 : return float_binary_op_range_finish (ret, r, type, wlhs, true);
2794 41068 : const REAL_VALUE_TYPE &lhs_lb = wlhs.lower_bound ();
2795 41068 : const REAL_VALUE_TYPE &lhs_ub = wlhs.upper_bound ();
2796 41068 : const REAL_VALUE_TYPE &op1_lb = op1.lower_bound ();
2797 41068 : const REAL_VALUE_TYPE &op1_ub = op1.upper_bound ();
2798 72232 : if ((contains_zero_p (lhs_lb, lhs_ub) && contains_zero_p (op1_lb, op1_ub))
2799 44546 : || ((real_isinf (&lhs_lb) || real_isinf (&lhs_ub))
2800 7623 : && (real_isinf (&op1_lb) || real_isinf (&op1_ub))))
2801 : {
2802 : // If both lhs and op1 could be zeros or both could be infinities,
2803 : // we don't know anything about op2 except maybe for the sign
2804 : // and perhaps if it can be NAN or not.
2805 31998 : REAL_VALUE_TYPE lb, ub;
2806 31998 : int signbit_known = signbit_known_p (lhs_lb, lhs_ub, op1_lb, op1_ub);
2807 31998 : zero_to_inf_range (lb, ub, signbit_known);
2808 31998 : r.set (type, lb, ub);
2809 : }
2810 41068 : return float_binary_op_range_finish (ret, r, type, wlhs, true);
2811 41088 : }
2812 : private:
2813 665154 : void rv_fold (frange &r, tree type,
2814 : const REAL_VALUE_TYPE &lh_lb,
2815 : const REAL_VALUE_TYPE &lh_ub,
2816 : const REAL_VALUE_TYPE &rh_lb,
2817 : const REAL_VALUE_TYPE &rh_ub,
2818 : relation_kind) const final override
2819 : {
2820 : // +-0.0 / +-0.0 or +-INF / +-INF is a known NAN.
2821 666330 : if ((zero_p (lh_lb, lh_ub) && zero_p (rh_lb, rh_ub))
2822 665682 : || (singleton_inf_p (lh_lb, lh_ub) && singleton_inf_p (rh_lb, rh_ub)))
2823 : {
2824 654 : r.set_nan (type);
2825 327953 : return;
2826 : }
2827 :
2828 664500 : REAL_VALUE_TYPE lb, ub;
2829 664500 : bool maybe_nan = false;
2830 : // If +-0.0 is in both ranges, it is a maybe NAN.
2831 664500 : if (contains_zero_p (lh_lb, lh_ub) && contains_zero_p (rh_lb, rh_ub))
2832 : maybe_nan = true;
2833 : // If +-INF is in both ranges, it is a maybe NAN.
2834 651165 : else if ((real_isinf (&lh_lb) || real_isinf (&lh_ub))
2835 382388 : && (real_isinf (&rh_lb) || real_isinf (&rh_ub)))
2836 : maybe_nan = true;
2837 :
2838 664500 : int signbit_known = signbit_known_p (lh_lb, lh_ub, rh_lb, rh_ub);
2839 :
2840 : // If dividend must be zero, the range is just +-0
2841 : // (including if the divisor is +-INF).
2842 : // If divisor must be +-INF, the range is just +-0
2843 : // (including if the dividend is zero).
2844 664500 : if (zero_p (lh_lb, lh_ub) || singleton_inf_p (rh_lb, rh_ub))
2845 : {
2846 530 : zero_range (lb, ub, signbit_known);
2847 530 : r.set (type, lb, ub, nan_state (maybe_nan));
2848 530 : return;
2849 : }
2850 :
2851 : // If divisor must be zero, the range is just +-INF
2852 : // (including if the dividend is +-INF).
2853 : // If dividend must be +-INF, the range is just +-INF
2854 : // (including if the dividend is zero).
2855 663970 : if (zero_p (rh_lb, rh_ub) || singleton_inf_p (lh_lb, lh_ub))
2856 : {
2857 3333 : inf_range (lb, ub, signbit_known);
2858 3333 : r.set (type, lb, ub, nan_state (maybe_nan));
2859 3333 : return;
2860 : }
2861 :
2862 : // Otherwise if both operands may be zero, divisor could be
2863 : // nextafter(0.0, +-1.0) and dividend +-0.0
2864 : // in which case result is going to INF or vice versa and
2865 : // result +0.0. So, all we can say for that case is if the
2866 : // signs of divisor and dividend are always the same we have
2867 : // [+0.0, +INF], if they are always different we have
2868 : // [-INF, -0.0]. If they vary, VARYING.
2869 : // If both may be +-INF, divisor could be INF and dividend FLT_MAX,
2870 : // in which case result is going to INF or vice versa and
2871 : // result +0.0. So, all we can say for that case is if the
2872 : // signs of divisor and dividend are always the same we have
2873 : // [+0.0, +INF], if they are always different we have
2874 : // [-INF, -0.0]. If they vary, VARYING.
2875 660637 : if (maybe_nan)
2876 : {
2877 323436 : zero_to_inf_range (lb, ub, signbit_known);
2878 323436 : r.set (type, lb, ub, nan_state (maybe_nan));
2879 323436 : return;
2880 : }
2881 :
2882 337201 : REAL_VALUE_TYPE cp[8];
2883 : // Do a cross-division. At this point none of the divisions should
2884 : // produce a NAN.
2885 337201 : frange_arithmetic (RDIV_EXPR, type, cp[0], lh_lb, rh_lb, dconstninf);
2886 337201 : frange_arithmetic (RDIV_EXPR, type, cp[1], lh_lb, rh_ub, dconstninf);
2887 337201 : frange_arithmetic (RDIV_EXPR, type, cp[2], lh_ub, rh_lb, dconstninf);
2888 337201 : frange_arithmetic (RDIV_EXPR, type, cp[3], lh_ub, rh_ub, dconstninf);
2889 337201 : frange_arithmetic (RDIV_EXPR, type, cp[4], lh_lb, rh_lb, dconstinf);
2890 337201 : frange_arithmetic (RDIV_EXPR, type, cp[5], lh_lb, rh_ub, dconstinf);
2891 337201 : frange_arithmetic (RDIV_EXPR, type, cp[6], lh_ub, rh_lb, dconstinf);
2892 337201 : frange_arithmetic (RDIV_EXPR, type, cp[7], lh_ub, rh_ub, dconstinf);
2893 :
2894 337201 : find_range (lb, ub, cp);
2895 :
2896 : // If divisor may be zero (but is not known to be only zero),
2897 : // and dividend can't be zero, the range can go up to -INF or +INF
2898 : // depending on the signs.
2899 337201 : if (contains_zero_p (rh_lb, rh_ub))
2900 : {
2901 50314 : if (signbit_known <= 0)
2902 47899 : real_inf (&lb, true);
2903 47899 : if (signbit_known >= 0)
2904 50276 : real_inf (&ub, false);
2905 : }
2906 :
2907 337201 : gcc_checking_assert (!real_isnan (&lb));
2908 337201 : gcc_checking_assert (!real_isnan (&ub));
2909 337201 : r.set (type, lb, ub, nan_state (maybe_nan));
2910 : }
2911 : };
2912 : static const foperator_div fop_div;
2913 :
2914 : bool
2915 913449 : operator_cast::fold_range (frange &r, tree type, const frange &op1,
2916 : const frange &, relation_trio) const
2917 : {
2918 913449 : REAL_VALUE_TYPE lb, ub;
2919 913449 : enum machine_mode mode = TYPE_MODE (type);
2920 6394143 : bool mode_composite = MODE_COMPOSITE_P (mode);
2921 :
2922 913449 : if (empty_range_varying (r, type, op1, op1))
2923 819 : return true;
2924 3650520 : if (!MODE_HAS_NANS (mode) && op1.maybe_isnan ())
2925 : {
2926 0 : r.set_varying (type);
2927 0 : return true;
2928 : }
2929 912630 : if (op1.known_isnan ())
2930 : {
2931 3006 : r.set_nan (type);
2932 3006 : return true;
2933 : }
2934 :
2935 909624 : const REAL_VALUE_TYPE &lh_lb = op1.lower_bound ();
2936 909624 : const REAL_VALUE_TYPE &lh_ub = op1.upper_bound ();
2937 909624 : real_convert (&lb, mode, &lh_lb);
2938 909624 : real_convert (&ub, mode, &lh_ub);
2939 :
2940 909624 : if (flag_rounding_math)
2941 : {
2942 30557 : if (real_less (&lh_lb, &lb))
2943 : {
2944 2668 : if (mode_composite
2945 2668 : && (real_isdenormal (&lb, mode) || real_iszero (&lb)))
2946 : {
2947 : // IBM extended denormals only have DFmode precision.
2948 0 : REAL_VALUE_TYPE tmp, tmp2;
2949 0 : real_convert (&tmp2, DFmode, &lh_lb);
2950 0 : real_nextafter (&tmp, REAL_MODE_FORMAT (DFmode), &tmp2,
2951 : &dconstninf);
2952 0 : real_convert (&lb, mode, &tmp);
2953 : }
2954 : else
2955 2668 : frange_nextafter (mode, lb, dconstninf);
2956 : }
2957 30557 : if (real_less (&ub, &lh_ub))
2958 : {
2959 1070 : if (mode_composite
2960 1070 : && (real_isdenormal (&ub, mode) || real_iszero (&ub)))
2961 : {
2962 : // IBM extended denormals only have DFmode precision.
2963 0 : REAL_VALUE_TYPE tmp, tmp2;
2964 0 : real_convert (&tmp2, DFmode, &lh_ub);
2965 0 : real_nextafter (&tmp, REAL_MODE_FORMAT (DFmode), &tmp2,
2966 : &dconstinf);
2967 0 : real_convert (&ub, mode, &tmp);
2968 : }
2969 : else
2970 1070 : frange_nextafter (mode, ub, dconstinf);
2971 : }
2972 : }
2973 :
2974 909624 : r.set (type, lb, ub, op1.get_nan_state ());
2975 :
2976 909624 : if (flag_trapping_math
2977 4092891 : && MODE_HAS_INFINITIES (TYPE_MODE (type))
2978 795817 : && r.known_isinf ()
2979 909704 : && !op1.known_isinf ())
2980 : {
2981 1 : REAL_VALUE_TYPE inf = r.lower_bound ();
2982 1 : if (real_isneg (&inf))
2983 : {
2984 0 : REAL_VALUE_TYPE min = real_min_representable (type);
2985 0 : r.set (type, inf, min);
2986 : }
2987 : else
2988 : {
2989 1 : REAL_VALUE_TYPE max = real_max_representable (type);
2990 1 : r.set (type, max, inf);
2991 : }
2992 : }
2993 :
2994 909624 : r.flush_denormals_to_zero ();
2995 909624 : return true;
2996 : }
2997 :
2998 : // Implement fold for a cast from float to another float.
2999 : bool
3000 53150 : operator_cast::op1_range (frange &r, tree type, const frange &lhs,
3001 : const frange &op2, relation_trio) const
3002 : {
3003 53150 : if (lhs.undefined_p ())
3004 : return false;
3005 53150 : tree lhs_type = lhs.type ();
3006 53150 : enum machine_mode mode = TYPE_MODE (type);
3007 53150 : enum machine_mode lhs_mode = TYPE_MODE (lhs_type);
3008 53150 : frange wlhs;
3009 53150 : bool rm;
3010 53150 : if (REAL_MODE_FORMAT (mode)->ieee_bits
3011 48786 : && REAL_MODE_FORMAT (lhs_mode)->ieee_bits
3012 45564 : && (REAL_MODE_FORMAT (lhs_mode)->ieee_bits
3013 : >= REAL_MODE_FORMAT (mode)->ieee_bits)
3014 73147 : && pow2p_hwi (REAL_MODE_FORMAT (mode)->ieee_bits))
3015 : {
3016 : /* If the cast is widening from IEEE exchange mode to
3017 : wider exchange mode or extended mode, no need to extend
3018 : the range on reverse operation. */
3019 19997 : rm = false;
3020 19997 : wlhs = lhs;
3021 : }
3022 : else
3023 : {
3024 33153 : rm = true;
3025 33153 : wlhs = float_widen_lhs_range (lhs_type, lhs);
3026 : }
3027 53150 : auto save_flag_rounding_math = flag_rounding_math;
3028 53150 : flag_rounding_math = rm;
3029 53150 : bool ret = float_binary_op_range_finish (fold_range (r, type, wlhs, op2),
3030 : r, type, lhs);
3031 53150 : flag_rounding_math = save_flag_rounding_math;
3032 53150 : return ret;
3033 53150 : }
3034 :
3035 : // Implement fold for a cast from float to an int.
3036 : bool
3037 209038 : operator_cast::fold_range (irange &r, tree type, const frange &op1,
3038 : const irange &, relation_trio) const
3039 : {
3040 209038 : if (empty_range_varying (r, type, op1, op1))
3041 540 : return true;
3042 208498 : if (op1.maybe_isnan () || op1.maybe_isinf ())
3043 : {
3044 182151 : r.set_varying (type);
3045 182151 : return true;
3046 : }
3047 26347 : REAL_VALUE_TYPE lb, ub;
3048 26347 : real_trunc (&lb, VOIDmode, &op1.lower_bound ());
3049 26347 : real_trunc (&ub, VOIDmode, &op1.upper_bound ());
3050 26347 : REAL_VALUE_TYPE l, u;
3051 26347 : l = real_value_from_int_cst (NULL_TREE, TYPE_MIN_VALUE (type));
3052 26347 : if (real_less (&lb, &l))
3053 : {
3054 9430 : r.set_varying (type);
3055 9430 : return true;
3056 : }
3057 16917 : u = real_value_from_int_cst (NULL_TREE, TYPE_MAX_VALUE (type));
3058 16917 : if (real_less (&u, &ub))
3059 : {
3060 7945 : r.set_varying (type);
3061 7945 : return true;
3062 : }
3063 8972 : bool fail = false;
3064 8972 : wide_int wlb = real_to_integer (&lb, &fail, TYPE_PRECISION (type));
3065 8972 : wide_int wub = real_to_integer (&ub, &fail, TYPE_PRECISION (type));
3066 8972 : if (fail)
3067 : {
3068 0 : r.set_varying (type);
3069 0 : return true;
3070 : }
3071 8972 : r.set (type, wlb, wub);
3072 8972 : return true;
3073 8972 : }
3074 :
3075 : // Implement op1_range for a cast from float to an int.
3076 : bool
3077 7453 : operator_cast::op1_range (frange &r, tree type, const irange &lhs,
3078 : const frange &, relation_trio) const
3079 : {
3080 7453 : if (lhs.undefined_p ())
3081 : return false;
3082 7453 : REAL_VALUE_TYPE lb, lbo, ub, ubo;
3083 7453 : wide_int lhs_lb = lhs.lower_bound ();
3084 7453 : wide_int lhs_ub = lhs.upper_bound ();
3085 7453 : tree lhs_type = lhs.type ();
3086 7453 : enum machine_mode mode = TYPE_MODE (type);
3087 7453 : real_from_integer (&lbo, VOIDmode, lhs_lb, TYPE_SIGN (lhs_type));
3088 7453 : real_from_integer (&ubo, VOIDmode, lhs_ub, TYPE_SIGN (lhs_type));
3089 7453 : real_convert (&lb, mode, &lbo);
3090 7453 : real_convert (&ub, mode, &ubo);
3091 7453 : if (real_identical (&lb, &lbo))
3092 : {
3093 : /* If low bound is exactly representable in type,
3094 : use nextafter (lb - 1., +inf). */
3095 7324 : real_arithmetic (&lb, PLUS_EXPR, &lbo, &dconstm1);
3096 7324 : real_convert (&lb, mode, &lb);
3097 7324 : if (!real_identical (&lb, &lbo))
3098 6085 : frange_nextafter (mode, lb, dconstinf);
3099 7324 : if (real_identical (&lb, &lbo))
3100 1241 : frange_nextafter (mode, lb, dconstninf);
3101 : }
3102 129 : else if (real_less (&lbo, &lb))
3103 13 : frange_nextafter (mode, lb, dconstninf);
3104 7453 : if (real_identical (&ub, &ubo))
3105 : {
3106 : /* If upper bound is exactly representable in type,
3107 : use nextafter (ub + 1., -inf). */
3108 5612 : real_arithmetic (&ub, PLUS_EXPR, &ubo, &dconst1);
3109 5612 : real_convert (&ub, mode, &ub);
3110 5612 : if (!real_identical (&ub, &ubo))
3111 5532 : frange_nextafter (mode, ub, dconstninf);
3112 5612 : if (real_identical (&ub, &ubo))
3113 80 : frange_nextafter (mode, ub, dconstinf);
3114 : }
3115 1841 : else if (real_less (&ub, &ubo))
3116 0 : frange_nextafter (mode, ub, dconstinf);
3117 7453 : r.set (type, lb, ub, nan_state (false));
3118 7453 : return true;
3119 7453 : }
3120 :
3121 : // Implement fold for a cast from int to a float.
3122 : bool
3123 816920 : operator_cast::fold_range (frange &r, tree type, const irange &op1,
3124 : const frange &, relation_trio) const
3125 : {
3126 816920 : if (empty_range_varying (r, type, op1, op1))
3127 1402 : return true;
3128 815518 : REAL_VALUE_TYPE lb, ub;
3129 815518 : wide_int op1_lb = op1.lower_bound ();
3130 815518 : wide_int op1_ub = op1.upper_bound ();
3131 815518 : tree op1_type = op1.type ();
3132 815518 : enum machine_mode mode = flag_rounding_math ? VOIDmode : TYPE_MODE (type);
3133 815518 : real_from_integer (&lb, mode, op1_lb, TYPE_SIGN (op1_type));
3134 815518 : real_from_integer (&ub, mode, op1_ub, TYPE_SIGN (op1_type));
3135 815518 : if (flag_rounding_math)
3136 : {
3137 1129 : REAL_VALUE_TYPE lbo = lb, ubo = ub;
3138 1129 : mode = TYPE_MODE (type);
3139 1129 : real_convert (&lb, mode, &lb);
3140 1129 : real_convert (&ub, mode, &ub);
3141 1129 : if (real_less (&lbo, &lb))
3142 322 : frange_nextafter (mode, lb, dconstninf);
3143 1129 : if (real_less (&ub, &ubo))
3144 192 : frange_nextafter (mode, ub, dconstinf);
3145 : }
3146 815518 : r.set (type, lb, ub, nan_state (false));
3147 815518 : frange_drop_infs (r, type);
3148 815518 : if (r.undefined_p ())
3149 4 : r.set_varying (type);
3150 815518 : return true;
3151 815530 : }
3152 :
3153 : // Implement op1_range for a cast from int to a float.
3154 : bool
3155 211681 : operator_cast::op1_range (irange &r, tree type, const frange &lhs,
3156 : const irange &, relation_trio) const
3157 : {
3158 211681 : if (lhs.undefined_p ())
3159 : return false;
3160 211681 : if (lhs.known_isnan ())
3161 : {
3162 0 : r.set_varying (type);
3163 0 : return true;
3164 : }
3165 211681 : REAL_VALUE_TYPE lb = lhs.lower_bound ();
3166 211681 : REAL_VALUE_TYPE ub = lhs.upper_bound ();
3167 211681 : enum machine_mode mode = TYPE_MODE (lhs.type ());
3168 211681 : frange_nextafter (mode, lb, dconstninf);
3169 211681 : frange_nextafter (mode, ub, dconstinf);
3170 211681 : if (flag_rounding_math)
3171 : {
3172 37 : real_floor (&lb, mode, &lb);
3173 37 : real_ceil (&ub, mode, &ub);
3174 : }
3175 : else
3176 : {
3177 211644 : real_trunc (&lb, mode, &lb);
3178 211644 : real_trunc (&ub, mode, &ub);
3179 : }
3180 211681 : REAL_VALUE_TYPE l, u;
3181 211681 : wide_int wlb, wub;
3182 211681 : l = real_value_from_int_cst (NULL_TREE, TYPE_MIN_VALUE (type));
3183 211681 : if (real_less (&lb, &l))
3184 28577 : wlb = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
3185 : else
3186 : {
3187 183104 : bool fail = false;
3188 183104 : wlb = real_to_integer (&lb, &fail, TYPE_PRECISION (type));
3189 183104 : if (fail)
3190 0 : wlb = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
3191 : }
3192 211681 : u = real_value_from_int_cst (NULL_TREE, TYPE_MAX_VALUE (type));
3193 211681 : if (real_less (&u, &ub))
3194 39630 : wub = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
3195 : else
3196 : {
3197 172051 : bool fail = false;
3198 172051 : wub = real_to_integer (&ub, &fail, TYPE_PRECISION (type));
3199 172051 : if (fail)
3200 0 : wub = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
3201 : }
3202 211681 : r.set (type, wlb, wub);
3203 211681 : return true;
3204 211681 : }
3205 :
3206 : // Initialize any float operators to the primary table
3207 :
3208 : void
3209 286916 : range_op_table::initialize_float_ops ()
3210 : {
3211 286916 : set (UNLE_EXPR, fop_unordered_le);
3212 286916 : set (UNLT_EXPR, fop_unordered_lt);
3213 286916 : set (UNGE_EXPR, fop_unordered_ge);
3214 286916 : set (UNGT_EXPR, fop_unordered_gt);
3215 286916 : set (UNEQ_EXPR, fop_unordered_equal);
3216 286916 : set (ORDERED_EXPR, fop_ordered);
3217 286916 : set (UNORDERED_EXPR, fop_unordered);
3218 286916 : set (LTGT_EXPR, fop_ltgt);
3219 286916 : set (RDIV_EXPR, fop_div);
3220 286916 : }
3221 :
3222 : #if CHECKING_P
3223 : #include "selftest.h"
3224 :
3225 : namespace selftest
3226 : {
3227 :
3228 : // Build an frange from string endpoints.
3229 :
3230 : static inline frange
3231 16 : frange_float (const char *lb, const char *ub, tree type = float_type_node)
3232 : {
3233 16 : REAL_VALUE_TYPE min, max;
3234 16 : gcc_assert (real_from_string (&min, lb) == 0);
3235 16 : gcc_assert (real_from_string (&max, ub) == 0);
3236 16 : return frange (type, min, max);
3237 : }
3238 :
3239 : void
3240 4 : range_op_float_tests ()
3241 : {
3242 4 : frange r, r0, r1;
3243 4 : frange trange (float_type_node);
3244 :
3245 : // negate([-5, +10]) => [-10, 5]
3246 4 : r0 = frange_float ("-5", "10");
3247 4 : range_op_handler (NEGATE_EXPR).fold_range (r, float_type_node, r0, trange);
3248 4 : ASSERT_EQ (r, frange_float ("-10", "5"));
3249 :
3250 : // negate([0, 1] -NAN) => [-1, -0] +NAN
3251 4 : r0 = frange_float ("0", "1");
3252 4 : r0.update_nan (true);
3253 4 : range_op_handler (NEGATE_EXPR).fold_range (r, float_type_node, r0, trange);
3254 4 : r1 = frange_float ("-1", "-0");
3255 4 : r1.update_nan (false);
3256 4 : ASSERT_EQ (r, r1);
3257 :
3258 : // [-INF,+INF] + [-INF,+INF] could be a NAN.
3259 4 : range_op_handler plus (PLUS_EXPR);
3260 4 : r0.set_varying (float_type_node);
3261 4 : r1.set_varying (float_type_node);
3262 4 : r0.clear_nan ();
3263 4 : r1.clear_nan ();
3264 4 : plus.fold_range (r, float_type_node, r0, r1);
3265 4 : if (HONOR_NANS (float_type_node))
3266 8 : ASSERT_TRUE (r.maybe_isnan ());
3267 4 : }
3268 :
3269 : } // namespace selftest
3270 :
3271 : #endif // CHECKING_P
|