compiler: only build thunk struct type when it is needed
[official-gcc.git] / gcc / range-op-float.cc
blob3cf117d8931491df1625f1fde1ea38eaeb7ec2a8
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 irange &rh ATTRIBUTE_UNUSED,
66 relation_kind rel ATTRIBUTE_UNUSED) const
68 return false;
71 bool
72 range_operator_float::fold_range (irange &r ATTRIBUTE_UNUSED,
73 tree type ATTRIBUTE_UNUSED,
74 const frange &lh ATTRIBUTE_UNUSED,
75 const frange &rh 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 frange &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::op1_range (frange &r ATTRIBUTE_UNUSED,
93 tree type ATTRIBUTE_UNUSED,
94 const irange &lhs ATTRIBUTE_UNUSED,
95 const frange &op2 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 frange &lhs ATTRIBUTE_UNUSED,
105 const frange &op1 ATTRIBUTE_UNUSED,
106 relation_kind rel ATTRIBUTE_UNUSED) const
108 return false;
111 bool
112 range_operator_float::op2_range (frange &r ATTRIBUTE_UNUSED,
113 tree type ATTRIBUTE_UNUSED,
114 const irange &lhs ATTRIBUTE_UNUSED,
115 const frange &op1 ATTRIBUTE_UNUSED,
116 relation_kind rel ATTRIBUTE_UNUSED) const
118 return false;
121 relation_kind
122 range_operator_float::lhs_op1_relation (const frange &lhs ATTRIBUTE_UNUSED,
123 const frange &op1 ATTRIBUTE_UNUSED,
124 const frange &op2 ATTRIBUTE_UNUSED,
125 relation_kind) const
127 return VREL_VARYING;
130 relation_kind
131 range_operator_float::lhs_op1_relation (const irange &lhs ATTRIBUTE_UNUSED,
132 const frange &op1 ATTRIBUTE_UNUSED,
133 const frange &op2 ATTRIBUTE_UNUSED,
134 relation_kind) const
136 return VREL_VARYING;
139 relation_kind
140 range_operator_float::lhs_op2_relation (const irange &lhs ATTRIBUTE_UNUSED,
141 const frange &op1 ATTRIBUTE_UNUSED,
142 const frange &op2 ATTRIBUTE_UNUSED,
143 relation_kind) const
145 return VREL_VARYING;
148 relation_kind
149 range_operator_float::lhs_op2_relation (const frange &lhs ATTRIBUTE_UNUSED,
150 const frange &op1 ATTRIBUTE_UNUSED,
151 const frange &op2 ATTRIBUTE_UNUSED,
152 relation_kind) const
154 return VREL_VARYING;
157 relation_kind
158 range_operator_float::op1_op2_relation (const irange &lhs ATTRIBUTE_UNUSED) const
160 return VREL_VARYING;
163 // Return TRUE if OP1 is known to be free of NANs.
165 static inline bool
166 finite_operand_p (const frange &op1)
168 return flag_finite_math_only || !op1.maybe_isnan ();
171 // Return TRUE if OP1 and OP2 are known to be free of NANs.
173 static inline bool
174 finite_operands_p (const frange &op1, const frange &op2)
176 return flag_finite_math_only || (!op1.maybe_isnan () && !op2.maybe_isnan ());
179 // Floating version of relop_early_resolve that takes into account NAN
180 // and -ffinite-math-only.
182 inline bool
183 frelop_early_resolve (irange &r, tree type,
184 const frange &op1, const frange &op2,
185 relation_kind rel, relation_kind my_rel)
187 // If either operand is undefined, return VARYING.
188 if (empty_range_varying (r, type, op1, op2))
189 return true;
191 // We can fold relations from the oracle when we know both operands
192 // are free of NANs, or when -ffinite-math-only.
193 return (finite_operands_p (op1, op2)
194 && relop_early_resolve (r, type, op1, op2, rel, my_rel));
197 // Crop R to [-INF, MAX] where MAX is the maximum representable number
198 // for TYPE.
200 static inline void
201 frange_drop_inf (frange &r, tree type)
203 REAL_VALUE_TYPE max = real_max_representable (type);
204 frange tmp (type, r.lower_bound (), max);
205 r.intersect (tmp);
208 // Crop R to [MIN, +INF] where MIN is the minimum representable number
209 // for TYPE.
211 static inline void
212 frange_drop_ninf (frange &r, tree type)
214 REAL_VALUE_TYPE min = real_min_representable (type);
215 frange tmp (type, min, r.upper_bound ());
216 r.intersect (tmp);
219 // If zero is in R, make sure both -0.0 and +0.0 are in the range.
221 static inline void
222 frange_add_zeros (frange &r, tree type)
224 if (r.undefined_p () || r.known_isnan ())
225 return;
227 if (HONOR_SIGNED_ZEROS (type)
228 && (real_iszero (&r.lower_bound ()) || real_iszero (&r.upper_bound ())))
230 frange zero;
231 zero.set_zero (type);
232 r.union_ (zero);
236 // Build a range that is <= VAL and store it in R.
238 static bool
239 build_le (frange &r, tree type, const frange &val)
241 gcc_checking_assert (!val.known_isnan ());
243 REAL_VALUE_TYPE ninf = frange_val_min (type);
244 r.set (type, ninf, val.upper_bound ());
246 // Add both zeros if there's the possibility of zero equality.
247 frange_add_zeros (r, type);
249 return true;
252 // Build a range that is < VAL and store it in R.
254 static bool
255 build_lt (frange &r, tree type, const frange &val)
257 gcc_checking_assert (!val.known_isnan ());
259 // < -INF is outside the range.
260 if (real_isinf (&val.upper_bound (), 1))
262 if (HONOR_NANS (type))
263 r.set_nan (type);
264 else
265 r.set_undefined ();
266 return false;
268 // We only support closed intervals.
269 REAL_VALUE_TYPE ninf = frange_val_min (type);
270 r.set (type, ninf, val.upper_bound ());
271 return true;
274 // Build a range that is >= VAL and store it in R.
276 static bool
277 build_ge (frange &r, tree type, const frange &val)
279 gcc_checking_assert (!val.known_isnan ());
281 REAL_VALUE_TYPE inf = frange_val_max (type);
282 r.set (type, val.lower_bound (), inf);
284 // Add both zeros if there's the possibility of zero equality.
285 frange_add_zeros (r, type);
287 return true;
290 // Build a range that is > VAL and store it in R.
292 static bool
293 build_gt (frange &r, tree type, const frange &val)
295 gcc_checking_assert (!val.known_isnan ());
297 // > +INF is outside the range.
298 if (real_isinf (&val.lower_bound (), 0))
300 if (HONOR_NANS (type))
301 r.set_nan (type);
302 else
303 r.set_undefined ();
304 return false;
307 // We only support closed intervals.
308 REAL_VALUE_TYPE inf = frange_val_max (type);
309 r.set (type, val.lower_bound (), inf);
310 return true;
314 class foperator_identity : public range_operator_float
316 using range_operator_float::fold_range;
317 using range_operator_float::op1_range;
318 public:
319 bool fold_range (frange &r, tree type ATTRIBUTE_UNUSED,
320 const frange &op1, const frange &op2 ATTRIBUTE_UNUSED,
321 relation_kind) const final override
323 r = op1;
324 return true;
326 bool op1_range (frange &r, tree type ATTRIBUTE_UNUSED,
327 const frange &lhs, const frange &op2 ATTRIBUTE_UNUSED,
328 relation_kind) const final override
330 r = lhs;
331 return true;
333 public:
334 } fop_identity;
336 class foperator_equal : public range_operator_float
338 using range_operator_float::fold_range;
339 using range_operator_float::op1_range;
340 using range_operator_float::op2_range;
341 public:
342 bool fold_range (irange &r, tree type,
343 const frange &op1, const frange &op2,
344 relation_kind rel) const final override;
345 relation_kind op1_op2_relation (const irange &lhs) const final override
347 return equal_op1_op2_relation (lhs);
349 bool op1_range (frange &r, tree type,
350 const irange &lhs, const frange &op2,
351 relation_kind rel) const final override;
352 bool op2_range (frange &r, tree type,
353 const irange &lhs, const frange &op1,
354 relation_kind rel) const final override
356 return op1_range (r, type, lhs, op1, rel);
358 } fop_equal;
360 bool
361 foperator_equal::fold_range (irange &r, tree type,
362 const frange &op1, const frange &op2,
363 relation_kind rel) const
365 if (frelop_early_resolve (r, type, op1, op2, rel, VREL_EQ))
366 return true;
368 if (op1.known_isnan () || op2.known_isnan ())
369 r = range_false (type);
370 // We can be sure the values are always equal or not if both ranges
371 // consist of a single value, and then compare them.
372 else if (op1.singleton_p () && op2.singleton_p ())
374 if (op1 == op2)
375 r = range_true (type);
376 else
377 r = range_false (type);
379 else if (finite_operands_p (op1, op2))
381 // If ranges do not intersect, we know the range is not equal,
382 // otherwise we don't know anything for sure.
383 frange tmp = op1;
384 tmp.intersect (op2);
385 if (tmp.undefined_p ())
386 r = range_false (type);
387 else
388 r = range_true_and_false (type);
390 else
391 r = range_true_and_false (type);
392 return true;
395 bool
396 foperator_equal::op1_range (frange &r, tree type,
397 const irange &lhs,
398 const frange &op2,
399 relation_kind rel) const
401 switch (get_bool_state (r, lhs, type))
403 case BRS_TRUE:
404 // The TRUE side of x == NAN is unreachable.
405 if (op2.known_isnan ())
406 r.set_undefined ();
407 else
409 // If it's true, the result is the same as OP2.
410 r = op2;
411 // Add both zeros if there's the possibility of zero equality.
412 frange_add_zeros (r, type);
413 // The TRUE side of op1 == op2 implies op1 is !NAN.
414 r.clear_nan ();
416 break;
418 case BRS_FALSE:
419 // The FALSE side of op1 == op1 implies op1 is a NAN.
420 if (rel == VREL_EQ)
421 r.set_nan (type);
422 // On the FALSE side of x == NAN, we know nothing about x.
423 else if (op2.known_isnan ())
424 r.set_varying (type);
425 // If the result is false, the only time we know anything is
426 // if OP2 is a constant.
427 else if (op2.singleton_p ()
428 || (finite_operand_p (op2) && op2.zero_p ()))
430 REAL_VALUE_TYPE tmp = op2.lower_bound ();
431 r.set (type, tmp, tmp, VR_ANTI_RANGE);
433 else
434 r.set_varying (type);
435 break;
437 default:
438 break;
440 return true;
443 class foperator_not_equal : public range_operator_float
445 using range_operator_float::fold_range;
446 using range_operator_float::op1_range;
447 public:
448 bool fold_range (irange &r, tree type,
449 const frange &op1, const frange &op2,
450 relation_kind rel) const final override;
451 relation_kind op1_op2_relation (const irange &lhs) const final override
453 return not_equal_op1_op2_relation (lhs);
455 bool op1_range (frange &r, tree type,
456 const irange &lhs, const frange &op2,
457 relation_kind rel) const final override;
458 } fop_not_equal;
460 bool
461 foperator_not_equal::fold_range (irange &r, tree type,
462 const frange &op1, const frange &op2,
463 relation_kind rel) const
465 if (frelop_early_resolve (r, type, op1, op2, rel, VREL_NE))
466 return true;
468 // x != NAN is always TRUE.
469 if (op1.known_isnan () || op2.known_isnan ())
470 r = range_true (type);
471 // We can be sure the values are always equal or not if both ranges
472 // consist of a single value, and then compare them.
473 else if (op1.singleton_p () && op2.singleton_p ())
475 if (op1 != op2)
476 r = range_true (type);
477 else
478 r = range_false (type);
480 else if (finite_operands_p (op1, op2))
482 // If ranges do not intersect, we know the range is not equal,
483 // otherwise we don't know anything for sure.
484 frange tmp = op1;
485 tmp.intersect (op2);
486 if (tmp.undefined_p ())
487 r = range_true (type);
488 else
489 r = range_true_and_false (type);
491 else
492 r = range_true_and_false (type);
493 return true;
496 bool
497 foperator_not_equal::op1_range (frange &r, tree type,
498 const irange &lhs,
499 const frange &op2,
500 relation_kind rel) const
502 switch (get_bool_state (r, lhs, type))
504 case BRS_TRUE:
505 // The TRUE side of op1 != op1 implies op1 is NAN.
506 if (rel == VREL_EQ)
507 r.set_nan (type);
508 // If the result is true, the only time we know anything is if
509 // OP2 is a constant.
510 else if (op2.singleton_p ())
512 // This is correct even if op1 is NAN, because the following
513 // range would be ~[tmp, tmp] with the NAN property set to
514 // maybe (VARYING).
515 REAL_VALUE_TYPE tmp = op2.lower_bound ();
516 r.set (type, tmp, tmp, VR_ANTI_RANGE);
518 else
519 r.set_varying (type);
520 break;
522 case BRS_FALSE:
523 // The FALSE side of x != NAN is impossible.
524 if (op2.known_isnan ())
525 r.set_undefined ();
526 else
528 // If it's false, the result is the same as OP2.
529 r = op2;
530 // Add both zeros if there's the possibility of zero equality.
531 frange_add_zeros (r, type);
532 // The FALSE side of op1 != op2 implies op1 is !NAN.
533 r.clear_nan ();
535 break;
537 default:
538 break;
540 return true;
543 class foperator_lt : public range_operator_float
545 using range_operator_float::fold_range;
546 using range_operator_float::op1_range;
547 using range_operator_float::op2_range;
548 public:
549 bool fold_range (irange &r, tree type,
550 const frange &op1, const frange &op2,
551 relation_kind rel) const final override;
552 relation_kind op1_op2_relation (const irange &lhs) const final override
554 return lt_op1_op2_relation (lhs);
556 bool op1_range (frange &r, tree type,
557 const irange &lhs, const frange &op2,
558 relation_kind rel) const final override;
559 bool op2_range (frange &r, tree type,
560 const irange &lhs, const frange &op1,
561 relation_kind rel) const final override;
562 } fop_lt;
564 bool
565 foperator_lt::fold_range (irange &r, tree type,
566 const frange &op1, const frange &op2,
567 relation_kind rel) const
569 if (frelop_early_resolve (r, type, op1, op2, rel, VREL_LT))
570 return true;
572 if (op1.known_isnan () || op2.known_isnan ())
573 r = range_false (type);
574 else if (finite_operands_p (op1, op2))
576 if (real_less (&op1.upper_bound (), &op2.lower_bound ()))
577 r = range_true (type);
578 else if (!real_less (&op1.lower_bound (), &op2.upper_bound ()))
579 r = range_false (type);
580 else
581 r = range_true_and_false (type);
583 else
584 r = range_true_and_false (type);
585 return true;
588 bool
589 foperator_lt::op1_range (frange &r,
590 tree type,
591 const irange &lhs,
592 const frange &op2,
593 relation_kind) const
595 switch (get_bool_state (r, lhs, type))
597 case BRS_TRUE:
598 // The TRUE side of x < NAN is unreachable.
599 if (op2.known_isnan ())
600 r.set_undefined ();
601 else if (build_lt (r, type, op2))
603 r.clear_nan ();
604 // x < y implies x is not +INF.
605 frange_drop_inf (r, type);
607 break;
609 case BRS_FALSE:
610 // On the FALSE side of x < NAN, we know nothing about x.
611 if (op2.known_isnan ())
612 r.set_varying (type);
613 else
614 build_ge (r, type, op2);
615 break;
617 default:
618 break;
620 return true;
623 bool
624 foperator_lt::op2_range (frange &r,
625 tree type,
626 const irange &lhs,
627 const frange &op1,
628 relation_kind) const
630 switch (get_bool_state (r, lhs, type))
632 case BRS_TRUE:
633 // The TRUE side of NAN < x is unreachable.
634 if (op1.known_isnan ())
635 r.set_undefined ();
636 else if (build_gt (r, type, op1))
638 r.clear_nan ();
639 // x < y implies y is not -INF.
640 frange_drop_ninf (r, type);
642 break;
644 case BRS_FALSE:
645 // On the FALSE side of NAN < x, we know nothing about x.
646 if (op1.known_isnan ())
647 r.set_varying (type);
648 else
649 build_le (r, type, op1);
650 break;
652 default:
653 break;
655 return true;
658 class foperator_le : public range_operator_float
660 using range_operator_float::fold_range;
661 using range_operator_float::op1_range;
662 using range_operator_float::op2_range;
663 public:
664 bool fold_range (irange &r, tree type,
665 const frange &op1, const frange &op2,
666 relation_kind rel) const final override;
667 relation_kind op1_op2_relation (const irange &lhs) const final override
669 return le_op1_op2_relation (lhs);
671 bool op1_range (frange &r, tree type,
672 const irange &lhs, const frange &op2,
673 relation_kind rel) const final override;
674 bool op2_range (frange &r, tree type,
675 const irange &lhs, const frange &op1,
676 relation_kind rel) const final override;
677 } fop_le;
679 bool
680 foperator_le::fold_range (irange &r, tree type,
681 const frange &op1, const frange &op2,
682 relation_kind rel) const
684 if (frelop_early_resolve (r, type, op1, op2, rel, VREL_LE))
685 return true;
687 if (op1.known_isnan () || op2.known_isnan ())
688 r = range_false (type);
689 else if (finite_operands_p (op1, op2))
691 if (real_compare (LE_EXPR, &op1.upper_bound (), &op2.lower_bound ()))
692 r = range_true (type);
693 else if (!real_compare (LE_EXPR, &op1.lower_bound (), &op2.upper_bound ()))
694 r = range_false (type);
695 else
696 r = range_true_and_false (type);
698 else
699 r = range_true_and_false (type);
700 return true;
703 bool
704 foperator_le::op1_range (frange &r,
705 tree type,
706 const irange &lhs,
707 const frange &op2,
708 relation_kind) const
710 switch (get_bool_state (r, lhs, type))
712 case BRS_TRUE:
713 // The TRUE side of x <= NAN is unreachable.
714 if (op2.known_isnan ())
715 r.set_undefined ();
716 else if (build_le (r, type, op2))
717 r.clear_nan ();
718 break;
720 case BRS_FALSE:
721 // On the FALSE side of x <= NAN, we know nothing about x.
722 if (op2.known_isnan ())
723 r.set_varying (type);
724 else
725 build_gt (r, type, op2);
726 break;
728 default:
729 break;
731 return true;
734 bool
735 foperator_le::op2_range (frange &r,
736 tree type,
737 const irange &lhs,
738 const frange &op1,
739 relation_kind) const
741 switch (get_bool_state (r, lhs, type))
743 case BRS_TRUE:
744 // The TRUE side of NAN <= x is unreachable.
745 if (op1.known_isnan ())
746 r.set_undefined ();
747 else if (build_ge (r, type, op1))
748 r.clear_nan ();
749 break;
751 case BRS_FALSE:
752 // On the FALSE side of NAN <= x, we know nothing about x.
753 if (op1.known_isnan ())
754 r.set_varying (type);
755 else
756 build_lt (r, type, op1);
757 break;
759 default:
760 break;
762 return true;
765 class foperator_gt : public range_operator_float
767 using range_operator_float::fold_range;
768 using range_operator_float::op1_range;
769 using range_operator_float::op2_range;
770 public:
771 bool fold_range (irange &r, tree type,
772 const frange &op1, const frange &op2,
773 relation_kind rel) const final override;
774 relation_kind op1_op2_relation (const irange &lhs) const final override
776 return gt_op1_op2_relation (lhs);
778 bool op1_range (frange &r, tree type,
779 const irange &lhs, const frange &op2,
780 relation_kind rel) const final override;
781 bool op2_range (frange &r, tree type,
782 const irange &lhs, const frange &op1,
783 relation_kind rel) const final override;
784 } fop_gt;
786 bool
787 foperator_gt::fold_range (irange &r, tree type,
788 const frange &op1, const frange &op2,
789 relation_kind rel) const
791 if (frelop_early_resolve (r, type, op1, op2, rel, VREL_GT))
792 return true;
794 if (op1.known_isnan () || op2.known_isnan ())
795 r = range_false (type);
796 else if (finite_operands_p (op1, op2))
798 if (real_compare (GT_EXPR, &op1.lower_bound (), &op2.upper_bound ()))
799 r = range_true (type);
800 else if (!real_compare (GT_EXPR, &op1.upper_bound (), &op2.lower_bound ()))
801 r = range_false (type);
802 else
803 r = range_true_and_false (type);
805 else
806 r = range_true_and_false (type);
807 return true;
810 bool
811 foperator_gt::op1_range (frange &r,
812 tree type,
813 const irange &lhs,
814 const frange &op2,
815 relation_kind) const
817 switch (get_bool_state (r, lhs, type))
819 case BRS_TRUE:
820 // The TRUE side of x > NAN is unreachable.
821 if (op2.known_isnan ())
822 r.set_undefined ();
823 else if (build_gt (r, type, op2))
825 r.clear_nan ();
826 // x > y implies x is not -INF.
827 frange_drop_ninf (r, type);
829 break;
831 case BRS_FALSE:
832 // On the FALSE side of x > NAN, we know nothing about x.
833 if (op2.known_isnan ())
834 r.set_varying (type);
835 else
836 build_le (r, type, op2);
837 break;
839 default:
840 break;
842 return true;
845 bool
846 foperator_gt::op2_range (frange &r,
847 tree type,
848 const irange &lhs,
849 const frange &op1,
850 relation_kind) const
852 switch (get_bool_state (r, lhs, type))
854 case BRS_TRUE:
855 // The TRUE side of NAN > x is unreachable.
856 if (op1.known_isnan ())
857 r.set_undefined ();
858 else if (build_lt (r, type, op1))
860 r.clear_nan ();
861 // x > y implies y is not +INF.
862 frange_drop_inf (r, type);
864 break;
866 case BRS_FALSE:
867 // On The FALSE side of NAN > x, we know nothing about x.
868 if (op1.known_isnan ())
869 r.set_varying (type);
870 else
871 build_ge (r, type, op1);
872 break;
874 default:
875 break;
877 return true;
880 class foperator_ge : public range_operator_float
882 using range_operator_float::fold_range;
883 using range_operator_float::op1_range;
884 using range_operator_float::op2_range;
885 public:
886 bool fold_range (irange &r, tree type,
887 const frange &op1, const frange &op2,
888 relation_kind rel) const final override;
889 relation_kind op1_op2_relation (const irange &lhs) const final override
891 return ge_op1_op2_relation (lhs);
893 bool op1_range (frange &r, tree type,
894 const irange &lhs, const frange &op2,
895 relation_kind rel) const final override;
896 bool op2_range (frange &r, tree type,
897 const irange &lhs, const frange &op1,
898 relation_kind rel) const final override;
899 } fop_ge;
901 bool
902 foperator_ge::fold_range (irange &r, tree type,
903 const frange &op1, const frange &op2,
904 relation_kind rel) const
906 if (frelop_early_resolve (r, type, op1, op2, rel, VREL_GE))
907 return true;
909 if (op1.known_isnan () || op2.known_isnan ())
910 r = range_false (type);
911 else if (finite_operands_p (op1, op2))
913 if (real_compare (GE_EXPR, &op1.lower_bound (), &op2.upper_bound ()))
914 r = range_true (type);
915 else if (!real_compare (GE_EXPR, &op1.upper_bound (), &op2.lower_bound ()))
916 r = range_false (type);
917 else
918 r = range_true_and_false (type);
920 else
921 r = range_true_and_false (type);
922 return true;
925 bool
926 foperator_ge::op1_range (frange &r,
927 tree type,
928 const irange &lhs,
929 const frange &op2,
930 relation_kind) const
932 switch (get_bool_state (r, lhs, type))
934 case BRS_TRUE:
935 // The TRUE side of x >= NAN is unreachable.
936 if (op2.known_isnan ())
937 r.set_undefined ();
938 else if (build_ge (r, type, op2))
939 r.clear_nan ();
940 break;
942 case BRS_FALSE:
943 // On the FALSE side of x >= NAN, we know nothing about x.
944 if (op2.known_isnan ())
945 r.set_varying (type);
946 else
947 build_lt (r, type, op2);
948 break;
950 default:
951 break;
953 return true;
956 bool
957 foperator_ge::op2_range (frange &r, tree type,
958 const irange &lhs,
959 const frange &op1,
960 relation_kind) const
962 switch (get_bool_state (r, lhs, type))
964 case BRS_TRUE:
965 // The TRUE side of NAN >= x is unreachable.
966 if (op1.known_isnan ())
967 r.set_undefined ();
968 else
970 build_le (r, type, op1);
971 r.clear_nan ();
973 break;
975 case BRS_FALSE:
976 // On the FALSE side of NAN >= x, we know nothing about x.
977 if (op1.known_isnan ())
978 r.set_varying (type);
979 else
980 build_gt (r, type, op1);
981 break;
983 default:
984 break;
986 return true;
989 // UNORDERED_EXPR comparison.
991 class foperator_unordered : public range_operator_float
993 using range_operator_float::fold_range;
994 using range_operator_float::op1_range;
995 using range_operator_float::op2_range;
996 public:
997 bool fold_range (irange &r, tree type,
998 const frange &op1, const frange &op2,
999 relation_kind rel) const final override;
1000 bool op1_range (frange &r, tree type,
1001 const irange &lhs, const frange &op2,
1002 relation_kind rel) const final override;
1003 bool op2_range (frange &r, tree type,
1004 const irange &lhs, const frange &op1,
1005 relation_kind rel) const final override
1007 return op1_range (r, type, lhs, op1, rel);
1009 } fop_unordered;
1011 bool
1012 foperator_unordered::fold_range (irange &r, tree type,
1013 const frange &op1, const frange &op2,
1014 relation_kind) const
1016 // UNORDERED is TRUE if either operand is a NAN.
1017 if (op1.known_isnan () || op2.known_isnan ())
1018 r = range_true (type);
1019 // UNORDERED is FALSE if neither operand is a NAN.
1020 else if (!op1.maybe_isnan () && !op2.maybe_isnan ())
1021 r = range_false (type);
1022 else
1023 r = range_true_and_false (type);
1024 return true;
1027 bool
1028 foperator_unordered::op1_range (frange &r, tree type,
1029 const irange &lhs,
1030 const frange &op2,
1031 relation_kind rel) const
1033 switch (get_bool_state (r, lhs, type))
1035 case BRS_TRUE:
1036 if (rel == VREL_EQ)
1037 r.set_nan (type);
1038 // Since at least one operand must be NAN, if one of them is
1039 // not, the other must be.
1040 else if (!op2.maybe_isnan ())
1041 r.set_nan (type);
1042 else
1043 r.set_varying (type);
1044 break;
1046 case BRS_FALSE:
1047 if (rel == VREL_EQ)
1048 r.clear_nan ();
1049 // A false UNORDERED means both operands are !NAN, so it's
1050 // impossible for op2 to be a NAN.
1051 else if (op2.known_isnan ())
1052 r.set_undefined ();
1053 else
1055 r.set_varying (type);
1056 r.clear_nan ();
1058 break;
1060 default:
1061 break;
1063 return true;
1066 // ORDERED_EXPR comparison.
1068 class foperator_ordered : public range_operator_float
1070 using range_operator_float::fold_range;
1071 using range_operator_float::op1_range;
1072 using range_operator_float::op2_range;
1073 public:
1074 bool fold_range (irange &r, tree type,
1075 const frange &op1, const frange &op2,
1076 relation_kind rel) const final override;
1077 bool op1_range (frange &r, tree type,
1078 const irange &lhs, const frange &op2,
1079 relation_kind rel) const final override;
1080 bool op2_range (frange &r, tree type,
1081 const irange &lhs, const frange &op1,
1082 relation_kind rel) const final override
1084 return op1_range (r, type, lhs, op1, rel);
1086 } fop_ordered;
1088 bool
1089 foperator_ordered::fold_range (irange &r, tree type,
1090 const frange &op1, const frange &op2,
1091 relation_kind) const
1093 if (op1.known_isnan () || op2.known_isnan ())
1094 r = range_false (type);
1095 else if (!op1.maybe_isnan () && !op2.maybe_isnan ())
1096 r = range_true (type);
1097 else
1098 r = range_true_and_false (type);
1099 return true;
1102 bool
1103 foperator_ordered::op1_range (frange &r, tree type,
1104 const irange &lhs,
1105 const frange &op2,
1106 relation_kind rel) const
1108 switch (get_bool_state (r, lhs, type))
1110 case BRS_TRUE:
1111 // The TRUE side of ORDERED means both operands are !NAN, so
1112 // it's impossible for op2 to be a NAN.
1113 if (op2.known_isnan ())
1114 r.set_undefined ();
1115 else
1117 r.set_varying (type);
1118 r.clear_nan ();
1120 break;
1122 case BRS_FALSE:
1123 r.set_varying (type);
1124 // The FALSE side of op1 ORDERED op1 implies op1 is !NAN.
1125 if (rel == VREL_EQ)
1126 r.clear_nan ();
1127 break;
1129 default:
1130 break;
1132 return true;
1135 // Placeholder for unimplemented relational operators.
1137 class foperator_relop_unknown : public range_operator_float
1139 using range_operator_float::fold_range;
1141 public:
1142 bool fold_range (irange &r, tree type,
1143 const frange &op1, const frange &op2,
1144 relation_kind) const final override
1146 if (op1.known_isnan () || op2.known_isnan ())
1147 r = range_true (type);
1148 else
1149 r.set_varying (type);
1150 return true;
1152 } fop_unordered_relop_unknown;
1155 // Instantiate a range_op_table for floating point operations.
1156 static floating_op_table global_floating_table;
1158 // Pointer to the float table so the dispatch code can access it.
1159 floating_op_table *floating_tree_table = &global_floating_table;
1161 floating_op_table::floating_op_table ()
1163 set (SSA_NAME, fop_identity);
1164 set (PAREN_EXPR, fop_identity);
1165 set (OBJ_TYPE_REF, fop_identity);
1166 set (REAL_CST, fop_identity);
1168 // All the relational operators are expected to work, because the
1169 // calculation of ranges on outgoing edges expect the handlers to be
1170 // present.
1171 set (EQ_EXPR, fop_equal);
1172 set (NE_EXPR, fop_not_equal);
1173 set (LT_EXPR, fop_lt);
1174 set (LE_EXPR, fop_le);
1175 set (GT_EXPR, fop_gt);
1176 set (GE_EXPR, fop_ge);
1177 set (UNLE_EXPR, fop_unordered_relop_unknown);
1178 set (UNLT_EXPR, fop_unordered_relop_unknown);
1179 set (UNGE_EXPR, fop_unordered_relop_unknown);
1180 set (UNGT_EXPR, fop_unordered_relop_unknown);
1181 set (UNEQ_EXPR, fop_unordered_relop_unknown);
1182 set (ORDERED_EXPR, fop_ordered);
1183 set (UNORDERED_EXPR, fop_unordered);
1186 // Return a pointer to the range_operator_float instance, if there is
1187 // one associated with tree_code CODE.
1189 range_operator_float *
1190 floating_op_table::operator[] (enum tree_code code)
1192 return m_range_tree[code];
1195 // Add OP to the handler table for CODE.
1197 void
1198 floating_op_table::set (enum tree_code code, range_operator_float &op)
1200 gcc_checking_assert (m_range_tree[code] == NULL);
1201 m_range_tree[code] = &op;