gccrs: add test case to show our query-type system is working
[official-gcc.git] / gcc / range-op-float.cc
blobe0e91bad44d6d1d7739768ccf662c882ba49b7ea
1 /* Floating point range operators.
2 Copyright (C) 2022-2023 Free Software Foundation, Inc.
3 Contributed by Aldy Hernandez <aldyh@redhat.com>.
5 This file is part of GCC.
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.
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.
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/>. */
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"
49 // Default definitions for floating point operators.
51 bool
52 range_operator_float::fold_range (frange &r, tree type,
53 const frange &op1, const frange &op2,
54 relation_trio trio) const
56 if (empty_range_varying (r, type, op1, op2))
57 return true;
58 if (op1.known_isnan () || op2.known_isnan ())
60 r.set_nan (op1.type ());
61 return true;
64 REAL_VALUE_TYPE lb, ub;
65 bool maybe_nan;
66 rv_fold (lb, ub, maybe_nan, type,
67 op1.lower_bound (), op1.upper_bound (),
68 op2.lower_bound (), op2.upper_bound (), trio.op1_op2 ());
70 // Handle possible NANs by saturating to the appropriate INF if only
71 // one end is a NAN. If both ends are a NAN, just return a NAN.
72 bool lb_nan = real_isnan (&lb);
73 bool ub_nan = real_isnan (&ub);
74 if (lb_nan && ub_nan)
76 r.set_nan (type);
77 return true;
79 if (lb_nan)
80 lb = dconstninf;
81 else if (ub_nan)
82 ub = dconstinf;
84 r.set (type, lb, ub);
86 if (lb_nan || ub_nan || maybe_nan
87 || op1.maybe_isnan ()
88 || op2.maybe_isnan ())
89 // Keep the default NAN (with a varying sign) set by the setter.
91 else
92 r.clear_nan ();
94 // If the result has overflowed and flag_trapping_math, folding this
95 // operation could elide an overflow or division by zero exception.
96 // Avoid returning a singleton +-INF, to keep the propagators (DOM
97 // and substitute_and_fold_engine) from folding. See PR107608.
98 if (flag_trapping_math
99 && MODE_HAS_INFINITIES (TYPE_MODE (type))
100 && r.known_isinf () && !op1.known_isinf () && !op2.known_isinf ())
102 REAL_VALUE_TYPE inf = r.lower_bound ();
103 if (real_isneg (&inf))
105 REAL_VALUE_TYPE min = real_min_representable (type);
106 r.set (type, inf, min);
108 else
110 REAL_VALUE_TYPE max = real_max_representable (type);
111 r.set (type, max, inf);
115 r.flush_denormals_to_zero ();
117 return true;
120 // For a given operation, fold two sets of ranges into [lb, ub].
121 // MAYBE_NAN is set to TRUE if, in addition to any result in LB or
122 // UB, the final range has the possibility of a NAN.
123 void
124 range_operator_float::rv_fold (REAL_VALUE_TYPE &lb,
125 REAL_VALUE_TYPE &ub,
126 bool &maybe_nan,
127 tree type ATTRIBUTE_UNUSED,
128 const REAL_VALUE_TYPE &lh_lb ATTRIBUTE_UNUSED,
129 const REAL_VALUE_TYPE &lh_ub ATTRIBUTE_UNUSED,
130 const REAL_VALUE_TYPE &rh_lb ATTRIBUTE_UNUSED,
131 const REAL_VALUE_TYPE &rh_ub ATTRIBUTE_UNUSED,
132 relation_kind) const
134 lb = dconstninf;
135 ub = dconstinf;
136 maybe_nan = true;
139 bool
140 range_operator_float::fold_range (irange &r ATTRIBUTE_UNUSED,
141 tree type ATTRIBUTE_UNUSED,
142 const frange &lh ATTRIBUTE_UNUSED,
143 const irange &rh ATTRIBUTE_UNUSED,
144 relation_trio) const
146 return false;
149 bool
150 range_operator_float::fold_range (irange &r ATTRIBUTE_UNUSED,
151 tree type ATTRIBUTE_UNUSED,
152 const frange &lh ATTRIBUTE_UNUSED,
153 const frange &rh ATTRIBUTE_UNUSED,
154 relation_trio) const
156 return false;
159 bool
160 range_operator_float::op1_range (frange &r ATTRIBUTE_UNUSED,
161 tree type ATTRIBUTE_UNUSED,
162 const frange &lhs ATTRIBUTE_UNUSED,
163 const frange &op2 ATTRIBUTE_UNUSED,
164 relation_trio) const
166 return false;
169 bool
170 range_operator_float::op1_range (frange &r ATTRIBUTE_UNUSED,
171 tree type ATTRIBUTE_UNUSED,
172 const irange &lhs ATTRIBUTE_UNUSED,
173 const frange &op2 ATTRIBUTE_UNUSED,
174 relation_trio) const
176 return false;
179 bool
180 range_operator_float::op2_range (frange &r ATTRIBUTE_UNUSED,
181 tree type ATTRIBUTE_UNUSED,
182 const frange &lhs ATTRIBUTE_UNUSED,
183 const frange &op1 ATTRIBUTE_UNUSED,
184 relation_trio) const
186 return false;
189 bool
190 range_operator_float::op2_range (frange &r ATTRIBUTE_UNUSED,
191 tree type ATTRIBUTE_UNUSED,
192 const irange &lhs ATTRIBUTE_UNUSED,
193 const frange &op1 ATTRIBUTE_UNUSED,
194 relation_trio) const
196 return false;
199 relation_kind
200 range_operator_float::lhs_op1_relation (const frange &lhs ATTRIBUTE_UNUSED,
201 const frange &op1 ATTRIBUTE_UNUSED,
202 const frange &op2 ATTRIBUTE_UNUSED,
203 relation_kind) const
205 return VREL_VARYING;
208 relation_kind
209 range_operator_float::lhs_op1_relation (const irange &lhs ATTRIBUTE_UNUSED,
210 const frange &op1 ATTRIBUTE_UNUSED,
211 const frange &op2 ATTRIBUTE_UNUSED,
212 relation_kind) const
214 return VREL_VARYING;
217 relation_kind
218 range_operator_float::lhs_op2_relation (const irange &lhs ATTRIBUTE_UNUSED,
219 const frange &op1 ATTRIBUTE_UNUSED,
220 const frange &op2 ATTRIBUTE_UNUSED,
221 relation_kind) const
223 return VREL_VARYING;
226 relation_kind
227 range_operator_float::lhs_op2_relation (const frange &lhs ATTRIBUTE_UNUSED,
228 const frange &op1 ATTRIBUTE_UNUSED,
229 const frange &op2 ATTRIBUTE_UNUSED,
230 relation_kind) const
232 return VREL_VARYING;
235 relation_kind
236 range_operator_float::op1_op2_relation (const irange &lhs ATTRIBUTE_UNUSED) const
238 return VREL_VARYING;
241 relation_kind
242 range_operator_float::op1_op2_relation (const frange &lhs ATTRIBUTE_UNUSED) const
244 return VREL_VARYING;
247 // Return TRUE if OP1 and OP2 may be a NAN.
249 static inline bool
250 maybe_isnan (const frange &op1, const frange &op2)
252 return op1.maybe_isnan () || op2.maybe_isnan ();
255 // Floating version of relop_early_resolve that takes into account NAN
256 // and -ffinite-math-only.
258 inline bool
259 frelop_early_resolve (irange &r, tree type,
260 const frange &op1, const frange &op2,
261 relation_trio rel, relation_kind my_rel)
263 // If either operand is undefined, return VARYING.
264 if (empty_range_varying (r, type, op1, op2))
265 return true;
267 // We can fold relations from the oracle when we know both operands
268 // are free of NANs, or when -ffinite-math-only.
269 return (!maybe_isnan (op1, op2)
270 && relop_early_resolve (r, type, op1, op2, rel, my_rel));
273 // Set VALUE to its next real value, or INF if the operation overflows.
275 inline void
276 frange_nextafter (enum machine_mode mode,
277 REAL_VALUE_TYPE &value,
278 const REAL_VALUE_TYPE &inf)
280 if (MODE_COMPOSITE_P (mode)
281 && (real_isdenormal (&value, mode) || real_iszero (&value)))
283 // IBM extended denormals only have DFmode precision.
284 REAL_VALUE_TYPE tmp, tmp2;
285 real_convert (&tmp2, DFmode, &value);
286 real_nextafter (&tmp, REAL_MODE_FORMAT (DFmode), &tmp2, &inf);
287 real_convert (&value, mode, &tmp);
289 else
291 REAL_VALUE_TYPE tmp;
292 real_nextafter (&tmp, REAL_MODE_FORMAT (mode), &value, &inf);
293 value = tmp;
297 // Like real_arithmetic, but round the result to INF if the operation
298 // produced inexact results.
300 // ?? There is still one problematic case, i387. With
301 // -fexcess-precision=standard we perform most SF/DFmode arithmetic in
302 // XFmode (long_double_type_node), so that case is OK. But without
303 // -mfpmath=sse, all the SF/DFmode computations are in XFmode
304 // precision (64-bit mantissa) and only occasionally rounded to
305 // SF/DFmode (when storing into memory from the 387 stack). Maybe
306 // this is ok as well though it is just occasionally more precise. ??
308 static void
309 frange_arithmetic (enum tree_code code, tree type,
310 REAL_VALUE_TYPE &result,
311 const REAL_VALUE_TYPE &op1,
312 const REAL_VALUE_TYPE &op2,
313 const REAL_VALUE_TYPE &inf)
315 REAL_VALUE_TYPE value;
316 enum machine_mode mode = TYPE_MODE (type);
317 bool mode_composite = MODE_COMPOSITE_P (mode);
319 bool inexact = real_arithmetic (&value, code, &op1, &op2);
320 real_convert (&result, mode, &value);
322 // Be extra careful if there may be discrepancies between the
323 // compile and runtime results.
324 bool round = false;
325 if (mode_composite)
326 round = true;
327 else
329 bool low = real_isneg (&inf);
330 round = (low ? !real_less (&result, &value)
331 : !real_less (&value, &result));
332 if (real_isinf (&result, !low)
333 && !real_isinf (&value)
334 && !flag_rounding_math)
336 // Use just [+INF, +INF] rather than [MAX, +INF]
337 // even if value is larger than MAX and rounds to
338 // nearest to +INF. Similarly just [-INF, -INF]
339 // rather than [-INF, +MAX] even if value is smaller
340 // than -MAX and rounds to nearest to -INF.
341 // Unless INEXACT is true, in that case we need some
342 // extra buffer.
343 if (!inexact)
344 round = false;
345 else
347 REAL_VALUE_TYPE tmp = result, tmp2;
348 frange_nextafter (mode, tmp, inf);
349 // TMP is at this point the maximum representable
350 // number.
351 real_arithmetic (&tmp2, MINUS_EXPR, &value, &tmp);
352 if (real_isneg (&tmp2) != low
353 && (REAL_EXP (&tmp2) - REAL_EXP (&tmp)
354 >= 2 - REAL_MODE_FORMAT (mode)->p))
355 round = false;
359 if (round && (inexact || !real_identical (&result, &value)))
361 if (mode_composite
362 && (real_isdenormal (&result, mode) || real_iszero (&result)))
364 // IBM extended denormals only have DFmode precision.
365 REAL_VALUE_TYPE tmp, tmp2;
366 real_convert (&tmp2, DFmode, &value);
367 real_nextafter (&tmp, REAL_MODE_FORMAT (DFmode), &tmp2, &inf);
368 real_convert (&result, mode, &tmp);
370 else
371 frange_nextafter (mode, result, inf);
373 if (mode_composite)
374 switch (code)
376 case PLUS_EXPR:
377 case MINUS_EXPR:
378 // ibm-ldouble-format documents 1ulp for + and -.
379 frange_nextafter (mode, result, inf);
380 break;
381 case MULT_EXPR:
382 // ibm-ldouble-format documents 2ulps for *.
383 frange_nextafter (mode, result, inf);
384 frange_nextafter (mode, result, inf);
385 break;
386 case RDIV_EXPR:
387 // ibm-ldouble-format documents 3ulps for /.
388 frange_nextafter (mode, result, inf);
389 frange_nextafter (mode, result, inf);
390 frange_nextafter (mode, result, inf);
391 break;
392 default:
393 break;
397 // Crop R to [-INF, MAX] where MAX is the maximum representable number
398 // for TYPE.
400 static inline void
401 frange_drop_inf (frange &r, tree type)
403 REAL_VALUE_TYPE max = real_max_representable (type);
404 frange tmp (type, r.lower_bound (), max);
405 r.intersect (tmp);
408 // Crop R to [MIN, +INF] where MIN is the minimum representable number
409 // for TYPE.
411 static inline void
412 frange_drop_ninf (frange &r, tree type)
414 REAL_VALUE_TYPE min = real_min_representable (type);
415 frange tmp (type, min, r.upper_bound ());
416 r.intersect (tmp);
419 // Crop R to [MIN, MAX] where MAX is the maximum representable number
420 // for TYPE and MIN the minimum representable number for TYPE.
422 static inline void
423 frange_drop_infs (frange &r, tree type)
425 REAL_VALUE_TYPE max = real_max_representable (type);
426 REAL_VALUE_TYPE min = real_min_representable (type);
427 frange tmp (type, min, max);
428 r.intersect (tmp);
431 // If zero is in R, make sure both -0.0 and +0.0 are in the range.
433 static inline void
434 frange_add_zeros (frange &r, tree type)
436 if (r.undefined_p () || r.known_isnan ())
437 return;
439 if (HONOR_SIGNED_ZEROS (type)
440 && (real_iszero (&r.lower_bound ()) || real_iszero (&r.upper_bound ())))
442 frange zero;
443 zero.set_zero (type);
444 r.union_ (zero);
448 // Build a range that is <= VAL and store it in R. Return TRUE if
449 // further changes may be needed for R, or FALSE if R is in its final
450 // form.
452 static bool
453 build_le (frange &r, tree type, const frange &val)
455 gcc_checking_assert (!val.known_isnan ());
457 REAL_VALUE_TYPE ninf = frange_val_min (type);
458 r.set (type, ninf, val.upper_bound ());
460 // Add both zeros if there's the possibility of zero equality.
461 frange_add_zeros (r, type);
463 return true;
466 // Build a range that is < VAL and store it in R. Return TRUE if
467 // further changes may be needed for R, or FALSE if R is in its final
468 // form.
470 static bool
471 build_lt (frange &r, tree type, const frange &val)
473 gcc_checking_assert (!val.known_isnan ());
475 // < -INF is outside the range.
476 if (real_isinf (&val.upper_bound (), 1))
478 if (HONOR_NANS (type))
479 r.set_nan (type);
480 else
481 r.set_undefined ();
482 return false;
485 REAL_VALUE_TYPE ninf = frange_val_min (type);
486 REAL_VALUE_TYPE prev = val.upper_bound ();
487 machine_mode mode = TYPE_MODE (type);
488 // Default to the conservatively correct closed ranges for
489 // MODE_COMPOSITE_P, otherwise use nextafter. Note that for
490 // !HONOR_INFINITIES, nextafter will yield -INF, but frange::set()
491 // will crop the range appropriately.
492 if (!MODE_COMPOSITE_P (mode))
493 frange_nextafter (mode, prev, ninf);
494 r.set (type, ninf, prev);
495 return true;
498 // Build a range that is >= VAL and store it in R. Return TRUE if
499 // further changes may be needed for R, or FALSE if R is in its final
500 // form.
502 static bool
503 build_ge (frange &r, tree type, const frange &val)
505 gcc_checking_assert (!val.known_isnan ());
507 REAL_VALUE_TYPE inf = frange_val_max (type);
508 r.set (type, val.lower_bound (), inf);
510 // Add both zeros if there's the possibility of zero equality.
511 frange_add_zeros (r, type);
513 return true;
516 // Build a range that is > VAL and store it in R. Return TRUE if
517 // further changes may be needed for R, or FALSE if R is in its final
518 // form.
520 static bool
521 build_gt (frange &r, tree type, const frange &val)
523 gcc_checking_assert (!val.known_isnan ());
525 // > +INF is outside the range.
526 if (real_isinf (&val.lower_bound (), 0))
528 if (HONOR_NANS (type))
529 r.set_nan (type);
530 else
531 r.set_undefined ();
532 return false;
535 REAL_VALUE_TYPE inf = frange_val_max (type);
536 REAL_VALUE_TYPE next = val.lower_bound ();
537 machine_mode mode = TYPE_MODE (type);
538 // Default to the conservatively correct closed ranges for
539 // MODE_COMPOSITE_P, otherwise use nextafter. Note that for
540 // !HONOR_INFINITIES, nextafter will yield +INF, but frange::set()
541 // will crop the range appropriately.
542 if (!MODE_COMPOSITE_P (mode))
543 frange_nextafter (mode, next, inf);
544 r.set (type, next, inf);
545 return true;
549 class foperator_identity : public range_operator_float
551 using range_operator_float::fold_range;
552 using range_operator_float::op1_range;
553 public:
554 bool fold_range (frange &r, tree type ATTRIBUTE_UNUSED,
555 const frange &op1, const frange &op2 ATTRIBUTE_UNUSED,
556 relation_trio = TRIO_VARYING) const final override
558 r = op1;
559 return true;
561 bool op1_range (frange &r, tree type ATTRIBUTE_UNUSED,
562 const frange &lhs, const frange &op2 ATTRIBUTE_UNUSED,
563 relation_trio = TRIO_VARYING) const final override
565 r = lhs;
566 return true;
568 public:
569 } fop_identity;
571 class foperator_equal : public range_operator_float
573 using range_operator_float::fold_range;
574 using range_operator_float::op1_range;
575 using range_operator_float::op2_range;
576 using range_operator_float::op1_op2_relation;
577 public:
578 bool fold_range (irange &r, tree type,
579 const frange &op1, const frange &op2,
580 relation_trio = TRIO_VARYING) const final override;
581 relation_kind op1_op2_relation (const irange &lhs) const final override
583 return equal_op1_op2_relation (lhs);
585 bool op1_range (frange &r, tree type,
586 const irange &lhs, const frange &op2,
587 relation_trio = TRIO_VARYING) const final override;
588 bool op2_range (frange &r, tree type,
589 const irange &lhs, const frange &op1,
590 relation_trio rel = TRIO_VARYING) const final override
592 return op1_range (r, type, lhs, op1, rel.swap_op1_op2 ());
594 } fop_equal;
596 bool
597 foperator_equal::fold_range (irange &r, tree type,
598 const frange &op1, const frange &op2,
599 relation_trio rel) const
601 if (frelop_early_resolve (r, type, op1, op2, rel, VREL_EQ))
602 return true;
604 if (op1.known_isnan () || op2.known_isnan ())
605 r = range_false (type);
606 // We can be sure the values are always equal or not if both ranges
607 // consist of a single value, and then compare them.
608 else if (op1.singleton_p () && op2.singleton_p ())
610 if (op1 == op2)
611 r = range_true (type);
612 // If one operand is -0.0 and other 0.0, they are still equal.
613 else if (real_iszero (&op1.lower_bound ())
614 && real_iszero (&op2.lower_bound ()))
615 r = range_true (type);
616 else
617 r = range_false (type);
619 else if (real_iszero (&op1.lower_bound ())
620 && real_iszero (&op1.upper_bound ())
621 && real_iszero (&op2.lower_bound ())
622 && real_iszero (&op2.upper_bound ())
623 && !maybe_isnan (op1, op2))
624 // [-0.0, 0.0] == [-0.0, 0.0] or similar.
625 r = range_true (type);
626 else
628 // If ranges do not intersect, we know the range is not equal,
629 // otherwise we don't know anything for sure.
630 frange tmp = op1;
631 tmp.intersect (op2);
632 if (tmp.undefined_p ())
634 // If one range is [whatever, -0.0] and another
635 // [0.0, whatever2], we don't know anything either,
636 // because -0.0 == 0.0.
637 if ((real_iszero (&op1.upper_bound ())
638 && real_iszero (&op2.lower_bound ()))
639 || (real_iszero (&op1.lower_bound ())
640 && real_iszero (&op2.upper_bound ())))
641 r = range_true_and_false (type);
642 else
643 r = range_false (type);
645 else
646 r = range_true_and_false (type);
648 return true;
651 bool
652 foperator_equal::op1_range (frange &r, tree type,
653 const irange &lhs,
654 const frange &op2,
655 relation_trio trio) const
657 relation_kind rel = trio.op1_op2 ();
658 switch (get_bool_state (r, lhs, type))
660 case BRS_TRUE:
661 // The TRUE side of x == NAN is unreachable.
662 if (op2.known_isnan ())
663 r.set_undefined ();
664 else
666 // If it's true, the result is the same as OP2.
667 r = op2;
668 // Add both zeros if there's the possibility of zero equality.
669 frange_add_zeros (r, type);
670 // The TRUE side of op1 == op2 implies op1 is !NAN.
671 r.clear_nan ();
673 break;
675 case BRS_FALSE:
676 // The FALSE side of op1 == op1 implies op1 is a NAN.
677 if (rel == VREL_EQ)
678 r.set_nan (type);
679 // On the FALSE side of x == NAN, we know nothing about x.
680 else if (op2.known_isnan ())
681 r.set_varying (type);
682 // If the result is false, the only time we know anything is
683 // if OP2 is a constant.
684 else if (op2.singleton_p ()
685 || (!op2.maybe_isnan () && op2.zero_p ()))
687 REAL_VALUE_TYPE tmp = op2.lower_bound ();
688 r.set (type, tmp, tmp, VR_ANTI_RANGE);
690 else
691 r.set_varying (type);
692 break;
694 default:
695 break;
697 return true;
700 class foperator_not_equal : public range_operator_float
702 using range_operator_float::fold_range;
703 using range_operator_float::op1_range;
704 using range_operator_float::op1_op2_relation;
705 public:
706 bool fold_range (irange &r, tree type,
707 const frange &op1, const frange &op2,
708 relation_trio rel = TRIO_VARYING) const final override;
709 relation_kind op1_op2_relation (const irange &lhs) const final override
711 return not_equal_op1_op2_relation (lhs);
713 bool op1_range (frange &r, tree type,
714 const irange &lhs, const frange &op2,
715 relation_trio = TRIO_VARYING) const final override;
716 } fop_not_equal;
718 bool
719 foperator_not_equal::fold_range (irange &r, tree type,
720 const frange &op1, const frange &op2,
721 relation_trio rel) const
723 if (frelop_early_resolve (r, type, op1, op2, rel, VREL_NE))
724 return true;
726 // x != NAN is always TRUE.
727 if (op1.known_isnan () || op2.known_isnan ())
728 r = range_true (type);
729 // We can be sure the values are always equal or not if both ranges
730 // consist of a single value, and then compare them.
731 else if (op1.singleton_p () && op2.singleton_p ())
733 if (op1 == op2)
734 r = range_false (type);
735 // If one operand is -0.0 and other 0.0, they are still equal.
736 else if (real_iszero (&op1.lower_bound ())
737 && real_iszero (&op2.lower_bound ()))
738 r = range_false (type);
739 else
740 r = range_true (type);
742 else if (real_iszero (&op1.lower_bound ())
743 && real_iszero (&op1.upper_bound ())
744 && real_iszero (&op2.lower_bound ())
745 && real_iszero (&op2.upper_bound ())
746 && !maybe_isnan (op1, op2))
747 // [-0.0, 0.0] != [-0.0, 0.0] or similar.
748 r = range_false (type);
749 else
751 // If ranges do not intersect, we know the range is not equal,
752 // otherwise we don't know anything for sure.
753 frange tmp = op1;
754 tmp.intersect (op2);
755 if (tmp.undefined_p ())
757 // If one range is [whatever, -0.0] and another
758 // [0.0, whatever2], we don't know anything either,
759 // because -0.0 == 0.0.
760 if ((real_iszero (&op1.upper_bound ())
761 && real_iszero (&op2.lower_bound ()))
762 || (real_iszero (&op1.lower_bound ())
763 && real_iszero (&op2.upper_bound ())))
764 r = range_true_and_false (type);
765 else
766 r = range_true (type);
768 else
769 r = range_true_and_false (type);
771 return true;
774 bool
775 foperator_not_equal::op1_range (frange &r, tree type,
776 const irange &lhs,
777 const frange &op2,
778 relation_trio trio) const
780 relation_kind rel = trio.op1_op2 ();
781 switch (get_bool_state (r, lhs, type))
783 case BRS_TRUE:
784 // If the result is true, the only time we know anything is if
785 // OP2 is a constant.
786 if (op2.singleton_p ())
788 // This is correct even if op1 is NAN, because the following
789 // range would be ~[tmp, tmp] with the NAN property set to
790 // maybe (VARYING).
791 REAL_VALUE_TYPE tmp = op2.lower_bound ();
792 r.set (type, tmp, tmp, VR_ANTI_RANGE);
794 // The TRUE side of op1 != op1 implies op1 is NAN.
795 else if (rel == VREL_EQ)
796 r.set_nan (type);
797 else
798 r.set_varying (type);
799 break;
801 case BRS_FALSE:
802 // The FALSE side of x != NAN is impossible.
803 if (op2.known_isnan ())
804 r.set_undefined ();
805 else
807 // If it's false, the result is the same as OP2.
808 r = op2;
809 // Add both zeros if there's the possibility of zero equality.
810 frange_add_zeros (r, type);
811 // The FALSE side of op1 != op2 implies op1 is !NAN.
812 r.clear_nan ();
814 break;
816 default:
817 break;
819 return true;
822 class foperator_lt : public range_operator_float
824 using range_operator_float::fold_range;
825 using range_operator_float::op1_range;
826 using range_operator_float::op2_range;
827 using range_operator_float::op1_op2_relation;
828 public:
829 bool fold_range (irange &r, tree type,
830 const frange &op1, const frange &op2,
831 relation_trio = TRIO_VARYING) const final override;
832 relation_kind op1_op2_relation (const irange &lhs) const final override
834 return lt_op1_op2_relation (lhs);
836 bool op1_range (frange &r, tree type,
837 const irange &lhs, const frange &op2,
838 relation_trio = TRIO_VARYING) const final override;
839 bool op2_range (frange &r, tree type,
840 const irange &lhs, const frange &op1,
841 relation_trio = TRIO_VARYING) const final override;
842 } fop_lt;
844 bool
845 foperator_lt::fold_range (irange &r, tree type,
846 const frange &op1, const frange &op2,
847 relation_trio rel) const
849 if (frelop_early_resolve (r, type, op1, op2, rel, VREL_LT))
850 return true;
852 if (op1.known_isnan ()
853 || op2.known_isnan ()
854 || !real_less (&op1.lower_bound (), &op2.upper_bound ()))
855 r = range_false (type);
856 else if (!maybe_isnan (op1, op2)
857 && real_less (&op1.upper_bound (), &op2.lower_bound ()))
858 r = range_true (type);
859 else
860 r = range_true_and_false (type);
861 return true;
864 bool
865 foperator_lt::op1_range (frange &r,
866 tree type,
867 const irange &lhs,
868 const frange &op2,
869 relation_trio) const
871 switch (get_bool_state (r, lhs, type))
873 case BRS_TRUE:
874 // The TRUE side of x < NAN is unreachable.
875 if (op2.known_isnan ())
876 r.set_undefined ();
877 else if (op2.undefined_p ())
878 return false;
879 else if (build_lt (r, type, op2))
881 r.clear_nan ();
882 // x < y implies x is not +INF.
883 frange_drop_inf (r, type);
885 break;
887 case BRS_FALSE:
888 // On the FALSE side of x < NAN, we know nothing about x.
889 if (op2.known_isnan () || op2.maybe_isnan ())
890 r.set_varying (type);
891 else
892 build_ge (r, type, op2);
893 break;
895 default:
896 break;
898 return true;
901 bool
902 foperator_lt::op2_range (frange &r,
903 tree type,
904 const irange &lhs,
905 const frange &op1,
906 relation_trio) const
908 switch (get_bool_state (r, lhs, type))
910 case BRS_TRUE:
911 // The TRUE side of NAN < x is unreachable.
912 if (op1.known_isnan ())
913 r.set_undefined ();
914 else if (op1.undefined_p ())
915 return false;
916 else if (build_gt (r, type, op1))
918 r.clear_nan ();
919 // x < y implies y is not -INF.
920 frange_drop_ninf (r, type);
922 break;
924 case BRS_FALSE:
925 // On the FALSE side of NAN < x, we know nothing about x.
926 if (op1.known_isnan () || op1.maybe_isnan ())
927 r.set_varying (type);
928 else
929 build_le (r, type, op1);
930 break;
932 default:
933 break;
935 return true;
938 class foperator_le : public range_operator_float
940 using range_operator_float::fold_range;
941 using range_operator_float::op1_range;
942 using range_operator_float::op2_range;
943 using range_operator_float::op1_op2_relation;
944 public:
945 bool fold_range (irange &r, tree type,
946 const frange &op1, const frange &op2,
947 relation_trio rel = TRIO_VARYING) const final override;
948 relation_kind op1_op2_relation (const irange &lhs) const final override
950 return le_op1_op2_relation (lhs);
952 bool op1_range (frange &r, tree type,
953 const irange &lhs, const frange &op2,
954 relation_trio rel = TRIO_VARYING) const final override;
955 bool op2_range (frange &r, tree type,
956 const irange &lhs, const frange &op1,
957 relation_trio rel = TRIO_VARYING) const final override;
958 } fop_le;
960 bool
961 foperator_le::fold_range (irange &r, tree type,
962 const frange &op1, const frange &op2,
963 relation_trio rel) const
965 if (frelop_early_resolve (r, type, op1, op2, rel, VREL_LE))
966 return true;
968 if (op1.known_isnan ()
969 || op2.known_isnan ()
970 || !real_compare (LE_EXPR, &op1.lower_bound (), &op2.upper_bound ()))
971 r = range_false (type);
972 else if (!maybe_isnan (op1, op2)
973 && real_compare (LE_EXPR, &op1.upper_bound (), &op2.lower_bound ()))
974 r = range_true (type);
975 else
976 r = range_true_and_false (type);
977 return true;
980 bool
981 foperator_le::op1_range (frange &r,
982 tree type,
983 const irange &lhs,
984 const frange &op2,
985 relation_trio) const
987 switch (get_bool_state (r, lhs, type))
989 case BRS_TRUE:
990 // The TRUE side of x <= NAN is unreachable.
991 if (op2.known_isnan ())
992 r.set_undefined ();
993 else if (op2.undefined_p ())
994 return false;
995 else if (build_le (r, type, op2))
996 r.clear_nan ();
997 break;
999 case BRS_FALSE:
1000 // On the FALSE side of x <= NAN, we know nothing about x.
1001 if (op2.known_isnan () || op2.maybe_isnan ())
1002 r.set_varying (type);
1003 else
1004 build_gt (r, type, op2);
1005 break;
1007 default:
1008 break;
1010 return true;
1013 bool
1014 foperator_le::op2_range (frange &r,
1015 tree type,
1016 const irange &lhs,
1017 const frange &op1,
1018 relation_trio) const
1020 switch (get_bool_state (r, lhs, type))
1022 case BRS_TRUE:
1023 // The TRUE side of NAN <= x is unreachable.
1024 if (op1.known_isnan ())
1025 r.set_undefined ();
1026 else if (op1.undefined_p ())
1027 return false;
1028 else if (build_ge (r, type, op1))
1029 r.clear_nan ();
1030 break;
1032 case BRS_FALSE:
1033 // On the FALSE side of NAN <= x, we know nothing about x.
1034 if (op1.known_isnan () || op1.maybe_isnan ())
1035 r.set_varying (type);
1036 else if (op1.undefined_p ())
1037 return false;
1038 else
1039 build_lt (r, type, op1);
1040 break;
1042 default:
1043 break;
1045 return true;
1048 class foperator_gt : public range_operator_float
1050 using range_operator_float::fold_range;
1051 using range_operator_float::op1_range;
1052 using range_operator_float::op2_range;
1053 using range_operator_float::op1_op2_relation;
1054 public:
1055 bool fold_range (irange &r, tree type,
1056 const frange &op1, const frange &op2,
1057 relation_trio = TRIO_VARYING) const final override;
1058 relation_kind op1_op2_relation (const irange &lhs) const final override
1060 return gt_op1_op2_relation (lhs);
1062 bool op1_range (frange &r, tree type,
1063 const irange &lhs, const frange &op2,
1064 relation_trio = TRIO_VARYING) const final override;
1065 bool op2_range (frange &r, tree type,
1066 const irange &lhs, const frange &op1,
1067 relation_trio = TRIO_VARYING) const final override;
1068 } fop_gt;
1070 bool
1071 foperator_gt::fold_range (irange &r, tree type,
1072 const frange &op1, const frange &op2,
1073 relation_trio rel) const
1075 if (frelop_early_resolve (r, type, op1, op2, rel, VREL_GT))
1076 return true;
1078 if (op1.known_isnan ()
1079 || op2.known_isnan ()
1080 || !real_compare (GT_EXPR, &op1.upper_bound (), &op2.lower_bound ()))
1081 r = range_false (type);
1082 else if (!maybe_isnan (op1, op2)
1083 && real_compare (GT_EXPR, &op1.lower_bound (), &op2.upper_bound ()))
1084 r = range_true (type);
1085 else
1086 r = range_true_and_false (type);
1087 return true;
1090 bool
1091 foperator_gt::op1_range (frange &r,
1092 tree type,
1093 const irange &lhs,
1094 const frange &op2,
1095 relation_trio) const
1097 switch (get_bool_state (r, lhs, type))
1099 case BRS_TRUE:
1100 // The TRUE side of x > NAN is unreachable.
1101 if (op2.known_isnan ())
1102 r.set_undefined ();
1103 else if (op2.undefined_p ())
1104 return false;
1105 else if (build_gt (r, type, op2))
1107 r.clear_nan ();
1108 // x > y implies x is not -INF.
1109 frange_drop_ninf (r, type);
1111 break;
1113 case BRS_FALSE:
1114 // On the FALSE side of x > NAN, we know nothing about x.
1115 if (op2.known_isnan () || op2.maybe_isnan ())
1116 r.set_varying (type);
1117 else if (op2.undefined_p ())
1118 return false;
1119 else
1120 build_le (r, type, op2);
1121 break;
1123 default:
1124 break;
1126 return true;
1129 bool
1130 foperator_gt::op2_range (frange &r,
1131 tree type,
1132 const irange &lhs,
1133 const frange &op1,
1134 relation_trio) const
1136 switch (get_bool_state (r, lhs, type))
1138 case BRS_TRUE:
1139 // The TRUE side of NAN > x is unreachable.
1140 if (op1.known_isnan ())
1141 r.set_undefined ();
1142 else if (op1.undefined_p ())
1143 return false;
1144 else if (build_lt (r, type, op1))
1146 r.clear_nan ();
1147 // x > y implies y is not +INF.
1148 frange_drop_inf (r, type);
1150 break;
1152 case BRS_FALSE:
1153 // On The FALSE side of NAN > x, we know nothing about x.
1154 if (op1.known_isnan () || op1.maybe_isnan ())
1155 r.set_varying (type);
1156 else if (op1.undefined_p ())
1157 return false;
1158 else
1159 build_ge (r, type, op1);
1160 break;
1162 default:
1163 break;
1165 return true;
1168 class foperator_ge : public range_operator_float
1170 using range_operator_float::fold_range;
1171 using range_operator_float::op1_range;
1172 using range_operator_float::op2_range;
1173 using range_operator_float::op1_op2_relation;
1174 public:
1175 bool fold_range (irange &r, tree type,
1176 const frange &op1, const frange &op2,
1177 relation_trio = TRIO_VARYING) const final override;
1178 relation_kind op1_op2_relation (const irange &lhs) const final override
1180 return ge_op1_op2_relation (lhs);
1182 bool op1_range (frange &r, tree type,
1183 const irange &lhs, const frange &op2,
1184 relation_trio = TRIO_VARYING) const final override;
1185 bool op2_range (frange &r, tree type,
1186 const irange &lhs, const frange &op1,
1187 relation_trio = TRIO_VARYING) const final override;
1188 } fop_ge;
1190 bool
1191 foperator_ge::fold_range (irange &r, tree type,
1192 const frange &op1, const frange &op2,
1193 relation_trio rel) const
1195 if (frelop_early_resolve (r, type, op1, op2, rel, VREL_GE))
1196 return true;
1198 if (op1.known_isnan ()
1199 || op2.known_isnan ()
1200 || !real_compare (GE_EXPR, &op1.upper_bound (), &op2.lower_bound ()))
1201 r = range_false (type);
1202 else if (!maybe_isnan (op1, op2)
1203 && real_compare (GE_EXPR, &op1.lower_bound (), &op2.upper_bound ()))
1204 r = range_true (type);
1205 else
1206 r = range_true_and_false (type);
1207 return true;
1210 bool
1211 foperator_ge::op1_range (frange &r,
1212 tree type,
1213 const irange &lhs,
1214 const frange &op2,
1215 relation_trio) const
1217 switch (get_bool_state (r, lhs, type))
1219 case BRS_TRUE:
1220 // The TRUE side of x >= NAN is unreachable.
1221 if (op2.known_isnan ())
1222 r.set_undefined ();
1223 else if (op2.undefined_p ())
1224 return false;
1225 else if (build_ge (r, type, op2))
1226 r.clear_nan ();
1227 break;
1229 case BRS_FALSE:
1230 // On the FALSE side of x >= NAN, we know nothing about x.
1231 if (op2.known_isnan () || op2.maybe_isnan ())
1232 r.set_varying (type);
1233 else if (op2.undefined_p ())
1234 return false;
1235 else
1236 build_lt (r, type, op2);
1237 break;
1239 default:
1240 break;
1242 return true;
1245 bool
1246 foperator_ge::op2_range (frange &r, tree type,
1247 const irange &lhs,
1248 const frange &op1,
1249 relation_trio) const
1251 switch (get_bool_state (r, lhs, type))
1253 case BRS_TRUE:
1254 // The TRUE side of NAN >= x is unreachable.
1255 if (op1.known_isnan ())
1256 r.set_undefined ();
1257 else if (op1.undefined_p ())
1258 return false;
1259 else if (build_le (r, type, op1))
1260 r.clear_nan ();
1261 break;
1263 case BRS_FALSE:
1264 // On the FALSE side of NAN >= x, we know nothing about x.
1265 if (op1.known_isnan () || op1.maybe_isnan ())
1266 r.set_varying (type);
1267 else if (op1.undefined_p ())
1268 return false;
1269 else
1270 build_gt (r, type, op1);
1271 break;
1273 default:
1274 break;
1276 return true;
1279 // UNORDERED_EXPR comparison.
1281 class foperator_unordered : public range_operator_float
1283 using range_operator_float::fold_range;
1284 using range_operator_float::op1_range;
1285 using range_operator_float::op2_range;
1286 public:
1287 bool fold_range (irange &r, tree type,
1288 const frange &op1, const frange &op2,
1289 relation_trio = TRIO_VARYING) const final override;
1290 bool op1_range (frange &r, tree type,
1291 const irange &lhs, const frange &op2,
1292 relation_trio = TRIO_VARYING) const final override;
1293 bool op2_range (frange &r, tree type,
1294 const irange &lhs, const frange &op1,
1295 relation_trio rel = TRIO_VARYING) const final override
1297 return op1_range (r, type, lhs, op1, rel.swap_op1_op2 ());
1299 } fop_unordered;
1301 bool
1302 foperator_unordered::fold_range (irange &r, tree type,
1303 const frange &op1, const frange &op2,
1304 relation_trio) const
1306 // UNORDERED is TRUE if either operand is a NAN.
1307 if (op1.known_isnan () || op2.known_isnan ())
1308 r = range_true (type);
1309 // UNORDERED is FALSE if neither operand is a NAN.
1310 else if (!op1.maybe_isnan () && !op2.maybe_isnan ())
1311 r = range_false (type);
1312 else
1313 r = range_true_and_false (type);
1314 return true;
1317 bool
1318 foperator_unordered::op1_range (frange &r, tree type,
1319 const irange &lhs,
1320 const frange &op2,
1321 relation_trio trio) const
1323 relation_kind rel = trio.op1_op2 ();
1324 switch (get_bool_state (r, lhs, type))
1326 case BRS_TRUE:
1327 // Since at least one operand must be NAN, if one of them is
1328 // not, the other must be.
1329 if (rel == VREL_EQ || !op2.maybe_isnan ())
1330 r.set_nan (type);
1331 else
1332 r.set_varying (type);
1333 break;
1335 case BRS_FALSE:
1336 // A false UNORDERED means both operands are !NAN, so it's
1337 // impossible for op2 to be a NAN.
1338 if (op2.known_isnan ())
1339 r.set_undefined ();
1340 else
1342 r.set_varying (type);
1343 r.clear_nan ();
1345 break;
1347 default:
1348 break;
1350 return true;
1353 // ORDERED_EXPR comparison.
1355 class foperator_ordered : public range_operator_float
1357 using range_operator_float::fold_range;
1358 using range_operator_float::op1_range;
1359 using range_operator_float::op2_range;
1360 public:
1361 bool fold_range (irange &r, tree type,
1362 const frange &op1, const frange &op2,
1363 relation_trio = TRIO_VARYING) const final override;
1364 bool op1_range (frange &r, tree type,
1365 const irange &lhs, const frange &op2,
1366 relation_trio = TRIO_VARYING) const final override;
1367 bool op2_range (frange &r, tree type,
1368 const irange &lhs, const frange &op1,
1369 relation_trio rel = TRIO_VARYING) const final override
1371 return op1_range (r, type, lhs, op1, rel.swap_op1_op2 ());
1373 } fop_ordered;
1375 bool
1376 foperator_ordered::fold_range (irange &r, tree type,
1377 const frange &op1, const frange &op2,
1378 relation_trio) const
1380 if (op1.known_isnan () || op2.known_isnan ())
1381 r = range_false (type);
1382 else if (!op1.maybe_isnan () && !op2.maybe_isnan ())
1383 r = range_true (type);
1384 else
1385 r = range_true_and_false (type);
1386 return true;
1389 bool
1390 foperator_ordered::op1_range (frange &r, tree type,
1391 const irange &lhs,
1392 const frange &op2,
1393 relation_trio trio) const
1395 relation_kind rel = trio.op1_op2 ();
1396 switch (get_bool_state (r, lhs, type))
1398 case BRS_TRUE:
1399 // The TRUE side of ORDERED means both operands are !NAN, so
1400 // it's impossible for op2 to be a NAN.
1401 if (op2.known_isnan ())
1402 r.set_undefined ();
1403 else
1405 r.set_varying (type);
1406 r.clear_nan ();
1408 break;
1410 case BRS_FALSE:
1411 // The FALSE side of op1 ORDERED op1 implies op1 is NAN.
1412 if (rel == VREL_EQ)
1413 r.set_nan (type);
1414 else
1415 r.set_varying (type);
1416 break;
1418 default:
1419 break;
1421 return true;
1424 class foperator_negate : public range_operator_float
1426 using range_operator_float::fold_range;
1427 using range_operator_float::op1_range;
1428 public:
1429 bool fold_range (frange &r, tree type,
1430 const frange &op1, const frange &op2,
1431 relation_trio = TRIO_VARYING) const final override
1433 if (empty_range_varying (r, type, op1, op2))
1434 return true;
1435 if (op1.known_isnan ())
1437 bool sign;
1438 if (op1.nan_signbit_p (sign))
1439 r.set_nan (type, !sign);
1440 else
1441 r.set_nan (type);
1442 return true;
1445 REAL_VALUE_TYPE lh_lb = op1.lower_bound ();
1446 REAL_VALUE_TYPE lh_ub = op1.upper_bound ();
1447 lh_lb = real_value_negate (&lh_lb);
1448 lh_ub = real_value_negate (&lh_ub);
1449 r.set (type, lh_ub, lh_lb);
1450 if (op1.maybe_isnan ())
1452 bool sign;
1453 if (op1.nan_signbit_p (sign))
1454 r.update_nan (!sign);
1455 else
1456 r.update_nan ();
1458 else
1459 r.clear_nan ();
1460 return true;
1462 bool op1_range (frange &r, tree type,
1463 const frange &lhs, const frange &op2,
1464 relation_trio rel = TRIO_VARYING) const final override
1466 return fold_range (r, type, lhs, op2, rel);
1468 } fop_negate;
1470 class foperator_abs : public range_operator_float
1472 using range_operator_float::fold_range;
1473 using range_operator_float::op1_range;
1474 public:
1475 bool fold_range (frange &r, tree type,
1476 const frange &op1, const frange &,
1477 relation_trio = TRIO_VARYING) const final override;
1478 bool op1_range (frange &r, tree type,
1479 const frange &lhs, const frange &op2,
1480 relation_trio rel = TRIO_VARYING) const final override;
1481 } fop_abs;
1483 bool
1484 foperator_abs::fold_range (frange &r, tree type,
1485 const frange &op1, const frange &op2,
1486 relation_trio) const
1488 if (empty_range_varying (r, type, op1, op2))
1489 return true;
1490 if (op1.known_isnan ())
1492 r.set_nan (type, /*sign=*/false);
1493 return true;
1496 const REAL_VALUE_TYPE lh_lb = op1.lower_bound ();
1497 const REAL_VALUE_TYPE lh_ub = op1.upper_bound ();
1498 // Handle the easy case where everything is positive.
1499 if (real_compare (GE_EXPR, &lh_lb, &dconst0)
1500 && !real_iszero (&lh_lb, /*sign=*/true)
1501 && !op1.maybe_isnan (/*sign=*/true))
1503 r = op1;
1504 return true;
1507 REAL_VALUE_TYPE min = real_value_abs (&lh_lb);
1508 REAL_VALUE_TYPE max = real_value_abs (&lh_ub);
1509 // If the range contains zero then we know that the minimum value in the
1510 // range will be zero.
1511 if (real_compare (LE_EXPR, &lh_lb, &dconst0)
1512 && real_compare (GE_EXPR, &lh_ub, &dconst0))
1514 if (real_compare (GT_EXPR, &min, &max))
1515 max = min;
1516 min = dconst0;
1518 else
1520 // If the range was reversed, swap MIN and MAX.
1521 if (real_compare (GT_EXPR, &min, &max))
1522 std::swap (min, max);
1525 r.set (type, min, max);
1526 if (op1.maybe_isnan ())
1527 r.update_nan (/*sign=*/false);
1528 else
1529 r.clear_nan ();
1530 return true;
1533 bool
1534 foperator_abs::op1_range (frange &r, tree type,
1535 const frange &lhs, const frange &op2,
1536 relation_trio) const
1538 if (empty_range_varying (r, type, lhs, op2))
1539 return true;
1540 if (lhs.known_isnan ())
1542 r.set_nan (type);
1543 return true;
1546 // Start with the positives because negatives are an impossible result.
1547 frange positives (type, dconst0, frange_val_max (type));
1548 positives.update_nan (/*sign=*/false);
1549 positives.intersect (lhs);
1550 r = positives;
1551 // Add -NAN if relevant.
1552 if (r.maybe_isnan ())
1554 frange neg_nan;
1555 neg_nan.set_nan (type, true);
1556 r.union_ (neg_nan);
1558 if (r.known_isnan () || r.undefined_p ())
1559 return true;
1560 // Then add the negative of each pair:
1561 // ABS(op1) = [5,20] would yield op1 => [-20,-5][5,20].
1562 frange negatives (type, real_value_negate (&positives.upper_bound ()),
1563 real_value_negate (&positives.lower_bound ()));
1564 negatives.clear_nan ();
1565 r.union_ (negatives);
1566 return true;
1569 class foperator_unordered_lt : public range_operator_float
1571 using range_operator_float::fold_range;
1572 using range_operator_float::op1_range;
1573 using range_operator_float::op2_range;
1574 public:
1575 bool fold_range (irange &r, tree type,
1576 const frange &op1, const frange &op2,
1577 relation_trio rel = TRIO_VARYING) const final override
1579 if (op1.known_isnan () || op2.known_isnan ())
1581 r = range_true (type);
1582 return true;
1584 frange op1_no_nan = op1;
1585 frange op2_no_nan = op2;
1586 if (op1.maybe_isnan ())
1587 op1_no_nan.clear_nan ();
1588 if (op2.maybe_isnan ())
1589 op2_no_nan.clear_nan ();
1590 if (!fop_lt.fold_range (r, type, op1_no_nan, op2_no_nan, rel))
1591 return false;
1592 // The result is the same as the ordered version when the
1593 // comparison is true or when the operands cannot be NANs.
1594 if (!maybe_isnan (op1, op2) || r == range_true (type))
1595 return true;
1596 else
1598 r = range_true_and_false (type);
1599 return true;
1602 bool op1_range (frange &r, tree type,
1603 const irange &lhs,
1604 const frange &op2,
1605 relation_trio trio) const final override;
1606 bool op2_range (frange &r, tree type,
1607 const irange &lhs,
1608 const frange &op1,
1609 relation_trio trio) const final override;
1610 } fop_unordered_lt;
1612 bool
1613 foperator_unordered_lt::op1_range (frange &r, tree type,
1614 const irange &lhs,
1615 const frange &op2,
1616 relation_trio) const
1618 switch (get_bool_state (r, lhs, type))
1620 case BRS_TRUE:
1621 if (op2.known_isnan () || op2.maybe_isnan ())
1622 r.set_varying (type);
1623 else if (op2.undefined_p ())
1624 return false;
1625 else
1626 build_lt (r, type, op2);
1627 break;
1629 case BRS_FALSE:
1630 // A false UNORDERED_LT means both operands are !NAN, so it's
1631 // impossible for op2 to be a NAN.
1632 if (op2.known_isnan ())
1633 r.set_undefined ();
1634 else if (op2.undefined_p ())
1635 return false;
1636 else if (build_ge (r, type, op2))
1637 r.clear_nan ();
1638 break;
1640 default:
1641 break;
1643 return true;
1646 bool
1647 foperator_unordered_lt::op2_range (frange &r, tree type,
1648 const irange &lhs,
1649 const frange &op1,
1650 relation_trio) const
1652 switch (get_bool_state (r, lhs, type))
1654 case BRS_TRUE:
1655 if (op1.known_isnan () || op1.maybe_isnan ())
1656 r.set_varying (type);
1657 else if (op1.undefined_p ())
1658 return false;
1659 else
1660 build_gt (r, type, op1);
1661 break;
1663 case BRS_FALSE:
1664 // A false UNORDERED_LT means both operands are !NAN, so it's
1665 // impossible for op1 to be a NAN.
1666 if (op1.known_isnan ())
1667 r.set_undefined ();
1668 else if (op1.undefined_p ())
1669 return false;
1670 else if (build_le (r, type, op1))
1671 r.clear_nan ();
1672 break;
1674 default:
1675 break;
1677 return true;
1680 class foperator_unordered_le : public range_operator_float
1682 using range_operator_float::fold_range;
1683 using range_operator_float::op1_range;
1684 using range_operator_float::op2_range;
1685 public:
1686 bool fold_range (irange &r, tree type,
1687 const frange &op1, const frange &op2,
1688 relation_trio rel = TRIO_VARYING) const final override
1690 if (op1.known_isnan () || op2.known_isnan ())
1692 r = range_true (type);
1693 return true;
1695 frange op1_no_nan = op1;
1696 frange op2_no_nan = op2;
1697 if (op1.maybe_isnan ())
1698 op1_no_nan.clear_nan ();
1699 if (op2.maybe_isnan ())
1700 op2_no_nan.clear_nan ();
1701 if (!fop_le.fold_range (r, type, op1_no_nan, op2_no_nan, rel))
1702 return false;
1703 // The result is the same as the ordered version when the
1704 // comparison is true or when the operands cannot be NANs.
1705 if (!maybe_isnan (op1, op2) || r == range_true (type))
1706 return true;
1707 else
1709 r = range_true_and_false (type);
1710 return true;
1713 bool op1_range (frange &r, tree type,
1714 const irange &lhs, const frange &op2,
1715 relation_trio = TRIO_VARYING) const final override;
1716 bool op2_range (frange &r, tree type,
1717 const irange &lhs, const frange &op1,
1718 relation_trio = TRIO_VARYING) const final override;
1719 } fop_unordered_le;
1721 bool
1722 foperator_unordered_le::op1_range (frange &r, tree type,
1723 const irange &lhs, const frange &op2,
1724 relation_trio) const
1726 switch (get_bool_state (r, lhs, type))
1728 case BRS_TRUE:
1729 if (op2.known_isnan () || op2.maybe_isnan ())
1730 r.set_varying (type);
1731 else if (op2.undefined_p ())
1732 return false;
1733 else
1734 build_le (r, type, op2);
1735 break;
1737 case BRS_FALSE:
1738 // A false UNORDERED_LE means both operands are !NAN, so it's
1739 // impossible for op2 to be a NAN.
1740 if (op2.known_isnan ())
1741 r.set_undefined ();
1742 else if (build_gt (r, type, op2))
1743 r.clear_nan ();
1744 break;
1746 default:
1747 break;
1749 return true;
1752 bool
1753 foperator_unordered_le::op2_range (frange &r,
1754 tree type,
1755 const irange &lhs,
1756 const frange &op1,
1757 relation_trio) const
1759 switch (get_bool_state (r, lhs, type))
1761 case BRS_TRUE:
1762 if (op1.known_isnan () || op1.maybe_isnan ())
1763 r.set_varying (type);
1764 else if (op1.undefined_p ())
1765 return false;
1766 else
1767 build_ge (r, type, op1);
1768 break;
1770 case BRS_FALSE:
1771 // A false UNORDERED_LE means both operands are !NAN, so it's
1772 // impossible for op1 to be a NAN.
1773 if (op1.known_isnan ())
1774 r.set_undefined ();
1775 else if (op1.undefined_p ())
1776 return false;
1777 else if (build_lt (r, type, op1))
1778 r.clear_nan ();
1779 break;
1781 default:
1782 break;
1784 return true;
1787 class foperator_unordered_gt : public range_operator_float
1789 using range_operator_float::fold_range;
1790 using range_operator_float::op1_range;
1791 using range_operator_float::op2_range;
1792 public:
1793 bool fold_range (irange &r, tree type,
1794 const frange &op1, const frange &op2,
1795 relation_trio rel = TRIO_VARYING) const final override
1797 if (op1.known_isnan () || op2.known_isnan ())
1799 r = range_true (type);
1800 return true;
1802 frange op1_no_nan = op1;
1803 frange op2_no_nan = op2;
1804 if (op1.maybe_isnan ())
1805 op1_no_nan.clear_nan ();
1806 if (op2.maybe_isnan ())
1807 op2_no_nan.clear_nan ();
1808 if (!fop_gt.fold_range (r, type, op1_no_nan, op2_no_nan, rel))
1809 return false;
1810 // The result is the same as the ordered version when the
1811 // comparison is true or when the operands cannot be NANs.
1812 if (!maybe_isnan (op1, op2) || r == range_true (type))
1813 return true;
1814 else
1816 r = range_true_and_false (type);
1817 return true;
1820 bool op1_range (frange &r, tree type,
1821 const irange &lhs, const frange &op2,
1822 relation_trio = TRIO_VARYING) const final override;
1823 bool op2_range (frange &r, tree type,
1824 const irange &lhs, const frange &op1,
1825 relation_trio = TRIO_VARYING) const final override;
1826 } fop_unordered_gt;
1828 bool
1829 foperator_unordered_gt::op1_range (frange &r,
1830 tree type,
1831 const irange &lhs,
1832 const frange &op2,
1833 relation_trio) const
1835 switch (get_bool_state (r, lhs, type))
1837 case BRS_TRUE:
1838 if (op2.known_isnan () || op2.maybe_isnan ())
1839 r.set_varying (type);
1840 else if (op2.undefined_p ())
1841 return false;
1842 else
1843 build_gt (r, type, op2);
1844 break;
1846 case BRS_FALSE:
1847 // A false UNORDERED_GT means both operands are !NAN, so it's
1848 // impossible for op2 to be a NAN.
1849 if (op2.known_isnan ())
1850 r.set_undefined ();
1851 else if (op2.undefined_p ())
1852 return false;
1853 else if (build_le (r, type, op2))
1854 r.clear_nan ();
1855 break;
1857 default:
1858 break;
1860 return true;
1863 bool
1864 foperator_unordered_gt::op2_range (frange &r,
1865 tree type,
1866 const irange &lhs,
1867 const frange &op1,
1868 relation_trio) const
1870 switch (get_bool_state (r, lhs, type))
1872 case BRS_TRUE:
1873 if (op1.known_isnan () || op1.maybe_isnan ())
1874 r.set_varying (type);
1875 else if (op1.undefined_p ())
1876 return false;
1877 else
1878 build_lt (r, type, op1);
1879 break;
1881 case BRS_FALSE:
1882 // A false UNORDERED_GT means both operands are !NAN, so it's
1883 // impossible for op1 to be a NAN.
1884 if (op1.known_isnan ())
1885 r.set_undefined ();
1886 else if (op1.undefined_p ())
1887 return false;
1888 else if (build_ge (r, type, op1))
1889 r.clear_nan ();
1890 break;
1892 default:
1893 break;
1895 return true;
1898 class foperator_unordered_ge : public range_operator_float
1900 using range_operator_float::fold_range;
1901 using range_operator_float::op1_range;
1902 using range_operator_float::op2_range;
1903 public:
1904 bool fold_range (irange &r, tree type,
1905 const frange &op1, const frange &op2,
1906 relation_trio rel = TRIO_VARYING) const final override
1908 if (op1.known_isnan () || op2.known_isnan ())
1910 r = range_true (type);
1911 return true;
1913 frange op1_no_nan = op1;
1914 frange op2_no_nan = op2;
1915 if (op1.maybe_isnan ())
1916 op1_no_nan.clear_nan ();
1917 if (op2.maybe_isnan ())
1918 op2_no_nan.clear_nan ();
1919 if (!fop_ge.fold_range (r, type, op1_no_nan, op2_no_nan, rel))
1920 return false;
1921 // The result is the same as the ordered version when the
1922 // comparison is true or when the operands cannot be NANs.
1923 if (!maybe_isnan (op1, op2) || r == range_true (type))
1924 return true;
1925 else
1927 r = range_true_and_false (type);
1928 return true;
1931 bool op1_range (frange &r, tree type,
1932 const irange &lhs, const frange &op2,
1933 relation_trio = TRIO_VARYING) const final override;
1934 bool op2_range (frange &r, tree type,
1935 const irange &lhs, const frange &op1,
1936 relation_trio = TRIO_VARYING) const final override;
1937 } fop_unordered_ge;
1939 bool
1940 foperator_unordered_ge::op1_range (frange &r,
1941 tree type,
1942 const irange &lhs,
1943 const frange &op2,
1944 relation_trio) const
1946 switch (get_bool_state (r, lhs, type))
1948 case BRS_TRUE:
1949 if (op2.known_isnan () || op2.maybe_isnan ())
1950 r.set_varying (type);
1951 else if (op2.undefined_p ())
1952 return false;
1953 else
1954 build_ge (r, type, op2);
1955 break;
1957 case BRS_FALSE:
1958 // A false UNORDERED_GE means both operands are !NAN, so it's
1959 // impossible for op2 to be a NAN.
1960 if (op2.known_isnan ())
1961 r.set_undefined ();
1962 else if (op2.undefined_p ())
1963 return false;
1964 else if (build_lt (r, type, op2))
1965 r.clear_nan ();
1966 break;
1968 default:
1969 break;
1971 return true;
1974 bool
1975 foperator_unordered_ge::op2_range (frange &r, tree type,
1976 const irange &lhs,
1977 const frange &op1,
1978 relation_trio) const
1980 switch (get_bool_state (r, lhs, type))
1982 case BRS_TRUE:
1983 if (op1.known_isnan () || op1.maybe_isnan ())
1984 r.set_varying (type);
1985 else if (op1.undefined_p ())
1986 return false;
1987 else
1988 build_le (r, type, op1);
1989 break;
1991 case BRS_FALSE:
1992 // A false UNORDERED_GE means both operands are !NAN, so it's
1993 // impossible for op1 to be a NAN.
1994 if (op1.known_isnan ())
1995 r.set_undefined ();
1996 else if (op1.undefined_p ())
1997 return false;
1998 else if (build_gt (r, type, op1))
1999 r.clear_nan ();
2000 break;
2002 default:
2003 break;
2005 return true;
2008 class foperator_unordered_equal : public range_operator_float
2010 using range_operator_float::fold_range;
2011 using range_operator_float::op1_range;
2012 using range_operator_float::op2_range;
2013 public:
2014 bool fold_range (irange &r, tree type,
2015 const frange &op1, const frange &op2,
2016 relation_trio rel = TRIO_VARYING) const final override
2018 if (op1.known_isnan () || op2.known_isnan ())
2020 r = range_true (type);
2021 return true;
2023 frange op1_no_nan = op1;
2024 frange op2_no_nan = op2;
2025 if (op1.maybe_isnan ())
2026 op1_no_nan.clear_nan ();
2027 if (op2.maybe_isnan ())
2028 op2_no_nan.clear_nan ();
2029 if (!fop_equal.fold_range (r, type, op1_no_nan, op2_no_nan, rel))
2030 return false;
2031 // The result is the same as the ordered version when the
2032 // comparison is true or when the operands cannot be NANs.
2033 if (!maybe_isnan (op1, op2) || r == range_true (type))
2034 return true;
2035 else
2037 r = range_true_and_false (type);
2038 return true;
2041 bool op1_range (frange &r, tree type,
2042 const irange &lhs, const frange &op2,
2043 relation_trio = TRIO_VARYING) const final override;
2044 bool op2_range (frange &r, tree type,
2045 const irange &lhs, const frange &op1,
2046 relation_trio rel = TRIO_VARYING) const final override
2048 return op1_range (r, type, lhs, op1, rel.swap_op1_op2 ());
2050 } fop_unordered_equal;
2052 bool
2053 foperator_unordered_equal::op1_range (frange &r, tree type,
2054 const irange &lhs,
2055 const frange &op2,
2056 relation_trio) const
2058 switch (get_bool_state (r, lhs, type))
2060 case BRS_TRUE:
2061 // If it's true, the result is the same as OP2 plus a NAN.
2062 r = op2;
2063 // Add both zeros if there's the possibility of zero equality.
2064 frange_add_zeros (r, type);
2065 // Add the possibility of a NAN.
2066 r.update_nan ();
2067 break;
2069 case BRS_FALSE:
2070 // A false UNORDERED_EQ means both operands are !NAN, so it's
2071 // impossible for op2 to be a NAN.
2072 if (op2.known_isnan ())
2073 r.set_undefined ();
2074 else
2076 // The false side indicates !NAN and not equal. We can at least
2077 // represent !NAN.
2078 r.set_varying (type);
2079 r.clear_nan ();
2081 break;
2083 default:
2084 break;
2086 return true;
2089 class foperator_ltgt : public range_operator_float
2091 using range_operator_float::fold_range;
2092 using range_operator_float::op1_range;
2093 using range_operator_float::op2_range;
2094 public:
2095 bool fold_range (irange &r, tree type,
2096 const frange &op1, const frange &op2,
2097 relation_trio rel = TRIO_VARYING) const final override
2099 if (op1.known_isnan () || op2.known_isnan ())
2101 r = range_false (type);
2102 return true;
2104 frange op1_no_nan = op1;
2105 frange op2_no_nan = op2;
2106 if (op1.maybe_isnan ())
2107 op1_no_nan.clear_nan ();
2108 if (op2.maybe_isnan ())
2109 op2_no_nan.clear_nan ();
2110 if (!fop_not_equal.fold_range (r, type, op1_no_nan, op2_no_nan, rel))
2111 return false;
2112 // The result is the same as the ordered version when the
2113 // comparison is true or when the operands cannot be NANs.
2114 if (!maybe_isnan (op1, op2) || r == range_false (type))
2115 return true;
2116 else
2118 r = range_true_and_false (type);
2119 return true;
2122 bool op1_range (frange &r, tree type,
2123 const irange &lhs, const frange &op2,
2124 relation_trio = TRIO_VARYING) const final override;
2125 bool op2_range (frange &r, tree type,
2126 const irange &lhs, const frange &op1,
2127 relation_trio rel = TRIO_VARYING) const final override
2129 return op1_range (r, type, lhs, op1, rel.swap_op1_op2 ());
2131 } fop_ltgt;
2133 bool
2134 foperator_ltgt::op1_range (frange &r, tree type,
2135 const irange &lhs,
2136 const frange &op2,
2137 relation_trio) const
2139 switch (get_bool_state (r, lhs, type))
2141 case BRS_TRUE:
2142 // A true LTGT means both operands are !NAN, so it's
2143 // impossible for op2 to be a NAN.
2144 if (op2.known_isnan ())
2145 r.set_undefined ();
2146 else
2148 // The true side indicates !NAN and not equal. We can at least
2149 // represent !NAN.
2150 r.set_varying (type);
2151 r.clear_nan ();
2153 break;
2155 case BRS_FALSE:
2156 // If it's false, the result is the same as OP2 plus a NAN.
2157 r = op2;
2158 // Add both zeros if there's the possibility of zero equality.
2159 frange_add_zeros (r, type);
2160 // Add the possibility of a NAN.
2161 r.update_nan ();
2162 break;
2164 default:
2165 break;
2167 return true;
2170 // Final tweaks for float binary op op1_range/op2_range.
2171 // Return TRUE if the operation is performed and a valid range is available.
2173 static bool
2174 float_binary_op_range_finish (bool ret, frange &r, tree type,
2175 const frange &lhs, bool div_op2 = false)
2177 if (!ret)
2178 return false;
2180 // If we get a known NAN from reverse op, it means either that
2181 // the other operand was known NAN (in that case we know nothing),
2182 // or the reverse operation introduced a known NAN.
2183 // Say for lhs = op1 * op2 if lhs is [-0, +0] and op2 is too,
2184 // 0 / 0 is known NAN. Just punt in that case.
2185 // If NANs aren't honored, we get for 0 / 0 UNDEFINED, so punt as well.
2186 // Or if lhs is a known NAN, we also don't know anything.
2187 if (r.known_isnan () || lhs.known_isnan () || r.undefined_p ())
2189 r.set_varying (type);
2190 return true;
2193 // If lhs isn't NAN, then neither operand could be NAN,
2194 // even if the reverse operation does introduce a maybe_nan.
2195 if (!lhs.maybe_isnan ())
2197 r.clear_nan ();
2198 if (div_op2
2199 ? !(real_compare (LE_EXPR, &lhs.lower_bound (), &dconst0)
2200 && real_compare (GE_EXPR, &lhs.upper_bound (), &dconst0))
2201 : !(real_isinf (&lhs.lower_bound ())
2202 || real_isinf (&lhs.upper_bound ())))
2203 // For reverse + or - or * or op1 of /, if result is finite, then
2204 // r must be finite too, as X + INF or X - INF or X * INF or
2205 // INF / X is always +-INF or NAN. For op2 of /, if result is
2206 // non-zero and not NAN, r must be finite, as X / INF is always
2207 // 0 or NAN.
2208 frange_drop_infs (r, type);
2210 // If lhs is a maybe or known NAN, the operand could be
2211 // NAN.
2212 else
2213 r.update_nan ();
2214 return true;
2217 // True if [lb, ub] is [+-0, +-0].
2218 static bool
2219 zero_p (const REAL_VALUE_TYPE &lb, const REAL_VALUE_TYPE &ub)
2221 return real_iszero (&lb) && real_iszero (&ub);
2224 // True if +0 or -0 is in [lb, ub] range.
2225 static bool
2226 contains_zero_p (const REAL_VALUE_TYPE &lb, const REAL_VALUE_TYPE &ub)
2228 return (real_compare (LE_EXPR, &lb, &dconst0)
2229 && real_compare (GE_EXPR, &ub, &dconst0));
2232 // True if [lb, ub] is [-INF, -INF] or [+INF, +INF].
2233 static bool
2234 singleton_inf_p (const REAL_VALUE_TYPE &lb, const REAL_VALUE_TYPE &ub)
2236 return real_isinf (&lb) && real_isinf (&ub, real_isneg (&lb));
2239 // Return -1 if binary op result must have sign bit set,
2240 // 1 if binary op result must have sign bit clear,
2241 // 0 otherwise.
2242 // Sign bit of binary op result is exclusive or of the
2243 // operand's sign bits.
2244 static int
2245 signbit_known_p (const REAL_VALUE_TYPE &lh_lb, const REAL_VALUE_TYPE &lh_ub,
2246 const REAL_VALUE_TYPE &rh_lb, const REAL_VALUE_TYPE &rh_ub)
2248 if (real_isneg (&lh_lb) == real_isneg (&lh_ub)
2249 && real_isneg (&rh_lb) == real_isneg (&rh_ub))
2251 if (real_isneg (&lh_lb) == real_isneg (&rh_ub))
2252 return 1;
2253 else
2254 return -1;
2256 return 0;
2259 // Set [lb, ub] to [-0, -0], [-0, +0] or [+0, +0] depending on
2260 // signbit_known.
2261 static void
2262 zero_range (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub, int signbit_known)
2264 ub = lb = dconst0;
2265 if (signbit_known <= 0)
2266 lb = real_value_negate (&dconst0);
2267 if (signbit_known < 0)
2268 ub = lb;
2271 // Set [lb, ub] to [-INF, -INF], [-INF, +INF] or [+INF, +INF] depending on
2272 // signbit_known.
2273 static void
2274 inf_range (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub, int signbit_known)
2276 if (signbit_known > 0)
2277 ub = lb = dconstinf;
2278 else if (signbit_known < 0)
2279 ub = lb = dconstninf;
2280 else
2282 lb = dconstninf;
2283 ub = dconstinf;
2287 // Set [lb, ub] to [-INF, -0], [-INF, +INF] or [+0, +INF] depending on
2288 // signbit_known.
2289 static void
2290 zero_to_inf_range (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub, int signbit_known)
2292 if (signbit_known > 0)
2294 lb = dconst0;
2295 ub = dconstinf;
2297 else if (signbit_known < 0)
2299 lb = dconstninf;
2300 ub = real_value_negate (&dconst0);
2302 else
2304 lb = dconstninf;
2305 ub = dconstinf;
2309 /* Extend the LHS range by 1ulp in each direction. For op1_range
2310 or op2_range of binary operations just computing the inverse
2311 operation on ranges isn't sufficient. Consider e.g.
2312 [1., 1.] = op1 + [1., 1.]. op1's range is not [0., 0.], but
2313 [-0x1.0p-54, 0x1.0p-53] (when not -frounding-math), any value for
2314 which adding 1. to it results in 1. after rounding to nearest.
2315 So, for op1_range/op2_range extend the lhs range by 1ulp (or 0.5ulp)
2316 in each direction. See PR109008 for more details. */
2318 static frange
2319 float_widen_lhs_range (tree type, const frange &lhs)
2321 frange ret = lhs;
2322 if (lhs.known_isnan ())
2323 return ret;
2324 REAL_VALUE_TYPE lb = lhs.lower_bound ();
2325 REAL_VALUE_TYPE ub = lhs.upper_bound ();
2326 if (real_isfinite (&lb))
2328 frange_nextafter (TYPE_MODE (type), lb, dconstninf);
2329 if (real_isinf (&lb))
2331 /* For -DBL_MAX, instead of -Inf use
2332 nexttoward (-DBL_MAX, -LDBL_MAX) in a hypothetical
2333 wider type with the same mantissa precision but larger
2334 exponent range; it is outside of range of double values,
2335 but makes it clear it is just one ulp larger rather than
2336 infinite amount larger. */
2337 lb = dconstm1;
2338 SET_REAL_EXP (&lb, FLOAT_MODE_FORMAT (TYPE_MODE (type))->emax + 1);
2340 if (!flag_rounding_math && !MODE_COMPOSITE_P (TYPE_MODE (type)))
2342 /* If not -frounding-math nor IBM double double, actually widen
2343 just by 0.5ulp rather than 1ulp. */
2344 REAL_VALUE_TYPE tem;
2345 real_arithmetic (&tem, PLUS_EXPR, &lhs.lower_bound (), &lb);
2346 real_arithmetic (&lb, RDIV_EXPR, &tem, &dconst2);
2349 if (real_isfinite (&ub))
2351 frange_nextafter (TYPE_MODE (type), ub, dconstinf);
2352 if (real_isinf (&ub))
2354 /* For DBL_MAX similarly. */
2355 ub = dconst1;
2356 SET_REAL_EXP (&ub, FLOAT_MODE_FORMAT (TYPE_MODE (type))->emax + 1);
2358 if (!flag_rounding_math && !MODE_COMPOSITE_P (TYPE_MODE (type)))
2360 /* If not -frounding-math nor IBM double double, actually widen
2361 just by 0.5ulp rather than 1ulp. */
2362 REAL_VALUE_TYPE tem;
2363 real_arithmetic (&tem, PLUS_EXPR, &lhs.upper_bound (), &ub);
2364 real_arithmetic (&ub, RDIV_EXPR, &tem, &dconst2);
2367 /* Temporarily disable -ffinite-math-only, so that frange::set doesn't
2368 reduce the range back to real_min_representable (type) as lower bound
2369 or real_max_representable (type) as upper bound. */
2370 bool save_flag_finite_math_only = flag_finite_math_only;
2371 flag_finite_math_only = false;
2372 ret.set (type, lb, ub, lhs.get_nan_state ());
2373 flag_finite_math_only = save_flag_finite_math_only;
2374 return ret;
2377 class foperator_plus : public range_operator_float
2379 using range_operator_float::op1_range;
2380 using range_operator_float::op2_range;
2381 public:
2382 virtual bool op1_range (frange &r, tree type,
2383 const frange &lhs,
2384 const frange &op2,
2385 relation_trio = TRIO_VARYING) const final override
2387 if (lhs.undefined_p ())
2388 return false;
2389 range_op_handler minus (MINUS_EXPR, type);
2390 if (!minus)
2391 return false;
2392 frange wlhs = float_widen_lhs_range (type, lhs);
2393 return float_binary_op_range_finish (minus.fold_range (r, type, wlhs, op2),
2394 r, type, wlhs);
2396 virtual bool op2_range (frange &r, tree type,
2397 const frange &lhs,
2398 const frange &op1,
2399 relation_trio = TRIO_VARYING) const final override
2401 return op1_range (r, type, lhs, op1);
2403 private:
2404 void rv_fold (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub, bool &maybe_nan,
2405 tree type,
2406 const REAL_VALUE_TYPE &lh_lb,
2407 const REAL_VALUE_TYPE &lh_ub,
2408 const REAL_VALUE_TYPE &rh_lb,
2409 const REAL_VALUE_TYPE &rh_ub,
2410 relation_kind) const final override
2412 frange_arithmetic (PLUS_EXPR, type, lb, lh_lb, rh_lb, dconstninf);
2413 frange_arithmetic (PLUS_EXPR, type, ub, lh_ub, rh_ub, dconstinf);
2415 // [-INF] + [+INF] = NAN
2416 if (real_isinf (&lh_lb, true) && real_isinf (&rh_ub, false))
2417 maybe_nan = true;
2418 // [+INF] + [-INF] = NAN
2419 else if (real_isinf (&lh_ub, false) && real_isinf (&rh_lb, true))
2420 maybe_nan = true;
2421 else
2422 maybe_nan = false;
2424 } fop_plus;
2427 class foperator_minus : public range_operator_float
2429 using range_operator_float::op1_range;
2430 using range_operator_float::op2_range;
2431 public:
2432 virtual bool op1_range (frange &r, tree type,
2433 const frange &lhs,
2434 const frange &op2,
2435 relation_trio = TRIO_VARYING) const final override
2437 if (lhs.undefined_p ())
2438 return false;
2439 frange wlhs = float_widen_lhs_range (type, lhs);
2440 return float_binary_op_range_finish (fop_plus.fold_range (r, type, wlhs,
2441 op2),
2442 r, type, wlhs);
2444 virtual bool op2_range (frange &r, tree type,
2445 const frange &lhs,
2446 const frange &op1,
2447 relation_trio = TRIO_VARYING) const final override
2449 if (lhs.undefined_p ())
2450 return false;
2451 frange wlhs = float_widen_lhs_range (type, lhs);
2452 return float_binary_op_range_finish (fold_range (r, type, op1, wlhs),
2453 r, type, wlhs);
2455 private:
2456 void rv_fold (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub, bool &maybe_nan,
2457 tree type,
2458 const REAL_VALUE_TYPE &lh_lb,
2459 const REAL_VALUE_TYPE &lh_ub,
2460 const REAL_VALUE_TYPE &rh_lb,
2461 const REAL_VALUE_TYPE &rh_ub,
2462 relation_kind) const final override
2464 frange_arithmetic (MINUS_EXPR, type, lb, lh_lb, rh_ub, dconstninf);
2465 frange_arithmetic (MINUS_EXPR, type, ub, lh_ub, rh_lb, dconstinf);
2467 // [+INF] - [+INF] = NAN
2468 if (real_isinf (&lh_ub, false) && real_isinf (&rh_ub, false))
2469 maybe_nan = true;
2470 // [-INF] - [-INF] = NAN
2471 else if (real_isinf (&lh_lb, true) && real_isinf (&rh_lb, true))
2472 maybe_nan = true;
2473 else
2474 maybe_nan = false;
2476 } fop_minus;
2479 class foperator_mult_div_base : public range_operator_float
2481 protected:
2482 // Given CP[0] to CP[3] floating point values rounded to -INF,
2483 // set LB to the smallest of them (treating -0 as smaller to +0).
2484 // Given CP[4] to CP[7] floating point values rounded to +INF,
2485 // set UB to the largest of them (treating -0 as smaller to +0).
2486 static void find_range (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub,
2487 const REAL_VALUE_TYPE (&cp)[8])
2489 lb = cp[0];
2490 ub = cp[4];
2491 for (int i = 1; i < 4; ++i)
2493 if (real_less (&cp[i], &lb)
2494 || (real_iszero (&lb) && real_isnegzero (&cp[i])))
2495 lb = cp[i];
2496 if (real_less (&ub, &cp[i + 4])
2497 || (real_isnegzero (&ub) && real_iszero (&cp[i + 4])))
2498 ub = cp[i + 4];
2504 class foperator_mult : public foperator_mult_div_base
2506 using range_operator_float::op1_range;
2507 using range_operator_float::op2_range;
2508 public:
2509 virtual bool op1_range (frange &r, tree type,
2510 const frange &lhs,
2511 const frange &op2,
2512 relation_trio = TRIO_VARYING) const final override
2514 if (lhs.undefined_p ())
2515 return false;
2516 range_op_handler rdiv (RDIV_EXPR, type);
2517 if (!rdiv)
2518 return false;
2519 frange wlhs = float_widen_lhs_range (type, lhs);
2520 bool ret = rdiv.fold_range (r, type, wlhs, op2);
2521 if (ret == false)
2522 return false;
2523 if (wlhs.known_isnan () || op2.known_isnan () || op2.undefined_p ())
2524 return float_binary_op_range_finish (ret, r, type, wlhs);
2525 const REAL_VALUE_TYPE &lhs_lb = wlhs.lower_bound ();
2526 const REAL_VALUE_TYPE &lhs_ub = wlhs.upper_bound ();
2527 const REAL_VALUE_TYPE &op2_lb = op2.lower_bound ();
2528 const REAL_VALUE_TYPE &op2_ub = op2.upper_bound ();
2529 if ((contains_zero_p (lhs_lb, lhs_ub) && contains_zero_p (op2_lb, op2_ub))
2530 || ((real_isinf (&lhs_lb) || real_isinf (&lhs_ub))
2531 && (real_isinf (&op2_lb) || real_isinf (&op2_ub))))
2533 // If both lhs and op2 could be zeros or both could be infinities,
2534 // we don't know anything about op1 except maybe for the sign
2535 // and perhaps if it can be NAN or not.
2536 REAL_VALUE_TYPE lb, ub;
2537 int signbit_known = signbit_known_p (lhs_lb, lhs_ub, op2_lb, op2_ub);
2538 zero_to_inf_range (lb, ub, signbit_known);
2539 r.set (type, lb, ub);
2541 // Otherwise, if op2 is a singleton INF and lhs doesn't include INF,
2542 // or if lhs must be zero and op2 doesn't include zero, it would be
2543 // UNDEFINED, while rdiv.fold_range computes a zero or singleton INF
2544 // range. Those are supersets of UNDEFINED, so let's keep that way.
2545 return float_binary_op_range_finish (ret, r, type, wlhs);
2547 virtual bool op2_range (frange &r, tree type,
2548 const frange &lhs,
2549 const frange &op1,
2550 relation_trio = TRIO_VARYING) const final override
2552 return op1_range (r, type, lhs, op1);
2554 private:
2555 void rv_fold (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub, bool &maybe_nan,
2556 tree type,
2557 const REAL_VALUE_TYPE &lh_lb,
2558 const REAL_VALUE_TYPE &lh_ub,
2559 const REAL_VALUE_TYPE &rh_lb,
2560 const REAL_VALUE_TYPE &rh_ub,
2561 relation_kind kind) const final override
2563 bool is_square
2564 = (kind == VREL_EQ
2565 && real_equal (&lh_lb, &rh_lb)
2566 && real_equal (&lh_ub, &rh_ub)
2567 && real_isneg (&lh_lb) == real_isneg (&rh_lb)
2568 && real_isneg (&lh_ub) == real_isneg (&rh_ub));
2570 maybe_nan = false;
2571 // x * x never produces a new NAN and we only multiply the same
2572 // values, so the 0 * INF problematic cases never appear there.
2573 if (!is_square)
2575 // [+-0, +-0] * [+INF,+INF] (or [-INF,-INF] or swapped is a known NAN.
2576 if ((zero_p (lh_lb, lh_ub) && singleton_inf_p (rh_lb, rh_ub))
2577 || (zero_p (rh_lb, rh_ub) && singleton_inf_p (lh_lb, lh_ub)))
2579 real_nan (&lb, "", 0, TYPE_MODE (type));
2580 ub = lb;
2581 maybe_nan = true;
2582 return;
2585 // Otherwise, if one range includes zero and the other ends with +-INF,
2586 // it is a maybe NAN.
2587 if ((contains_zero_p (lh_lb, lh_ub)
2588 && (real_isinf (&rh_lb) || real_isinf (&rh_ub)))
2589 || (contains_zero_p (rh_lb, rh_ub)
2590 && (real_isinf (&lh_lb) || real_isinf (&lh_ub))))
2592 maybe_nan = true;
2594 int signbit_known = signbit_known_p (lh_lb, lh_ub, rh_lb, rh_ub);
2596 // If one of the ranges that includes INF is singleton
2597 // and the other range includes zero, the resulting
2598 // range is INF and NAN, because the 0 * INF boundary
2599 // case will be NAN, but already nextafter (0, 1) * INF
2600 // is INF.
2601 if (singleton_inf_p (lh_lb, lh_ub)
2602 || singleton_inf_p (rh_lb, rh_ub))
2603 return inf_range (lb, ub, signbit_known);
2605 // If one of the multiplicands must be zero, the resulting
2606 // range is +-0 and NAN.
2607 if (zero_p (lh_lb, lh_ub) || zero_p (rh_lb, rh_ub))
2608 return zero_range (lb, ub, signbit_known);
2610 // Otherwise one of the multiplicands could be
2611 // [0.0, nextafter (0.0, 1.0)] and the [DBL_MAX, INF]
2612 // or similarly with different signs. 0.0 * DBL_MAX
2613 // is still 0.0, nextafter (0.0, 1.0) * INF is still INF,
2614 // so if the signs are always the same or always different,
2615 // result is [+0.0, +INF] or [-INF, -0.0], otherwise VARYING.
2616 return zero_to_inf_range (lb, ub, signbit_known);
2620 REAL_VALUE_TYPE cp[8];
2621 // Do a cross-product. At this point none of the multiplications
2622 // should produce a NAN.
2623 frange_arithmetic (MULT_EXPR, type, cp[0], lh_lb, rh_lb, dconstninf);
2624 frange_arithmetic (MULT_EXPR, type, cp[4], lh_lb, rh_lb, dconstinf);
2625 if (is_square)
2627 // For x * x we can just do max (lh_lb * lh_lb, lh_ub * lh_ub)
2628 // as maximum and -0.0 as minimum if 0.0 is in the range,
2629 // otherwise min (lh_lb * lh_lb, lh_ub * lh_ub).
2630 // -0.0 rather than 0.0 because VREL_EQ doesn't prove that
2631 // x and y are bitwise equal, just that they compare equal.
2632 if (contains_zero_p (lh_lb, lh_ub))
2634 if (real_isneg (&lh_lb) == real_isneg (&lh_ub))
2635 cp[1] = dconst0;
2636 else
2637 cp[1] = real_value_negate (&dconst0);
2639 else
2640 cp[1] = cp[0];
2641 cp[2] = cp[0];
2642 cp[5] = cp[4];
2643 cp[6] = cp[4];
2645 else
2647 frange_arithmetic (MULT_EXPR, type, cp[1], lh_lb, rh_ub, dconstninf);
2648 frange_arithmetic (MULT_EXPR, type, cp[5], lh_lb, rh_ub, dconstinf);
2649 frange_arithmetic (MULT_EXPR, type, cp[2], lh_ub, rh_lb, dconstninf);
2650 frange_arithmetic (MULT_EXPR, type, cp[6], lh_ub, rh_lb, dconstinf);
2652 frange_arithmetic (MULT_EXPR, type, cp[3], lh_ub, rh_ub, dconstninf);
2653 frange_arithmetic (MULT_EXPR, type, cp[7], lh_ub, rh_ub, dconstinf);
2655 find_range (lb, ub, cp);
2657 } fop_mult;
2660 class foperator_div : public foperator_mult_div_base
2662 using range_operator_float::op1_range;
2663 using range_operator_float::op2_range;
2664 public:
2665 virtual bool op1_range (frange &r, tree type,
2666 const frange &lhs,
2667 const frange &op2,
2668 relation_trio = TRIO_VARYING) const final override
2670 if (lhs.undefined_p ())
2671 return false;
2672 frange wlhs = float_widen_lhs_range (type, lhs);
2673 bool ret = fop_mult.fold_range (r, type, wlhs, op2);
2674 if (!ret)
2675 return ret;
2676 if (wlhs.known_isnan () || op2.known_isnan () || op2.undefined_p ())
2677 return float_binary_op_range_finish (ret, r, type, wlhs);
2678 const REAL_VALUE_TYPE &lhs_lb = wlhs.lower_bound ();
2679 const REAL_VALUE_TYPE &lhs_ub = wlhs.upper_bound ();
2680 const REAL_VALUE_TYPE &op2_lb = op2.lower_bound ();
2681 const REAL_VALUE_TYPE &op2_ub = op2.upper_bound ();
2682 if ((contains_zero_p (lhs_lb, lhs_ub)
2683 && (real_isinf (&op2_lb) || real_isinf (&op2_ub)))
2684 || ((contains_zero_p (op2_lb, op2_ub))
2685 && (real_isinf (&lhs_lb) || real_isinf (&lhs_ub))))
2687 // If both lhs could be zero and op2 infinity or vice versa,
2688 // we don't know anything about op1 except maybe for the sign
2689 // and perhaps if it can be NAN or not.
2690 REAL_VALUE_TYPE lb, ub;
2691 int signbit_known = signbit_known_p (lhs_lb, lhs_ub, op2_lb, op2_ub);
2692 zero_to_inf_range (lb, ub, signbit_known);
2693 r.set (type, lb, ub);
2695 return float_binary_op_range_finish (ret, r, type, wlhs);
2697 virtual bool op2_range (frange &r, tree type,
2698 const frange &lhs,
2699 const frange &op1,
2700 relation_trio = TRIO_VARYING) const final override
2702 if (lhs.undefined_p ())
2703 return false;
2704 frange wlhs = float_widen_lhs_range (type, lhs);
2705 bool ret = fold_range (r, type, op1, wlhs);
2706 if (!ret)
2707 return ret;
2708 if (wlhs.known_isnan () || op1.known_isnan () || op1.undefined_p ())
2709 return float_binary_op_range_finish (ret, r, type, wlhs, true);
2710 const REAL_VALUE_TYPE &lhs_lb = wlhs.lower_bound ();
2711 const REAL_VALUE_TYPE &lhs_ub = wlhs.upper_bound ();
2712 const REAL_VALUE_TYPE &op1_lb = op1.lower_bound ();
2713 const REAL_VALUE_TYPE &op1_ub = op1.upper_bound ();
2714 if ((contains_zero_p (lhs_lb, lhs_ub) && contains_zero_p (op1_lb, op1_ub))
2715 || ((real_isinf (&lhs_lb) || real_isinf (&lhs_ub))
2716 && (real_isinf (&op1_lb) || real_isinf (&op1_ub))))
2718 // If both lhs and op1 could be zeros or both could be infinities,
2719 // we don't know anything about op2 except maybe for the sign
2720 // and perhaps if it can be NAN or not.
2721 REAL_VALUE_TYPE lb, ub;
2722 int signbit_known = signbit_known_p (lhs_lb, lhs_ub, op1_lb, op1_ub);
2723 zero_to_inf_range (lb, ub, signbit_known);
2724 r.set (type, lb, ub);
2726 return float_binary_op_range_finish (ret, r, type, wlhs, true);
2728 private:
2729 void rv_fold (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub, bool &maybe_nan,
2730 tree type,
2731 const REAL_VALUE_TYPE &lh_lb,
2732 const REAL_VALUE_TYPE &lh_ub,
2733 const REAL_VALUE_TYPE &rh_lb,
2734 const REAL_VALUE_TYPE &rh_ub,
2735 relation_kind) const final override
2737 // +-0.0 / +-0.0 or +-INF / +-INF is a known NAN.
2738 if ((zero_p (lh_lb, lh_ub) && zero_p (rh_lb, rh_ub))
2739 || (singleton_inf_p (lh_lb, lh_ub) && singleton_inf_p (rh_lb, rh_ub)))
2741 real_nan (&lb, "", 0, TYPE_MODE (type));
2742 ub = lb;
2743 maybe_nan = true;
2744 return;
2747 // If +-0.0 is in both ranges, it is a maybe NAN.
2748 if (contains_zero_p (lh_lb, lh_ub) && contains_zero_p (rh_lb, rh_ub))
2749 maybe_nan = true;
2750 // If +-INF is in both ranges, it is a maybe NAN.
2751 else if ((real_isinf (&lh_lb) || real_isinf (&lh_ub))
2752 && (real_isinf (&rh_lb) || real_isinf (&rh_ub)))
2753 maybe_nan = true;
2754 else
2755 maybe_nan = false;
2757 int signbit_known = signbit_known_p (lh_lb, lh_ub, rh_lb, rh_ub);
2759 // If dividend must be zero, the range is just +-0
2760 // (including if the divisor is +-INF).
2761 // If divisor must be +-INF, the range is just +-0
2762 // (including if the dividend is zero).
2763 if (zero_p (lh_lb, lh_ub) || singleton_inf_p (rh_lb, rh_ub))
2764 return zero_range (lb, ub, signbit_known);
2766 // If divisor must be zero, the range is just +-INF
2767 // (including if the dividend is +-INF).
2768 // If dividend must be +-INF, the range is just +-INF
2769 // (including if the dividend is zero).
2770 if (zero_p (rh_lb, rh_ub) || singleton_inf_p (lh_lb, lh_ub))
2771 return inf_range (lb, ub, signbit_known);
2773 // Otherwise if both operands may be zero, divisor could be
2774 // nextafter(0.0, +-1.0) and dividend +-0.0
2775 // in which case result is going to INF or vice versa and
2776 // result +0.0. So, all we can say for that case is if the
2777 // signs of divisor and dividend are always the same we have
2778 // [+0.0, +INF], if they are always different we have
2779 // [-INF, -0.0]. If they vary, VARYING.
2780 // If both may be +-INF, divisor could be INF and dividend FLT_MAX,
2781 // in which case result is going to INF or vice versa and
2782 // result +0.0. So, all we can say for that case is if the
2783 // signs of divisor and dividend are always the same we have
2784 // [+0.0, +INF], if they are always different we have
2785 // [-INF, -0.0]. If they vary, VARYING.
2786 if (maybe_nan)
2787 return zero_to_inf_range (lb, ub, signbit_known);
2789 REAL_VALUE_TYPE cp[8];
2790 // Do a cross-division. At this point none of the divisions should
2791 // produce a NAN.
2792 frange_arithmetic (RDIV_EXPR, type, cp[0], lh_lb, rh_lb, dconstninf);
2793 frange_arithmetic (RDIV_EXPR, type, cp[1], lh_lb, rh_ub, dconstninf);
2794 frange_arithmetic (RDIV_EXPR, type, cp[2], lh_ub, rh_lb, dconstninf);
2795 frange_arithmetic (RDIV_EXPR, type, cp[3], lh_ub, rh_ub, dconstninf);
2796 frange_arithmetic (RDIV_EXPR, type, cp[4], lh_lb, rh_lb, dconstinf);
2797 frange_arithmetic (RDIV_EXPR, type, cp[5], lh_lb, rh_ub, dconstinf);
2798 frange_arithmetic (RDIV_EXPR, type, cp[6], lh_ub, rh_lb, dconstinf);
2799 frange_arithmetic (RDIV_EXPR, type, cp[7], lh_ub, rh_ub, dconstinf);
2801 find_range (lb, ub, cp);
2803 // If divisor may be zero (but is not known to be only zero),
2804 // and dividend can't be zero, the range can go up to -INF or +INF
2805 // depending on the signs.
2806 if (contains_zero_p (rh_lb, rh_ub))
2808 if (signbit_known <= 0)
2809 real_inf (&lb, true);
2810 if (signbit_known >= 0)
2811 real_inf (&ub, false);
2814 } fop_div;
2816 // Instantiate a range_op_table for floating point operations.
2817 static floating_op_table global_floating_table;
2819 // Pointer to the float table so the dispatch code can access it.
2820 floating_op_table *floating_tree_table = &global_floating_table;
2822 floating_op_table::floating_op_table ()
2824 set (SSA_NAME, fop_identity);
2825 set (PAREN_EXPR, fop_identity);
2826 set (OBJ_TYPE_REF, fop_identity);
2827 set (REAL_CST, fop_identity);
2829 // All the relational operators are expected to work, because the
2830 // calculation of ranges on outgoing edges expect the handlers to be
2831 // present.
2832 set (EQ_EXPR, fop_equal);
2833 set (NE_EXPR, fop_not_equal);
2834 set (LT_EXPR, fop_lt);
2835 set (LE_EXPR, fop_le);
2836 set (GT_EXPR, fop_gt);
2837 set (GE_EXPR, fop_ge);
2838 set (UNLE_EXPR, fop_unordered_le);
2839 set (UNLT_EXPR, fop_unordered_lt);
2840 set (UNGE_EXPR, fop_unordered_ge);
2841 set (UNGT_EXPR, fop_unordered_gt);
2842 set (UNEQ_EXPR, fop_unordered_equal);
2843 set (ORDERED_EXPR, fop_ordered);
2844 set (UNORDERED_EXPR, fop_unordered);
2845 set (LTGT_EXPR, fop_ltgt);
2847 set (ABS_EXPR, fop_abs);
2848 set (NEGATE_EXPR, fop_negate);
2849 set (PLUS_EXPR, fop_plus);
2850 set (MINUS_EXPR, fop_minus);
2851 set (MULT_EXPR, fop_mult);
2852 set (RDIV_EXPR, fop_div);
2855 // Return a pointer to the range_operator_float instance, if there is
2856 // one associated with tree_code CODE.
2858 range_operator_float *
2859 floating_op_table::operator[] (enum tree_code code)
2861 return m_range_tree[code];
2864 // Add OP to the handler table for CODE.
2866 void
2867 floating_op_table::set (enum tree_code code, range_operator_float &op)
2869 gcc_checking_assert (m_range_tree[code] == NULL);
2870 m_range_tree[code] = &op;
2873 #if CHECKING_P
2874 #include "selftest.h"
2876 namespace selftest
2879 // Build an frange from string endpoints.
2881 inline frange
2882 frange_float (const char *lb, const char *ub, tree type = float_type_node)
2884 REAL_VALUE_TYPE min, max;
2885 gcc_assert (real_from_string (&min, lb) == 0);
2886 gcc_assert (real_from_string (&max, ub) == 0);
2887 return frange (type, min, max);
2890 void
2891 range_op_float_tests ()
2893 frange r, r0, r1;
2894 frange trange (float_type_node);
2896 // negate([-5, +10]) => [-10, 5]
2897 r0 = frange_float ("-5", "10");
2898 fop_negate.fold_range (r, float_type_node, r0, trange);
2899 ASSERT_EQ (r, frange_float ("-10", "5"));
2901 // negate([0, 1] -NAN) => [-1, -0] +NAN
2902 r0 = frange_float ("0", "1");
2903 r0.update_nan (true);
2904 fop_negate.fold_range (r, float_type_node, r0, trange);
2905 r1 = frange_float ("-1", "-0");
2906 r1.update_nan (false);
2907 ASSERT_EQ (r, r1);
2909 // [-INF,+INF] + [-INF,+INF] could be a NAN.
2910 range_op_handler plus (PLUS_EXPR, float_type_node);
2911 r0.set_varying (float_type_node);
2912 r1.set_varying (float_type_node);
2913 r0.clear_nan ();
2914 r1.clear_nan ();
2915 plus.fold_range (r, float_type_node, r0, r1);
2916 if (HONOR_NANS (float_type_node))
2917 ASSERT_TRUE (r.maybe_isnan ());
2920 } // namespace selftest
2922 #endif // CHECKING_P