c++: top level bind when rewriting coroutines [PR106188]
[official-gcc.git] / gcc / range-op-float.cc
blob5fbbaa1fb36f4a32bae88e92115a4e4f62bfbb38
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 ATTRIBUTE_UNUSED,
53 tree type ATTRIBUTE_UNUSED,
54 const frange &lh ATTRIBUTE_UNUSED,
55 const frange &rh ATTRIBUTE_UNUSED,
56 relation_kind rel ATTRIBUTE_UNUSED) const
58 return false;
61 bool
62 range_operator_float::fold_range (irange &r ATTRIBUTE_UNUSED,
63 tree type ATTRIBUTE_UNUSED,
64 const frange &lh ATTRIBUTE_UNUSED,
65 const frange &rh ATTRIBUTE_UNUSED,
66 relation_kind rel ATTRIBUTE_UNUSED) const
68 return false;
71 bool
72 range_operator_float::op1_range (frange &r ATTRIBUTE_UNUSED,
73 tree type ATTRIBUTE_UNUSED,
74 const frange &lhs ATTRIBUTE_UNUSED,
75 const frange &op2 ATTRIBUTE_UNUSED,
76 relation_kind rel ATTRIBUTE_UNUSED) const
78 return false;
81 bool
82 range_operator_float::op1_range (frange &r ATTRIBUTE_UNUSED,
83 tree type ATTRIBUTE_UNUSED,
84 const irange &lhs ATTRIBUTE_UNUSED,
85 const frange &op2 ATTRIBUTE_UNUSED,
86 relation_kind rel ATTRIBUTE_UNUSED) const
88 return false;
91 bool
92 range_operator_float::op2_range (frange &r ATTRIBUTE_UNUSED,
93 tree type ATTRIBUTE_UNUSED,
94 const frange &lhs ATTRIBUTE_UNUSED,
95 const frange &op1 ATTRIBUTE_UNUSED,
96 relation_kind rel ATTRIBUTE_UNUSED) const
98 return false;
101 bool
102 range_operator_float::op2_range (frange &r ATTRIBUTE_UNUSED,
103 tree type ATTRIBUTE_UNUSED,
104 const irange &lhs ATTRIBUTE_UNUSED,
105 const frange &op1 ATTRIBUTE_UNUSED,
106 relation_kind rel ATTRIBUTE_UNUSED) const
108 return false;
111 relation_kind
112 range_operator_float::lhs_op1_relation (const frange &lhs ATTRIBUTE_UNUSED,
113 const frange &op1 ATTRIBUTE_UNUSED,
114 const frange &op2 ATTRIBUTE_UNUSED,
115 relation_kind) const
117 return VREL_VARYING;
120 relation_kind
121 range_operator_float::lhs_op1_relation (const irange &lhs ATTRIBUTE_UNUSED,
122 const frange &op1 ATTRIBUTE_UNUSED,
123 const frange &op2 ATTRIBUTE_UNUSED,
124 relation_kind) const
126 return VREL_VARYING;
129 relation_kind
130 range_operator_float::lhs_op2_relation (const irange &lhs ATTRIBUTE_UNUSED,
131 const frange &op1 ATTRIBUTE_UNUSED,
132 const frange &op2 ATTRIBUTE_UNUSED,
133 relation_kind) const
135 return VREL_VARYING;
138 relation_kind
139 range_operator_float::lhs_op2_relation (const frange &lhs ATTRIBUTE_UNUSED,
140 const frange &op1 ATTRIBUTE_UNUSED,
141 const frange &op2 ATTRIBUTE_UNUSED,
142 relation_kind) const
144 return VREL_VARYING;
147 relation_kind
148 range_operator_float::op1_op2_relation (const irange &lhs ATTRIBUTE_UNUSED) const
150 return VREL_VARYING;
153 // Set R to [NAN, NAN].
155 static inline void
156 frange_set_nan (frange &r, tree type)
158 REAL_VALUE_TYPE rv;
159 bool res = real_nan (&rv, "", 1, TYPE_MODE (type));
160 if (flag_checking)
161 gcc_assert (res);
162 r.set (type, rv, rv);
165 // Return TRUE if OP1 is known to be free of NANs.
167 static inline bool
168 finite_operand_p (const frange &op1)
170 return flag_finite_math_only || op1.get_nan ().no_p ();
173 // Return TRUE if OP1 and OP2 are known to be free of NANs.
175 static inline bool
176 finite_operands_p (const frange &op1, const frange &op2)
178 return (flag_finite_math_only
179 || (op1.get_nan ().no_p ()
180 && op2.get_nan ().no_p ()));
183 // Floating version of relop_early_resolve that takes into account NAN
184 // and -ffinite-math-only.
186 inline bool
187 frelop_early_resolve (irange &r, tree type,
188 const frange &op1, const frange &op2,
189 relation_kind rel, relation_kind my_rel)
191 // If either operand is undefined, return VARYING.
192 if (empty_range_varying (r, type, op1, op2))
193 return true;
195 // We can fold relations from the oracle when we know both operands
196 // are free of NANs, or when -ffinite-math-only.
197 return (finite_operands_p (op1, op2)
198 && relop_early_resolve (r, type, op1, op2, rel, my_rel));
201 // Crop R to [-INF, MAX] where MAX is the maximum representable number
202 // for TYPE.
204 static inline void
205 frange_drop_inf (frange &r, tree type)
207 REAL_VALUE_TYPE max;
208 real_max_representable (&max, type);
209 frange tmp (type, r.lower_bound (), max);
210 r.intersect (tmp);
213 // Crop R to [MIN, +INF] where MIN is the minimum representable number
214 // for TYPE.
216 static inline void
217 frange_drop_ninf (frange &r, tree type)
219 REAL_VALUE_TYPE min;
220 real_min_representable (&min, type);
221 frange tmp (type, min, r.upper_bound ());
222 r.intersect (tmp);
225 // (X <= VAL) produces the range of [-INF, VAL].
227 static bool
228 build_le (frange &r, tree type, const REAL_VALUE_TYPE &val)
230 if (real_isnan (&val))
232 r.set_undefined ();
233 return false;
235 r.set (type, dconstninf, val);
236 return true;
239 // (X < VAL) produces the range of [-INF, VAL).
241 static bool
242 build_lt (frange &r, tree type, const REAL_VALUE_TYPE &val)
244 if (real_isnan (&val))
246 r.set_undefined ();
247 return false;
249 // < -INF is outside the range.
250 if (real_isinf (&val, 1))
252 if (HONOR_NANS (type))
253 frange_set_nan (r, type);
254 else
255 r.set_undefined ();
256 return false;
258 // Hijack LE because we only support closed intervals.
259 build_le (r, type, val);
260 return true;
263 // (X >= VAL) produces the range of [VAL, +INF].
265 static bool
266 build_ge (frange &r, tree type, const REAL_VALUE_TYPE &val)
268 if (real_isnan (&val))
270 r.set_undefined ();
271 return false;
273 r.set (type, val, dconstinf);
274 return true;
277 // (X > VAL) produces the range of (VAL, +INF].
279 static bool
280 build_gt (frange &r, tree type, const REAL_VALUE_TYPE &val)
282 if (real_isnan (&val))
284 r.set_undefined ();
285 return false;
287 // > +INF is outside the range.
288 if (real_isinf (&val, 0))
290 if (HONOR_NANS (type))
291 frange_set_nan (r, type);
292 else
293 r.set_undefined ();
294 return false;
297 // Hijack GE because we only support closed intervals.
298 build_ge (r, type, val);
299 return true;
303 class foperator_identity : public range_operator_float
305 using range_operator_float::fold_range;
306 using range_operator_float::op1_range;
308 bool fold_range (frange &r, tree type ATTRIBUTE_UNUSED,
309 const frange &op1, const frange &op2 ATTRIBUTE_UNUSED,
310 relation_kind) const final override
312 r = op1;
313 return true;
315 bool op1_range (frange &r, tree type ATTRIBUTE_UNUSED,
316 const frange &lhs, const frange &op2 ATTRIBUTE_UNUSED,
317 relation_kind) const final override
319 r = lhs;
320 return true;
322 public:
323 } fop_identity;
325 class foperator_equal : public range_operator_float
327 using range_operator_float::fold_range;
328 using range_operator_float::op1_range;
329 using range_operator_float::op2_range;
331 bool fold_range (irange &r, tree type,
332 const frange &op1, const frange &op2,
333 relation_kind rel) const final override;
334 relation_kind op1_op2_relation (const irange &lhs) const final override
336 return equal_op1_op2_relation (lhs);
338 bool op1_range (frange &r, tree type,
339 const irange &lhs, const frange &op2,
340 relation_kind rel) const final override;
341 bool op2_range (frange &r, tree type,
342 const irange &lhs, const frange &op1,
343 relation_kind rel) const final override
345 return op1_range (r, type, lhs, op1, rel);
347 } fop_equal;
349 bool
350 foperator_equal::fold_range (irange &r, tree type,
351 const frange &op1, const frange &op2,
352 relation_kind rel) const
354 if (frelop_early_resolve (r, type, op1, op2, rel, VREL_EQ))
355 return true;
357 // We can be sure the values are always equal or not if both ranges
358 // consist of a single value, and then compare them.
359 if (op1.singleton_p () && op2.singleton_p ())
361 if (op1 == op2)
362 r = range_true (type);
363 else
364 r = range_false (type);
366 else if (finite_operands_p (op1, op2))
368 // If ranges do not intersect, we know the range is not equal,
369 // otherwise we don't know anything for sure.
370 frange tmp = op1;
371 tmp.intersect (op2);
372 if (tmp.undefined_p ())
373 r = range_false (type);
374 else
375 r = range_true_and_false (type);
377 else
378 r = range_true_and_false (type);
379 return true;
382 bool
383 foperator_equal::op1_range (frange &r, tree type,
384 const irange &lhs,
385 const frange &op2 ATTRIBUTE_UNUSED,
386 relation_kind rel) const
388 switch (get_bool_state (r, lhs, type))
390 case BRS_TRUE:
391 // If it's true, the result is the same as OP2.
392 r = op2;
393 // Make sure we don't copy the sign bit if we may have a zero.
394 if (HONOR_SIGNED_ZEROS (type) && r.contains_p (build_zero_cst (type)))
395 r.set_signbit (fp_prop::VARYING);
396 // The TRUE side of op1 == op2 implies op1 is !NAN.
397 r.set_nan (fp_prop::NO);
398 break;
400 case BRS_FALSE:
401 r.set_varying (type);
402 // The FALSE side of op1 == op1 implies op1 is a NAN.
403 if (rel == VREL_EQ)
404 frange_set_nan (r, type);
405 // If the result is false, the only time we know anything is
406 // if OP2 is a constant.
407 else if (op2.singleton_p ()
408 || (finite_operand_p (op2) && op2.zero_p ()))
410 REAL_VALUE_TYPE tmp = op2.lower_bound ();
411 r.set (type, tmp, tmp, VR_ANTI_RANGE);
413 break;
415 default:
416 break;
418 return true;
421 class foperator_not_equal : public range_operator_float
423 using range_operator_float::fold_range;
424 using range_operator_float::op1_range;
426 bool fold_range (irange &r, tree type,
427 const frange &op1, const frange &op2,
428 relation_kind rel) const final override;
429 relation_kind op1_op2_relation (const irange &lhs) const final override
431 return not_equal_op1_op2_relation (lhs);
433 bool op1_range (frange &r, tree type,
434 const irange &lhs, const frange &op2,
435 relation_kind rel) const final override;
436 } fop_not_equal;
438 bool
439 foperator_not_equal::fold_range (irange &r, tree type,
440 const frange &op1, const frange &op2,
441 relation_kind rel) const
443 if (frelop_early_resolve (r, type, op1, op2, rel, VREL_NE))
444 return true;
446 // We can be sure the values are always equal or not if both ranges
447 // consist of a single value, and then compare them.
448 if (op1.singleton_p () && op2.singleton_p ())
450 if (op1 != op2)
451 r = range_true (type);
452 else
453 r = range_false (type);
455 else if (finite_operands_p (op1, op2))
457 // If ranges do not intersect, we know the range is not equal,
458 // otherwise we don't know anything for sure.
459 frange tmp = op1;
460 tmp.intersect (op2);
461 if (tmp.undefined_p ())
462 r = range_true (type);
463 else
464 r = range_true_and_false (type);
466 else
467 r = range_true_and_false (type);
468 return true;
471 bool
472 foperator_not_equal::op1_range (frange &r, tree type,
473 const irange &lhs,
474 const frange &op2 ATTRIBUTE_UNUSED,
475 relation_kind) const
477 switch (get_bool_state (r, lhs, type))
479 case BRS_TRUE:
480 // If the result is true, the only time we know anything is if
481 // OP2 is a constant.
482 if (op2.singleton_p ())
484 // This is correct even if op1 is NAN, because the following
485 // range would be ~[tmp, tmp] with the NAN property set to
486 // maybe (VARYING).
487 REAL_VALUE_TYPE tmp = op2.lower_bound ();
488 r.set (type, tmp, tmp, VR_ANTI_RANGE);
490 else
491 r.set_varying (type);
492 break;
494 case BRS_FALSE:
495 // If it's false, the result is the same as OP2.
496 r = op2;
497 // Make sure we don't copy the sign bit if we may have a zero.
498 if (HONOR_SIGNED_ZEROS (type) && r.contains_p (build_zero_cst (type)))
499 r.set_signbit (fp_prop::VARYING);
500 // The FALSE side of op1 != op2 implies op1 is !NAN.
501 r.set_nan (fp_prop::NO);
502 break;
504 default:
505 break;
507 return true;
510 class foperator_lt : public range_operator_float
512 using range_operator_float::fold_range;
513 using range_operator_float::op1_range;
514 using range_operator_float::op2_range;
516 bool fold_range (irange &r, tree type,
517 const frange &op1, const frange &op2,
518 relation_kind rel) const final override;
519 relation_kind op1_op2_relation (const irange &lhs) const final override
521 return lt_op1_op2_relation (lhs);
523 bool op1_range (frange &r, tree type,
524 const irange &lhs, const frange &op2,
525 relation_kind rel) const final override;
526 bool op2_range (frange &r, tree type,
527 const irange &lhs, const frange &op1,
528 relation_kind rel) const final override;
529 } fop_lt;
531 bool
532 foperator_lt::fold_range (irange &r, tree type,
533 const frange &op1, const frange &op2,
534 relation_kind rel) const
536 if (frelop_early_resolve (r, type, op1, op2, rel, VREL_LT))
537 return true;
539 if (finite_operands_p (op1, op2))
541 if (real_less (&op1.upper_bound (), &op2.lower_bound ()))
542 r = range_true (type);
543 else if (finite_operands_p (op1, op2)
544 && !real_less (&op1.lower_bound (), &op2.upper_bound ()))
545 r = range_false (type);
546 else
547 r = range_true_and_false (type);
549 else if (op1.get_nan ().yes_p () || op2.get_nan ().yes_p ())
550 r = range_false (type);
551 else
552 r = range_true_and_false (type);
553 return true;
556 bool
557 foperator_lt::op1_range (frange &r,
558 tree type,
559 const irange &lhs,
560 const frange &op2 ATTRIBUTE_UNUSED,
561 relation_kind) const
563 switch (get_bool_state (r, lhs, type))
565 case BRS_TRUE:
566 if (build_lt (r, type, op2.upper_bound ()))
568 r.set_nan (fp_prop::NO);
569 // x < y implies x is not +INF.
570 frange_drop_inf (r, type);
572 break;
574 case BRS_FALSE:
575 build_ge (r, type, op2.lower_bound ());
576 break;
578 default:
579 break;
581 return true;
584 bool
585 foperator_lt::op2_range (frange &r,
586 tree type,
587 const irange &lhs,
588 const frange &op1 ATTRIBUTE_UNUSED,
589 relation_kind) const
591 switch (get_bool_state (r, lhs, type))
593 case BRS_TRUE:
594 if (build_gt (r, type, op1.lower_bound ()))
596 r.set_nan (fp_prop::NO);
597 // x < y implies y is not -INF.
598 frange_drop_ninf (r, type);
600 break;
602 case BRS_FALSE:
603 build_le (r, type, op1.upper_bound ());
604 break;
606 default:
607 break;
609 return true;
612 class foperator_le : public range_operator_float
614 using range_operator_float::fold_range;
615 using range_operator_float::op1_range;
616 using range_operator_float::op2_range;
618 bool fold_range (irange &r, tree type,
619 const frange &op1, const frange &op2,
620 relation_kind rel) const final override;
621 relation_kind op1_op2_relation (const irange &lhs) const final override
623 return le_op1_op2_relation (lhs);
625 bool op1_range (frange &r, tree type,
626 const irange &lhs, const frange &op2,
627 relation_kind rel) const final override;
628 bool op2_range (frange &r, tree type,
629 const irange &lhs, const frange &op1,
630 relation_kind rel) const final override;
631 } fop_le;
633 bool
634 foperator_le::fold_range (irange &r, tree type,
635 const frange &op1, const frange &op2,
636 relation_kind rel) const
638 if (frelop_early_resolve (r, type, op1, op2, rel, VREL_LE))
639 return true;
641 if (finite_operands_p (op1, op2))
643 if (real_compare (LE_EXPR, &op1.upper_bound (), &op2.lower_bound ()))
644 r = range_true (type);
645 else if (finite_operands_p (op1, op2)
646 && !real_compare (LE_EXPR, &op1.lower_bound (), &op2.upper_bound ()))
647 r = range_false (type);
648 else
649 r = range_true_and_false (type);
651 else if (op1.get_nan ().yes_p () || op2.get_nan ().yes_p ())
652 r = range_false (type);
653 else
654 r = range_true_and_false (type);
655 return true;
658 bool
659 foperator_le::op1_range (frange &r,
660 tree type,
661 const irange &lhs,
662 const frange &op2,
663 relation_kind) const
665 switch (get_bool_state (r, lhs, type))
667 case BRS_TRUE:
668 if (build_le (r, type, op2.upper_bound ()))
669 r.set_nan (fp_prop::NO);
670 break;
672 case BRS_FALSE:
673 build_gt (r, type, op2.lower_bound ());
674 break;
676 default:
677 break;
679 return true;
682 bool
683 foperator_le::op2_range (frange &r,
684 tree type,
685 const irange &lhs,
686 const frange &op1,
687 relation_kind) const
689 switch (get_bool_state (r, lhs, type))
691 case BRS_TRUE:
692 if (build_ge (r, type, op1.lower_bound ()))
693 r.set_nan (fp_prop::NO);
694 break;
696 case BRS_FALSE:
697 build_lt (r, type, op1.upper_bound ());
698 break;
700 default:
701 break;
703 return true;
706 class foperator_gt : public range_operator_float
708 using range_operator_float::fold_range;
709 using range_operator_float::op1_range;
710 using range_operator_float::op2_range;
712 bool fold_range (irange &r, tree type,
713 const frange &op1, const frange &op2,
714 relation_kind rel) const final override;
715 relation_kind op1_op2_relation (const irange &lhs) const final override
717 return gt_op1_op2_relation (lhs);
719 bool op1_range (frange &r, tree type,
720 const irange &lhs, const frange &op2,
721 relation_kind rel) const final override;
722 bool op2_range (frange &r, tree type,
723 const irange &lhs, const frange &op1,
724 relation_kind rel) const final override;
725 } fop_gt;
727 bool
728 foperator_gt::fold_range (irange &r, tree type,
729 const frange &op1, const frange &op2,
730 relation_kind rel) const
732 if (frelop_early_resolve (r, type, op1, op2, rel, VREL_GT))
733 return true;
735 if (finite_operands_p (op1, op2))
737 if (real_compare (GT_EXPR, &op1.lower_bound (), &op2.upper_bound ()))
738 r = range_true (type);
739 else if (finite_operands_p (op1, op2)
740 && !real_compare (GT_EXPR, &op1.upper_bound (), &op2.lower_bound ()))
741 r = range_false (type);
742 else
743 r = range_true_and_false (type);
745 else if (op1.get_nan ().yes_p () || op2.get_nan ().yes_p ())
746 r = range_false (type);
747 else
748 r = range_true_and_false (type);
749 return true;
752 bool
753 foperator_gt::op1_range (frange &r,
754 tree type,
755 const irange &lhs,
756 const frange &op2 ATTRIBUTE_UNUSED,
757 relation_kind) const
759 switch (get_bool_state (r, lhs, type))
761 case BRS_TRUE:
762 if (build_gt (r, type, op2.lower_bound ()))
764 r.set_nan (fp_prop::NO);
765 // x > y implies x is not -INF.
766 frange_drop_ninf (r, type);
768 break;
770 case BRS_FALSE:
771 build_le (r, type, op2.upper_bound ());
772 break;
774 default:
775 break;
777 return true;
780 bool
781 foperator_gt::op2_range (frange &r,
782 tree type,
783 const irange &lhs,
784 const frange &op1 ATTRIBUTE_UNUSED,
785 relation_kind) const
787 switch (get_bool_state (r, lhs, type))
789 case BRS_TRUE:
790 if (build_lt (r, type, op1.upper_bound ()))
792 r.set_nan (fp_prop::NO);
793 // x > y implies y is not +INF.
794 frange_drop_inf (r, type);
796 break;
798 case BRS_FALSE:
799 build_ge (r, type, op1.lower_bound ());
800 break;
802 default:
803 break;
805 return true;
808 class foperator_ge : public range_operator_float
810 using range_operator_float::fold_range;
811 using range_operator_float::op1_range;
812 using range_operator_float::op2_range;
814 bool fold_range (irange &r, tree type,
815 const frange &op1, const frange &op2,
816 relation_kind rel) const final override;
817 relation_kind op1_op2_relation (const irange &lhs) const final override
819 return ge_op1_op2_relation (lhs);
821 bool op1_range (frange &r, tree type,
822 const irange &lhs, const frange &op2,
823 relation_kind rel) const final override;
824 bool op2_range (frange &r, tree type,
825 const irange &lhs, const frange &op1,
826 relation_kind rel) const final override;
827 } fop_ge;
829 bool
830 foperator_ge::fold_range (irange &r, tree type,
831 const frange &op1, const frange &op2,
832 relation_kind rel) const
834 if (frelop_early_resolve (r, type, op1, op2, rel, VREL_GE))
835 return true;
837 if (finite_operands_p (op1, op2))
839 if (real_compare (GE_EXPR, &op1.lower_bound (), &op2.upper_bound ()))
840 r = range_true (type);
841 else if (finite_operands_p (op1, op2)
842 && !real_compare (GE_EXPR, &op1.upper_bound (), &op2.lower_bound ()))
843 r = range_false (type);
844 else
845 r = range_true_and_false (type);
847 else if (op1.get_nan ().yes_p () || op2.get_nan ().yes_p ())
848 r = range_false (type);
849 else
850 r = range_true_and_false (type);
851 return true;
854 bool
855 foperator_ge::op1_range (frange &r,
856 tree type,
857 const irange &lhs,
858 const frange &op2,
859 relation_kind) const
861 switch (get_bool_state (r, lhs, type))
863 case BRS_TRUE:
864 build_ge (r, type, op2.lower_bound ());
865 r.set_nan (fp_prop::NO);
866 break;
868 case BRS_FALSE:
869 build_lt (r, type, op2.upper_bound ());
870 break;
872 default:
873 break;
875 return true;
878 bool
879 foperator_ge::op2_range (frange &r, tree type,
880 const irange &lhs,
881 const frange &op1,
882 relation_kind) const
884 switch (get_bool_state (r, lhs, type))
886 case BRS_FALSE:
887 build_gt (r, type, op1.lower_bound ());
888 break;
890 case BRS_TRUE:
891 build_le (r, type, op1.upper_bound ());
892 r.set_nan (fp_prop::NO);
893 break;
895 default:
896 break;
898 return true;
901 // UNORDERED_EXPR comparison.
903 class foperator_unordered : public range_operator_float
905 using range_operator_float::fold_range;
906 using range_operator_float::op1_range;
907 using range_operator_float::op2_range;
909 public:
910 bool fold_range (irange &r, tree type,
911 const frange &op1, const frange &op2,
912 relation_kind rel) const final override;
913 bool op1_range (frange &r, tree type,
914 const irange &lhs, const frange &op2,
915 relation_kind rel) const final override;
916 bool op2_range (frange &r, tree type,
917 const irange &lhs, const frange &op1,
918 relation_kind rel) const final override
920 return op1_range (r, type, lhs, op1, rel);
922 } fop_unordered;
924 bool
925 foperator_unordered::fold_range (irange &r, tree type,
926 const frange &op1, const frange &op2,
927 relation_kind) const
929 // UNORDERED is TRUE if either operand is a NAN.
930 if (op1.get_nan ().yes_p () || op2.get_nan ().yes_p ())
931 r = range_true (type);
932 // UNORDERED is FALSE if neither operand is a NAN.
933 else if (op1.get_nan ().no_p () && op2.get_nan ().no_p ())
934 r = range_false (type);
935 else
936 r = range_true_and_false (type);
937 return true;
940 bool
941 foperator_unordered::op1_range (frange &r, tree type,
942 const irange &lhs,
943 const frange &op2 ATTRIBUTE_UNUSED,
944 relation_kind) const
946 switch (get_bool_state (r, lhs, type))
948 case BRS_TRUE:
949 r.set_varying (type);
950 // Since at least one operand must be NAN, if one of them is
951 // not, the other must be.
952 if (op2.get_nan ().no_p ())
953 frange_set_nan (r, type);
954 break;
956 case BRS_FALSE:
957 r.set_varying (type);
958 // A false UNORDERED means both operands are !NAN.
959 r.set_nan (fp_prop::NO);
960 break;
962 default:
963 break;
965 return true;
968 // ORDERED_EXPR comparison.
970 class foperator_ordered : public range_operator_float
972 using range_operator_float::fold_range;
973 using range_operator_float::op1_range;
974 using range_operator_float::op2_range;
976 public:
977 bool fold_range (irange &r, tree type,
978 const frange &op1, const frange &op2,
979 relation_kind rel) const final override;
980 bool op1_range (frange &r, tree type,
981 const irange &lhs, const frange &op2,
982 relation_kind rel) const final override;
983 bool op2_range (frange &r, tree type,
984 const irange &lhs, const frange &op1,
985 relation_kind rel) const final override
987 return op1_range (r, type, lhs, op1, rel);
989 } fop_ordered;
991 bool
992 foperator_ordered::fold_range (irange &r, tree type,
993 const frange &op1, const frange &op2,
994 relation_kind) const
996 // ORDERED is TRUE if neither operand is a NAN.
997 if (op1.get_nan ().no_p () && op2.get_nan ().no_p ())
998 r = range_true (type);
999 // ORDERED is FALSE if either operand is a NAN.
1000 else if (op1.get_nan ().yes_p () || op2.get_nan ().yes_p ())
1001 r = range_false (type);
1002 else
1003 r = range_true_and_false (type);
1004 return true;
1007 bool
1008 foperator_ordered::op1_range (frange &r, tree type,
1009 const irange &lhs,
1010 const frange &op2 ATTRIBUTE_UNUSED,
1011 relation_kind rel) const
1013 switch (get_bool_state (r, lhs, type))
1015 case BRS_TRUE:
1016 r.set_varying (type);
1017 // The TRUE side of op1 ORDERED op2 implies op1 is !NAN.
1018 r.set_nan (fp_prop::NO);
1019 break;
1021 case BRS_FALSE:
1022 r.set_varying (type);
1023 // The FALSE side of op1 ORDERED op1 implies op1 is !NAN.
1024 if (rel == VREL_EQ)
1025 r.set_nan (fp_prop::NO);
1026 break;
1028 default:
1029 break;
1031 return true;
1034 // Placeholder for unimplemented relational operators.
1036 class foperator_relop_unknown : public range_operator_float
1038 using range_operator_float::fold_range;
1040 public:
1041 bool fold_range (irange &r, tree type,
1042 const frange &, const frange &,
1043 relation_kind) const final override
1045 r.set_varying (type);
1046 return true;
1048 } fop_relop_unknown;
1051 // Instantiate a range_op_table for floating point operations.
1052 static floating_op_table global_floating_table;
1054 // Pointer to the float table so the dispatch code can access it.
1055 floating_op_table *floating_tree_table = &global_floating_table;
1057 floating_op_table::floating_op_table ()
1059 set (SSA_NAME, fop_identity);
1060 set (PAREN_EXPR, fop_identity);
1061 set (OBJ_TYPE_REF, fop_identity);
1062 set (REAL_CST, fop_identity);
1064 // All the relational operators are expected to work, because the
1065 // calculation of ranges on outgoing edges expect the handlers to be
1066 // present.
1067 set (EQ_EXPR, fop_equal);
1068 set (NE_EXPR, fop_not_equal);
1069 set (LT_EXPR, fop_lt);
1070 set (LE_EXPR, fop_le);
1071 set (GT_EXPR, fop_gt);
1072 set (GE_EXPR, fop_ge);
1073 set (UNLE_EXPR, fop_relop_unknown);
1074 set (UNLT_EXPR, fop_relop_unknown);
1075 set (UNGE_EXPR, fop_relop_unknown);
1076 set (UNGT_EXPR, fop_relop_unknown);
1077 set (UNEQ_EXPR, fop_relop_unknown);
1078 set (ORDERED_EXPR, fop_ordered);
1079 set (UNORDERED_EXPR, fop_unordered);
1082 // Return a pointer to the range_operator_float instance, if there is
1083 // one associated with tree_code CODE.
1085 range_operator_float *
1086 floating_op_table::operator[] (enum tree_code code)
1088 return m_range_tree[code];
1091 // Add OP to the handler table for CODE.
1093 void
1094 floating_op_table::set (enum tree_code code, range_operator_float &op)
1096 gcc_checking_assert (m_range_tree[code] == NULL);
1097 m_range_tree[code] = &op;