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)
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/>. */
23 #include "coretypes.h"
25 #include "insn-codes.h"
30 #include "tree-pass.h"
32 #include "optabs-tree.h"
33 #include "gimple-pretty-print.h"
34 #include "diagnostic-core.h"
36 #include "fold-const.h"
37 #include "stor-layout.h"
40 #include "gimple-iterator.h"
41 #include "gimple-fold.h"
43 #include "gimple-walk.h"
46 #include "value-relation.h"
49 // Default definitions for floating point operators.
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
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
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
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
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
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
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
122 range_operator_float::lhs_op1_relation (const frange
&lhs ATTRIBUTE_UNUSED
,
123 const frange
&op1 ATTRIBUTE_UNUSED
,
124 const frange
&op2 ATTRIBUTE_UNUSED
,
131 range_operator_float::lhs_op1_relation (const irange
&lhs ATTRIBUTE_UNUSED
,
132 const frange
&op1 ATTRIBUTE_UNUSED
,
133 const frange
&op2 ATTRIBUTE_UNUSED
,
140 range_operator_float::lhs_op2_relation (const irange
&lhs ATTRIBUTE_UNUSED
,
141 const frange
&op1 ATTRIBUTE_UNUSED
,
142 const frange
&op2 ATTRIBUTE_UNUSED
,
149 range_operator_float::lhs_op2_relation (const frange
&lhs ATTRIBUTE_UNUSED
,
150 const frange
&op1 ATTRIBUTE_UNUSED
,
151 const frange
&op2 ATTRIBUTE_UNUSED
,
158 range_operator_float::op1_op2_relation (const irange
&lhs ATTRIBUTE_UNUSED
) const
163 // Return TRUE if OP1 is known to be free of NANs.
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.
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.
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
))
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
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
);
208 // Crop R to [MIN, +INF] where MIN is the minimum representable number
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 ());
219 // If zero is in R, make sure both -0.0 and +0.0 are in the range.
222 frange_add_zeros (frange
&r
, tree type
)
224 if (r
.undefined_p () || r
.known_isnan ())
227 if (HONOR_SIGNED_ZEROS (type
)
228 && (real_iszero (&r
.lower_bound ()) || real_iszero (&r
.upper_bound ())))
231 zero
.set_zero (type
);
236 // Build a range that is <= VAL and store it in R.
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
);
252 // Build a range that is < VAL and store it in R.
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
))
268 // We only support closed intervals.
269 REAL_VALUE_TYPE ninf
= frange_val_min (type
);
270 r
.set (type
, ninf
, val
.upper_bound ());
274 // Build a range that is >= VAL and store it in R.
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
);
290 // Build a range that is > VAL and store it in R.
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
))
307 // We only support closed intervals.
308 REAL_VALUE_TYPE inf
= frange_val_max (type
);
309 r
.set (type
, val
.lower_bound (), inf
);
314 class foperator_identity
: public range_operator_float
316 using range_operator_float::fold_range
;
317 using range_operator_float::op1_range
;
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
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
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
;
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
);
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
))
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 ())
375 r
= range_true (type
);
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.
385 if (tmp
.undefined_p ())
386 r
= range_false (type
);
388 r
= range_true_and_false (type
);
391 r
= range_true_and_false (type
);
396 foperator_equal::op1_range (frange
&r
, tree type
,
399 relation_kind rel
) const
401 switch (get_bool_state (r
, lhs
, type
))
404 // The TRUE side of x == NAN is unreachable.
405 if (op2
.known_isnan ())
409 // If it's true, the result is the same as 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.
419 // The FALSE side of op1 == op1 implies op1 is a NAN.
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
);
434 r
.set_varying (type
);
443 class foperator_not_equal
: public range_operator_float
445 using range_operator_float::fold_range
;
446 using range_operator_float::op1_range
;
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
;
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
))
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 ())
476 r
= range_true (type
);
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.
486 if (tmp
.undefined_p ())
487 r
= range_true (type
);
489 r
= range_true_and_false (type
);
492 r
= range_true_and_false (type
);
497 foperator_not_equal::op1_range (frange
&r
, tree type
,
500 relation_kind rel
) const
502 switch (get_bool_state (r
, lhs
, type
))
505 // The TRUE side of op1 != op1 implies op1 is NAN.
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
515 REAL_VALUE_TYPE tmp
= op2
.lower_bound ();
516 r
.set (type
, tmp
, tmp
, VR_ANTI_RANGE
);
519 r
.set_varying (type
);
523 // The FALSE side of x != NAN is impossible.
524 if (op2
.known_isnan ())
528 // If it's false, the result is the same as 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.
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
;
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
;
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
))
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
);
581 r
= range_true_and_false (type
);
584 r
= range_true_and_false (type
);
589 foperator_lt::op1_range (frange
&r
,
595 switch (get_bool_state (r
, lhs
, type
))
598 // The TRUE side of x < NAN is unreachable.
599 if (op2
.known_isnan ())
601 else if (build_lt (r
, type
, op2
))
604 // x < y implies x is not +INF.
605 frange_drop_inf (r
, type
);
610 // On the FALSE side of x < NAN, we know nothing about x.
611 if (op2
.known_isnan ())
612 r
.set_varying (type
);
614 build_ge (r
, type
, op2
);
624 foperator_lt::op2_range (frange
&r
,
630 switch (get_bool_state (r
, lhs
, type
))
633 // The TRUE side of NAN < x is unreachable.
634 if (op1
.known_isnan ())
636 else if (build_gt (r
, type
, op1
))
639 // x < y implies y is not -INF.
640 frange_drop_ninf (r
, type
);
645 // On the FALSE side of NAN < x, we know nothing about x.
646 if (op1
.known_isnan ())
647 r
.set_varying (type
);
649 build_le (r
, type
, op1
);
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
;
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
;
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
))
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
);
696 r
= range_true_and_false (type
);
699 r
= range_true_and_false (type
);
704 foperator_le::op1_range (frange
&r
,
710 switch (get_bool_state (r
, lhs
, type
))
713 // The TRUE side of x <= NAN is unreachable.
714 if (op2
.known_isnan ())
716 else if (build_le (r
, type
, op2
))
721 // On the FALSE side of x <= NAN, we know nothing about x.
722 if (op2
.known_isnan ())
723 r
.set_varying (type
);
725 build_gt (r
, type
, op2
);
735 foperator_le::op2_range (frange
&r
,
741 switch (get_bool_state (r
, lhs
, type
))
744 // The TRUE side of NAN <= x is unreachable.
745 if (op1
.known_isnan ())
747 else if (build_ge (r
, type
, op1
))
752 // On the FALSE side of NAN <= x, we know nothing about x.
753 if (op1
.known_isnan ())
754 r
.set_varying (type
);
756 build_lt (r
, type
, op1
);
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
;
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
;
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
))
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
);
803 r
= range_true_and_false (type
);
806 r
= range_true_and_false (type
);
811 foperator_gt::op1_range (frange
&r
,
817 switch (get_bool_state (r
, lhs
, type
))
820 // The TRUE side of x > NAN is unreachable.
821 if (op2
.known_isnan ())
823 else if (build_gt (r
, type
, op2
))
826 // x > y implies x is not -INF.
827 frange_drop_ninf (r
, type
);
832 // On the FALSE side of x > NAN, we know nothing about x.
833 if (op2
.known_isnan ())
834 r
.set_varying (type
);
836 build_le (r
, type
, op2
);
846 foperator_gt::op2_range (frange
&r
,
852 switch (get_bool_state (r
, lhs
, type
))
855 // The TRUE side of NAN > x is unreachable.
856 if (op1
.known_isnan ())
858 else if (build_lt (r
, type
, op1
))
861 // x > y implies y is not +INF.
862 frange_drop_inf (r
, type
);
867 // On The FALSE side of NAN > x, we know nothing about x.
868 if (op1
.known_isnan ())
869 r
.set_varying (type
);
871 build_ge (r
, type
, op1
);
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
;
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
;
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
))
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
);
918 r
= range_true_and_false (type
);
921 r
= range_true_and_false (type
);
926 foperator_ge::op1_range (frange
&r
,
932 switch (get_bool_state (r
, lhs
, type
))
935 // The TRUE side of x >= NAN is unreachable.
936 if (op2
.known_isnan ())
938 else if (build_ge (r
, type
, op2
))
943 // On the FALSE side of x >= NAN, we know nothing about x.
944 if (op2
.known_isnan ())
945 r
.set_varying (type
);
947 build_lt (r
, type
, op2
);
957 foperator_ge::op2_range (frange
&r
, tree type
,
962 switch (get_bool_state (r
, lhs
, type
))
965 // The TRUE side of NAN >= x is unreachable.
966 if (op1
.known_isnan ())
970 build_le (r
, type
, op1
);
976 // On the FALSE side of NAN >= x, we know nothing about x.
977 if (op1
.known_isnan ())
978 r
.set_varying (type
);
980 build_gt (r
, type
, op1
);
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
;
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
);
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
);
1023 r
= range_true_and_false (type
);
1028 foperator_unordered::op1_range (frange
&r
, tree type
,
1031 relation_kind rel
) const
1033 switch (get_bool_state (r
, lhs
, 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 ())
1043 r
.set_varying (type
);
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 ())
1055 r
.set_varying (type
);
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
;
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
);
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
);
1098 r
= range_true_and_false (type
);
1103 foperator_ordered::op1_range (frange
&r
, tree type
,
1106 relation_kind rel
) const
1108 switch (get_bool_state (r
, lhs
, type
))
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 ())
1117 r
.set_varying (type
);
1123 r
.set_varying (type
);
1124 // The FALSE side of op1 ORDERED op1 implies op1 is !NAN.
1135 // Placeholder for unimplemented relational operators.
1137 class foperator_relop_unknown
: public range_operator_float
1139 using range_operator_float::fold_range
;
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
);
1149 r
.set_varying (type
);
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
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.
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
;