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 frange
&rh ATTRIBUTE_UNUSED
,
66 relation_kind rel ATTRIBUTE_UNUSED
) const
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
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
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
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
112 range_operator_float::lhs_op1_relation (const frange
&lhs ATTRIBUTE_UNUSED
,
113 const frange
&op1 ATTRIBUTE_UNUSED
,
114 const frange
&op2 ATTRIBUTE_UNUSED
,
121 range_operator_float::lhs_op1_relation (const irange
&lhs ATTRIBUTE_UNUSED
,
122 const frange
&op1 ATTRIBUTE_UNUSED
,
123 const frange
&op2 ATTRIBUTE_UNUSED
,
130 range_operator_float::lhs_op2_relation (const irange
&lhs ATTRIBUTE_UNUSED
,
131 const frange
&op1 ATTRIBUTE_UNUSED
,
132 const frange
&op2 ATTRIBUTE_UNUSED
,
139 range_operator_float::lhs_op2_relation (const frange
&lhs ATTRIBUTE_UNUSED
,
140 const frange
&op1 ATTRIBUTE_UNUSED
,
141 const frange
&op2 ATTRIBUTE_UNUSED
,
148 range_operator_float::op1_op2_relation (const irange
&lhs ATTRIBUTE_UNUSED
) const
153 // Set R to [NAN, NAN].
156 frange_set_nan (frange
&r
, tree type
)
159 bool res
= real_nan (&rv
, "", 1, TYPE_MODE (type
));
162 r
.set (type
, rv
, rv
);
165 // Return TRUE if OP1 is known to be free of NANs.
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.
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.
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
))
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
205 frange_drop_inf (frange
&r
, tree type
)
208 real_max_representable (&max
, type
);
209 frange
tmp (type
, r
.lower_bound (), max
);
213 // Crop R to [MIN, +INF] where MIN is the minimum representable number
217 frange_drop_ninf (frange
&r
, tree type
)
220 real_min_representable (&min
, type
);
221 frange
tmp (type
, min
, r
.upper_bound ());
225 // (X <= VAL) produces the range of [-INF, VAL].
228 build_le (frange
&r
, tree type
, const REAL_VALUE_TYPE
&val
)
230 if (real_isnan (&val
))
235 r
.set (type
, dconstninf
, val
);
239 // (X < VAL) produces the range of [-INF, VAL).
242 build_lt (frange
&r
, tree type
, const REAL_VALUE_TYPE
&val
)
244 if (real_isnan (&val
))
249 // < -INF is outside the range.
250 if (real_isinf (&val
, 1))
252 if (HONOR_NANS (type
))
253 frange_set_nan (r
, type
);
258 // Hijack LE because we only support closed intervals.
259 build_le (r
, type
, val
);
263 // (X >= VAL) produces the range of [VAL, +INF].
266 build_ge (frange
&r
, tree type
, const REAL_VALUE_TYPE
&val
)
268 if (real_isnan (&val
))
273 r
.set (type
, val
, dconstinf
);
277 // (X > VAL) produces the range of (VAL, +INF].
280 build_gt (frange
&r
, tree type
, const REAL_VALUE_TYPE
&val
)
282 if (real_isnan (&val
))
287 // > +INF is outside the range.
288 if (real_isinf (&val
, 0))
290 if (HONOR_NANS (type
))
291 frange_set_nan (r
, type
);
297 // Hijack GE because we only support closed intervals.
298 build_ge (r
, type
, val
);
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
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
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
);
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
))
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 ())
362 r
= range_true (type
);
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.
372 if (tmp
.undefined_p ())
373 r
= range_false (type
);
375 r
= range_true_and_false (type
);
378 r
= range_true_and_false (type
);
383 foperator_equal::op1_range (frange
&r
, tree type
,
385 const frange
&op2 ATTRIBUTE_UNUSED
,
386 relation_kind rel
) const
388 switch (get_bool_state (r
, lhs
, type
))
391 // If it's true, the result is the same as 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
);
401 r
.set_varying (type
);
402 // The FALSE side of op1 == op1 implies op1 is a NAN.
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
);
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
;
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
))
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 ())
451 r
= range_true (type
);
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.
461 if (tmp
.undefined_p ())
462 r
= range_true (type
);
464 r
= range_true_and_false (type
);
467 r
= range_true_and_false (type
);
472 foperator_not_equal::op1_range (frange
&r
, tree type
,
474 const frange
&op2 ATTRIBUTE_UNUSED
,
477 switch (get_bool_state (r
, lhs
, type
))
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
487 REAL_VALUE_TYPE tmp
= op2
.lower_bound ();
488 r
.set (type
, tmp
, tmp
, VR_ANTI_RANGE
);
491 r
.set_varying (type
);
495 // If it's false, the result is the same as 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
);
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
;
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
))
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
);
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
);
552 r
= range_true_and_false (type
);
557 foperator_lt::op1_range (frange
&r
,
560 const frange
&op2 ATTRIBUTE_UNUSED
,
563 switch (get_bool_state (r
, lhs
, type
))
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
);
575 build_ge (r
, type
, op2
.lower_bound ());
585 foperator_lt::op2_range (frange
&r
,
588 const frange
&op1 ATTRIBUTE_UNUSED
,
591 switch (get_bool_state (r
, lhs
, type
))
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
);
603 build_le (r
, type
, op1
.upper_bound ());
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
;
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
))
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
);
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
);
654 r
= range_true_and_false (type
);
659 foperator_le::op1_range (frange
&r
,
665 switch (get_bool_state (r
, lhs
, type
))
668 if (build_le (r
, type
, op2
.upper_bound ()))
669 r
.set_nan (fp_prop::NO
);
673 build_gt (r
, type
, op2
.lower_bound ());
683 foperator_le::op2_range (frange
&r
,
689 switch (get_bool_state (r
, lhs
, type
))
692 if (build_ge (r
, type
, op1
.lower_bound ()))
693 r
.set_nan (fp_prop::NO
);
697 build_lt (r
, type
, op1
.upper_bound ());
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
;
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
))
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
);
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
);
748 r
= range_true_and_false (type
);
753 foperator_gt::op1_range (frange
&r
,
756 const frange
&op2 ATTRIBUTE_UNUSED
,
759 switch (get_bool_state (r
, lhs
, type
))
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
);
771 build_le (r
, type
, op2
.upper_bound ());
781 foperator_gt::op2_range (frange
&r
,
784 const frange
&op1 ATTRIBUTE_UNUSED
,
787 switch (get_bool_state (r
, lhs
, type
))
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
);
799 build_ge (r
, type
, op1
.lower_bound ());
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
;
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
))
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
);
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
);
850 r
= range_true_and_false (type
);
855 foperator_ge::op1_range (frange
&r
,
861 switch (get_bool_state (r
, lhs
, type
))
864 build_ge (r
, type
, op2
.lower_bound ());
865 r
.set_nan (fp_prop::NO
);
869 build_lt (r
, type
, op2
.upper_bound ());
879 foperator_ge::op2_range (frange
&r
, tree type
,
884 switch (get_bool_state (r
, lhs
, type
))
887 build_gt (r
, type
, op1
.lower_bound ());
891 build_le (r
, type
, op1
.upper_bound ());
892 r
.set_nan (fp_prop::NO
);
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
;
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
);
925 foperator_unordered::fold_range (irange
&r
, tree type
,
926 const frange
&op1
, const frange
&op2
,
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
);
936 r
= range_true_and_false (type
);
941 foperator_unordered::op1_range (frange
&r
, tree type
,
943 const frange
&op2 ATTRIBUTE_UNUSED
,
946 switch (get_bool_state (r
, lhs
, type
))
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
);
957 r
.set_varying (type
);
958 // A false UNORDERED means both operands are !NAN.
959 r
.set_nan (fp_prop::NO
);
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
;
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
);
992 foperator_ordered::fold_range (irange
&r
, tree type
,
993 const frange
&op1
, const frange
&op2
,
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
);
1003 r
= range_true_and_false (type
);
1008 foperator_ordered::op1_range (frange
&r
, tree type
,
1010 const frange
&op2 ATTRIBUTE_UNUSED
,
1011 relation_kind rel
) const
1013 switch (get_bool_state (r
, lhs
, type
))
1016 r
.set_varying (type
);
1017 // The TRUE side of op1 ORDERED op2 implies op1 is !NAN.
1018 r
.set_nan (fp_prop::NO
);
1022 r
.set_varying (type
);
1023 // The FALSE side of op1 ORDERED op1 implies op1 is !NAN.
1025 r
.set_nan (fp_prop::NO
);
1034 // Placeholder for unimplemented relational operators.
1036 class foperator_relop_unknown
: public range_operator_float
1038 using range_operator_float::fold_range
;
1041 bool fold_range (irange
&r
, tree type
,
1042 const frange
&, const frange
&,
1043 relation_kind
) const final override
1045 r
.set_varying (type
);
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
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.
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
;