syscall, runtime: always call XSI strerror_r
[official-gcc.git] / gcc / range-op-float.cc
blobee88511eba0b4b02425c936b38a3406d97426bae
1 /* Floating point range operators.
2 Copyright (C) 2022 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 return true;
97 // For a given operation, fold two sets of ranges into [lb, ub].
98 // MAYBE_NAN is set to TRUE if, in addition to any result in LB or
99 // UB, the final range has the possiblity of a NAN.
100 void
101 range_operator_float::rv_fold (REAL_VALUE_TYPE &lb,
102 REAL_VALUE_TYPE &ub,
103 bool &maybe_nan,
104 tree type ATTRIBUTE_UNUSED,
105 const REAL_VALUE_TYPE &lh_lb ATTRIBUTE_UNUSED,
106 const REAL_VALUE_TYPE &lh_ub ATTRIBUTE_UNUSED,
107 const REAL_VALUE_TYPE &rh_lb ATTRIBUTE_UNUSED,
108 const REAL_VALUE_TYPE &rh_ub ATTRIBUTE_UNUSED,
109 relation_kind) const
111 lb = dconstninf;
112 ub = dconstinf;
113 maybe_nan = true;
116 bool
117 range_operator_float::fold_range (irange &r ATTRIBUTE_UNUSED,
118 tree type ATTRIBUTE_UNUSED,
119 const frange &lh ATTRIBUTE_UNUSED,
120 const irange &rh ATTRIBUTE_UNUSED,
121 relation_trio) const
123 return false;
126 bool
127 range_operator_float::fold_range (irange &r ATTRIBUTE_UNUSED,
128 tree type ATTRIBUTE_UNUSED,
129 const frange &lh ATTRIBUTE_UNUSED,
130 const frange &rh ATTRIBUTE_UNUSED,
131 relation_trio) const
133 return false;
136 bool
137 range_operator_float::op1_range (frange &r ATTRIBUTE_UNUSED,
138 tree type ATTRIBUTE_UNUSED,
139 const frange &lhs ATTRIBUTE_UNUSED,
140 const frange &op2 ATTRIBUTE_UNUSED,
141 relation_trio) const
143 return false;
146 bool
147 range_operator_float::op1_range (frange &r ATTRIBUTE_UNUSED,
148 tree type ATTRIBUTE_UNUSED,
149 const irange &lhs ATTRIBUTE_UNUSED,
150 const frange &op2 ATTRIBUTE_UNUSED,
151 relation_trio) const
153 return false;
156 bool
157 range_operator_float::op2_range (frange &r ATTRIBUTE_UNUSED,
158 tree type ATTRIBUTE_UNUSED,
159 const frange &lhs ATTRIBUTE_UNUSED,
160 const frange &op1 ATTRIBUTE_UNUSED,
161 relation_trio) const
163 return false;
166 bool
167 range_operator_float::op2_range (frange &r ATTRIBUTE_UNUSED,
168 tree type ATTRIBUTE_UNUSED,
169 const irange &lhs ATTRIBUTE_UNUSED,
170 const frange &op1 ATTRIBUTE_UNUSED,
171 relation_trio) const
173 return false;
176 relation_kind
177 range_operator_float::lhs_op1_relation (const frange &lhs ATTRIBUTE_UNUSED,
178 const frange &op1 ATTRIBUTE_UNUSED,
179 const frange &op2 ATTRIBUTE_UNUSED,
180 relation_kind) const
182 return VREL_VARYING;
185 relation_kind
186 range_operator_float::lhs_op1_relation (const irange &lhs ATTRIBUTE_UNUSED,
187 const frange &op1 ATTRIBUTE_UNUSED,
188 const frange &op2 ATTRIBUTE_UNUSED,
189 relation_kind) const
191 return VREL_VARYING;
194 relation_kind
195 range_operator_float::lhs_op2_relation (const irange &lhs ATTRIBUTE_UNUSED,
196 const frange &op1 ATTRIBUTE_UNUSED,
197 const frange &op2 ATTRIBUTE_UNUSED,
198 relation_kind) const
200 return VREL_VARYING;
203 relation_kind
204 range_operator_float::lhs_op2_relation (const frange &lhs ATTRIBUTE_UNUSED,
205 const frange &op1 ATTRIBUTE_UNUSED,
206 const frange &op2 ATTRIBUTE_UNUSED,
207 relation_kind) const
209 return VREL_VARYING;
212 relation_kind
213 range_operator_float::op1_op2_relation (const irange &lhs ATTRIBUTE_UNUSED) const
215 return VREL_VARYING;
218 relation_kind
219 range_operator_float::op1_op2_relation (const frange &lhs ATTRIBUTE_UNUSED) const
221 return VREL_VARYING;
224 // Return TRUE if OP1 and OP2 may be a NAN.
226 static inline bool
227 maybe_isnan (const frange &op1, const frange &op2)
229 return op1.maybe_isnan () || op2.maybe_isnan ();
232 // Floating version of relop_early_resolve that takes into account NAN
233 // and -ffinite-math-only.
235 inline bool
236 frelop_early_resolve (irange &r, tree type,
237 const frange &op1, const frange &op2,
238 relation_trio rel, relation_kind my_rel)
240 // If either operand is undefined, return VARYING.
241 if (empty_range_varying (r, type, op1, op2))
242 return true;
244 // We can fold relations from the oracle when we know both operands
245 // are free of NANs, or when -ffinite-math-only.
246 return (!maybe_isnan (op1, op2)
247 && relop_early_resolve (r, type, op1, op2, rel, my_rel));
250 // Set VALUE to its next real value, or INF if the operation overflows.
252 inline void
253 frange_nextafter (enum machine_mode mode,
254 REAL_VALUE_TYPE &value,
255 const REAL_VALUE_TYPE &inf)
257 const real_format *fmt = REAL_MODE_FORMAT (mode);
258 REAL_VALUE_TYPE tmp;
259 real_nextafter (&tmp, fmt, &value, &inf);
260 value = tmp;
263 // Like real_arithmetic, but round the result to INF if the operation
264 // produced inexact results.
266 // ?? There is still one problematic case, i387. With
267 // -fexcess-precision=standard we perform most SF/DFmode arithmetic in
268 // XFmode (long_double_type_node), so that case is OK. But without
269 // -mfpmath=sse, all the SF/DFmode computations are in XFmode
270 // precision (64-bit mantissa) and only occassionally rounded to
271 // SF/DFmode (when storing into memory from the 387 stack). Maybe
272 // this is ok as well though it is just occassionally more precise. ??
274 static void
275 frange_arithmetic (enum tree_code code, tree type,
276 REAL_VALUE_TYPE &result,
277 const REAL_VALUE_TYPE &op1,
278 const REAL_VALUE_TYPE &op2,
279 const REAL_VALUE_TYPE &inf)
281 REAL_VALUE_TYPE value;
282 enum machine_mode mode = TYPE_MODE (type);
283 bool mode_composite = MODE_COMPOSITE_P (mode);
285 bool inexact = real_arithmetic (&value, code, &op1, &op2);
286 real_convert (&result, mode, &value);
288 // Be extra careful if there may be discrepancies between the
289 // compile and runtime results.
290 if ((mode_composite || (real_isneg (&inf) ? real_less (&result, &value)
291 : !real_less (&value, &result)))
292 && (inexact || !real_identical (&result, &value)))
294 if (mode_composite)
296 if (real_isdenormal (&result, mode)
297 || real_iszero (&result))
299 // IBM extended denormals only have DFmode precision.
300 REAL_VALUE_TYPE tmp;
301 real_convert (&tmp, DFmode, &value);
302 frange_nextafter (DFmode, tmp, inf);
303 real_convert (&result, mode, &tmp);
304 return;
307 frange_nextafter (mode, result, inf);
311 // Crop R to [-INF, MAX] where MAX is the maximum representable number
312 // for TYPE.
314 static inline void
315 frange_drop_inf (frange &r, tree type)
317 REAL_VALUE_TYPE max = real_max_representable (type);
318 frange tmp (type, r.lower_bound (), max);
319 r.intersect (tmp);
322 // Crop R to [MIN, +INF] where MIN is the minimum representable number
323 // for TYPE.
325 static inline void
326 frange_drop_ninf (frange &r, tree type)
328 REAL_VALUE_TYPE min = real_min_representable (type);
329 frange tmp (type, min, r.upper_bound ());
330 r.intersect (tmp);
333 // If zero is in R, make sure both -0.0 and +0.0 are in the range.
335 static inline void
336 frange_add_zeros (frange &r, tree type)
338 if (r.undefined_p () || r.known_isnan ())
339 return;
341 if (HONOR_SIGNED_ZEROS (type)
342 && (real_iszero (&r.lower_bound ()) || real_iszero (&r.upper_bound ())))
344 frange zero;
345 zero.set_zero (type);
346 r.union_ (zero);
350 // Build a range that is <= VAL and store it in R. Return TRUE if
351 // further changes may be needed for R, or FALSE if R is in its final
352 // form.
354 static bool
355 build_le (frange &r, tree type, const frange &val)
357 gcc_checking_assert (!val.known_isnan ());
359 REAL_VALUE_TYPE ninf = frange_val_min (type);
360 r.set (type, ninf, val.upper_bound ());
362 // Add both zeros if there's the possibility of zero equality.
363 frange_add_zeros (r, type);
365 return true;
368 // Build a range that is < VAL and store it in R. Return TRUE if
369 // further changes may be needed for R, or FALSE if R is in its final
370 // form.
372 static bool
373 build_lt (frange &r, tree type, const frange &val)
375 gcc_checking_assert (!val.known_isnan ());
377 // < -INF is outside the range.
378 if (real_isinf (&val.upper_bound (), 1))
380 if (HONOR_NANS (type))
381 r.set_nan (type);
382 else
383 r.set_undefined ();
384 return false;
387 REAL_VALUE_TYPE ninf = frange_val_min (type);
388 REAL_VALUE_TYPE prev = val.upper_bound ();
389 machine_mode mode = TYPE_MODE (type);
390 // Default to the conservatively correct closed ranges for
391 // MODE_COMPOSITE_P, otherwise use nextafter. Note that for
392 // !HONOR_INFINITIES, nextafter will yield -INF, but frange::set()
393 // will crop the range appropriately.
394 if (!MODE_COMPOSITE_P (mode))
395 frange_nextafter (mode, prev, ninf);
396 r.set (type, ninf, prev);
397 return true;
400 // Build a range that is >= VAL and store it in R. Return TRUE if
401 // further changes may be needed for R, or FALSE if R is in its final
402 // form.
404 static bool
405 build_ge (frange &r, tree type, const frange &val)
407 gcc_checking_assert (!val.known_isnan ());
409 REAL_VALUE_TYPE inf = frange_val_max (type);
410 r.set (type, val.lower_bound (), inf);
412 // Add both zeros if there's the possibility of zero equality.
413 frange_add_zeros (r, type);
415 return true;
418 // Build a range that is > VAL and store it in R. Return TRUE if
419 // further changes may be needed for R, or FALSE if R is in its final
420 // form.
422 static bool
423 build_gt (frange &r, tree type, const frange &val)
425 gcc_checking_assert (!val.known_isnan ());
427 // > +INF is outside the range.
428 if (real_isinf (&val.lower_bound (), 0))
430 if (HONOR_NANS (type))
431 r.set_nan (type);
432 else
433 r.set_undefined ();
434 return false;
437 REAL_VALUE_TYPE inf = frange_val_max (type);
438 REAL_VALUE_TYPE next = val.lower_bound ();
439 machine_mode mode = TYPE_MODE (type);
440 // Default to the conservatively correct closed ranges for
441 // MODE_COMPOSITE_P, otherwise use nextafter. Note that for
442 // !HONOR_INFINITIES, nextafter will yield +INF, but frange::set()
443 // will crop the range appropriately.
444 if (!MODE_COMPOSITE_P (mode))
445 frange_nextafter (mode, next, inf);
446 r.set (type, next, inf);
447 return true;
451 class foperator_identity : public range_operator_float
453 using range_operator_float::fold_range;
454 using range_operator_float::op1_range;
455 public:
456 bool fold_range (frange &r, tree type ATTRIBUTE_UNUSED,
457 const frange &op1, const frange &op2 ATTRIBUTE_UNUSED,
458 relation_trio = TRIO_VARYING) const final override
460 r = op1;
461 return true;
463 bool op1_range (frange &r, tree type ATTRIBUTE_UNUSED,
464 const frange &lhs, const frange &op2 ATTRIBUTE_UNUSED,
465 relation_trio = TRIO_VARYING) const final override
467 r = lhs;
468 return true;
470 public:
471 } fop_identity;
473 class foperator_equal : public range_operator_float
475 using range_operator_float::fold_range;
476 using range_operator_float::op1_range;
477 using range_operator_float::op2_range;
478 using range_operator_float::op1_op2_relation;
479 public:
480 bool fold_range (irange &r, tree type,
481 const frange &op1, const frange &op2,
482 relation_trio = TRIO_VARYING) const final override;
483 relation_kind op1_op2_relation (const irange &lhs) const final override
485 return equal_op1_op2_relation (lhs);
487 bool op1_range (frange &r, tree type,
488 const irange &lhs, const frange &op2,
489 relation_trio = TRIO_VARYING) const final override;
490 bool op2_range (frange &r, tree type,
491 const irange &lhs, const frange &op1,
492 relation_trio rel = TRIO_VARYING) const final override
494 return op1_range (r, type, lhs, op1, rel.swap_op1_op2 ());
496 } fop_equal;
498 bool
499 foperator_equal::fold_range (irange &r, tree type,
500 const frange &op1, const frange &op2,
501 relation_trio rel) const
503 if (frelop_early_resolve (r, type, op1, op2, rel, VREL_EQ))
504 return true;
506 if (op1.known_isnan () || op2.known_isnan ())
507 r = range_false (type);
508 // We can be sure the values are always equal or not if both ranges
509 // consist of a single value, and then compare them.
510 else if (op1.singleton_p () && op2.singleton_p ())
512 if (op1 == op2)
513 r = range_true (type);
514 else
515 r = range_false (type);
517 else if (!maybe_isnan (op1, op2))
519 // If ranges do not intersect, we know the range is not equal,
520 // otherwise we don't know anything for sure.
521 frange tmp = op1;
522 tmp.intersect (op2);
523 if (tmp.undefined_p ())
524 r = range_false (type);
525 else
526 r = range_true_and_false (type);
528 else
529 r = range_true_and_false (type);
530 return true;
533 bool
534 foperator_equal::op1_range (frange &r, tree type,
535 const irange &lhs,
536 const frange &op2,
537 relation_trio trio) const
539 relation_kind rel = trio.op1_op2 ();
540 switch (get_bool_state (r, lhs, type))
542 case BRS_TRUE:
543 // The TRUE side of x == NAN is unreachable.
544 if (op2.known_isnan ())
545 r.set_undefined ();
546 else
548 // If it's true, the result is the same as OP2.
549 r = op2;
550 // Add both zeros if there's the possibility of zero equality.
551 frange_add_zeros (r, type);
552 // The TRUE side of op1 == op2 implies op1 is !NAN.
553 r.clear_nan ();
555 break;
557 case BRS_FALSE:
558 // The FALSE side of op1 == op1 implies op1 is a NAN.
559 if (rel == VREL_EQ)
560 r.set_nan (type);
561 // On the FALSE side of x == NAN, we know nothing about x.
562 else if (op2.known_isnan ())
563 r.set_varying (type);
564 // If the result is false, the only time we know anything is
565 // if OP2 is a constant.
566 else if (op2.singleton_p ()
567 || (!op2.maybe_isnan () && op2.zero_p ()))
569 REAL_VALUE_TYPE tmp = op2.lower_bound ();
570 r.set (type, tmp, tmp, VR_ANTI_RANGE);
572 else
573 r.set_varying (type);
574 break;
576 default:
577 break;
579 return true;
582 class foperator_not_equal : public range_operator_float
584 using range_operator_float::fold_range;
585 using range_operator_float::op1_range;
586 using range_operator_float::op1_op2_relation;
587 public:
588 bool fold_range (irange &r, tree type,
589 const frange &op1, const frange &op2,
590 relation_trio rel = TRIO_VARYING) const final override;
591 relation_kind op1_op2_relation (const irange &lhs) const final override
593 return not_equal_op1_op2_relation (lhs);
595 bool op1_range (frange &r, tree type,
596 const irange &lhs, const frange &op2,
597 relation_trio = TRIO_VARYING) const final override;
598 } fop_not_equal;
600 bool
601 foperator_not_equal::fold_range (irange &r, tree type,
602 const frange &op1, const frange &op2,
603 relation_trio rel) const
605 if (frelop_early_resolve (r, type, op1, op2, rel, VREL_NE))
606 return true;
608 // x != NAN is always TRUE.
609 if (op1.known_isnan () || op2.known_isnan ())
610 r = range_true (type);
611 // We can be sure the values are always equal or not if both ranges
612 // consist of a single value, and then compare them.
613 else if (op1.singleton_p () && op2.singleton_p ())
615 if (op1 != op2)
616 r = range_true (type);
617 else
618 r = range_false (type);
620 else if (!maybe_isnan (op1, op2))
622 // If ranges do not intersect, we know the range is not equal,
623 // otherwise we don't know anything for sure.
624 frange tmp = op1;
625 tmp.intersect (op2);
626 if (tmp.undefined_p ())
627 r = range_true (type);
628 else
629 r = range_true_and_false (type);
631 else
632 r = range_true_and_false (type);
633 return true;
636 bool
637 foperator_not_equal::op1_range (frange &r, tree type,
638 const irange &lhs,
639 const frange &op2,
640 relation_trio trio) const
642 relation_kind rel = trio.op1_op2 ();
643 switch (get_bool_state (r, lhs, type))
645 case BRS_TRUE:
646 // If the result is true, the only time we know anything is if
647 // OP2 is a constant.
648 if (op2.singleton_p ())
650 // This is correct even if op1 is NAN, because the following
651 // range would be ~[tmp, tmp] with the NAN property set to
652 // maybe (VARYING).
653 REAL_VALUE_TYPE tmp = op2.lower_bound ();
654 r.set (type, tmp, tmp, VR_ANTI_RANGE);
656 // The TRUE side of op1 != op1 implies op1 is NAN.
657 else if (rel == VREL_EQ)
658 r.set_nan (type);
659 else
660 r.set_varying (type);
661 break;
663 case BRS_FALSE:
664 // The FALSE side of x != NAN is impossible.
665 if (op2.known_isnan ())
666 r.set_undefined ();
667 else
669 // If it's false, the result is the same as OP2.
670 r = op2;
671 // Add both zeros if there's the possibility of zero equality.
672 frange_add_zeros (r, type);
673 // The FALSE side of op1 != op2 implies op1 is !NAN.
674 r.clear_nan ();
676 break;
678 default:
679 break;
681 return true;
684 class foperator_lt : public range_operator_float
686 using range_operator_float::fold_range;
687 using range_operator_float::op1_range;
688 using range_operator_float::op2_range;
689 using range_operator_float::op1_op2_relation;
690 public:
691 bool fold_range (irange &r, tree type,
692 const frange &op1, const frange &op2,
693 relation_trio = TRIO_VARYING) const final override;
694 relation_kind op1_op2_relation (const irange &lhs) const final override
696 return lt_op1_op2_relation (lhs);
698 bool op1_range (frange &r, tree type,
699 const irange &lhs, const frange &op2,
700 relation_trio = TRIO_VARYING) const final override;
701 bool op2_range (frange &r, tree type,
702 const irange &lhs, const frange &op1,
703 relation_trio = TRIO_VARYING) const final override;
704 } fop_lt;
706 bool
707 foperator_lt::fold_range (irange &r, tree type,
708 const frange &op1, const frange &op2,
709 relation_trio rel) const
711 if (frelop_early_resolve (r, type, op1, op2, rel, VREL_LT))
712 return true;
714 if (op1.known_isnan () || op2.known_isnan ())
715 r = range_false (type);
716 else if (!maybe_isnan (op1, op2))
718 if (real_less (&op1.upper_bound (), &op2.lower_bound ()))
719 r = range_true (type);
720 else if (!real_less (&op1.lower_bound (), &op2.upper_bound ()))
721 r = range_false (type);
722 else
723 r = range_true_and_false (type);
725 else
726 r = range_true_and_false (type);
727 return true;
730 bool
731 foperator_lt::op1_range (frange &r,
732 tree type,
733 const irange &lhs,
734 const frange &op2,
735 relation_trio) const
737 switch (get_bool_state (r, lhs, type))
739 case BRS_TRUE:
740 // The TRUE side of x < NAN is unreachable.
741 if (op2.known_isnan ())
742 r.set_undefined ();
743 else if (build_lt (r, type, op2))
745 r.clear_nan ();
746 // x < y implies x is not +INF.
747 frange_drop_inf (r, type);
749 break;
751 case BRS_FALSE:
752 // On the FALSE side of x < NAN, we know nothing about x.
753 if (op2.known_isnan ())
754 r.set_varying (type);
755 else
756 build_ge (r, type, op2);
757 break;
759 default:
760 break;
762 return true;
765 bool
766 foperator_lt::op2_range (frange &r,
767 tree type,
768 const irange &lhs,
769 const frange &op1,
770 relation_trio) const
772 switch (get_bool_state (r, lhs, type))
774 case BRS_TRUE:
775 // The TRUE side of NAN < x is unreachable.
776 if (op1.known_isnan ())
777 r.set_undefined ();
778 else if (build_gt (r, type, op1))
780 r.clear_nan ();
781 // x < y implies y is not -INF.
782 frange_drop_ninf (r, type);
784 break;
786 case BRS_FALSE:
787 // On the FALSE side of NAN < x, we know nothing about x.
788 if (op1.known_isnan ())
789 r.set_varying (type);
790 else
791 build_le (r, type, op1);
792 break;
794 default:
795 break;
797 return true;
800 class foperator_le : public range_operator_float
802 using range_operator_float::fold_range;
803 using range_operator_float::op1_range;
804 using range_operator_float::op2_range;
805 using range_operator_float::op1_op2_relation;
806 public:
807 bool fold_range (irange &r, tree type,
808 const frange &op1, const frange &op2,
809 relation_trio rel = TRIO_VARYING) const final override;
810 relation_kind op1_op2_relation (const irange &lhs) const final override
812 return le_op1_op2_relation (lhs);
814 bool op1_range (frange &r, tree type,
815 const irange &lhs, const frange &op2,
816 relation_trio rel = TRIO_VARYING) const final override;
817 bool op2_range (frange &r, tree type,
818 const irange &lhs, const frange &op1,
819 relation_trio rel = TRIO_VARYING) const final override;
820 } fop_le;
822 bool
823 foperator_le::fold_range (irange &r, tree type,
824 const frange &op1, const frange &op2,
825 relation_trio rel) const
827 if (frelop_early_resolve (r, type, op1, op2, rel, VREL_LE))
828 return true;
830 if (op1.known_isnan () || op2.known_isnan ())
831 r = range_false (type);
832 else if (!maybe_isnan (op1, op2))
834 if (real_compare (LE_EXPR, &op1.upper_bound (), &op2.lower_bound ()))
835 r = range_true (type);
836 else if (!real_compare (LE_EXPR, &op1.lower_bound (), &op2.upper_bound ()))
837 r = range_false (type);
838 else
839 r = range_true_and_false (type);
841 else
842 r = range_true_and_false (type);
843 return true;
846 bool
847 foperator_le::op1_range (frange &r,
848 tree type,
849 const irange &lhs,
850 const frange &op2,
851 relation_trio) const
853 switch (get_bool_state (r, lhs, type))
855 case BRS_TRUE:
856 // The TRUE side of x <= NAN is unreachable.
857 if (op2.known_isnan ())
858 r.set_undefined ();
859 else if (build_le (r, type, op2))
860 r.clear_nan ();
861 break;
863 case BRS_FALSE:
864 // On the FALSE side of x <= NAN, we know nothing about x.
865 if (op2.known_isnan ())
866 r.set_varying (type);
867 else
868 build_gt (r, type, op2);
869 break;
871 default:
872 break;
874 return true;
877 bool
878 foperator_le::op2_range (frange &r,
879 tree type,
880 const irange &lhs,
881 const frange &op1,
882 relation_trio) const
884 switch (get_bool_state (r, lhs, type))
886 case BRS_TRUE:
887 // The TRUE side of NAN <= x is unreachable.
888 if (op1.known_isnan ())
889 r.set_undefined ();
890 else if (build_ge (r, type, op1))
891 r.clear_nan ();
892 break;
894 case BRS_FALSE:
895 // On the FALSE side of NAN <= x, we know nothing about x.
896 if (op1.known_isnan ())
897 r.set_varying (type);
898 else
899 build_lt (r, type, op1);
900 break;
902 default:
903 break;
905 return true;
908 class foperator_gt : public range_operator_float
910 using range_operator_float::fold_range;
911 using range_operator_float::op1_range;
912 using range_operator_float::op2_range;
913 using range_operator_float::op1_op2_relation;
914 public:
915 bool fold_range (irange &r, tree type,
916 const frange &op1, const frange &op2,
917 relation_trio = TRIO_VARYING) const final override;
918 relation_kind op1_op2_relation (const irange &lhs) const final override
920 return gt_op1_op2_relation (lhs);
922 bool op1_range (frange &r, tree type,
923 const irange &lhs, const frange &op2,
924 relation_trio = TRIO_VARYING) const final override;
925 bool op2_range (frange &r, tree type,
926 const irange &lhs, const frange &op1,
927 relation_trio = TRIO_VARYING) const final override;
928 } fop_gt;
930 bool
931 foperator_gt::fold_range (irange &r, tree type,
932 const frange &op1, const frange &op2,
933 relation_trio rel) const
935 if (frelop_early_resolve (r, type, op1, op2, rel, VREL_GT))
936 return true;
938 if (op1.known_isnan () || op2.known_isnan ())
939 r = range_false (type);
940 else if (!maybe_isnan (op1, op2))
942 if (real_compare (GT_EXPR, &op1.lower_bound (), &op2.upper_bound ()))
943 r = range_true (type);
944 else if (!real_compare (GT_EXPR, &op1.upper_bound (), &op2.lower_bound ()))
945 r = range_false (type);
946 else
947 r = range_true_and_false (type);
949 else
950 r = range_true_and_false (type);
951 return true;
954 bool
955 foperator_gt::op1_range (frange &r,
956 tree type,
957 const irange &lhs,
958 const frange &op2,
959 relation_trio) const
961 switch (get_bool_state (r, lhs, type))
963 case BRS_TRUE:
964 // The TRUE side of x > NAN is unreachable.
965 if (op2.known_isnan ())
966 r.set_undefined ();
967 else if (build_gt (r, type, op2))
969 r.clear_nan ();
970 // x > y implies x is not -INF.
971 frange_drop_ninf (r, type);
973 break;
975 case BRS_FALSE:
976 // On the FALSE side of x > NAN, we know nothing about x.
977 if (op2.known_isnan ())
978 r.set_varying (type);
979 else
980 build_le (r, type, op2);
981 break;
983 default:
984 break;
986 return true;
989 bool
990 foperator_gt::op2_range (frange &r,
991 tree type,
992 const irange &lhs,
993 const frange &op1,
994 relation_trio) const
996 switch (get_bool_state (r, lhs, type))
998 case BRS_TRUE:
999 // The TRUE side of NAN > x is unreachable.
1000 if (op1.known_isnan ())
1001 r.set_undefined ();
1002 else if (build_lt (r, type, op1))
1004 r.clear_nan ();
1005 // x > y implies y is not +INF.
1006 frange_drop_inf (r, type);
1008 break;
1010 case BRS_FALSE:
1011 // On The FALSE side of NAN > x, we know nothing about x.
1012 if (op1.known_isnan ())
1013 r.set_varying (type);
1014 else
1015 build_ge (r, type, op1);
1016 break;
1018 default:
1019 break;
1021 return true;
1024 class foperator_ge : public range_operator_float
1026 using range_operator_float::fold_range;
1027 using range_operator_float::op1_range;
1028 using range_operator_float::op2_range;
1029 using range_operator_float::op1_op2_relation;
1030 public:
1031 bool fold_range (irange &r, tree type,
1032 const frange &op1, const frange &op2,
1033 relation_trio = TRIO_VARYING) const final override;
1034 relation_kind op1_op2_relation (const irange &lhs) const final override
1036 return ge_op1_op2_relation (lhs);
1038 bool op1_range (frange &r, tree type,
1039 const irange &lhs, const frange &op2,
1040 relation_trio = TRIO_VARYING) const final override;
1041 bool op2_range (frange &r, tree type,
1042 const irange &lhs, const frange &op1,
1043 relation_trio = TRIO_VARYING) const final override;
1044 } fop_ge;
1046 bool
1047 foperator_ge::fold_range (irange &r, tree type,
1048 const frange &op1, const frange &op2,
1049 relation_trio rel) const
1051 if (frelop_early_resolve (r, type, op1, op2, rel, VREL_GE))
1052 return true;
1054 if (op1.known_isnan () || op2.known_isnan ())
1055 r = range_false (type);
1056 else if (!maybe_isnan (op1, op2))
1058 if (real_compare (GE_EXPR, &op1.lower_bound (), &op2.upper_bound ()))
1059 r = range_true (type);
1060 else if (!real_compare (GE_EXPR, &op1.upper_bound (), &op2.lower_bound ()))
1061 r = range_false (type);
1062 else
1063 r = range_true_and_false (type);
1065 else
1066 r = range_true_and_false (type);
1067 return true;
1070 bool
1071 foperator_ge::op1_range (frange &r,
1072 tree type,
1073 const irange &lhs,
1074 const frange &op2,
1075 relation_trio) const
1077 switch (get_bool_state (r, lhs, type))
1079 case BRS_TRUE:
1080 // The TRUE side of x >= NAN is unreachable.
1081 if (op2.known_isnan ())
1082 r.set_undefined ();
1083 else if (build_ge (r, type, op2))
1084 r.clear_nan ();
1085 break;
1087 case BRS_FALSE:
1088 // On the FALSE side of x >= NAN, we know nothing about x.
1089 if (op2.known_isnan ())
1090 r.set_varying (type);
1091 else
1092 build_lt (r, type, op2);
1093 break;
1095 default:
1096 break;
1098 return true;
1101 bool
1102 foperator_ge::op2_range (frange &r, tree type,
1103 const irange &lhs,
1104 const frange &op1,
1105 relation_trio) const
1107 switch (get_bool_state (r, lhs, type))
1109 case BRS_TRUE:
1110 // The TRUE side of NAN >= x is unreachable.
1111 if (op1.known_isnan ())
1112 r.set_undefined ();
1113 else if (build_le (r, type, op1))
1114 r.clear_nan ();
1115 break;
1117 case BRS_FALSE:
1118 // On the FALSE side of NAN >= x, we know nothing about x.
1119 if (op1.known_isnan ())
1120 r.set_varying (type);
1121 else
1122 build_gt (r, type, op1);
1123 break;
1125 default:
1126 break;
1128 return true;
1131 // UNORDERED_EXPR comparison.
1133 class foperator_unordered : public range_operator_float
1135 using range_operator_float::fold_range;
1136 using range_operator_float::op1_range;
1137 using range_operator_float::op2_range;
1138 public:
1139 bool fold_range (irange &r, tree type,
1140 const frange &op1, const frange &op2,
1141 relation_trio = TRIO_VARYING) const final override;
1142 bool op1_range (frange &r, tree type,
1143 const irange &lhs, const frange &op2,
1144 relation_trio = TRIO_VARYING) const final override;
1145 bool op2_range (frange &r, tree type,
1146 const irange &lhs, const frange &op1,
1147 relation_trio rel = TRIO_VARYING) const final override
1149 return op1_range (r, type, lhs, op1, rel.swap_op1_op2 ());
1151 } fop_unordered;
1153 bool
1154 foperator_unordered::fold_range (irange &r, tree type,
1155 const frange &op1, const frange &op2,
1156 relation_trio) const
1158 // UNORDERED is TRUE if either operand is a NAN.
1159 if (op1.known_isnan () || op2.known_isnan ())
1160 r = range_true (type);
1161 // UNORDERED is FALSE if neither operand is a NAN.
1162 else if (!op1.maybe_isnan () && !op2.maybe_isnan ())
1163 r = range_false (type);
1164 else
1165 r = range_true_and_false (type);
1166 return true;
1169 bool
1170 foperator_unordered::op1_range (frange &r, tree type,
1171 const irange &lhs,
1172 const frange &op2,
1173 relation_trio trio) const
1175 relation_kind rel = trio.op1_op2 ();
1176 switch (get_bool_state (r, lhs, type))
1178 case BRS_TRUE:
1179 // Since at least one operand must be NAN, if one of them is
1180 // not, the other must be.
1181 if (rel == VREL_EQ || !op2.maybe_isnan ())
1182 r.set_nan (type);
1183 else
1184 r.set_varying (type);
1185 break;
1187 case BRS_FALSE:
1188 // A false UNORDERED means both operands are !NAN, so it's
1189 // impossible for op2 to be a NAN.
1190 if (op2.known_isnan ())
1191 r.set_undefined ();
1192 else
1194 r.set_varying (type);
1195 r.clear_nan ();
1197 break;
1199 default:
1200 break;
1202 return true;
1205 // ORDERED_EXPR comparison.
1207 class foperator_ordered : public range_operator_float
1209 using range_operator_float::fold_range;
1210 using range_operator_float::op1_range;
1211 using range_operator_float::op2_range;
1212 public:
1213 bool fold_range (irange &r, tree type,
1214 const frange &op1, const frange &op2,
1215 relation_trio = TRIO_VARYING) const final override;
1216 bool op1_range (frange &r, tree type,
1217 const irange &lhs, const frange &op2,
1218 relation_trio = TRIO_VARYING) const final override;
1219 bool op2_range (frange &r, tree type,
1220 const irange &lhs, const frange &op1,
1221 relation_trio rel = TRIO_VARYING) const final override
1223 return op1_range (r, type, lhs, op1, rel.swap_op1_op2 ());
1225 } fop_ordered;
1227 bool
1228 foperator_ordered::fold_range (irange &r, tree type,
1229 const frange &op1, const frange &op2,
1230 relation_trio) const
1232 if (op1.known_isnan () || op2.known_isnan ())
1233 r = range_false (type);
1234 else if (!op1.maybe_isnan () && !op2.maybe_isnan ())
1235 r = range_true (type);
1236 else
1237 r = range_true_and_false (type);
1238 return true;
1241 bool
1242 foperator_ordered::op1_range (frange &r, tree type,
1243 const irange &lhs,
1244 const frange &op2,
1245 relation_trio trio) const
1247 relation_kind rel = trio.op1_op2 ();
1248 switch (get_bool_state (r, lhs, type))
1250 case BRS_TRUE:
1251 // The TRUE side of ORDERED means both operands are !NAN, so
1252 // it's impossible for op2 to be a NAN.
1253 if (op2.known_isnan ())
1254 r.set_undefined ();
1255 else
1257 r.set_varying (type);
1258 r.clear_nan ();
1260 break;
1262 case BRS_FALSE:
1263 // The FALSE side of op1 ORDERED op1 implies op1 is NAN.
1264 if (rel == VREL_EQ)
1265 r.set_nan (type);
1266 else
1267 r.set_varying (type);
1268 break;
1270 default:
1271 break;
1273 return true;
1276 class foperator_negate : public range_operator_float
1278 using range_operator_float::fold_range;
1279 using range_operator_float::op1_range;
1280 public:
1281 bool fold_range (frange &r, tree type,
1282 const frange &op1, const frange &op2,
1283 relation_trio = TRIO_VARYING) const final override
1285 if (empty_range_varying (r, type, op1, op2))
1286 return true;
1287 if (op1.known_isnan ())
1289 bool sign;
1290 if (op1.nan_signbit_p (sign))
1291 r.set_nan (type, !sign);
1292 else
1293 r.set_nan (type);
1294 return true;
1297 REAL_VALUE_TYPE lh_lb = op1.lower_bound ();
1298 REAL_VALUE_TYPE lh_ub = op1.upper_bound ();
1299 lh_lb = real_value_negate (&lh_lb);
1300 lh_ub = real_value_negate (&lh_ub);
1301 r.set (type, lh_ub, lh_lb);
1302 if (op1.maybe_isnan ())
1304 bool sign;
1305 if (op1.nan_signbit_p (sign))
1306 r.update_nan (!sign);
1307 else
1308 r.update_nan ();
1310 else
1311 r.clear_nan ();
1312 return true;
1314 bool op1_range (frange &r, tree type,
1315 const frange &lhs, const frange &op2,
1316 relation_trio rel = TRIO_VARYING) const final override
1318 return fold_range (r, type, lhs, op2, rel);
1320 } fop_negate;
1322 class foperator_abs : public range_operator_float
1324 using range_operator_float::fold_range;
1325 using range_operator_float::op1_range;
1326 public:
1327 bool fold_range (frange &r, tree type,
1328 const frange &op1, const frange &,
1329 relation_trio = TRIO_VARYING) const final override;
1330 bool op1_range (frange &r, tree type,
1331 const frange &lhs, const frange &op2,
1332 relation_trio rel = TRIO_VARYING) const final override;
1333 } fop_abs;
1335 bool
1336 foperator_abs::fold_range (frange &r, tree type,
1337 const frange &op1, const frange &op2,
1338 relation_trio) const
1340 if (empty_range_varying (r, type, op1, op2))
1341 return true;
1342 if (op1.known_isnan ())
1344 r.set_nan (type, /*sign=*/false);
1345 return true;
1348 const REAL_VALUE_TYPE lh_lb = op1.lower_bound ();
1349 const REAL_VALUE_TYPE lh_ub = op1.upper_bound ();
1350 // Handle the easy case where everything is positive.
1351 if (real_compare (GE_EXPR, &lh_lb, &dconst0)
1352 && !real_iszero (&lh_lb, /*sign=*/true)
1353 && !op1.maybe_isnan (/*sign=*/true))
1355 r = op1;
1356 return true;
1359 REAL_VALUE_TYPE min = real_value_abs (&lh_lb);
1360 REAL_VALUE_TYPE max = real_value_abs (&lh_ub);
1361 // If the range contains zero then we know that the minimum value in the
1362 // range will be zero.
1363 if (real_compare (LE_EXPR, &lh_lb, &dconst0)
1364 && real_compare (GE_EXPR, &lh_ub, &dconst0))
1366 if (real_compare (GT_EXPR, &min, &max))
1367 max = min;
1368 min = dconst0;
1370 else
1372 // If the range was reversed, swap MIN and MAX.
1373 if (real_compare (GT_EXPR, &min, &max))
1374 std::swap (min, max);
1377 r.set (type, min, max);
1378 if (op1.maybe_isnan ())
1379 r.update_nan (/*sign=*/false);
1380 else
1381 r.clear_nan ();
1382 return true;
1385 bool
1386 foperator_abs::op1_range (frange &r, tree type,
1387 const frange &lhs, const frange &op2,
1388 relation_trio) const
1390 if (empty_range_varying (r, type, lhs, op2))
1391 return true;
1392 if (lhs.known_isnan ())
1394 r.set_nan (type);
1395 return true;
1398 // Start with the positives because negatives are an impossible result.
1399 frange positives (type, dconst0, frange_val_max (type));
1400 positives.update_nan (/*sign=*/false);
1401 positives.intersect (lhs);
1402 r = positives;
1403 // Add -NAN if relevant.
1404 if (r.maybe_isnan ())
1406 frange neg_nan;
1407 neg_nan.set_nan (type, true);
1408 r.union_ (neg_nan);
1410 if (r.known_isnan () || r.undefined_p ())
1411 return true;
1412 // Then add the negative of each pair:
1413 // ABS(op1) = [5,20] would yield op1 => [-20,-5][5,20].
1414 frange negatives (type, real_value_negate (&positives.upper_bound ()),
1415 real_value_negate (&positives.lower_bound ()));
1416 negatives.clear_nan ();
1417 r.union_ (negatives);
1418 return true;
1421 class foperator_unordered_lt : public range_operator_float
1423 using range_operator_float::fold_range;
1424 using range_operator_float::op1_range;
1425 using range_operator_float::op2_range;
1426 public:
1427 bool fold_range (irange &r, tree type,
1428 const frange &op1, const frange &op2,
1429 relation_trio rel = TRIO_VARYING) const final override
1431 if (op1.known_isnan () || op2.known_isnan ())
1433 r = range_true (type);
1434 return true;
1436 if (!fop_lt.fold_range (r, type, op1, op2, rel))
1437 return false;
1438 // The result is the same as the ordered version when the
1439 // comparison is true or when the operands cannot be NANs.
1440 if (!maybe_isnan (op1, op2) || r == range_true (type))
1441 return true;
1442 else
1444 r = range_true_and_false (type);
1445 return true;
1448 bool op1_range (frange &r, tree type,
1449 const irange &lhs,
1450 const frange &op2,
1451 relation_trio trio) const final override;
1452 bool op2_range (frange &r, tree type,
1453 const irange &lhs,
1454 const frange &op1,
1455 relation_trio trio) const final override;
1456 } fop_unordered_lt;
1458 bool
1459 foperator_unordered_lt::op1_range (frange &r, tree type,
1460 const irange &lhs,
1461 const frange &op2,
1462 relation_trio) const
1464 switch (get_bool_state (r, lhs, type))
1466 case BRS_TRUE:
1467 if (op2.known_isnan ())
1468 r.set_varying (type);
1469 else
1470 build_lt (r, type, op2);
1471 break;
1473 case BRS_FALSE:
1474 // A false UNORDERED_LT means both operands are !NAN, so it's
1475 // impossible for op2 to be a NAN.
1476 if (op2.known_isnan ())
1477 r.set_undefined ();
1478 else if (build_ge (r, type, op2))
1479 r.clear_nan ();
1480 break;
1482 default:
1483 break;
1485 return true;
1488 bool
1489 foperator_unordered_lt::op2_range (frange &r, tree type,
1490 const irange &lhs,
1491 const frange &op1,
1492 relation_trio) const
1494 switch (get_bool_state (r, lhs, type))
1496 case BRS_TRUE:
1497 if (op1.known_isnan ())
1498 r.set_varying (type);
1499 else
1500 build_gt (r, type, op1);
1501 break;
1503 case BRS_FALSE:
1504 // A false UNORDERED_LT means both operands are !NAN, so it's
1505 // impossible for op1 to be a NAN.
1506 if (op1.known_isnan ())
1507 r.set_undefined ();
1508 else if (build_le (r, type, op1))
1509 r.clear_nan ();
1510 break;
1512 default:
1513 break;
1515 return true;
1518 class foperator_unordered_le : public range_operator_float
1520 using range_operator_float::fold_range;
1521 using range_operator_float::op1_range;
1522 using range_operator_float::op2_range;
1523 public:
1524 bool fold_range (irange &r, tree type,
1525 const frange &op1, const frange &op2,
1526 relation_trio rel = TRIO_VARYING) const final override
1528 if (op1.known_isnan () || op2.known_isnan ())
1530 r = range_true (type);
1531 return true;
1533 if (!fop_le.fold_range (r, type, op1, op2, rel))
1534 return false;
1535 // The result is the same as the ordered version when the
1536 // comparison is true or when the operands cannot be NANs.
1537 if (!maybe_isnan (op1, op2) || r == range_true (type))
1538 return true;
1539 else
1541 r = range_true_and_false (type);
1542 return true;
1545 bool op1_range (frange &r, tree type,
1546 const irange &lhs, const frange &op2,
1547 relation_trio = TRIO_VARYING) const final override;
1548 bool op2_range (frange &r, tree type,
1549 const irange &lhs, const frange &op1,
1550 relation_trio = TRIO_VARYING) const final override;
1551 } fop_unordered_le;
1553 bool
1554 foperator_unordered_le::op1_range (frange &r, tree type,
1555 const irange &lhs, const frange &op2,
1556 relation_trio) const
1558 switch (get_bool_state (r, lhs, type))
1560 case BRS_TRUE:
1561 if (op2.known_isnan ())
1562 r.set_varying (type);
1563 else
1564 build_le (r, type, op2);
1565 break;
1567 case BRS_FALSE:
1568 // A false UNORDERED_LE means both operands are !NAN, so it's
1569 // impossible for op2 to be a NAN.
1570 if (op2.known_isnan ())
1571 r.set_undefined ();
1572 else if (build_gt (r, type, op2))
1573 r.clear_nan ();
1574 break;
1576 default:
1577 break;
1579 return true;
1582 bool
1583 foperator_unordered_le::op2_range (frange &r,
1584 tree type,
1585 const irange &lhs,
1586 const frange &op1,
1587 relation_trio) const
1589 switch (get_bool_state (r, lhs, type))
1591 case BRS_TRUE:
1592 if (op1.known_isnan ())
1593 r.set_varying (type);
1594 else
1595 build_ge (r, type, op1);
1596 break;
1598 case BRS_FALSE:
1599 // A false UNORDERED_LE means both operands are !NAN, so it's
1600 // impossible for op1 to be a NAN.
1601 if (op1.known_isnan ())
1602 r.set_undefined ();
1603 else if (build_lt (r, type, op1))
1604 r.clear_nan ();
1605 break;
1607 default:
1608 break;
1610 return true;
1613 class foperator_unordered_gt : public range_operator_float
1615 using range_operator_float::fold_range;
1616 using range_operator_float::op1_range;
1617 using range_operator_float::op2_range;
1618 public:
1619 bool fold_range (irange &r, tree type,
1620 const frange &op1, const frange &op2,
1621 relation_trio rel = TRIO_VARYING) const final override
1623 if (op1.known_isnan () || op2.known_isnan ())
1625 r = range_true (type);
1626 return true;
1628 if (!fop_gt.fold_range (r, type, op1, op2, rel))
1629 return false;
1630 // The result is the same as the ordered version when the
1631 // comparison is true or when the operands cannot be NANs.
1632 if (!maybe_isnan (op1, op2) || r == range_true (type))
1633 return true;
1634 else
1636 r = range_true_and_false (type);
1637 return true;
1640 bool op1_range (frange &r, tree type,
1641 const irange &lhs, const frange &op2,
1642 relation_trio = TRIO_VARYING) const final override;
1643 bool op2_range (frange &r, tree type,
1644 const irange &lhs, const frange &op1,
1645 relation_trio = TRIO_VARYING) const final override;
1646 } fop_unordered_gt;
1648 bool
1649 foperator_unordered_gt::op1_range (frange &r,
1650 tree type,
1651 const irange &lhs,
1652 const frange &op2,
1653 relation_trio) const
1655 switch (get_bool_state (r, lhs, type))
1657 case BRS_TRUE:
1658 if (op2.known_isnan ())
1659 r.set_varying (type);
1660 else
1661 build_gt (r, type, op2);
1662 break;
1664 case BRS_FALSE:
1665 // A false UNORDERED_GT means both operands are !NAN, so it's
1666 // impossible for op2 to be a NAN.
1667 if (op2.known_isnan ())
1668 r.set_undefined ();
1669 else if (build_le (r, type, op2))
1670 r.clear_nan ();
1671 break;
1673 default:
1674 break;
1676 return true;
1679 bool
1680 foperator_unordered_gt::op2_range (frange &r,
1681 tree type,
1682 const irange &lhs,
1683 const frange &op1,
1684 relation_trio) const
1686 switch (get_bool_state (r, lhs, type))
1688 case BRS_TRUE:
1689 if (op1.known_isnan ())
1690 r.set_varying (type);
1691 else
1692 build_lt (r, type, op1);
1693 break;
1695 case BRS_FALSE:
1696 // A false UNORDERED_GT means both operands are !NAN, so it's
1697 // impossible for op1 to be a NAN.
1698 if (op1.known_isnan ())
1699 r.set_undefined ();
1700 else if (build_ge (r, type, op1))
1701 r.clear_nan ();
1702 break;
1704 default:
1705 break;
1707 return true;
1710 class foperator_unordered_ge : public range_operator_float
1712 using range_operator_float::fold_range;
1713 using range_operator_float::op1_range;
1714 using range_operator_float::op2_range;
1715 public:
1716 bool fold_range (irange &r, tree type,
1717 const frange &op1, const frange &op2,
1718 relation_trio rel = TRIO_VARYING) const final override
1720 if (op1.known_isnan () || op2.known_isnan ())
1722 r = range_true (type);
1723 return true;
1725 if (!fop_ge.fold_range (r, type, op1, op2, rel))
1726 return false;
1727 // The result is the same as the ordered version when the
1728 // comparison is true or when the operands cannot be NANs.
1729 if (!maybe_isnan (op1, op2) || r == range_true (type))
1730 return true;
1731 else
1733 r = range_true_and_false (type);
1734 return true;
1737 bool op1_range (frange &r, tree type,
1738 const irange &lhs, const frange &op2,
1739 relation_trio = TRIO_VARYING) const final override;
1740 bool op2_range (frange &r, tree type,
1741 const irange &lhs, const frange &op1,
1742 relation_trio = TRIO_VARYING) const final override;
1743 } fop_unordered_ge;
1745 bool
1746 foperator_unordered_ge::op1_range (frange &r,
1747 tree type,
1748 const irange &lhs,
1749 const frange &op2,
1750 relation_trio) const
1752 switch (get_bool_state (r, lhs, type))
1754 case BRS_TRUE:
1755 if (op2.known_isnan ())
1756 r.set_varying (type);
1757 else
1758 build_ge (r, type, op2);
1759 break;
1761 case BRS_FALSE:
1762 // A false UNORDERED_GE means both operands are !NAN, so it's
1763 // impossible for op2 to be a NAN.
1764 if (op2.known_isnan ())
1765 r.set_undefined ();
1766 else if (build_lt (r, type, op2))
1767 r.clear_nan ();
1768 break;
1770 default:
1771 break;
1773 return true;
1776 bool
1777 foperator_unordered_ge::op2_range (frange &r, tree type,
1778 const irange &lhs,
1779 const frange &op1,
1780 relation_trio) const
1782 switch (get_bool_state (r, lhs, type))
1784 case BRS_TRUE:
1785 if (op1.known_isnan ())
1786 r.set_varying (type);
1787 else
1788 build_le (r, type, op1);
1789 break;
1791 case BRS_FALSE:
1792 // A false UNORDERED_GE means both operands are !NAN, so it's
1793 // impossible for op1 to be a NAN.
1794 if (op1.known_isnan ())
1795 r.set_undefined ();
1796 else if (build_gt (r, type, op1))
1797 r.clear_nan ();
1798 break;
1800 default:
1801 break;
1803 return true;
1806 class foperator_unordered_equal : public range_operator_float
1808 using range_operator_float::fold_range;
1809 using range_operator_float::op1_range;
1810 using range_operator_float::op2_range;
1811 public:
1812 bool fold_range (irange &r, tree type,
1813 const frange &op1, const frange &op2,
1814 relation_trio rel = TRIO_VARYING) const final override
1816 if (op1.known_isnan () || op2.known_isnan ())
1818 r = range_true (type);
1819 return true;
1821 if (!fop_equal.fold_range (r, type, op1, op2, rel))
1822 return false;
1823 // The result is the same as the ordered version when the
1824 // comparison is true or when the operands cannot be NANs.
1825 if (!maybe_isnan (op1, op2) || r == range_true (type))
1826 return true;
1827 else
1829 r = range_true_and_false (type);
1830 return true;
1833 bool op1_range (frange &r, tree type,
1834 const irange &lhs, const frange &op2,
1835 relation_trio = TRIO_VARYING) const final override;
1836 bool op2_range (frange &r, tree type,
1837 const irange &lhs, const frange &op1,
1838 relation_trio rel = TRIO_VARYING) const final override
1840 return op1_range (r, type, lhs, op1, rel.swap_op1_op2 ());
1842 } fop_unordered_equal;
1844 bool
1845 foperator_unordered_equal::op1_range (frange &r, tree type,
1846 const irange &lhs,
1847 const frange &op2,
1848 relation_trio) const
1850 switch (get_bool_state (r, lhs, type))
1852 case BRS_TRUE:
1853 // If it's true, the result is the same as OP2 plus a NAN.
1854 r = op2;
1855 // Add both zeros if there's the possibility of zero equality.
1856 frange_add_zeros (r, type);
1857 // Add the posibility of a NAN.
1858 r.update_nan ();
1859 break;
1861 case BRS_FALSE:
1862 // A false UNORDERED_EQ means both operands are !NAN, so it's
1863 // impossible for op2 to be a NAN.
1864 if (op2.known_isnan ())
1865 r.set_undefined ();
1866 else
1868 // The false side indictates !NAN and not equal. We can at least
1869 // represent !NAN.
1870 r.set_varying (type);
1871 r.clear_nan ();
1873 break;
1875 default:
1876 break;
1878 return true;
1881 // Final tweaks for float binary op op1_range/op2_range.
1882 // Return TRUE if the operation is performed and a valid range is available.
1884 static bool
1885 float_binary_op_range_finish (bool ret, frange &r, tree type,
1886 const frange &lhs)
1888 if (!ret)
1889 return false;
1891 // If we get a known NAN from reverse op, it means either that
1892 // the other operand was known NAN (in that case we know nothing),
1893 // or the reverse operation introduced a known NAN.
1894 // Say for lhs = op1 * op2 if lhs is [-0, +0] and op2 is too,
1895 // 0 / 0 is known NAN. Just punt in that case.
1896 // If NANs aren't honored, we get for 0 / 0 UNDEFINED, so punt as well.
1897 // Or if lhs is a known NAN, we also don't know anything.
1898 if (r.known_isnan () || lhs.known_isnan () || r.undefined_p ())
1900 r.set_varying (type);
1901 return true;
1904 // If lhs isn't NAN, then neither operand could be NAN,
1905 // even if the reverse operation does introduce a maybe_nan.
1906 if (!lhs.maybe_isnan ())
1907 r.clear_nan ();
1908 // If lhs is a maybe or known NAN, the operand could be
1909 // NAN.
1910 else
1911 r.update_nan ();
1912 return true;
1915 // True if [lb, ub] is [+-0, +-0].
1916 static bool
1917 zero_p (const REAL_VALUE_TYPE &lb, const REAL_VALUE_TYPE &ub)
1919 return real_iszero (&lb) && real_iszero (&ub);
1922 // True if +0 or -0 is in [lb, ub] range.
1923 static bool
1924 contains_zero_p (const REAL_VALUE_TYPE &lb, const REAL_VALUE_TYPE &ub)
1926 return (real_compare (LE_EXPR, &lb, &dconst0)
1927 && real_compare (GE_EXPR, &ub, &dconst0));
1930 // True if [lb, ub] is [-INF, -INF] or [+INF, +INF].
1931 static bool
1932 singleton_inf_p (const REAL_VALUE_TYPE &lb, const REAL_VALUE_TYPE &ub)
1934 return real_isinf (&lb) && real_isinf (&ub, real_isneg (&lb));
1937 // Return -1 if binary op result must have sign bit set,
1938 // 1 if binary op result must have sign bit clear,
1939 // 0 otherwise.
1940 // Sign bit of binary op result is exclusive or of the
1941 // operand's sign bits.
1942 static int
1943 signbit_known_p (const REAL_VALUE_TYPE &lh_lb, const REAL_VALUE_TYPE &lh_ub,
1944 const REAL_VALUE_TYPE &rh_lb, const REAL_VALUE_TYPE &rh_ub)
1946 if (real_isneg (&lh_lb) == real_isneg (&lh_ub)
1947 && real_isneg (&rh_lb) == real_isneg (&rh_ub))
1949 if (real_isneg (&lh_lb) == real_isneg (&rh_ub))
1950 return 1;
1951 else
1952 return -1;
1954 return 0;
1957 // Set [lb, ub] to [-0, -0], [-0, +0] or [+0, +0] depending on
1958 // signbit_known.
1959 static void
1960 zero_range (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub, int signbit_known)
1962 ub = lb = dconst0;
1963 if (signbit_known <= 0)
1964 lb = real_value_negate (&dconst0);
1965 if (signbit_known < 0)
1966 ub = lb;
1969 // Set [lb, ub] to [-INF, -INF], [-INF, +INF] or [+INF, +INF] depending on
1970 // signbit_known.
1971 static void
1972 inf_range (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub, int signbit_known)
1974 if (signbit_known > 0)
1975 ub = lb = dconstinf;
1976 else if (signbit_known < 0)
1977 ub = lb = dconstninf;
1978 else
1980 lb = dconstninf;
1981 ub = dconstinf;
1985 // Set [lb, ub] to [-INF, -0], [-INF, +INF] or [+0, +INF] depending on
1986 // signbit_known.
1987 static void
1988 zero_to_inf_range (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub, int signbit_known)
1990 if (signbit_known > 0)
1992 lb = dconst0;
1993 ub = dconstinf;
1995 else if (signbit_known < 0)
1997 lb = dconstninf;
1998 ub = real_value_negate (&dconst0);
2000 else
2002 lb = dconstninf;
2003 ub = dconstinf;
2007 class foperator_plus : public range_operator_float
2009 using range_operator_float::op1_range;
2010 using range_operator_float::op2_range;
2011 public:
2012 virtual bool op1_range (frange &r, tree type,
2013 const frange &lhs,
2014 const frange &op2,
2015 relation_trio = TRIO_VARYING) const final override
2017 if (lhs.undefined_p ())
2018 return false;
2019 range_op_handler minus (MINUS_EXPR, type);
2020 if (!minus)
2021 return false;
2022 return float_binary_op_range_finish (minus.fold_range (r, type, lhs, op2),
2023 r, type, lhs);
2025 virtual bool op2_range (frange &r, tree type,
2026 const frange &lhs,
2027 const frange &op1,
2028 relation_trio = TRIO_VARYING) const final override
2030 return op1_range (r, type, lhs, op1);
2032 private:
2033 void rv_fold (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub, bool &maybe_nan,
2034 tree type,
2035 const REAL_VALUE_TYPE &lh_lb,
2036 const REAL_VALUE_TYPE &lh_ub,
2037 const REAL_VALUE_TYPE &rh_lb,
2038 const REAL_VALUE_TYPE &rh_ub,
2039 relation_kind) const final override
2041 frange_arithmetic (PLUS_EXPR, type, lb, lh_lb, rh_lb, dconstninf);
2042 frange_arithmetic (PLUS_EXPR, type, ub, lh_ub, rh_ub, dconstinf);
2044 // [-INF] + [+INF] = NAN
2045 if (real_isinf (&lh_lb, true) && real_isinf (&rh_ub, false))
2046 maybe_nan = true;
2047 // [+INF] + [-INF] = NAN
2048 else if (real_isinf (&lh_ub, false) && real_isinf (&rh_lb, true))
2049 maybe_nan = true;
2050 else
2051 maybe_nan = false;
2053 } fop_plus;
2056 class foperator_minus : public range_operator_float
2058 using range_operator_float::op1_range;
2059 using range_operator_float::op2_range;
2060 public:
2061 virtual bool op1_range (frange &r, tree type,
2062 const frange &lhs,
2063 const frange &op2,
2064 relation_trio = TRIO_VARYING) const final override
2066 if (lhs.undefined_p ())
2067 return false;
2068 return float_binary_op_range_finish (fop_plus.fold_range (r, type, lhs,
2069 op2),
2070 r, type, lhs);
2072 virtual bool op2_range (frange &r, tree type,
2073 const frange &lhs,
2074 const frange &op1,
2075 relation_trio = TRIO_VARYING) const final override
2077 if (lhs.undefined_p ())
2078 return false;
2079 return float_binary_op_range_finish (fold_range (r, type, op1, lhs),
2080 r, type, lhs);
2082 private:
2083 void rv_fold (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub, bool &maybe_nan,
2084 tree type,
2085 const REAL_VALUE_TYPE &lh_lb,
2086 const REAL_VALUE_TYPE &lh_ub,
2087 const REAL_VALUE_TYPE &rh_lb,
2088 const REAL_VALUE_TYPE &rh_ub,
2089 relation_kind) const final override
2091 frange_arithmetic (MINUS_EXPR, type, lb, lh_lb, rh_ub, dconstninf);
2092 frange_arithmetic (MINUS_EXPR, type, ub, lh_ub, rh_lb, dconstinf);
2094 // [+INF] - [+INF] = NAN
2095 if (real_isinf (&lh_ub, false) && real_isinf (&rh_ub, false))
2096 maybe_nan = true;
2097 // [-INF] - [-INF] = NAN
2098 else if (real_isinf (&lh_lb, true) && real_isinf (&rh_lb, true))
2099 maybe_nan = true;
2100 else
2101 maybe_nan = false;
2103 } fop_minus;
2106 class foperator_mult_div_base : public range_operator_float
2108 protected:
2109 // Given CP[0] to CP[3] floating point values rounded to -INF,
2110 // set LB to the smallest of them (treating -0 as smaller to +0).
2111 // Given CP[4] to CP[7] floating point values rounded to +INF,
2112 // set UB to the largest of them (treating -0 as smaller to +0).
2113 static void find_range (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub,
2114 const REAL_VALUE_TYPE (&cp)[8])
2116 lb = cp[0];
2117 ub = cp[4];
2118 for (int i = 1; i < 4; ++i)
2120 if (real_less (&cp[i], &lb)
2121 || (real_iszero (&lb) && real_isnegzero (&cp[i])))
2122 lb = cp[i];
2123 if (real_less (&ub, &cp[i + 4])
2124 || (real_isnegzero (&ub) && real_iszero (&cp[i + 4])))
2125 ub = cp[i + 4];
2131 class foperator_mult : public foperator_mult_div_base
2133 using range_operator_float::op1_range;
2134 using range_operator_float::op2_range;
2135 public:
2136 virtual bool op1_range (frange &r, tree type,
2137 const frange &lhs,
2138 const frange &op2,
2139 relation_trio = TRIO_VARYING) const final override
2141 if (lhs.undefined_p ())
2142 return false;
2143 range_op_handler rdiv (RDIV_EXPR, type);
2144 if (!rdiv)
2145 return false;
2146 return float_binary_op_range_finish (rdiv.fold_range (r, type, lhs, op2),
2147 r, type, lhs);
2149 virtual bool op2_range (frange &r, tree type,
2150 const frange &lhs,
2151 const frange &op1,
2152 relation_trio = TRIO_VARYING) const final override
2154 return op1_range (r, type, lhs, op1);
2156 private:
2157 void rv_fold (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub, bool &maybe_nan,
2158 tree type,
2159 const REAL_VALUE_TYPE &lh_lb,
2160 const REAL_VALUE_TYPE &lh_ub,
2161 const REAL_VALUE_TYPE &rh_lb,
2162 const REAL_VALUE_TYPE &rh_ub,
2163 relation_kind kind) const final override
2165 bool is_square
2166 = (kind == VREL_EQ
2167 && real_equal (&lh_lb, &rh_lb)
2168 && real_equal (&lh_ub, &rh_ub)
2169 && real_isneg (&lh_lb) == real_isneg (&rh_lb)
2170 && real_isneg (&lh_ub) == real_isneg (&rh_ub));
2172 maybe_nan = false;
2173 // x * x never produces a new NAN and we only multiply the same
2174 // values, so the 0 * INF problematic cases never appear there.
2175 if (!is_square)
2177 // [+-0, +-0] * [+INF,+INF] (or [-INF,-INF] or swapped is a known NAN.
2178 if ((zero_p (lh_lb, lh_ub) && singleton_inf_p (rh_lb, rh_ub))
2179 || (zero_p (rh_lb, rh_ub) && singleton_inf_p (lh_lb, lh_ub)))
2181 real_nan (&lb, "", 0, TYPE_MODE (type));
2182 ub = lb;
2183 maybe_nan = true;
2184 return;
2187 // Otherwise, if one range includes zero and the other ends with +-INF,
2188 // it is a maybe NAN.
2189 if ((contains_zero_p (lh_lb, lh_ub)
2190 && (real_isinf (&rh_lb) || real_isinf (&rh_ub)))
2191 || (contains_zero_p (rh_lb, rh_ub)
2192 && (real_isinf (&lh_lb) || real_isinf (&lh_ub))))
2194 maybe_nan = true;
2196 int signbit_known = signbit_known_p (lh_lb, lh_ub, rh_lb, rh_ub);
2198 // If one of the ranges that includes INF is singleton
2199 // and the other range includes zero, the resulting
2200 // range is INF and NAN, because the 0 * INF boundary
2201 // case will be NAN, but already nextafter (0, 1) * INF
2202 // is INF.
2203 if (singleton_inf_p (lh_lb, lh_ub)
2204 || singleton_inf_p (rh_lb, rh_ub))
2205 return inf_range (lb, ub, signbit_known);
2207 // If one of the multiplicands must be zero, the resulting
2208 // range is +-0 and NAN.
2209 if (zero_p (lh_lb, lh_ub) || zero_p (rh_lb, rh_ub))
2210 return zero_range (lb, ub, signbit_known);
2212 // Otherwise one of the multiplicands could be
2213 // [0.0, nextafter (0.0, 1.0)] and the [DBL_MAX, INF]
2214 // or similarly with different signs. 0.0 * DBL_MAX
2215 // is still 0.0, nextafter (0.0, 1.0) * INF is still INF,
2216 // so if the signs are always the same or always different,
2217 // result is [+0.0, +INF] or [-INF, -0.0], otherwise VARYING.
2218 return zero_to_inf_range (lb, ub, signbit_known);
2222 REAL_VALUE_TYPE cp[8];
2223 // Do a cross-product. At this point none of the multiplications
2224 // should produce a NAN.
2225 frange_arithmetic (MULT_EXPR, type, cp[0], lh_lb, rh_lb, dconstninf);
2226 frange_arithmetic (MULT_EXPR, type, cp[4], lh_lb, rh_lb, dconstinf);
2227 if (is_square)
2229 // For x * x we can just do max (lh_lb * lh_lb, lh_ub * lh_ub)
2230 // as maximum and -0.0 as minimum if 0.0 is in the range,
2231 // otherwise min (lh_lb * lh_lb, lh_ub * lh_ub).
2232 // -0.0 rather than 0.0 because VREL_EQ doesn't prove that
2233 // x and y are bitwise equal, just that they compare equal.
2234 if (contains_zero_p (lh_lb, lh_ub))
2236 if (real_isneg (&lh_lb) == real_isneg (&lh_ub))
2237 cp[1] = dconst0;
2238 else
2239 cp[1] = real_value_negate (&dconst0);
2241 else
2242 cp[1] = cp[0];
2243 cp[2] = cp[0];
2244 cp[5] = cp[4];
2245 cp[6] = cp[4];
2247 else
2249 frange_arithmetic (MULT_EXPR, type, cp[1], lh_lb, rh_ub, dconstninf);
2250 frange_arithmetic (MULT_EXPR, type, cp[5], lh_lb, rh_ub, dconstinf);
2251 frange_arithmetic (MULT_EXPR, type, cp[2], lh_ub, rh_lb, dconstninf);
2252 frange_arithmetic (MULT_EXPR, type, cp[6], lh_ub, rh_lb, dconstinf);
2254 frange_arithmetic (MULT_EXPR, type, cp[3], lh_ub, rh_ub, dconstninf);
2255 frange_arithmetic (MULT_EXPR, type, cp[7], lh_ub, rh_ub, dconstinf);
2257 find_range (lb, ub, cp);
2259 } fop_mult;
2262 class foperator_div : public foperator_mult_div_base
2264 using range_operator_float::op1_range;
2265 using range_operator_float::op2_range;
2266 public:
2267 virtual bool op1_range (frange &r, tree type,
2268 const frange &lhs,
2269 const frange &op2,
2270 relation_trio = TRIO_VARYING) const final override
2272 if (lhs.undefined_p ())
2273 return false;
2274 return float_binary_op_range_finish (fop_mult.fold_range (r, type, lhs,
2275 op2),
2276 r, type, lhs);
2278 virtual bool op2_range (frange &r, tree type,
2279 const frange &lhs,
2280 const frange &op1,
2281 relation_trio = TRIO_VARYING) const final override
2283 if (lhs.undefined_p ())
2284 return false;
2285 return float_binary_op_range_finish (fold_range (r, type, op1, lhs),
2286 r, type, lhs);
2288 private:
2289 void rv_fold (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub, bool &maybe_nan,
2290 tree type,
2291 const REAL_VALUE_TYPE &lh_lb,
2292 const REAL_VALUE_TYPE &lh_ub,
2293 const REAL_VALUE_TYPE &rh_lb,
2294 const REAL_VALUE_TYPE &rh_ub,
2295 relation_kind) const final override
2297 // +-0.0 / +-0.0 or +-INF / +-INF is a known NAN.
2298 if ((zero_p (lh_lb, lh_ub) && zero_p (rh_lb, rh_ub))
2299 || (singleton_inf_p (lh_lb, lh_ub) || singleton_inf_p (rh_lb, rh_ub)))
2301 real_nan (&lb, "", 0, TYPE_MODE (type));
2302 ub = lb;
2303 maybe_nan = true;
2304 return;
2307 // If +-0.0 is in both ranges, it is a maybe NAN.
2308 if (contains_zero_p (lh_lb, lh_ub) && contains_zero_p (rh_lb, rh_ub))
2309 maybe_nan = true;
2310 // If +-INF is in both ranges, it is a maybe NAN.
2311 else if ((real_isinf (&lh_lb) || real_isinf (&lh_ub))
2312 && (real_isinf (&rh_lb) || real_isinf (&rh_ub)))
2313 maybe_nan = true;
2314 else
2315 maybe_nan = false;
2317 int signbit_known = signbit_known_p (lh_lb, lh_ub, rh_lb, rh_ub);
2319 // If dividend must be zero, the range is just +-0
2320 // (including if the divisor is +-INF).
2321 // If divisor must be +-INF, the range is just +-0
2322 // (including if the dividend is zero).
2323 if (zero_p (lh_lb, lh_ub) || singleton_inf_p (rh_lb, rh_ub))
2324 return zero_range (lb, ub, signbit_known);
2326 // If divisor must be zero, the range is just +-INF
2327 // (including if the dividend is +-INF).
2328 // If dividend must be +-INF, the range is just +-INF
2329 // (including if the dividend is zero).
2330 if (zero_p (rh_lb, rh_ub) || singleton_inf_p (lh_lb, lh_ub))
2331 return inf_range (lb, ub, signbit_known);
2333 // Otherwise if both operands may be zero, divisor could be
2334 // nextafter(0.0, +-1.0) and dividend +-0.0
2335 // in which case result is going to INF or vice versa and
2336 // result +0.0. So, all we can say for that case is if the
2337 // signs of divisor and dividend are always the same we have
2338 // [+0.0, +INF], if they are always different we have
2339 // [-INF, -0.0]. If they vary, VARING.
2340 // If both may be +-INF, divisor could be INF and dividend FLT_MAX,
2341 // in which case result is going to INF or vice versa and
2342 // result +0.0. So, all we can say for that case is if the
2343 // signs of divisor and dividend are always the same we have
2344 // [+0.0, +INF], if they are always different we have
2345 // [-INF, -0.0]. If they vary, VARYING.
2346 if (maybe_nan)
2347 return zero_to_inf_range (lb, ub, signbit_known);
2349 REAL_VALUE_TYPE cp[8];
2350 // Do a cross-division. At this point none of the divisions should
2351 // produce a NAN.
2352 frange_arithmetic (RDIV_EXPR, type, cp[0], lh_lb, rh_lb, dconstninf);
2353 frange_arithmetic (RDIV_EXPR, type, cp[1], lh_lb, rh_ub, dconstninf);
2354 frange_arithmetic (RDIV_EXPR, type, cp[2], lh_ub, rh_lb, dconstninf);
2355 frange_arithmetic (RDIV_EXPR, type, cp[3], lh_ub, rh_ub, dconstninf);
2356 frange_arithmetic (RDIV_EXPR, type, cp[4], lh_lb, rh_lb, dconstinf);
2357 frange_arithmetic (RDIV_EXPR, type, cp[5], lh_lb, rh_ub, dconstinf);
2358 frange_arithmetic (RDIV_EXPR, type, cp[6], lh_ub, rh_lb, dconstinf);
2359 frange_arithmetic (RDIV_EXPR, type, cp[7], lh_ub, rh_ub, dconstinf);
2361 find_range (lb, ub, cp);
2363 // If divisor may be zero (but is not known to be only zero),
2364 // and dividend can't be zero, the range can go up to -INF or +INF
2365 // depending on the signs.
2366 if (contains_zero_p (rh_lb, rh_ub))
2368 if (signbit_known <= 0)
2369 real_inf (&lb, true);
2370 if (signbit_known >= 0)
2371 real_inf (&ub, false);
2374 } fop_div;
2376 // Instantiate a range_op_table for floating point operations.
2377 static floating_op_table global_floating_table;
2379 // Pointer to the float table so the dispatch code can access it.
2380 floating_op_table *floating_tree_table = &global_floating_table;
2382 floating_op_table::floating_op_table ()
2384 set (SSA_NAME, fop_identity);
2385 set (PAREN_EXPR, fop_identity);
2386 set (OBJ_TYPE_REF, fop_identity);
2387 set (REAL_CST, fop_identity);
2389 // All the relational operators are expected to work, because the
2390 // calculation of ranges on outgoing edges expect the handlers to be
2391 // present.
2392 set (EQ_EXPR, fop_equal);
2393 set (NE_EXPR, fop_not_equal);
2394 set (LT_EXPR, fop_lt);
2395 set (LE_EXPR, fop_le);
2396 set (GT_EXPR, fop_gt);
2397 set (GE_EXPR, fop_ge);
2398 set (UNLE_EXPR, fop_unordered_le);
2399 set (UNLT_EXPR, fop_unordered_lt);
2400 set (UNGE_EXPR, fop_unordered_ge);
2401 set (UNGT_EXPR, fop_unordered_gt);
2402 set (UNEQ_EXPR, fop_unordered_equal);
2403 set (ORDERED_EXPR, fop_ordered);
2404 set (UNORDERED_EXPR, fop_unordered);
2406 set (ABS_EXPR, fop_abs);
2407 set (NEGATE_EXPR, fop_negate);
2408 set (PLUS_EXPR, fop_plus);
2409 set (MINUS_EXPR, fop_minus);
2410 set (MULT_EXPR, fop_mult);
2411 set (RDIV_EXPR, fop_div);
2414 // Return a pointer to the range_operator_float instance, if there is
2415 // one associated with tree_code CODE.
2417 range_operator_float *
2418 floating_op_table::operator[] (enum tree_code code)
2420 return m_range_tree[code];
2423 // Add OP to the handler table for CODE.
2425 void
2426 floating_op_table::set (enum tree_code code, range_operator_float &op)
2428 gcc_checking_assert (m_range_tree[code] == NULL);
2429 m_range_tree[code] = &op;
2432 #if CHECKING_P
2433 #include "selftest.h"
2435 namespace selftest
2438 // Build an frange from string endpoints.
2440 inline frange
2441 frange_float (const char *lb, const char *ub, tree type = float_type_node)
2443 REAL_VALUE_TYPE min, max;
2444 gcc_assert (real_from_string (&min, lb) == 0);
2445 gcc_assert (real_from_string (&max, ub) == 0);
2446 return frange (type, min, max);
2449 void
2450 range_op_float_tests ()
2452 frange r, r0, r1;
2453 frange trange (float_type_node);
2455 // negate([-5, +10]) => [-10, 5]
2456 r0 = frange_float ("-5", "10");
2457 fop_negate.fold_range (r, float_type_node, r0, trange);
2458 ASSERT_EQ (r, frange_float ("-10", "5"));
2460 // negate([0, 1] -NAN) => [-1, -0] +NAN
2461 r0 = frange_float ("0", "1");
2462 r0.update_nan (true);
2463 fop_negate.fold_range (r, float_type_node, r0, trange);
2464 r1 = frange_float ("-1", "-0");
2465 r1.update_nan (false);
2466 ASSERT_EQ (r, r1);
2468 // [-INF,+INF] + [-INF,+INF] could be a NAN.
2469 range_op_handler plus (PLUS_EXPR, float_type_node);
2470 r0.set_varying (float_type_node);
2471 r1.set_varying (float_type_node);
2472 r0.clear_nan ();
2473 r1.clear_nan ();
2474 plus.fold_range (r, float_type_node, r0, r1);
2475 if (HONOR_NANS (float_type_node))
2476 ASSERT_TRUE (r.maybe_isnan ());
2479 } // namespace selftest
2481 #endif // CHECKING_P