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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
164 range_operator_float::op1_op2_relation (const frange
&lhs ATTRIBUTE_UNUSED
) const
169 // Return TRUE if OP1 and OP2 may be a NAN.
172 maybe_isnan (const frange
&op1
, const frange
&op2
)
174 return op1
.maybe_isnan () || op2
.maybe_isnan ();
177 // Floating version of relop_early_resolve that takes into account NAN
178 // and -ffinite-math-only.
181 frelop_early_resolve (irange
&r
, tree type
,
182 const frange
&op1
, const frange
&op2
,
183 relation_trio rel
, relation_kind my_rel
)
185 // If either operand is undefined, return VARYING.
186 if (empty_range_varying (r
, type
, op1
, op2
))
189 // We can fold relations from the oracle when we know both operands
190 // are free of NANs, or when -ffinite-math-only.
191 return (!maybe_isnan (op1
, op2
)
192 && relop_early_resolve (r
, type
, op1
, op2
, rel
, my_rel
));
195 // Crop R to [-INF, MAX] where MAX is the maximum representable number
199 frange_drop_inf (frange
&r
, tree type
)
201 REAL_VALUE_TYPE max
= real_max_representable (type
);
202 frange
tmp (type
, r
.lower_bound (), max
);
206 // Crop R to [MIN, +INF] where MIN is the minimum representable number
210 frange_drop_ninf (frange
&r
, tree type
)
212 REAL_VALUE_TYPE min
= real_min_representable (type
);
213 frange
tmp (type
, min
, r
.upper_bound ());
217 // If zero is in R, make sure both -0.0 and +0.0 are in the range.
220 frange_add_zeros (frange
&r
, tree type
)
222 if (r
.undefined_p () || r
.known_isnan ())
225 if (HONOR_SIGNED_ZEROS (type
)
226 && (real_iszero (&r
.lower_bound ()) || real_iszero (&r
.upper_bound ())))
229 zero
.set_zero (type
);
234 // Build a range that is <= VAL and store it in R. Return TRUE if
235 // further changes may be needed for R, or FALSE if R is in its final
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. Return TRUE if
253 // further changes may be needed for R, or FALSE if R is in its final
257 build_lt (frange
&r
, tree type
, const frange
&val
)
259 gcc_checking_assert (!val
.known_isnan ());
261 // < -INF is outside the range.
262 if (real_isinf (&val
.upper_bound (), 1))
264 if (HONOR_NANS (type
))
270 // We only support closed intervals.
271 REAL_VALUE_TYPE ninf
= frange_val_min (type
);
272 r
.set (type
, ninf
, val
.upper_bound ());
276 // Build a range that is >= VAL and store it in R. Return TRUE if
277 // further changes may be needed for R, or FALSE if R is in its final
281 build_ge (frange
&r
, tree type
, const frange
&val
)
283 gcc_checking_assert (!val
.known_isnan ());
285 REAL_VALUE_TYPE inf
= frange_val_max (type
);
286 r
.set (type
, val
.lower_bound (), inf
);
288 // Add both zeros if there's the possibility of zero equality.
289 frange_add_zeros (r
, type
);
294 // Build a range that is > VAL and store it in R. Return TRUE if
295 // further changes may be needed for R, or FALSE if R is in its final
299 build_gt (frange
&r
, tree type
, const frange
&val
)
301 gcc_checking_assert (!val
.known_isnan ());
303 // > +INF is outside the range.
304 if (real_isinf (&val
.lower_bound (), 0))
306 if (HONOR_NANS (type
))
313 // We only support closed intervals.
314 REAL_VALUE_TYPE inf
= frange_val_max (type
);
315 r
.set (type
, val
.lower_bound (), inf
);
320 class foperator_identity
: public range_operator_float
322 using range_operator_float::fold_range
;
323 using range_operator_float::op1_range
;
325 bool fold_range (frange
&r
, tree type ATTRIBUTE_UNUSED
,
326 const frange
&op1
, const frange
&op2 ATTRIBUTE_UNUSED
,
327 relation_trio
= TRIO_VARYING
) const final override
332 bool op1_range (frange
&r
, tree type ATTRIBUTE_UNUSED
,
333 const frange
&lhs
, const frange
&op2 ATTRIBUTE_UNUSED
,
334 relation_trio
= TRIO_VARYING
) const final override
342 class foperator_equal
: public range_operator_float
344 using range_operator_float::fold_range
;
345 using range_operator_float::op1_range
;
346 using range_operator_float::op2_range
;
347 using range_operator_float::op1_op2_relation
;
349 bool fold_range (irange
&r
, tree type
,
350 const frange
&op1
, const frange
&op2
,
351 relation_trio
= TRIO_VARYING
) const final override
;
352 relation_kind
op1_op2_relation (const irange
&lhs
) const final override
354 return equal_op1_op2_relation (lhs
);
356 bool op1_range (frange
&r
, tree type
,
357 const irange
&lhs
, const frange
&op2
,
358 relation_trio
= TRIO_VARYING
) const final override
;
359 bool op2_range (frange
&r
, tree type
,
360 const irange
&lhs
, const frange
&op1
,
361 relation_trio rel
= TRIO_VARYING
) const final override
363 return op1_range (r
, type
, lhs
, op1
, rel
.swap_op1_op2 ());
368 foperator_equal::fold_range (irange
&r
, tree type
,
369 const frange
&op1
, const frange
&op2
,
370 relation_trio rel
) const
372 if (frelop_early_resolve (r
, type
, op1
, op2
, rel
, VREL_EQ
))
375 if (op1
.known_isnan () || op2
.known_isnan ())
376 r
= range_false (type
);
377 // We can be sure the values are always equal or not if both ranges
378 // consist of a single value, and then compare them.
379 else if (op1
.singleton_p () && op2
.singleton_p ())
382 r
= range_true (type
);
384 r
= range_false (type
);
386 else if (!maybe_isnan (op1
, op2
))
388 // If ranges do not intersect, we know the range is not equal,
389 // otherwise we don't know anything for sure.
392 if (tmp
.undefined_p ())
393 r
= range_false (type
);
395 r
= range_true_and_false (type
);
398 r
= range_true_and_false (type
);
403 foperator_equal::op1_range (frange
&r
, tree type
,
406 relation_trio trio
) const
408 relation_kind rel
= trio
.op1_op2 ();
409 switch (get_bool_state (r
, lhs
, type
))
412 // The TRUE side of x == NAN is unreachable.
413 if (op2
.known_isnan ())
417 // If it's true, the result is the same as OP2.
419 // Add both zeros if there's the possibility of zero equality.
420 frange_add_zeros (r
, type
);
421 // The TRUE side of op1 == op2 implies op1 is !NAN.
427 // The FALSE side of op1 == op1 implies op1 is a NAN.
430 // On the FALSE side of x == NAN, we know nothing about x.
431 else if (op2
.known_isnan ())
432 r
.set_varying (type
);
433 // If the result is false, the only time we know anything is
434 // if OP2 is a constant.
435 else if (op2
.singleton_p ()
436 || (!op2
.maybe_isnan () && op2
.zero_p ()))
438 REAL_VALUE_TYPE tmp
= op2
.lower_bound ();
439 r
.set (type
, tmp
, tmp
, VR_ANTI_RANGE
);
442 r
.set_varying (type
);
451 class foperator_not_equal
: public range_operator_float
453 using range_operator_float::fold_range
;
454 using range_operator_float::op1_range
;
455 using range_operator_float::op1_op2_relation
;
457 bool fold_range (irange
&r
, tree type
,
458 const frange
&op1
, const frange
&op2
,
459 relation_trio rel
= TRIO_VARYING
) const final override
;
460 relation_kind
op1_op2_relation (const irange
&lhs
) const final override
462 return not_equal_op1_op2_relation (lhs
);
464 bool op1_range (frange
&r
, tree type
,
465 const irange
&lhs
, const frange
&op2
,
466 relation_trio
= TRIO_VARYING
) const final override
;
470 foperator_not_equal::fold_range (irange
&r
, tree type
,
471 const frange
&op1
, const frange
&op2
,
472 relation_trio rel
) const
474 if (frelop_early_resolve (r
, type
, op1
, op2
, rel
, VREL_NE
))
477 // x != NAN is always TRUE.
478 if (op1
.known_isnan () || op2
.known_isnan ())
479 r
= range_true (type
);
480 // We can be sure the values are always equal or not if both ranges
481 // consist of a single value, and then compare them.
482 else if (op1
.singleton_p () && op2
.singleton_p ())
485 r
= range_true (type
);
487 r
= range_false (type
);
489 else if (!maybe_isnan (op1
, op2
))
491 // If ranges do not intersect, we know the range is not equal,
492 // otherwise we don't know anything for sure.
495 if (tmp
.undefined_p ())
496 r
= range_true (type
);
498 r
= range_true_and_false (type
);
501 r
= range_true_and_false (type
);
506 foperator_not_equal::op1_range (frange
&r
, tree type
,
509 relation_trio trio
) const
511 relation_kind rel
= trio
.op1_op2 ();
512 switch (get_bool_state (r
, lhs
, type
))
515 // If the result is true, the only time we know anything is if
516 // OP2 is a constant.
517 if (op2
.singleton_p ())
519 // This is correct even if op1 is NAN, because the following
520 // range would be ~[tmp, tmp] with the NAN property set to
522 REAL_VALUE_TYPE tmp
= op2
.lower_bound ();
523 r
.set (type
, tmp
, tmp
, VR_ANTI_RANGE
);
525 // The TRUE side of op1 != op1 implies op1 is NAN.
526 else if (rel
== VREL_EQ
)
529 r
.set_varying (type
);
533 // The FALSE side of x != NAN is impossible.
534 if (op2
.known_isnan ())
538 // If it's false, the result is the same as OP2.
540 // Add both zeros if there's the possibility of zero equality.
541 frange_add_zeros (r
, type
);
542 // The FALSE side of op1 != op2 implies op1 is !NAN.
553 class foperator_lt
: public range_operator_float
555 using range_operator_float::fold_range
;
556 using range_operator_float::op1_range
;
557 using range_operator_float::op2_range
;
558 using range_operator_float::op1_op2_relation
;
560 bool fold_range (irange
&r
, tree type
,
561 const frange
&op1
, const frange
&op2
,
562 relation_trio
= TRIO_VARYING
) const final override
;
563 relation_kind
op1_op2_relation (const irange
&lhs
) const final override
565 return lt_op1_op2_relation (lhs
);
567 bool op1_range (frange
&r
, tree type
,
568 const irange
&lhs
, const frange
&op2
,
569 relation_trio
= TRIO_VARYING
) const final override
;
570 bool op2_range (frange
&r
, tree type
,
571 const irange
&lhs
, const frange
&op1
,
572 relation_trio
= TRIO_VARYING
) const final override
;
576 foperator_lt::fold_range (irange
&r
, tree type
,
577 const frange
&op1
, const frange
&op2
,
578 relation_trio rel
) const
580 if (frelop_early_resolve (r
, type
, op1
, op2
, rel
, VREL_LT
))
583 if (op1
.known_isnan () || op2
.known_isnan ())
584 r
= range_false (type
);
585 else if (!maybe_isnan (op1
, op2
))
587 if (real_less (&op1
.upper_bound (), &op2
.lower_bound ()))
588 r
= range_true (type
);
589 else if (!real_less (&op1
.lower_bound (), &op2
.upper_bound ()))
590 r
= range_false (type
);
592 r
= range_true_and_false (type
);
595 r
= range_true_and_false (type
);
600 foperator_lt::op1_range (frange
&r
,
606 switch (get_bool_state (r
, lhs
, type
))
609 // The TRUE side of x < NAN is unreachable.
610 if (op2
.known_isnan ())
612 else if (build_lt (r
, type
, op2
))
615 // x < y implies x is not +INF.
616 frange_drop_inf (r
, type
);
621 // On the FALSE side of x < NAN, we know nothing about x.
622 if (op2
.known_isnan ())
623 r
.set_varying (type
);
625 build_ge (r
, type
, op2
);
635 foperator_lt::op2_range (frange
&r
,
641 switch (get_bool_state (r
, lhs
, type
))
644 // The TRUE side of NAN < x is unreachable.
645 if (op1
.known_isnan ())
647 else if (build_gt (r
, type
, op1
))
650 // x < y implies y is not -INF.
651 frange_drop_ninf (r
, type
);
656 // On the FALSE side of NAN < x, we know nothing about x.
657 if (op1
.known_isnan ())
658 r
.set_varying (type
);
660 build_le (r
, type
, op1
);
669 class foperator_le
: public range_operator_float
671 using range_operator_float::fold_range
;
672 using range_operator_float::op1_range
;
673 using range_operator_float::op2_range
;
674 using range_operator_float::op1_op2_relation
;
676 bool fold_range (irange
&r
, tree type
,
677 const frange
&op1
, const frange
&op2
,
678 relation_trio rel
= TRIO_VARYING
) const final override
;
679 relation_kind
op1_op2_relation (const irange
&lhs
) const final override
681 return le_op1_op2_relation (lhs
);
683 bool op1_range (frange
&r
, tree type
,
684 const irange
&lhs
, const frange
&op2
,
685 relation_trio rel
= TRIO_VARYING
) const final override
;
686 bool op2_range (frange
&r
, tree type
,
687 const irange
&lhs
, const frange
&op1
,
688 relation_trio rel
= TRIO_VARYING
) const final override
;
692 foperator_le::fold_range (irange
&r
, tree type
,
693 const frange
&op1
, const frange
&op2
,
694 relation_trio rel
) const
696 if (frelop_early_resolve (r
, type
, op1
, op2
, rel
, VREL_LE
))
699 if (op1
.known_isnan () || op2
.known_isnan ())
700 r
= range_false (type
);
701 else if (!maybe_isnan (op1
, op2
))
703 if (real_compare (LE_EXPR
, &op1
.upper_bound (), &op2
.lower_bound ()))
704 r
= range_true (type
);
705 else if (!real_compare (LE_EXPR
, &op1
.lower_bound (), &op2
.upper_bound ()))
706 r
= range_false (type
);
708 r
= range_true_and_false (type
);
711 r
= range_true_and_false (type
);
716 foperator_le::op1_range (frange
&r
,
722 switch (get_bool_state (r
, lhs
, type
))
725 // The TRUE side of x <= NAN is unreachable.
726 if (op2
.known_isnan ())
728 else if (build_le (r
, type
, op2
))
733 // On the FALSE side of x <= NAN, we know nothing about x.
734 if (op2
.known_isnan ())
735 r
.set_varying (type
);
737 build_gt (r
, type
, op2
);
747 foperator_le::op2_range (frange
&r
,
753 switch (get_bool_state (r
, lhs
, type
))
756 // The TRUE side of NAN <= x is unreachable.
757 if (op1
.known_isnan ())
759 else if (build_ge (r
, type
, op1
))
764 // On the FALSE side of NAN <= x, we know nothing about x.
765 if (op1
.known_isnan ())
766 r
.set_varying (type
);
768 build_lt (r
, type
, op1
);
777 class foperator_gt
: public range_operator_float
779 using range_operator_float::fold_range
;
780 using range_operator_float::op1_range
;
781 using range_operator_float::op2_range
;
782 using range_operator_float::op1_op2_relation
;
784 bool fold_range (irange
&r
, tree type
,
785 const frange
&op1
, const frange
&op2
,
786 relation_trio
= TRIO_VARYING
) const final override
;
787 relation_kind
op1_op2_relation (const irange
&lhs
) const final override
789 return gt_op1_op2_relation (lhs
);
791 bool op1_range (frange
&r
, tree type
,
792 const irange
&lhs
, const frange
&op2
,
793 relation_trio
= TRIO_VARYING
) const final override
;
794 bool op2_range (frange
&r
, tree type
,
795 const irange
&lhs
, const frange
&op1
,
796 relation_trio
= TRIO_VARYING
) const final override
;
800 foperator_gt::fold_range (irange
&r
, tree type
,
801 const frange
&op1
, const frange
&op2
,
802 relation_trio rel
) const
804 if (frelop_early_resolve (r
, type
, op1
, op2
, rel
, VREL_GT
))
807 if (op1
.known_isnan () || op2
.known_isnan ())
808 r
= range_false (type
);
809 else if (!maybe_isnan (op1
, op2
))
811 if (real_compare (GT_EXPR
, &op1
.lower_bound (), &op2
.upper_bound ()))
812 r
= range_true (type
);
813 else if (!real_compare (GT_EXPR
, &op1
.upper_bound (), &op2
.lower_bound ()))
814 r
= range_false (type
);
816 r
= range_true_and_false (type
);
819 r
= range_true_and_false (type
);
824 foperator_gt::op1_range (frange
&r
,
830 switch (get_bool_state (r
, lhs
, type
))
833 // The TRUE side of x > NAN is unreachable.
834 if (op2
.known_isnan ())
836 else if (build_gt (r
, type
, op2
))
839 // x > y implies x is not -INF.
840 frange_drop_ninf (r
, type
);
845 // On the FALSE side of x > NAN, we know nothing about x.
846 if (op2
.known_isnan ())
847 r
.set_varying (type
);
849 build_le (r
, type
, op2
);
859 foperator_gt::op2_range (frange
&r
,
865 switch (get_bool_state (r
, lhs
, type
))
868 // The TRUE side of NAN > x is unreachable.
869 if (op1
.known_isnan ())
871 else if (build_lt (r
, type
, op1
))
874 // x > y implies y is not +INF.
875 frange_drop_inf (r
, type
);
880 // On The FALSE side of NAN > x, we know nothing about x.
881 if (op1
.known_isnan ())
882 r
.set_varying (type
);
884 build_ge (r
, type
, op1
);
893 class foperator_ge
: public range_operator_float
895 using range_operator_float::fold_range
;
896 using range_operator_float::op1_range
;
897 using range_operator_float::op2_range
;
898 using range_operator_float::op1_op2_relation
;
900 bool fold_range (irange
&r
, tree type
,
901 const frange
&op1
, const frange
&op2
,
902 relation_trio
= TRIO_VARYING
) const final override
;
903 relation_kind
op1_op2_relation (const irange
&lhs
) const final override
905 return ge_op1_op2_relation (lhs
);
907 bool op1_range (frange
&r
, tree type
,
908 const irange
&lhs
, const frange
&op2
,
909 relation_trio
= TRIO_VARYING
) const final override
;
910 bool op2_range (frange
&r
, tree type
,
911 const irange
&lhs
, const frange
&op1
,
912 relation_trio
= TRIO_VARYING
) const final override
;
916 foperator_ge::fold_range (irange
&r
, tree type
,
917 const frange
&op1
, const frange
&op2
,
918 relation_trio rel
) const
920 if (frelop_early_resolve (r
, type
, op1
, op2
, rel
, VREL_GE
))
923 if (op1
.known_isnan () || op2
.known_isnan ())
924 r
= range_false (type
);
925 else if (!maybe_isnan (op1
, op2
))
927 if (real_compare (GE_EXPR
, &op1
.lower_bound (), &op2
.upper_bound ()))
928 r
= range_true (type
);
929 else if (!real_compare (GE_EXPR
, &op1
.upper_bound (), &op2
.lower_bound ()))
930 r
= range_false (type
);
932 r
= range_true_and_false (type
);
935 r
= range_true_and_false (type
);
940 foperator_ge::op1_range (frange
&r
,
946 switch (get_bool_state (r
, lhs
, type
))
949 // The TRUE side of x >= NAN is unreachable.
950 if (op2
.known_isnan ())
952 else if (build_ge (r
, type
, op2
))
957 // On the FALSE side of x >= NAN, we know nothing about x.
958 if (op2
.known_isnan ())
959 r
.set_varying (type
);
961 build_lt (r
, type
, op2
);
971 foperator_ge::op2_range (frange
&r
, tree type
,
976 switch (get_bool_state (r
, lhs
, type
))
979 // The TRUE side of NAN >= x is unreachable.
980 if (op1
.known_isnan ())
982 else if (build_le (r
, type
, op1
))
987 // On the FALSE side of NAN >= x, we know nothing about x.
988 if (op1
.known_isnan ())
989 r
.set_varying (type
);
991 build_gt (r
, type
, op1
);
1000 // UNORDERED_EXPR comparison.
1002 class foperator_unordered
: public range_operator_float
1004 using range_operator_float::fold_range
;
1005 using range_operator_float::op1_range
;
1006 using range_operator_float::op2_range
;
1008 bool fold_range (irange
&r
, tree type
,
1009 const frange
&op1
, const frange
&op2
,
1010 relation_trio
= TRIO_VARYING
) const final override
;
1011 bool op1_range (frange
&r
, tree type
,
1012 const irange
&lhs
, const frange
&op2
,
1013 relation_trio
= TRIO_VARYING
) const final override
;
1014 bool op2_range (frange
&r
, tree type
,
1015 const irange
&lhs
, const frange
&op1
,
1016 relation_trio rel
= TRIO_VARYING
) const final override
1018 return op1_range (r
, type
, lhs
, op1
, rel
.swap_op1_op2 ());
1023 foperator_unordered::fold_range (irange
&r
, tree type
,
1024 const frange
&op1
, const frange
&op2
,
1025 relation_trio
) const
1027 // UNORDERED is TRUE if either operand is a NAN.
1028 if (op1
.known_isnan () || op2
.known_isnan ())
1029 r
= range_true (type
);
1030 // UNORDERED is FALSE if neither operand is a NAN.
1031 else if (!op1
.maybe_isnan () && !op2
.maybe_isnan ())
1032 r
= range_false (type
);
1034 r
= range_true_and_false (type
);
1039 foperator_unordered::op1_range (frange
&r
, tree type
,
1042 relation_trio trio
) const
1044 relation_kind rel
= trio
.op1_op2 ();
1045 switch (get_bool_state (r
, lhs
, type
))
1048 // Since at least one operand must be NAN, if one of them is
1049 // not, the other must be.
1050 if (rel
== VREL_EQ
|| !op2
.maybe_isnan ())
1053 r
.set_varying (type
);
1057 // A false UNORDERED means both operands are !NAN, so it's
1058 // impossible for op2 to be a NAN.
1059 if (op2
.known_isnan ())
1063 r
.set_varying (type
);
1074 // ORDERED_EXPR comparison.
1076 class foperator_ordered
: public range_operator_float
1078 using range_operator_float::fold_range
;
1079 using range_operator_float::op1_range
;
1080 using range_operator_float::op2_range
;
1082 bool fold_range (irange
&r
, tree type
,
1083 const frange
&op1
, const frange
&op2
,
1084 relation_trio
= TRIO_VARYING
) const final override
;
1085 bool op1_range (frange
&r
, tree type
,
1086 const irange
&lhs
, const frange
&op2
,
1087 relation_trio
= TRIO_VARYING
) const final override
;
1088 bool op2_range (frange
&r
, tree type
,
1089 const irange
&lhs
, const frange
&op1
,
1090 relation_trio rel
= TRIO_VARYING
) const final override
1092 return op1_range (r
, type
, lhs
, op1
, rel
.swap_op1_op2 ());
1097 foperator_ordered::fold_range (irange
&r
, tree type
,
1098 const frange
&op1
, const frange
&op2
,
1099 relation_trio
) const
1101 if (op1
.known_isnan () || op2
.known_isnan ())
1102 r
= range_false (type
);
1103 else if (!op1
.maybe_isnan () && !op2
.maybe_isnan ())
1104 r
= range_true (type
);
1106 r
= range_true_and_false (type
);
1111 foperator_ordered::op1_range (frange
&r
, tree type
,
1114 relation_trio trio
) const
1116 relation_kind rel
= trio
.op1_op2 ();
1117 switch (get_bool_state (r
, lhs
, type
))
1120 // The TRUE side of ORDERED means both operands are !NAN, so
1121 // it's impossible for op2 to be a NAN.
1122 if (op2
.known_isnan ())
1126 r
.set_varying (type
);
1132 // The FALSE side of op1 ORDERED op1 implies op1 is NAN.
1136 r
.set_varying (type
);
1145 class foperator_negate
: public range_operator_float
1147 using range_operator_float::fold_range
;
1148 using range_operator_float::op1_range
;
1150 bool fold_range (frange
&r
, tree type
,
1151 const frange
&op1
, const frange
&op2
,
1152 relation_trio
= TRIO_VARYING
) const final override
1154 if (empty_range_varying (r
, type
, op1
, op2
))
1156 if (op1
.known_isnan ())
1159 if (op1
.nan_signbit_p (sign
))
1160 r
.set_nan (type
, !sign
);
1166 REAL_VALUE_TYPE lh_lb
= op1
.lower_bound ();
1167 REAL_VALUE_TYPE lh_ub
= op1
.upper_bound ();
1168 lh_lb
= real_value_negate (&lh_lb
);
1169 lh_ub
= real_value_negate (&lh_ub
);
1170 r
.set (type
, lh_ub
, lh_lb
);
1171 if (op1
.maybe_isnan ())
1174 if (op1
.nan_signbit_p (sign
))
1175 r
.update_nan (!sign
);
1183 bool op1_range (frange
&r
, tree type
,
1184 const frange
&lhs
, const frange
&op2
,
1185 relation_trio rel
= TRIO_VARYING
) const final override
1187 return fold_range (r
, type
, lhs
, op2
, rel
);
1191 class foperator_abs
: public range_operator_float
1193 using range_operator_float::fold_range
;
1194 using range_operator_float::op1_range
;
1196 bool fold_range (frange
&r
, tree type
,
1197 const frange
&op1
, const frange
&,
1198 relation_trio
= TRIO_VARYING
) const final override
;
1199 bool op1_range (frange
&r
, tree type
,
1200 const frange
&lhs
, const frange
&op2
,
1201 relation_trio rel
= TRIO_VARYING
) const final override
;
1205 foperator_abs::fold_range (frange
&r
, tree type
,
1206 const frange
&op1
, const frange
&op2
,
1207 relation_trio
) const
1209 if (empty_range_varying (r
, type
, op1
, op2
))
1211 if (op1
.known_isnan ())
1213 r
.set_nan (type
, /*sign=*/false);
1217 const REAL_VALUE_TYPE lh_lb
= op1
.lower_bound ();
1218 const REAL_VALUE_TYPE lh_ub
= op1
.upper_bound ();
1219 // Handle the easy case where everything is positive.
1220 if (real_compare (GE_EXPR
, &lh_lb
, &dconst0
)
1221 && !real_iszero (&lh_lb
, /*sign=*/true)
1222 && !op1
.maybe_isnan (/*sign=*/true))
1228 REAL_VALUE_TYPE min
= real_value_abs (&lh_lb
);
1229 REAL_VALUE_TYPE max
= real_value_abs (&lh_ub
);
1230 // If the range contains zero then we know that the minimum value in the
1231 // range will be zero.
1232 if (real_compare (LE_EXPR
, &lh_lb
, &dconst0
)
1233 && real_compare (GE_EXPR
, &lh_ub
, &dconst0
))
1235 if (real_compare (GT_EXPR
, &min
, &max
))
1241 // If the range was reversed, swap MIN and MAX.
1242 if (real_compare (GT_EXPR
, &min
, &max
))
1243 std::swap (min
, max
);
1246 r
.set (type
, min
, max
);
1247 if (op1
.maybe_isnan ())
1248 r
.update_nan (/*sign=*/false);
1255 foperator_abs::op1_range (frange
&r
, tree type
,
1256 const frange
&lhs
, const frange
&op2
,
1257 relation_trio
) const
1259 if (empty_range_varying (r
, type
, lhs
, op2
))
1261 if (lhs
.known_isnan ())
1267 // Start with the positives because negatives are an impossible result.
1268 frange
positives (type
, dconst0
, frange_val_max (type
));
1269 positives
.update_nan (/*sign=*/false);
1270 positives
.intersect (lhs
);
1272 // Then add the negative of each pair:
1273 // ABS(op1) = [5,20] would yield op1 => [-20,-5][5,20].
1274 r
.union_ (frange (type
,
1275 real_value_negate (&positives
.upper_bound ()),
1276 real_value_negate (&positives
.lower_bound ())));
1280 class foperator_unordered_lt
: public range_operator_float
1282 using range_operator_float::fold_range
;
1283 using range_operator_float::op1_range
;
1284 using range_operator_float::op2_range
;
1286 bool fold_range (irange
&r
, tree type
,
1287 const frange
&op1
, const frange
&op2
,
1288 relation_trio rel
= TRIO_VARYING
) const final override
1290 if (op1
.known_isnan () || op2
.known_isnan ())
1292 r
= range_true (type
);
1295 if (!fop_lt
.fold_range (r
, type
, op1
, op2
, rel
))
1297 // The result is the same as the ordered version when the
1298 // comparison is true or when the operands cannot be NANs.
1299 if (!maybe_isnan (op1
, op2
) || r
== range_true (type
))
1303 r
= range_true_and_false (type
);
1307 bool op1_range (frange
&r
, tree type
,
1310 relation_trio trio
) const final override
;
1311 bool op2_range (frange
&r
, tree type
,
1314 relation_trio trio
) const final override
;
1318 foperator_unordered_lt::op1_range (frange
&r
, tree type
,
1321 relation_trio
) const
1323 switch (get_bool_state (r
, lhs
, type
))
1326 build_lt (r
, type
, op2
);
1330 // A false UNORDERED_LT means both operands are !NAN, so it's
1331 // impossible for op2 to be a NAN.
1332 if (op2
.known_isnan ())
1334 else if (build_ge (r
, type
, op2
))
1345 foperator_unordered_lt::op2_range (frange
&r
, tree type
,
1348 relation_trio
) const
1350 switch (get_bool_state (r
, lhs
, type
))
1353 build_gt (r
, type
, op1
);
1357 // A false UNORDERED_LT means both operands are !NAN, so it's
1358 // impossible for op1 to be a NAN.
1359 if (op1
.known_isnan ())
1361 else if (build_le (r
, type
, op1
))
1371 class foperator_unordered_le
: public range_operator_float
1373 using range_operator_float::fold_range
;
1374 using range_operator_float::op1_range
;
1375 using range_operator_float::op2_range
;
1377 bool fold_range (irange
&r
, tree type
,
1378 const frange
&op1
, const frange
&op2
,
1379 relation_trio rel
= TRIO_VARYING
) const final override
1381 if (op1
.known_isnan () || op2
.known_isnan ())
1383 r
= range_true (type
);
1386 if (!fop_le
.fold_range (r
, type
, op1
, op2
, rel
))
1388 // The result is the same as the ordered version when the
1389 // comparison is true or when the operands cannot be NANs.
1390 if (!maybe_isnan (op1
, op2
) || r
== range_true (type
))
1394 r
= range_true_and_false (type
);
1398 bool op1_range (frange
&r
, tree type
,
1399 const irange
&lhs
, const frange
&op2
,
1400 relation_trio
= TRIO_VARYING
) const final override
;
1401 bool op2_range (frange
&r
, tree type
,
1402 const irange
&lhs
, const frange
&op1
,
1403 relation_trio
= TRIO_VARYING
) const final override
;
1407 foperator_unordered_le::op1_range (frange
&r
, tree type
,
1408 const irange
&lhs
, const frange
&op2
,
1409 relation_trio
) const
1411 switch (get_bool_state (r
, lhs
, type
))
1414 build_le (r
, type
, op2
);
1418 // A false UNORDERED_LE means both operands are !NAN, so it's
1419 // impossible for op2 to be a NAN.
1420 if (op2
.known_isnan ())
1422 else if (build_gt (r
, type
, op2
))
1433 foperator_unordered_le::op2_range (frange
&r
,
1437 relation_trio
) const
1439 switch (get_bool_state (r
, lhs
, type
))
1442 build_ge (r
, type
, op1
);
1446 // A false UNORDERED_LE means both operands are !NAN, so it's
1447 // impossible for op1 to be a NAN.
1448 if (op1
.known_isnan ())
1450 else if (build_lt (r
, type
, op1
))
1460 class foperator_unordered_gt
: public range_operator_float
1462 using range_operator_float::fold_range
;
1463 using range_operator_float::op1_range
;
1464 using range_operator_float::op2_range
;
1466 bool fold_range (irange
&r
, tree type
,
1467 const frange
&op1
, const frange
&op2
,
1468 relation_trio rel
= TRIO_VARYING
) const final override
1470 if (op1
.known_isnan () || op2
.known_isnan ())
1472 r
= range_true (type
);
1475 if (!fop_gt
.fold_range (r
, type
, op1
, op2
, rel
))
1477 // The result is the same as the ordered version when the
1478 // comparison is true or when the operands cannot be NANs.
1479 if (!maybe_isnan (op1
, op2
) || r
== range_true (type
))
1483 r
= range_true_and_false (type
);
1487 bool op1_range (frange
&r
, tree type
,
1488 const irange
&lhs
, const frange
&op2
,
1489 relation_trio
= TRIO_VARYING
) const final override
;
1490 bool op2_range (frange
&r
, tree type
,
1491 const irange
&lhs
, const frange
&op1
,
1492 relation_trio
= TRIO_VARYING
) const final override
;
1496 foperator_unordered_gt::op1_range (frange
&r
,
1500 relation_trio
) const
1502 switch (get_bool_state (r
, lhs
, type
))
1505 build_gt (r
, type
, op2
);
1509 // A false UNORDERED_GT means both operands are !NAN, so it's
1510 // impossible for op2 to be a NAN.
1511 if (op2
.known_isnan ())
1513 else if (build_le (r
, type
, op2
))
1524 foperator_unordered_gt::op2_range (frange
&r
,
1528 relation_trio
) const
1530 switch (get_bool_state (r
, lhs
, type
))
1533 build_lt (r
, type
, op1
);
1537 // A false UNORDERED_GT means both operands are !NAN, so it's
1538 // impossible for op1 to be a NAN.
1539 if (op1
.known_isnan ())
1541 else if (build_ge (r
, type
, op1
))
1551 class foperator_unordered_ge
: public range_operator_float
1553 using range_operator_float::fold_range
;
1554 using range_operator_float::op1_range
;
1555 using range_operator_float::op2_range
;
1557 bool fold_range (irange
&r
, tree type
,
1558 const frange
&op1
, const frange
&op2
,
1559 relation_trio rel
= TRIO_VARYING
) const final override
1561 if (op1
.known_isnan () || op2
.known_isnan ())
1563 r
= range_true (type
);
1566 if (!fop_ge
.fold_range (r
, type
, op1
, op2
, rel
))
1568 // The result is the same as the ordered version when the
1569 // comparison is true or when the operands cannot be NANs.
1570 if (!maybe_isnan (op1
, op2
) || r
== range_true (type
))
1574 r
= range_true_and_false (type
);
1578 bool op1_range (frange
&r
, tree type
,
1579 const irange
&lhs
, const frange
&op2
,
1580 relation_trio
= TRIO_VARYING
) const final override
;
1581 bool op2_range (frange
&r
, tree type
,
1582 const irange
&lhs
, const frange
&op1
,
1583 relation_trio
= TRIO_VARYING
) const final override
;
1587 foperator_unordered_ge::op1_range (frange
&r
,
1591 relation_trio
) const
1593 switch (get_bool_state (r
, lhs
, type
))
1596 build_ge (r
, type
, op2
);
1600 // A false UNORDERED_GE means both operands are !NAN, so it's
1601 // impossible for op2 to be a NAN.
1602 if (op2
.known_isnan ())
1604 else if (build_lt (r
, type
, op2
))
1615 foperator_unordered_ge::op2_range (frange
&r
, tree type
,
1618 relation_trio
) const
1620 switch (get_bool_state (r
, lhs
, type
))
1623 build_le (r
, type
, op1
);
1627 // A false UNORDERED_GE means both operands are !NAN, so it's
1628 // impossible for op1 to be a NAN.
1629 if (op1
.known_isnan ())
1631 else if (build_gt (r
, type
, op1
))
1641 class foperator_unordered_equal
: public range_operator_float
1643 using range_operator_float::fold_range
;
1644 using range_operator_float::op1_range
;
1645 using range_operator_float::op2_range
;
1647 bool fold_range (irange
&r
, tree type
,
1648 const frange
&op1
, const frange
&op2
,
1649 relation_trio rel
= TRIO_VARYING
) const final override
1651 if (op1
.known_isnan () || op2
.known_isnan ())
1653 r
= range_true (type
);
1656 if (!fop_equal
.fold_range (r
, type
, op1
, op2
, rel
))
1658 // The result is the same as the ordered version when the
1659 // comparison is true or when the operands cannot be NANs.
1660 if (!maybe_isnan (op1
, op2
) || r
== range_true (type
))
1664 r
= range_true_and_false (type
);
1668 bool op1_range (frange
&r
, tree type
,
1669 const irange
&lhs
, const frange
&op2
,
1670 relation_trio
= TRIO_VARYING
) const final override
;
1671 bool op2_range (frange
&r
, tree type
,
1672 const irange
&lhs
, const frange
&op1
,
1673 relation_trio rel
= TRIO_VARYING
) const final override
1675 return op1_range (r
, type
, lhs
, op1
, rel
.swap_op1_op2 ());
1677 } fop_unordered_equal
;
1680 foperator_unordered_equal::op1_range (frange
&r
, tree type
,
1683 relation_trio
) const
1685 switch (get_bool_state (r
, lhs
, type
))
1688 // If it's true, the result is the same as OP2 plus a NAN.
1690 // Add both zeros if there's the possibility of zero equality.
1691 frange_add_zeros (r
, type
);
1692 // Add the posibility of a NAN.
1697 // A false UNORDERED_EQ means both operands are !NAN, so it's
1698 // impossible for op2 to be a NAN.
1699 if (op2
.known_isnan ())
1703 // The false side indictates !NAN and not equal. We can at least
1705 r
.set_varying (type
);
1716 // Instantiate a range_op_table for floating point operations.
1717 static floating_op_table global_floating_table
;
1719 // Pointer to the float table so the dispatch code can access it.
1720 floating_op_table
*floating_tree_table
= &global_floating_table
;
1722 floating_op_table::floating_op_table ()
1724 set (SSA_NAME
, fop_identity
);
1725 set (PAREN_EXPR
, fop_identity
);
1726 set (OBJ_TYPE_REF
, fop_identity
);
1727 set (REAL_CST
, fop_identity
);
1729 // All the relational operators are expected to work, because the
1730 // calculation of ranges on outgoing edges expect the handlers to be
1732 set (EQ_EXPR
, fop_equal
);
1733 set (NE_EXPR
, fop_not_equal
);
1734 set (LT_EXPR
, fop_lt
);
1735 set (LE_EXPR
, fop_le
);
1736 set (GT_EXPR
, fop_gt
);
1737 set (GE_EXPR
, fop_ge
);
1738 set (UNLE_EXPR
, fop_unordered_le
);
1739 set (UNLT_EXPR
, fop_unordered_lt
);
1740 set (UNGE_EXPR
, fop_unordered_ge
);
1741 set (UNGT_EXPR
, fop_unordered_gt
);
1742 set (UNEQ_EXPR
, fop_unordered_equal
);
1743 set (ORDERED_EXPR
, fop_ordered
);
1744 set (UNORDERED_EXPR
, fop_unordered
);
1746 set (ABS_EXPR
, fop_abs
);
1747 set (NEGATE_EXPR
, fop_negate
);
1750 // Return a pointer to the range_operator_float instance, if there is
1751 // one associated with tree_code CODE.
1753 range_operator_float
*
1754 floating_op_table::operator[] (enum tree_code code
)
1756 return m_range_tree
[code
];
1759 // Add OP to the handler table for CODE.
1762 floating_op_table::set (enum tree_code code
, range_operator_float
&op
)
1764 gcc_checking_assert (m_range_tree
[code
] == NULL
);
1765 m_range_tree
[code
] = &op
;
1769 #include "selftest.h"
1774 // Build an frange from string endpoints.
1777 frange_float (const char *lb
, const char *ub
, tree type
= float_type_node
)
1779 REAL_VALUE_TYPE min
, max
;
1780 gcc_assert (real_from_string (&min
, lb
) == 0);
1781 gcc_assert (real_from_string (&max
, ub
) == 0);
1782 return frange (type
, min
, max
);
1786 range_op_float_tests ()
1789 frange
trange (float_type_node
);
1791 // negate([-5, +10]) => [-10, 5]
1792 r0
= frange_float ("-5", "10");
1793 fop_negate
.fold_range (r
, float_type_node
, r0
, trange
);
1794 ASSERT_EQ (r
, frange_float ("-10", "5"));
1796 // negate([0, 1] -NAN) => [-1, -0] +NAN
1797 r0
= frange_float ("0", "1");
1798 r0
.update_nan (true);
1799 fop_negate
.fold_range (r
, float_type_node
, r0
, trange
);
1800 r1
= frange_float ("-1", "-0");
1801 r1
.update_nan (false);
1805 } // namespace selftest
1807 #endif // CHECKING_P