1 /* Floating point range operators.
2 Copyright (C) 2022-2023 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"
48 #include "range-op-mixed.h"
50 // Default definitions for floating point operators.
53 range_operator::fold_range (frange
&r
, tree type
,
54 const frange
&op1
, const frange
&op2
,
55 relation_trio trio
) const
57 if (empty_range_varying (r
, type
, op1
, op2
))
59 if (op1
.known_isnan () || op2
.known_isnan ())
65 REAL_VALUE_TYPE lb
, ub
;
67 rv_fold (lb
, ub
, maybe_nan
, type
,
68 op1
.lower_bound (), op1
.upper_bound (),
69 op2
.lower_bound (), op2
.upper_bound (), trio
.op1_op2 ());
71 // Handle possible NANs by saturating to the appropriate INF if only
72 // one end is a NAN. If both ends are a NAN, just return a NAN.
73 bool lb_nan
= real_isnan (&lb
);
74 bool ub_nan
= real_isnan (&ub
);
87 if (lb_nan
|| ub_nan
|| maybe_nan
89 || op2
.maybe_isnan ())
90 // Keep the default NAN (with a varying sign) set by the setter.
95 // If the result has overflowed and flag_trapping_math, folding this
96 // operation could elide an overflow or division by zero exception.
97 // Avoid returning a singleton +-INF, to keep the propagators (DOM
98 // and substitute_and_fold_engine) from folding. See PR107608.
99 if (flag_trapping_math
100 && MODE_HAS_INFINITIES (TYPE_MODE (type
))
101 && r
.known_isinf () && !op1
.known_isinf () && !op2
.known_isinf ())
103 REAL_VALUE_TYPE inf
= r
.lower_bound ();
104 if (real_isneg (&inf
))
106 REAL_VALUE_TYPE min
= real_min_representable (type
);
107 r
.set (type
, inf
, min
);
111 REAL_VALUE_TYPE max
= real_max_representable (type
);
112 r
.set (type
, max
, inf
);
116 r
.flush_denormals_to_zero ();
121 // For a given operation, fold two sets of ranges into [lb, ub].
122 // MAYBE_NAN is set to TRUE if, in addition to any result in LB or
123 // UB, the final range has the possibility of a NAN.
125 range_operator::rv_fold (REAL_VALUE_TYPE
&lb
,
128 tree type ATTRIBUTE_UNUSED
,
129 const REAL_VALUE_TYPE
&lh_lb ATTRIBUTE_UNUSED
,
130 const REAL_VALUE_TYPE
&lh_ub ATTRIBUTE_UNUSED
,
131 const REAL_VALUE_TYPE
&rh_lb ATTRIBUTE_UNUSED
,
132 const REAL_VALUE_TYPE
&rh_ub ATTRIBUTE_UNUSED
,
141 range_operator::fold_range (irange
&r ATTRIBUTE_UNUSED
,
142 tree type ATTRIBUTE_UNUSED
,
143 const frange
&lh ATTRIBUTE_UNUSED
,
144 const irange
&rh ATTRIBUTE_UNUSED
,
151 range_operator::fold_range (irange
&r ATTRIBUTE_UNUSED
,
152 tree type ATTRIBUTE_UNUSED
,
153 const frange
&lh ATTRIBUTE_UNUSED
,
154 const frange
&rh ATTRIBUTE_UNUSED
,
161 range_operator::fold_range (frange
&r ATTRIBUTE_UNUSED
,
162 tree type ATTRIBUTE_UNUSED
,
163 const irange
&lh ATTRIBUTE_UNUSED
,
164 const irange
&rh ATTRIBUTE_UNUSED
,
171 range_operator::op1_range (frange
&r ATTRIBUTE_UNUSED
,
172 tree type ATTRIBUTE_UNUSED
,
173 const frange
&lhs ATTRIBUTE_UNUSED
,
174 const frange
&op2 ATTRIBUTE_UNUSED
,
181 range_operator::op1_range (frange
&r ATTRIBUTE_UNUSED
,
182 tree type ATTRIBUTE_UNUSED
,
183 const irange
&lhs ATTRIBUTE_UNUSED
,
184 const frange
&op2 ATTRIBUTE_UNUSED
,
191 range_operator::op2_range (frange
&r ATTRIBUTE_UNUSED
,
192 tree type ATTRIBUTE_UNUSED
,
193 const frange
&lhs ATTRIBUTE_UNUSED
,
194 const frange
&op1 ATTRIBUTE_UNUSED
,
201 range_operator::op2_range (frange
&r ATTRIBUTE_UNUSED
,
202 tree type ATTRIBUTE_UNUSED
,
203 const irange
&lhs ATTRIBUTE_UNUSED
,
204 const frange
&op1 ATTRIBUTE_UNUSED
,
211 range_operator::lhs_op1_relation (const frange
&lhs ATTRIBUTE_UNUSED
,
212 const frange
&op1 ATTRIBUTE_UNUSED
,
213 const frange
&op2 ATTRIBUTE_UNUSED
,
220 range_operator::lhs_op1_relation (const irange
&lhs ATTRIBUTE_UNUSED
,
221 const frange
&op1 ATTRIBUTE_UNUSED
,
222 const frange
&op2 ATTRIBUTE_UNUSED
,
229 range_operator::lhs_op2_relation (const irange
&lhs ATTRIBUTE_UNUSED
,
230 const frange
&op1 ATTRIBUTE_UNUSED
,
231 const frange
&op2 ATTRIBUTE_UNUSED
,
238 range_operator::lhs_op2_relation (const frange
&lhs ATTRIBUTE_UNUSED
,
239 const frange
&op1 ATTRIBUTE_UNUSED
,
240 const frange
&op2 ATTRIBUTE_UNUSED
,
247 range_operator::op1_op2_relation (const irange
&,
249 const frange
&) const
256 range_operator::op1_op2_relation (const frange
&,
258 const frange
&) const
263 // Return TRUE if OP1 and OP2 may be a NAN.
266 maybe_isnan (const frange
&op1
, const frange
&op2
)
268 return op1
.maybe_isnan () || op2
.maybe_isnan ();
271 // Floating version of relop_early_resolve that takes into account NAN
272 // and -ffinite-math-only.
275 frelop_early_resolve (irange
&r
, tree type
,
276 const frange
&op1
, const frange
&op2
,
277 relation_trio rel
, relation_kind my_rel
)
279 // If either operand is undefined, return VARYING.
280 if (empty_range_varying (r
, type
, op1
, op2
))
283 // We can fold relations from the oracle when we know both operands
284 // are free of NANs, or when -ffinite-math-only.
285 return (!maybe_isnan (op1
, op2
)
286 && relop_early_resolve (r
, type
, op1
, op2
, rel
, my_rel
));
289 // Set VALUE to its next real value, or INF if the operation overflows.
292 frange_nextafter (enum machine_mode mode
,
293 REAL_VALUE_TYPE
&value
,
294 const REAL_VALUE_TYPE
&inf
)
296 if (MODE_COMPOSITE_P (mode
)
297 && (real_isdenormal (&value
, mode
) || real_iszero (&value
)))
299 // IBM extended denormals only have DFmode precision.
300 REAL_VALUE_TYPE tmp
, tmp2
;
301 real_convert (&tmp2
, DFmode
, &value
);
302 real_nextafter (&tmp
, REAL_MODE_FORMAT (DFmode
), &tmp2
, &inf
);
303 real_convert (&value
, mode
, &tmp
);
308 real_nextafter (&tmp
, REAL_MODE_FORMAT (mode
), &value
, &inf
);
313 // Like real_arithmetic, but round the result to INF if the operation
314 // produced inexact results.
316 // ?? There is still one problematic case, i387. With
317 // -fexcess-precision=standard we perform most SF/DFmode arithmetic in
318 // XFmode (long_double_type_node), so that case is OK. But without
319 // -mfpmath=sse, all the SF/DFmode computations are in XFmode
320 // precision (64-bit mantissa) and only occasionally rounded to
321 // SF/DFmode (when storing into memory from the 387 stack). Maybe
322 // this is ok as well though it is just occasionally more precise. ??
325 frange_arithmetic (enum tree_code code
, tree type
,
326 REAL_VALUE_TYPE
&result
,
327 const REAL_VALUE_TYPE
&op1
,
328 const REAL_VALUE_TYPE
&op2
,
329 const REAL_VALUE_TYPE
&inf
)
331 REAL_VALUE_TYPE value
;
332 enum machine_mode mode
= TYPE_MODE (type
);
333 bool mode_composite
= MODE_COMPOSITE_P (mode
);
335 bool inexact
= real_arithmetic (&value
, code
, &op1
, &op2
);
336 real_convert (&result
, mode
, &value
);
338 /* When rounding towards negative infinity, x + (-x) and
339 x - x is -0 rather than +0 real_arithmetic computes.
340 So, when we are looking for lower bound (inf is negative),
341 use -0 rather than +0. */
342 if (flag_rounding_math
343 && (code
== PLUS_EXPR
|| code
== MINUS_EXPR
)
345 && real_iszero (&result
)
346 && !real_isneg (&result
)
347 && real_isneg (&inf
))
349 REAL_VALUE_TYPE op2a
= op2
;
350 if (code
== PLUS_EXPR
)
352 if (real_isneg (&op1
) == real_isneg (&op2a
) && real_equal (&op1
, &op2a
))
356 // Be extra careful if there may be discrepancies between the
357 // compile and runtime results.
363 bool low
= real_isneg (&inf
);
364 round
= (low
? !real_less (&result
, &value
)
365 : !real_less (&value
, &result
));
366 if (real_isinf (&result
, !low
)
367 && !real_isinf (&value
)
368 && !flag_rounding_math
)
370 // Use just [+INF, +INF] rather than [MAX, +INF]
371 // even if value is larger than MAX and rounds to
372 // nearest to +INF. Similarly just [-INF, -INF]
373 // rather than [-INF, +MAX] even if value is smaller
374 // than -MAX and rounds to nearest to -INF.
375 // Unless INEXACT is true, in that case we need some
381 REAL_VALUE_TYPE tmp
= result
, tmp2
;
382 frange_nextafter (mode
, tmp
, inf
);
383 // TMP is at this point the maximum representable
385 real_arithmetic (&tmp2
, MINUS_EXPR
, &value
, &tmp
);
386 if (real_isneg (&tmp2
) != low
387 && (REAL_EXP (&tmp2
) - REAL_EXP (&tmp
)
388 >= 2 - REAL_MODE_FORMAT (mode
)->p
))
393 if (round
&& (inexact
|| !real_identical (&result
, &value
)))
396 && (real_isdenormal (&result
, mode
) || real_iszero (&result
)))
398 // IBM extended denormals only have DFmode precision.
399 REAL_VALUE_TYPE tmp
, tmp2
;
400 real_convert (&tmp2
, DFmode
, &value
);
401 real_nextafter (&tmp
, REAL_MODE_FORMAT (DFmode
), &tmp2
, &inf
);
402 real_convert (&result
, mode
, &tmp
);
405 frange_nextafter (mode
, result
, inf
);
412 // ibm-ldouble-format documents 1ulp for + and -.
413 frange_nextafter (mode
, result
, inf
);
416 // ibm-ldouble-format documents 2ulps for *.
417 frange_nextafter (mode
, result
, inf
);
418 frange_nextafter (mode
, result
, inf
);
421 // ibm-ldouble-format documents 3ulps for /.
422 frange_nextafter (mode
, result
, inf
);
423 frange_nextafter (mode
, result
, inf
);
424 frange_nextafter (mode
, result
, inf
);
431 // Crop R to [-INF, MAX] where MAX is the maximum representable number
435 frange_drop_inf (frange
&r
, tree type
)
437 REAL_VALUE_TYPE max
= real_max_representable (type
);
438 frange
tmp (type
, r
.lower_bound (), max
);
442 // Crop R to [MIN, +INF] where MIN is the minimum representable number
446 frange_drop_ninf (frange
&r
, tree type
)
448 REAL_VALUE_TYPE min
= real_min_representable (type
);
449 frange
tmp (type
, min
, r
.upper_bound ());
453 // Crop R to [MIN, MAX] where MAX is the maximum representable number
454 // for TYPE and MIN the minimum representable number for TYPE.
457 frange_drop_infs (frange
&r
, tree type
)
459 REAL_VALUE_TYPE max
= real_max_representable (type
);
460 REAL_VALUE_TYPE min
= real_min_representable (type
);
461 frange
tmp (type
, min
, max
);
465 // If zero is in R, make sure both -0.0 and +0.0 are in the range.
468 frange_add_zeros (frange
&r
, tree type
)
470 if (r
.undefined_p () || r
.known_isnan ())
473 if (HONOR_SIGNED_ZEROS (type
)
474 && (real_iszero (&r
.lower_bound ()) || real_iszero (&r
.upper_bound ())))
477 zero
.set_zero (type
);
482 // Build a range that is <= VAL and store it in R. Return TRUE if
483 // further changes may be needed for R, or FALSE if R is in its final
487 build_le (frange
&r
, tree type
, const frange
&val
)
489 gcc_checking_assert (!val
.known_isnan ());
491 REAL_VALUE_TYPE ninf
= frange_val_min (type
);
492 r
.set (type
, ninf
, val
.upper_bound ());
494 // Add both zeros if there's the possibility of zero equality.
495 frange_add_zeros (r
, type
);
500 // Build a range that is < VAL and store it in R. Return TRUE if
501 // further changes may be needed for R, or FALSE if R is in its final
505 build_lt (frange
&r
, tree type
, const frange
&val
)
507 gcc_checking_assert (!val
.known_isnan ());
509 // < -INF is outside the range.
510 if (real_isinf (&val
.upper_bound (), 1))
512 if (HONOR_NANS (type
))
519 REAL_VALUE_TYPE ninf
= frange_val_min (type
);
520 REAL_VALUE_TYPE prev
= val
.upper_bound ();
521 machine_mode mode
= TYPE_MODE (type
);
522 // Default to the conservatively correct closed ranges for
523 // MODE_COMPOSITE_P, otherwise use nextafter. Note that for
524 // !HONOR_INFINITIES, nextafter will yield -INF, but frange::set()
525 // will crop the range appropriately.
526 if (!MODE_COMPOSITE_P (mode
))
527 frange_nextafter (mode
, prev
, ninf
);
528 r
.set (type
, ninf
, prev
);
532 // Build a range that is >= VAL and store it in R. Return TRUE if
533 // further changes may be needed for R, or FALSE if R is in its final
537 build_ge (frange
&r
, tree type
, const frange
&val
)
539 gcc_checking_assert (!val
.known_isnan ());
541 REAL_VALUE_TYPE inf
= frange_val_max (type
);
542 r
.set (type
, val
.lower_bound (), inf
);
544 // Add both zeros if there's the possibility of zero equality.
545 frange_add_zeros (r
, type
);
550 // Build a range that is > VAL and store it in R. Return TRUE if
551 // further changes may be needed for R, or FALSE if R is in its final
555 build_gt (frange
&r
, tree type
, const frange
&val
)
557 gcc_checking_assert (!val
.known_isnan ());
559 // > +INF is outside the range.
560 if (real_isinf (&val
.lower_bound (), 0))
562 if (HONOR_NANS (type
))
569 REAL_VALUE_TYPE inf
= frange_val_max (type
);
570 REAL_VALUE_TYPE next
= val
.lower_bound ();
571 machine_mode mode
= TYPE_MODE (type
);
572 // Default to the conservatively correct closed ranges for
573 // MODE_COMPOSITE_P, otherwise use nextafter. Note that for
574 // !HONOR_INFINITIES, nextafter will yield +INF, but frange::set()
575 // will crop the range appropriately.
576 if (!MODE_COMPOSITE_P (mode
))
577 frange_nextafter (mode
, next
, inf
);
578 r
.set (type
, next
, inf
);
584 operator_identity::fold_range (frange
&r
, tree
, const frange
&op1
,
585 const frange
&, relation_trio
) const
592 operator_identity::op1_range (frange
&r
, tree
, const frange
&lhs
,
593 const frange
&, relation_trio
) const
600 operator_cst::fold_range (frange
&r
, tree
, const frange
&op1
,
601 const frange
&, relation_trio
) const
608 operator_equal::op2_range (frange
&r
, tree type
,
609 const irange
&lhs
, const frange
&op1
,
610 relation_trio rel
) const
612 return op1_range (r
, type
, lhs
, op1
, rel
.swap_op1_op2 ());
616 operator_equal::fold_range (irange
&r
, tree type
,
617 const frange
&op1
, const frange
&op2
,
618 relation_trio rel
) const
620 if (frelop_early_resolve (r
, type
, op1
, op2
, rel
, VREL_EQ
))
623 if (op1
.known_isnan () || op2
.known_isnan ())
624 r
= range_false (type
);
625 // We can be sure the values are always equal or not if both ranges
626 // consist of a single value, and then compare them.
627 else if (op1
.singleton_p () && op2
.singleton_p ())
630 r
= range_true (type
);
631 // If one operand is -0.0 and other 0.0, they are still equal.
632 else if (real_iszero (&op1
.lower_bound ())
633 && real_iszero (&op2
.lower_bound ()))
634 r
= range_true (type
);
636 r
= range_false (type
);
638 else if (real_iszero (&op1
.lower_bound ())
639 && real_iszero (&op1
.upper_bound ())
640 && real_iszero (&op2
.lower_bound ())
641 && real_iszero (&op2
.upper_bound ())
642 && !maybe_isnan (op1
, op2
))
643 // [-0.0, 0.0] == [-0.0, 0.0] or similar.
644 r
= range_true (type
);
647 // If ranges do not intersect, we know the range is not equal,
648 // otherwise we don't know anything for sure.
651 if (tmp
.undefined_p ())
653 // If one range is [whatever, -0.0] and another
654 // [0.0, whatever2], we don't know anything either,
655 // because -0.0 == 0.0.
656 if ((real_iszero (&op1
.upper_bound ())
657 && real_iszero (&op2
.lower_bound ()))
658 || (real_iszero (&op1
.lower_bound ())
659 && real_iszero (&op2
.upper_bound ())))
660 r
= range_true_and_false (type
);
662 r
= range_false (type
);
665 r
= range_true_and_false (type
);
671 operator_equal::op1_range (frange
&r
, tree type
,
674 relation_trio trio
) const
676 relation_kind rel
= trio
.op1_op2 ();
677 switch (get_bool_state (r
, lhs
, type
))
680 // The TRUE side of x == NAN is unreachable.
681 if (op2
.known_isnan ())
685 // If it's true, the result is the same as OP2.
687 // Add both zeros if there's the possibility of zero equality.
688 frange_add_zeros (r
, type
);
689 // The TRUE side of op1 == op2 implies op1 is !NAN.
695 // The FALSE side of op1 == op1 implies op1 is a NAN.
698 // On the FALSE side of x == NAN, we know nothing about x.
699 else if (op2
.known_isnan ())
700 r
.set_varying (type
);
701 // If the result is false, the only time we know anything is
702 // if OP2 is a constant.
703 else if (op2
.singleton_p ()
704 || (!op2
.maybe_isnan () && op2
.zero_p ()))
706 REAL_VALUE_TYPE tmp
= op2
.lower_bound ();
707 r
.set (type
, tmp
, tmp
, VR_ANTI_RANGE
);
710 r
.set_varying (type
);
719 // Check if the LHS range indicates a relation between OP1 and OP2.
722 operator_equal::op1_op2_relation (const irange
&lhs
, const frange
&,
723 const frange
&) const
725 if (lhs
.undefined_p ())
726 return VREL_UNDEFINED
;
728 // FALSE = op1 == op2 indicates NE_EXPR.
732 // TRUE = op1 == op2 indicates EQ_EXPR.
733 if (lhs
.undefined_p () || !contains_zero_p (lhs
))
739 operator_not_equal::fold_range (irange
&r
, tree type
,
740 const frange
&op1
, const frange
&op2
,
741 relation_trio rel
) const
743 if (frelop_early_resolve (r
, type
, op1
, op2
, rel
, VREL_NE
))
746 // x != NAN is always TRUE.
747 if (op1
.known_isnan () || op2
.known_isnan ())
748 r
= range_true (type
);
749 // We can be sure the values are always equal or not if both ranges
750 // consist of a single value, and then compare them.
751 else if (op1
.singleton_p () && op2
.singleton_p ())
754 r
= range_false (type
);
755 // If one operand is -0.0 and other 0.0, they are still equal.
756 else if (real_iszero (&op1
.lower_bound ())
757 && real_iszero (&op2
.lower_bound ()))
758 r
= range_false (type
);
760 r
= range_true (type
);
762 else if (real_iszero (&op1
.lower_bound ())
763 && real_iszero (&op1
.upper_bound ())
764 && real_iszero (&op2
.lower_bound ())
765 && real_iszero (&op2
.upper_bound ())
766 && !maybe_isnan (op1
, op2
))
767 // [-0.0, 0.0] != [-0.0, 0.0] or similar.
768 r
= range_false (type
);
771 // If ranges do not intersect, we know the range is not equal,
772 // otherwise we don't know anything for sure.
775 if (tmp
.undefined_p ())
777 // If one range is [whatever, -0.0] and another
778 // [0.0, whatever2], we don't know anything either,
779 // because -0.0 == 0.0.
780 if ((real_iszero (&op1
.upper_bound ())
781 && real_iszero (&op2
.lower_bound ()))
782 || (real_iszero (&op1
.lower_bound ())
783 && real_iszero (&op2
.upper_bound ())))
784 r
= range_true_and_false (type
);
786 r
= range_true (type
);
789 r
= range_true_and_false (type
);
795 operator_not_equal::op1_range (frange
&r
, tree type
,
798 relation_trio trio
) const
800 relation_kind rel
= trio
.op1_op2 ();
801 switch (get_bool_state (r
, lhs
, type
))
804 // If the result is true, the only time we know anything is if
805 // OP2 is a constant.
806 if (op2
.singleton_p ())
808 // This is correct even if op1 is NAN, because the following
809 // range would be ~[tmp, tmp] with the NAN property set to
811 REAL_VALUE_TYPE tmp
= op2
.lower_bound ();
812 r
.set (type
, tmp
, tmp
, VR_ANTI_RANGE
);
814 // The TRUE side of op1 != op1 implies op1 is NAN.
815 else if (rel
== VREL_EQ
)
818 r
.set_varying (type
);
822 // The FALSE side of x != NAN is impossible.
823 if (op2
.known_isnan ())
827 // If it's false, the result is the same as OP2.
829 // Add both zeros if there's the possibility of zero equality.
830 frange_add_zeros (r
, type
);
831 // The FALSE side of op1 != op2 implies op1 is !NAN.
843 // Check if the LHS range indicates a relation between OP1 and OP2.
846 operator_not_equal::op1_op2_relation (const irange
&lhs
, const frange
&,
847 const frange
&) const
849 if (lhs
.undefined_p ())
850 return VREL_UNDEFINED
;
852 // FALSE = op1 != op2 indicates EQ_EXPR.
856 // TRUE = op1 != op2 indicates NE_EXPR.
857 if (lhs
.undefined_p () || !contains_zero_p (lhs
))
863 operator_lt::fold_range (irange
&r
, tree type
,
864 const frange
&op1
, const frange
&op2
,
865 relation_trio rel
) const
867 if (frelop_early_resolve (r
, type
, op1
, op2
, rel
, VREL_LT
))
870 if (op1
.known_isnan ()
871 || op2
.known_isnan ()
872 || !real_less (&op1
.lower_bound (), &op2
.upper_bound ()))
873 r
= range_false (type
);
874 else if (!maybe_isnan (op1
, op2
)
875 && real_less (&op1
.upper_bound (), &op2
.lower_bound ()))
876 r
= range_true (type
);
878 r
= range_true_and_false (type
);
883 operator_lt::op1_range (frange
&r
,
889 switch (get_bool_state (r
, lhs
, type
))
892 // The TRUE side of x < NAN is unreachable.
893 if (op2
.known_isnan ())
895 else if (op2
.undefined_p ())
897 else if (build_lt (r
, type
, op2
))
900 // x < y implies x is not +INF.
901 frange_drop_inf (r
, type
);
906 // On the FALSE side of x < NAN, we know nothing about x.
907 if (op2
.known_isnan () || op2
.maybe_isnan ())
908 r
.set_varying (type
);
910 build_ge (r
, type
, op2
);
920 operator_lt::op2_range (frange
&r
,
926 switch (get_bool_state (r
, lhs
, type
))
929 // The TRUE side of NAN < x is unreachable.
930 if (op1
.known_isnan ())
932 else if (op1
.undefined_p ())
934 else if (build_gt (r
, type
, op1
))
937 // x < y implies y is not -INF.
938 frange_drop_ninf (r
, type
);
943 // On the FALSE side of NAN < x, we know nothing about x.
944 if (op1
.known_isnan () || op1
.maybe_isnan ())
945 r
.set_varying (type
);
947 build_le (r
, type
, op1
);
957 // Check if the LHS range indicates a relation between OP1 and OP2.
960 operator_lt::op1_op2_relation (const irange
&lhs
, const frange
&,
961 const frange
&) const
963 if (lhs
.undefined_p ())
964 return VREL_UNDEFINED
;
966 // FALSE = op1 < op2 indicates GE_EXPR.
970 // TRUE = op1 < op2 indicates LT_EXPR.
971 if (lhs
.undefined_p () || !contains_zero_p (lhs
))
977 operator_le::fold_range (irange
&r
, tree type
,
978 const frange
&op1
, const frange
&op2
,
979 relation_trio rel
) const
981 if (frelop_early_resolve (r
, type
, op1
, op2
, rel
, VREL_LE
))
984 if (op1
.known_isnan ()
985 || op2
.known_isnan ()
986 || !real_compare (LE_EXPR
, &op1
.lower_bound (), &op2
.upper_bound ()))
987 r
= range_false (type
);
988 else if (!maybe_isnan (op1
, op2
)
989 && real_compare (LE_EXPR
, &op1
.upper_bound (), &op2
.lower_bound ()))
990 r
= range_true (type
);
992 r
= range_true_and_false (type
);
997 operator_le::op1_range (frange
&r
,
1001 relation_trio
) const
1003 switch (get_bool_state (r
, lhs
, type
))
1006 // The TRUE side of x <= NAN is unreachable.
1007 if (op2
.known_isnan ())
1009 else if (op2
.undefined_p ())
1011 else if (build_le (r
, type
, op2
))
1016 // On the FALSE side of x <= NAN, we know nothing about x.
1017 if (op2
.known_isnan () || op2
.maybe_isnan ())
1018 r
.set_varying (type
);
1020 build_gt (r
, type
, op2
);
1030 operator_le::op2_range (frange
&r
,
1034 relation_trio
) const
1036 switch (get_bool_state (r
, lhs
, type
))
1039 // The TRUE side of NAN <= x is unreachable.
1040 if (op1
.known_isnan ())
1042 else if (op1
.undefined_p ())
1044 else if (build_ge (r
, type
, op1
))
1049 // On the FALSE side of NAN <= x, we know nothing about x.
1050 if (op1
.known_isnan () || op1
.maybe_isnan ())
1051 r
.set_varying (type
);
1052 else if (op1
.undefined_p ())
1055 build_lt (r
, type
, op1
);
1064 // Check if the LHS range indicates a relation between OP1 and OP2.
1067 operator_le::op1_op2_relation (const irange
&lhs
, const frange
&,
1068 const frange
&) const
1070 if (lhs
.undefined_p ())
1071 return VREL_UNDEFINED
;
1073 // FALSE = op1 <= op2 indicates GT_EXPR.
1077 // TRUE = op1 <= op2 indicates LE_EXPR.
1078 if (lhs
.undefined_p () || !contains_zero_p (lhs
))
1080 return VREL_VARYING
;
1084 operator_gt::fold_range (irange
&r
, tree type
,
1085 const frange
&op1
, const frange
&op2
,
1086 relation_trio rel
) const
1088 if (frelop_early_resolve (r
, type
, op1
, op2
, rel
, VREL_GT
))
1091 if (op1
.known_isnan ()
1092 || op2
.known_isnan ()
1093 || !real_compare (GT_EXPR
, &op1
.upper_bound (), &op2
.lower_bound ()))
1094 r
= range_false (type
);
1095 else if (!maybe_isnan (op1
, op2
)
1096 && real_compare (GT_EXPR
, &op1
.lower_bound (), &op2
.upper_bound ()))
1097 r
= range_true (type
);
1099 r
= range_true_and_false (type
);
1104 operator_gt::op1_range (frange
&r
,
1108 relation_trio
) const
1110 switch (get_bool_state (r
, lhs
, type
))
1113 // The TRUE side of x > NAN is unreachable.
1114 if (op2
.known_isnan ())
1116 else if (op2
.undefined_p ())
1118 else if (build_gt (r
, type
, op2
))
1121 // x > y implies x is not -INF.
1122 frange_drop_ninf (r
, type
);
1127 // On the FALSE side of x > NAN, we know nothing about x.
1128 if (op2
.known_isnan () || op2
.maybe_isnan ())
1129 r
.set_varying (type
);
1130 else if (op2
.undefined_p ())
1133 build_le (r
, type
, op2
);
1143 operator_gt::op2_range (frange
&r
,
1147 relation_trio
) const
1149 switch (get_bool_state (r
, lhs
, type
))
1152 // The TRUE side of NAN > x is unreachable.
1153 if (op1
.known_isnan ())
1155 else if (op1
.undefined_p ())
1157 else if (build_lt (r
, type
, op1
))
1160 // x > y implies y is not +INF.
1161 frange_drop_inf (r
, type
);
1166 // On The FALSE side of NAN > x, we know nothing about x.
1167 if (op1
.known_isnan () || op1
.maybe_isnan ())
1168 r
.set_varying (type
);
1169 else if (op1
.undefined_p ())
1172 build_ge (r
, type
, op1
);
1181 // Check if the LHS range indicates a relation between OP1 and OP2.
1184 operator_gt::op1_op2_relation (const irange
&lhs
, const frange
&,
1185 const frange
&) const
1187 if (lhs
.undefined_p ())
1188 return VREL_UNDEFINED
;
1190 // FALSE = op1 > op2 indicates LE_EXPR.
1194 // TRUE = op1 > op2 indicates GT_EXPR.
1195 if (!contains_zero_p (lhs
))
1197 return VREL_VARYING
;
1201 operator_ge::fold_range (irange
&r
, tree type
,
1202 const frange
&op1
, const frange
&op2
,
1203 relation_trio rel
) const
1205 if (frelop_early_resolve (r
, type
, op1
, op2
, rel
, VREL_GE
))
1208 if (op1
.known_isnan ()
1209 || op2
.known_isnan ()
1210 || !real_compare (GE_EXPR
, &op1
.upper_bound (), &op2
.lower_bound ()))
1211 r
= range_false (type
);
1212 else if (!maybe_isnan (op1
, op2
)
1213 && real_compare (GE_EXPR
, &op1
.lower_bound (), &op2
.upper_bound ()))
1214 r
= range_true (type
);
1216 r
= range_true_and_false (type
);
1221 operator_ge::op1_range (frange
&r
,
1225 relation_trio
) const
1227 switch (get_bool_state (r
, lhs
, type
))
1230 // The TRUE side of x >= NAN is unreachable.
1231 if (op2
.known_isnan ())
1233 else if (op2
.undefined_p ())
1235 else if (build_ge (r
, type
, op2
))
1240 // On the FALSE side of x >= NAN, we know nothing about x.
1241 if (op2
.known_isnan () || op2
.maybe_isnan ())
1242 r
.set_varying (type
);
1243 else if (op2
.undefined_p ())
1246 build_lt (r
, type
, op2
);
1256 operator_ge::op2_range (frange
&r
, tree type
,
1259 relation_trio
) const
1261 switch (get_bool_state (r
, lhs
, type
))
1264 // The TRUE side of NAN >= x is unreachable.
1265 if (op1
.known_isnan ())
1267 else if (op1
.undefined_p ())
1269 else if (build_le (r
, type
, op1
))
1274 // On the FALSE side of NAN >= x, we know nothing about x.
1275 if (op1
.known_isnan () || op1
.maybe_isnan ())
1276 r
.set_varying (type
);
1277 else if (op1
.undefined_p ())
1280 build_gt (r
, type
, op1
);
1289 // Check if the LHS range indicates a relation between OP1 and OP2.
1292 operator_ge::op1_op2_relation (const irange
&lhs
, const frange
&,
1293 const frange
&) const
1295 if (lhs
.undefined_p ())
1296 return VREL_UNDEFINED
;
1298 // FALSE = op1 >= op2 indicates LT_EXPR.
1302 // TRUE = op1 >= op2 indicates GE_EXPR.
1303 if (!contains_zero_p (lhs
))
1305 return VREL_VARYING
;
1308 // UNORDERED_EXPR comparison.
1310 class foperator_unordered
: public range_operator
1312 using range_operator::fold_range
;
1313 using range_operator::op1_range
;
1314 using range_operator::op2_range
;
1316 bool fold_range (irange
&r
, tree type
,
1317 const frange
&op1
, const frange
&op2
,
1318 relation_trio
= TRIO_VARYING
) const final override
;
1319 bool op1_range (frange
&r
, tree type
,
1320 const irange
&lhs
, const frange
&op2
,
1321 relation_trio
= TRIO_VARYING
) const final override
;
1322 bool op2_range (frange
&r
, tree type
,
1323 const irange
&lhs
, const frange
&op1
,
1324 relation_trio rel
= TRIO_VARYING
) const final override
1326 return op1_range (r
, type
, lhs
, op1
, rel
.swap_op1_op2 ());
1331 foperator_unordered::fold_range (irange
&r
, tree type
,
1332 const frange
&op1
, const frange
&op2
,
1333 relation_trio
) const
1335 // UNORDERED is TRUE if either operand is a NAN.
1336 if (op1
.known_isnan () || op2
.known_isnan ())
1337 r
= range_true (type
);
1338 // UNORDERED is FALSE if neither operand is a NAN.
1339 else if (!op1
.maybe_isnan () && !op2
.maybe_isnan ())
1340 r
= range_false (type
);
1342 r
= range_true_and_false (type
);
1347 foperator_unordered::op1_range (frange
&r
, tree type
,
1350 relation_trio trio
) const
1352 relation_kind rel
= trio
.op1_op2 ();
1353 switch (get_bool_state (r
, lhs
, type
))
1356 // Since at least one operand must be NAN, if one of them is
1357 // not, the other must be.
1358 if (rel
== VREL_EQ
|| !op2
.maybe_isnan ())
1361 r
.set_varying (type
);
1365 // A false UNORDERED means both operands are !NAN, so it's
1366 // impossible for op2 to be a NAN.
1367 if (op2
.known_isnan ())
1371 r
.set_varying (type
);
1382 // ORDERED_EXPR comparison.
1384 class foperator_ordered
: public range_operator
1386 using range_operator::fold_range
;
1387 using range_operator::op1_range
;
1388 using range_operator::op2_range
;
1390 bool fold_range (irange
&r
, tree type
,
1391 const frange
&op1
, const frange
&op2
,
1392 relation_trio
= TRIO_VARYING
) const final override
;
1393 bool op1_range (frange
&r
, tree type
,
1394 const irange
&lhs
, const frange
&op2
,
1395 relation_trio
= TRIO_VARYING
) const final override
;
1396 bool op2_range (frange
&r
, tree type
,
1397 const irange
&lhs
, const frange
&op1
,
1398 relation_trio rel
= TRIO_VARYING
) const final override
1400 return op1_range (r
, type
, lhs
, op1
, rel
.swap_op1_op2 ());
1405 foperator_ordered::fold_range (irange
&r
, tree type
,
1406 const frange
&op1
, const frange
&op2
,
1407 relation_trio
) const
1409 if (op1
.known_isnan () || op2
.known_isnan ())
1410 r
= range_false (type
);
1411 else if (!op1
.maybe_isnan () && !op2
.maybe_isnan ())
1412 r
= range_true (type
);
1414 r
= range_true_and_false (type
);
1419 foperator_ordered::op1_range (frange
&r
, tree type
,
1422 relation_trio trio
) const
1424 relation_kind rel
= trio
.op1_op2 ();
1425 switch (get_bool_state (r
, lhs
, type
))
1428 // The TRUE side of ORDERED means both operands are !NAN, so
1429 // it's impossible for op2 to be a NAN.
1430 if (op2
.known_isnan ())
1434 r
.set_varying (type
);
1440 // The FALSE side of op1 ORDERED op1 implies op1 is NAN.
1444 r
.set_varying (type
);
1454 operator_negate::fold_range (frange
&r
, tree type
,
1455 const frange
&op1
, const frange
&op2
,
1456 relation_trio
) const
1458 if (empty_range_varying (r
, type
, op1
, op2
))
1460 if (op1
.known_isnan ())
1463 if (op1
.nan_signbit_p (sign
))
1464 r
.set_nan (type
, !sign
);
1470 REAL_VALUE_TYPE lh_lb
= op1
.lower_bound ();
1471 REAL_VALUE_TYPE lh_ub
= op1
.upper_bound ();
1472 lh_lb
= real_value_negate (&lh_lb
);
1473 lh_ub
= real_value_negate (&lh_ub
);
1474 r
.set (type
, lh_ub
, lh_lb
);
1475 if (op1
.maybe_isnan ())
1478 if (op1
.nan_signbit_p (sign
))
1479 r
.update_nan (!sign
);
1489 operator_negate::op1_range (frange
&r
, tree type
,
1490 const frange
&lhs
, const frange
&op2
,
1491 relation_trio rel
) const
1493 return fold_range (r
, type
, lhs
, op2
, rel
);
1497 operator_abs::fold_range (frange
&r
, tree type
,
1498 const frange
&op1
, const frange
&op2
,
1499 relation_trio
) const
1501 if (empty_range_varying (r
, type
, op1
, op2
))
1503 if (op1
.known_isnan ())
1505 r
.set_nan (type
, /*sign=*/false);
1509 const REAL_VALUE_TYPE lh_lb
= op1
.lower_bound ();
1510 const REAL_VALUE_TYPE lh_ub
= op1
.upper_bound ();
1511 // Handle the easy case where everything is positive.
1512 if (real_compare (GE_EXPR
, &lh_lb
, &dconst0
)
1513 && !real_iszero (&lh_lb
, /*sign=*/true)
1514 && !op1
.maybe_isnan (/*sign=*/true))
1520 REAL_VALUE_TYPE min
= real_value_abs (&lh_lb
);
1521 REAL_VALUE_TYPE max
= real_value_abs (&lh_ub
);
1522 // If the range contains zero then we know that the minimum value in the
1523 // range will be zero.
1524 if (real_compare (LE_EXPR
, &lh_lb
, &dconst0
)
1525 && real_compare (GE_EXPR
, &lh_ub
, &dconst0
))
1527 if (real_compare (GT_EXPR
, &min
, &max
))
1533 // If the range was reversed, swap MIN and MAX.
1534 if (real_compare (GT_EXPR
, &min
, &max
))
1535 std::swap (min
, max
);
1538 r
.set (type
, min
, max
);
1539 if (op1
.maybe_isnan ())
1540 r
.update_nan (/*sign=*/false);
1547 operator_abs::op1_range (frange
&r
, tree type
,
1548 const frange
&lhs
, const frange
&op2
,
1549 relation_trio
) const
1551 if (empty_range_varying (r
, type
, lhs
, op2
))
1553 if (lhs
.known_isnan ())
1559 // Start with the positives because negatives are an impossible result.
1560 frange
positives (type
, dconst0
, frange_val_max (type
));
1561 positives
.update_nan (/*sign=*/false);
1562 positives
.intersect (lhs
);
1564 // Add -NAN if relevant.
1565 if (r
.maybe_isnan ())
1568 neg_nan
.set_nan (type
, true);
1571 if (r
.known_isnan () || r
.undefined_p ())
1573 // Then add the negative of each pair:
1574 // ABS(op1) = [5,20] would yield op1 => [-20,-5][5,20].
1575 frange
negatives (type
, real_value_negate (&positives
.upper_bound ()),
1576 real_value_negate (&positives
.lower_bound ()));
1577 negatives
.clear_nan ();
1578 r
.union_ (negatives
);
1582 class foperator_unordered_lt
: public range_operator
1584 using range_operator::fold_range
;
1585 using range_operator::op1_range
;
1586 using range_operator::op2_range
;
1588 bool fold_range (irange
&r
, tree type
,
1589 const frange
&op1
, const frange
&op2
,
1590 relation_trio rel
= TRIO_VARYING
) const final override
1592 if (op1
.known_isnan () || op2
.known_isnan ())
1594 r
= range_true (type
);
1597 frange op1_no_nan
= op1
;
1598 frange op2_no_nan
= op2
;
1599 if (op1
.maybe_isnan ())
1600 op1_no_nan
.clear_nan ();
1601 if (op2
.maybe_isnan ())
1602 op2_no_nan
.clear_nan ();
1603 if (!range_op_handler (LT_EXPR
).fold_range (r
, type
, op1_no_nan
,
1606 // The result is the same as the ordered version when the
1607 // comparison is true or when the operands cannot be NANs.
1608 if (!maybe_isnan (op1
, op2
) || r
== range_true (type
))
1612 r
= range_true_and_false (type
);
1616 bool op1_range (frange
&r
, tree type
,
1619 relation_trio trio
) const final override
;
1620 bool op2_range (frange
&r
, tree type
,
1623 relation_trio trio
) const final override
;
1627 foperator_unordered_lt::op1_range (frange
&r
, tree type
,
1630 relation_trio
) const
1632 switch (get_bool_state (r
, lhs
, type
))
1635 if (op2
.known_isnan () || op2
.maybe_isnan ())
1636 r
.set_varying (type
);
1637 else if (op2
.undefined_p ())
1640 build_lt (r
, type
, op2
);
1644 // A false UNORDERED_LT means both operands are !NAN, so it's
1645 // impossible for op2 to be a NAN.
1646 if (op2
.known_isnan ())
1648 else if (op2
.undefined_p ())
1650 else if (build_ge (r
, type
, op2
))
1661 foperator_unordered_lt::op2_range (frange
&r
, tree type
,
1664 relation_trio
) const
1666 switch (get_bool_state (r
, lhs
, type
))
1669 if (op1
.known_isnan () || op1
.maybe_isnan ())
1670 r
.set_varying (type
);
1671 else if (op1
.undefined_p ())
1674 build_gt (r
, type
, op1
);
1678 // A false UNORDERED_LT means both operands are !NAN, so it's
1679 // impossible for op1 to be a NAN.
1680 if (op1
.known_isnan ())
1682 else if (op1
.undefined_p ())
1684 else if (build_le (r
, type
, op1
))
1694 class foperator_unordered_le
: public range_operator
1696 using range_operator::fold_range
;
1697 using range_operator::op1_range
;
1698 using range_operator::op2_range
;
1700 bool fold_range (irange
&r
, tree type
,
1701 const frange
&op1
, const frange
&op2
,
1702 relation_trio rel
= TRIO_VARYING
) const final override
1704 if (op1
.known_isnan () || op2
.known_isnan ())
1706 r
= range_true (type
);
1709 frange op1_no_nan
= op1
;
1710 frange op2_no_nan
= op2
;
1711 if (op1
.maybe_isnan ())
1712 op1_no_nan
.clear_nan ();
1713 if (op2
.maybe_isnan ())
1714 op2_no_nan
.clear_nan ();
1715 if (!range_op_handler (LE_EXPR
).fold_range (r
, type
, op1_no_nan
,
1718 // The result is the same as the ordered version when the
1719 // comparison is true or when the operands cannot be NANs.
1720 if (!maybe_isnan (op1
, op2
) || r
== range_true (type
))
1724 r
= range_true_and_false (type
);
1728 bool op1_range (frange
&r
, tree type
,
1729 const irange
&lhs
, const frange
&op2
,
1730 relation_trio
= TRIO_VARYING
) const final override
;
1731 bool op2_range (frange
&r
, tree type
,
1732 const irange
&lhs
, const frange
&op1
,
1733 relation_trio
= TRIO_VARYING
) const final override
;
1737 foperator_unordered_le::op1_range (frange
&r
, tree type
,
1738 const irange
&lhs
, const frange
&op2
,
1739 relation_trio
) const
1741 switch (get_bool_state (r
, lhs
, type
))
1744 if (op2
.known_isnan () || op2
.maybe_isnan ())
1745 r
.set_varying (type
);
1746 else if (op2
.undefined_p ())
1749 build_le (r
, type
, op2
);
1753 // A false UNORDERED_LE means both operands are !NAN, so it's
1754 // impossible for op2 to be a NAN.
1755 if (op2
.known_isnan ())
1757 else if (build_gt (r
, type
, op2
))
1768 foperator_unordered_le::op2_range (frange
&r
,
1772 relation_trio
) const
1774 switch (get_bool_state (r
, lhs
, type
))
1777 if (op1
.known_isnan () || op1
.maybe_isnan ())
1778 r
.set_varying (type
);
1779 else if (op1
.undefined_p ())
1782 build_ge (r
, type
, op1
);
1786 // A false UNORDERED_LE means both operands are !NAN, so it's
1787 // impossible for op1 to be a NAN.
1788 if (op1
.known_isnan ())
1790 else if (op1
.undefined_p ())
1792 else if (build_lt (r
, type
, op1
))
1802 class foperator_unordered_gt
: public range_operator
1804 using range_operator::fold_range
;
1805 using range_operator::op1_range
;
1806 using range_operator::op2_range
;
1808 bool fold_range (irange
&r
, tree type
,
1809 const frange
&op1
, const frange
&op2
,
1810 relation_trio rel
= TRIO_VARYING
) const final override
1812 if (op1
.known_isnan () || op2
.known_isnan ())
1814 r
= range_true (type
);
1817 frange op1_no_nan
= op1
;
1818 frange op2_no_nan
= op2
;
1819 if (op1
.maybe_isnan ())
1820 op1_no_nan
.clear_nan ();
1821 if (op2
.maybe_isnan ())
1822 op2_no_nan
.clear_nan ();
1823 if (!range_op_handler (GT_EXPR
).fold_range (r
, type
, op1_no_nan
,
1826 // The result is the same as the ordered version when the
1827 // comparison is true or when the operands cannot be NANs.
1828 if (!maybe_isnan (op1
, op2
) || r
== range_true (type
))
1832 r
= range_true_and_false (type
);
1836 bool op1_range (frange
&r
, tree type
,
1837 const irange
&lhs
, const frange
&op2
,
1838 relation_trio
= TRIO_VARYING
) const final override
;
1839 bool op2_range (frange
&r
, tree type
,
1840 const irange
&lhs
, const frange
&op1
,
1841 relation_trio
= TRIO_VARYING
) const final override
;
1845 foperator_unordered_gt::op1_range (frange
&r
,
1849 relation_trio
) const
1851 switch (get_bool_state (r
, lhs
, type
))
1854 if (op2
.known_isnan () || op2
.maybe_isnan ())
1855 r
.set_varying (type
);
1856 else if (op2
.undefined_p ())
1859 build_gt (r
, type
, op2
);
1863 // A false UNORDERED_GT means both operands are !NAN, so it's
1864 // impossible for op2 to be a NAN.
1865 if (op2
.known_isnan ())
1867 else if (op2
.undefined_p ())
1869 else if (build_le (r
, type
, op2
))
1880 foperator_unordered_gt::op2_range (frange
&r
,
1884 relation_trio
) const
1886 switch (get_bool_state (r
, lhs
, type
))
1889 if (op1
.known_isnan () || op1
.maybe_isnan ())
1890 r
.set_varying (type
);
1891 else if (op1
.undefined_p ())
1894 build_lt (r
, type
, op1
);
1898 // A false UNORDERED_GT means both operands are !NAN, so it's
1899 // impossible for op1 to be a NAN.
1900 if (op1
.known_isnan ())
1902 else if (op1
.undefined_p ())
1904 else if (build_ge (r
, type
, op1
))
1914 class foperator_unordered_ge
: public range_operator
1916 using range_operator::fold_range
;
1917 using range_operator::op1_range
;
1918 using range_operator::op2_range
;
1920 bool fold_range (irange
&r
, tree type
,
1921 const frange
&op1
, const frange
&op2
,
1922 relation_trio rel
= TRIO_VARYING
) const final override
1924 if (op1
.known_isnan () || op2
.known_isnan ())
1926 r
= range_true (type
);
1929 frange op1_no_nan
= op1
;
1930 frange op2_no_nan
= op2
;
1931 if (op1
.maybe_isnan ())
1932 op1_no_nan
.clear_nan ();
1933 if (op2
.maybe_isnan ())
1934 op2_no_nan
.clear_nan ();
1935 if (!range_op_handler (GE_EXPR
).fold_range (r
, type
, op1_no_nan
,
1938 // The result is the same as the ordered version when the
1939 // comparison is true or when the operands cannot be NANs.
1940 if (!maybe_isnan (op1
, op2
) || r
== range_true (type
))
1944 r
= range_true_and_false (type
);
1948 bool op1_range (frange
&r
, tree type
,
1949 const irange
&lhs
, const frange
&op2
,
1950 relation_trio
= TRIO_VARYING
) const final override
;
1951 bool op2_range (frange
&r
, tree type
,
1952 const irange
&lhs
, const frange
&op1
,
1953 relation_trio
= TRIO_VARYING
) const final override
;
1957 foperator_unordered_ge::op1_range (frange
&r
,
1961 relation_trio
) const
1963 switch (get_bool_state (r
, lhs
, type
))
1966 if (op2
.known_isnan () || op2
.maybe_isnan ())
1967 r
.set_varying (type
);
1968 else if (op2
.undefined_p ())
1971 build_ge (r
, type
, op2
);
1975 // A false UNORDERED_GE means both operands are !NAN, so it's
1976 // impossible for op2 to be a NAN.
1977 if (op2
.known_isnan ())
1979 else if (op2
.undefined_p ())
1981 else if (build_lt (r
, type
, op2
))
1992 foperator_unordered_ge::op2_range (frange
&r
, tree type
,
1995 relation_trio
) const
1997 switch (get_bool_state (r
, lhs
, type
))
2000 if (op1
.known_isnan () || op1
.maybe_isnan ())
2001 r
.set_varying (type
);
2002 else if (op1
.undefined_p ())
2005 build_le (r
, type
, op1
);
2009 // A false UNORDERED_GE means both operands are !NAN, so it's
2010 // impossible for op1 to be a NAN.
2011 if (op1
.known_isnan ())
2013 else if (op1
.undefined_p ())
2015 else if (build_gt (r
, type
, op1
))
2025 class foperator_unordered_equal
: public range_operator
2027 using range_operator::fold_range
;
2028 using range_operator::op1_range
;
2029 using range_operator::op2_range
;
2031 bool fold_range (irange
&r
, tree type
,
2032 const frange
&op1
, const frange
&op2
,
2033 relation_trio rel
= TRIO_VARYING
) const final override
2035 if (op1
.known_isnan () || op2
.known_isnan ())
2037 r
= range_true (type
);
2040 frange op1_no_nan
= op1
;
2041 frange op2_no_nan
= op2
;
2042 if (op1
.maybe_isnan ())
2043 op1_no_nan
.clear_nan ();
2044 if (op2
.maybe_isnan ())
2045 op2_no_nan
.clear_nan ();
2046 if (!range_op_handler (EQ_EXPR
).fold_range (r
, type
, op1_no_nan
,
2049 // The result is the same as the ordered version when the
2050 // comparison is true or when the operands cannot be NANs.
2051 if (!maybe_isnan (op1
, op2
) || r
== range_true (type
))
2055 r
= range_true_and_false (type
);
2059 bool op1_range (frange
&r
, tree type
,
2060 const irange
&lhs
, const frange
&op2
,
2061 relation_trio
= TRIO_VARYING
) const final override
;
2062 bool op2_range (frange
&r
, tree type
,
2063 const irange
&lhs
, const frange
&op1
,
2064 relation_trio rel
= TRIO_VARYING
) const final override
2066 return op1_range (r
, type
, lhs
, op1
, rel
.swap_op1_op2 ());
2068 } fop_unordered_equal
;
2071 foperator_unordered_equal::op1_range (frange
&r
, tree type
,
2074 relation_trio
) const
2076 switch (get_bool_state (r
, lhs
, type
))
2079 // If it's true, the result is the same as OP2 plus a NAN.
2081 // Add both zeros if there's the possibility of zero equality.
2082 frange_add_zeros (r
, type
);
2083 // Add the possibility of a NAN.
2088 // A false UNORDERED_EQ means both operands are !NAN, so it's
2089 // impossible for op2 to be a NAN.
2090 if (op2
.known_isnan ())
2094 // The false side indicates !NAN and not equal. We can at least
2096 r
.set_varying (type
);
2107 class foperator_ltgt
: public range_operator
2109 using range_operator::fold_range
;
2110 using range_operator::op1_range
;
2111 using range_operator::op2_range
;
2113 bool fold_range (irange
&r
, tree type
,
2114 const frange
&op1
, const frange
&op2
,
2115 relation_trio rel
= TRIO_VARYING
) const final override
2117 if (op1
.known_isnan () || op2
.known_isnan ())
2119 r
= range_false (type
);
2122 frange op1_no_nan
= op1
;
2123 frange op2_no_nan
= op2
;
2124 if (op1
.maybe_isnan ())
2125 op1_no_nan
.clear_nan ();
2126 if (op2
.maybe_isnan ())
2127 op2_no_nan
.clear_nan ();
2128 if (!range_op_handler (NE_EXPR
).fold_range (r
, type
, op1_no_nan
,
2131 // The result is the same as the ordered version when the
2132 // comparison is true or when the operands cannot be NANs.
2133 if (!maybe_isnan (op1
, op2
) || r
== range_false (type
))
2137 r
= range_true_and_false (type
);
2141 bool op1_range (frange
&r
, tree type
,
2142 const irange
&lhs
, const frange
&op2
,
2143 relation_trio
= TRIO_VARYING
) const final override
;
2144 bool op2_range (frange
&r
, tree type
,
2145 const irange
&lhs
, const frange
&op1
,
2146 relation_trio rel
= TRIO_VARYING
) const final override
2148 return op1_range (r
, type
, lhs
, op1
, rel
.swap_op1_op2 ());
2153 foperator_ltgt::op1_range (frange
&r
, tree type
,
2156 relation_trio
) const
2158 switch (get_bool_state (r
, lhs
, type
))
2161 // A true LTGT means both operands are !NAN, so it's
2162 // impossible for op2 to be a NAN.
2163 if (op2
.known_isnan ())
2167 // The true side indicates !NAN and not equal. We can at least
2169 r
.set_varying (type
);
2175 // If it's false, the result is the same as OP2 plus a NAN.
2177 // Add both zeros if there's the possibility of zero equality.
2178 frange_add_zeros (r
, type
);
2179 // Add the possibility of a NAN.
2189 // Final tweaks for float binary op op1_range/op2_range.
2190 // Return TRUE if the operation is performed and a valid range is available.
2193 float_binary_op_range_finish (bool ret
, frange
&r
, tree type
,
2194 const frange
&lhs
, bool div_op2
= false)
2199 // If we get a known NAN from reverse op, it means either that
2200 // the other operand was known NAN (in that case we know nothing),
2201 // or the reverse operation introduced a known NAN.
2202 // Say for lhs = op1 * op2 if lhs is [-0, +0] and op2 is too,
2203 // 0 / 0 is known NAN. Just punt in that case.
2204 // If NANs aren't honored, we get for 0 / 0 UNDEFINED, so punt as well.
2205 // Or if lhs is a known NAN, we also don't know anything.
2206 if (r
.known_isnan () || lhs
.known_isnan () || r
.undefined_p ())
2208 r
.set_varying (type
);
2212 // If lhs isn't NAN, then neither operand could be NAN,
2213 // even if the reverse operation does introduce a maybe_nan.
2214 if (!lhs
.maybe_isnan ())
2218 ? !(real_compare (LE_EXPR
, &lhs
.lower_bound (), &dconst0
)
2219 && real_compare (GE_EXPR
, &lhs
.upper_bound (), &dconst0
))
2220 : !(real_isinf (&lhs
.lower_bound ())
2221 || real_isinf (&lhs
.upper_bound ())))
2222 // For reverse + or - or * or op1 of /, if result is finite, then
2223 // r must be finite too, as X + INF or X - INF or X * INF or
2224 // INF / X is always +-INF or NAN. For op2 of /, if result is
2225 // non-zero and not NAN, r must be finite, as X / INF is always
2227 frange_drop_infs (r
, type
);
2229 // If lhs is a maybe or known NAN, the operand could be
2236 // True if [lb, ub] is [+-0, +-0].
2238 zero_p (const REAL_VALUE_TYPE
&lb
, const REAL_VALUE_TYPE
&ub
)
2240 return real_iszero (&lb
) && real_iszero (&ub
);
2243 // True if +0 or -0 is in [lb, ub] range.
2245 contains_zero_p (const REAL_VALUE_TYPE
&lb
, const REAL_VALUE_TYPE
&ub
)
2247 return (real_compare (LE_EXPR
, &lb
, &dconst0
)
2248 && real_compare (GE_EXPR
, &ub
, &dconst0
));
2251 // True if [lb, ub] is [-INF, -INF] or [+INF, +INF].
2253 singleton_inf_p (const REAL_VALUE_TYPE
&lb
, const REAL_VALUE_TYPE
&ub
)
2255 return real_isinf (&lb
) && real_isinf (&ub
, real_isneg (&lb
));
2258 // Return -1 if binary op result must have sign bit set,
2259 // 1 if binary op result must have sign bit clear,
2261 // Sign bit of binary op result is exclusive or of the
2262 // operand's sign bits.
2264 signbit_known_p (const REAL_VALUE_TYPE
&lh_lb
, const REAL_VALUE_TYPE
&lh_ub
,
2265 const REAL_VALUE_TYPE
&rh_lb
, const REAL_VALUE_TYPE
&rh_ub
)
2267 if (real_isneg (&lh_lb
) == real_isneg (&lh_ub
)
2268 && real_isneg (&rh_lb
) == real_isneg (&rh_ub
))
2270 if (real_isneg (&lh_lb
) == real_isneg (&rh_ub
))
2278 // Set [lb, ub] to [-0, -0], [-0, +0] or [+0, +0] depending on
2281 zero_range (REAL_VALUE_TYPE
&lb
, REAL_VALUE_TYPE
&ub
, int signbit_known
)
2284 if (signbit_known
<= 0)
2286 if (signbit_known
< 0)
2290 // Set [lb, ub] to [-INF, -INF], [-INF, +INF] or [+INF, +INF] depending on
2293 inf_range (REAL_VALUE_TYPE
&lb
, REAL_VALUE_TYPE
&ub
, int signbit_known
)
2295 if (signbit_known
> 0)
2296 ub
= lb
= dconstinf
;
2297 else if (signbit_known
< 0)
2298 ub
= lb
= dconstninf
;
2306 // Set [lb, ub] to [-INF, -0], [-INF, +INF] or [+0, +INF] depending on
2309 zero_to_inf_range (REAL_VALUE_TYPE
&lb
, REAL_VALUE_TYPE
&ub
, int signbit_known
)
2311 if (signbit_known
> 0)
2316 else if (signbit_known
< 0)
2328 /* Extend the LHS range by 1ulp in each direction. For op1_range
2329 or op2_range of binary operations just computing the inverse
2330 operation on ranges isn't sufficient. Consider e.g.
2331 [1., 1.] = op1 + [1., 1.]. op1's range is not [0., 0.], but
2332 [-0x1.0p-54, 0x1.0p-53] (when not -frounding-math), any value for
2333 which adding 1. to it results in 1. after rounding to nearest.
2334 So, for op1_range/op2_range extend the lhs range by 1ulp (or 0.5ulp)
2335 in each direction. See PR109008 for more details. */
2338 float_widen_lhs_range (tree type
, const frange
&lhs
)
2341 if (lhs
.known_isnan ())
2343 REAL_VALUE_TYPE lb
= lhs
.lower_bound ();
2344 REAL_VALUE_TYPE ub
= lhs
.upper_bound ();
2345 if (real_isfinite (&lb
))
2347 frange_nextafter (TYPE_MODE (type
), lb
, dconstninf
);
2348 if (real_isinf (&lb
))
2350 /* For -DBL_MAX, instead of -Inf use
2351 nexttoward (-DBL_MAX, -LDBL_MAX) in a hypothetical
2352 wider type with the same mantissa precision but larger
2353 exponent range; it is outside of range of double values,
2354 but makes it clear it is just one ulp larger rather than
2355 infinite amount larger. */
2357 SET_REAL_EXP (&lb
, FLOAT_MODE_FORMAT (TYPE_MODE (type
))->emax
+ 1);
2359 if (!flag_rounding_math
&& !MODE_COMPOSITE_P (TYPE_MODE (type
)))
2361 /* If not -frounding-math nor IBM double double, actually widen
2362 just by 0.5ulp rather than 1ulp. */
2363 REAL_VALUE_TYPE tem
;
2364 real_arithmetic (&tem
, PLUS_EXPR
, &lhs
.lower_bound (), &lb
);
2365 real_arithmetic (&lb
, RDIV_EXPR
, &tem
, &dconst2
);
2368 if (real_isfinite (&ub
))
2370 frange_nextafter (TYPE_MODE (type
), ub
, dconstinf
);
2371 if (real_isinf (&ub
))
2373 /* For DBL_MAX similarly. */
2375 SET_REAL_EXP (&ub
, FLOAT_MODE_FORMAT (TYPE_MODE (type
))->emax
+ 1);
2377 if (!flag_rounding_math
&& !MODE_COMPOSITE_P (TYPE_MODE (type
)))
2379 /* If not -frounding-math nor IBM double double, actually widen
2380 just by 0.5ulp rather than 1ulp. */
2381 REAL_VALUE_TYPE tem
;
2382 real_arithmetic (&tem
, PLUS_EXPR
, &lhs
.upper_bound (), &ub
);
2383 real_arithmetic (&ub
, RDIV_EXPR
, &tem
, &dconst2
);
2386 /* Temporarily disable -ffinite-math-only, so that frange::set doesn't
2387 reduce the range back to real_min_representable (type) as lower bound
2388 or real_max_representable (type) as upper bound. */
2389 bool save_flag_finite_math_only
= flag_finite_math_only
;
2390 flag_finite_math_only
= false;
2391 ret
.set (type
, lb
, ub
, lhs
.get_nan_state ());
2392 flag_finite_math_only
= save_flag_finite_math_only
;
2397 operator_plus::op1_range (frange
&r
, tree type
, const frange
&lhs
,
2398 const frange
&op2
, relation_trio
) const
2400 if (lhs
.undefined_p ())
2402 range_op_handler
minus (MINUS_EXPR
);
2405 frange wlhs
= float_widen_lhs_range (type
, lhs
);
2406 return float_binary_op_range_finish (minus
.fold_range (r
, type
, wlhs
, op2
),
2411 operator_plus::op2_range (frange
&r
, tree type
,
2412 const frange
&lhs
, const frange
&op1
,
2413 relation_trio
) const
2415 return op1_range (r
, type
, lhs
, op1
);
2419 operator_plus::rv_fold (REAL_VALUE_TYPE
&lb
, REAL_VALUE_TYPE
&ub
,
2420 bool &maybe_nan
, tree type
,
2421 const REAL_VALUE_TYPE
&lh_lb
,
2422 const REAL_VALUE_TYPE
&lh_ub
,
2423 const REAL_VALUE_TYPE
&rh_lb
,
2424 const REAL_VALUE_TYPE
&rh_ub
,
2425 relation_kind
) const
2427 frange_arithmetic (PLUS_EXPR
, type
, lb
, lh_lb
, rh_lb
, dconstninf
);
2428 frange_arithmetic (PLUS_EXPR
, type
, ub
, lh_ub
, rh_ub
, dconstinf
);
2430 // [-INF] + [+INF] = NAN
2431 if (real_isinf (&lh_lb
, true) && real_isinf (&rh_ub
, false))
2433 // [+INF] + [-INF] = NAN
2434 else if (real_isinf (&lh_ub
, false) && real_isinf (&rh_lb
, true))
2442 operator_minus::op1_range (frange
&r
, tree type
,
2443 const frange
&lhs
, const frange
&op2
,
2444 relation_trio
) const
2446 if (lhs
.undefined_p ())
2448 frange wlhs
= float_widen_lhs_range (type
, lhs
);
2449 return float_binary_op_range_finish (
2450 range_op_handler (PLUS_EXPR
).fold_range (r
, type
, wlhs
, op2
),
2455 operator_minus::op2_range (frange
&r
, tree type
,
2456 const frange
&lhs
, const frange
&op1
,
2457 relation_trio
) const
2459 if (lhs
.undefined_p ())
2461 frange wlhs
= float_widen_lhs_range (type
, lhs
);
2462 return float_binary_op_range_finish (fold_range (r
, type
, op1
, wlhs
),
2467 operator_minus::rv_fold (REAL_VALUE_TYPE
&lb
, REAL_VALUE_TYPE
&ub
,
2468 bool &maybe_nan
, tree type
,
2469 const REAL_VALUE_TYPE
&lh_lb
,
2470 const REAL_VALUE_TYPE
&lh_ub
,
2471 const REAL_VALUE_TYPE
&rh_lb
,
2472 const REAL_VALUE_TYPE
&rh_ub
,
2473 relation_kind
) const
2475 frange_arithmetic (MINUS_EXPR
, type
, lb
, lh_lb
, rh_ub
, dconstninf
);
2476 frange_arithmetic (MINUS_EXPR
, type
, ub
, lh_ub
, rh_lb
, dconstinf
);
2478 // [+INF] - [+INF] = NAN
2479 if (real_isinf (&lh_ub
, false) && real_isinf (&rh_ub
, false))
2481 // [-INF] - [-INF] = NAN
2482 else if (real_isinf (&lh_lb
, true) && real_isinf (&rh_lb
, true))
2489 // Given CP[0] to CP[3] floating point values rounded to -INF,
2490 // set LB to the smallest of them (treating -0 as smaller to +0).
2491 // Given CP[4] to CP[7] floating point values rounded to +INF,
2492 // set UB to the largest of them (treating -0 as smaller to +0).
2495 find_range (REAL_VALUE_TYPE
&lb
, REAL_VALUE_TYPE
&ub
,
2496 const REAL_VALUE_TYPE (&cp
)[8])
2500 for (int i
= 1; i
< 4; ++i
)
2502 if (real_less (&cp
[i
], &lb
)
2503 || (real_iszero (&lb
) && real_isnegzero (&cp
[i
])))
2505 if (real_less (&ub
, &cp
[i
+ 4])
2506 || (real_isnegzero (&ub
) && real_iszero (&cp
[i
+ 4])))
2513 operator_mult::op1_range (frange
&r
, tree type
,
2514 const frange
&lhs
, const frange
&op2
,
2515 relation_trio
) const
2517 if (lhs
.undefined_p ())
2519 range_op_handler
rdiv (RDIV_EXPR
);
2522 frange wlhs
= float_widen_lhs_range (type
, lhs
);
2523 bool ret
= rdiv
.fold_range (r
, type
, wlhs
, op2
);
2526 if (wlhs
.known_isnan () || op2
.known_isnan () || op2
.undefined_p ())
2527 return float_binary_op_range_finish (ret
, r
, type
, wlhs
);
2528 const REAL_VALUE_TYPE
&lhs_lb
= wlhs
.lower_bound ();
2529 const REAL_VALUE_TYPE
&lhs_ub
= wlhs
.upper_bound ();
2530 const REAL_VALUE_TYPE
&op2_lb
= op2
.lower_bound ();
2531 const REAL_VALUE_TYPE
&op2_ub
= op2
.upper_bound ();
2532 if ((contains_zero_p (lhs_lb
, lhs_ub
) && contains_zero_p (op2_lb
, op2_ub
))
2533 || ((real_isinf (&lhs_lb
) || real_isinf (&lhs_ub
))
2534 && (real_isinf (&op2_lb
) || real_isinf (&op2_ub
))))
2536 // If both lhs and op2 could be zeros or both could be infinities,
2537 // we don't know anything about op1 except maybe for the sign
2538 // and perhaps if it can be NAN or not.
2539 REAL_VALUE_TYPE lb
, ub
;
2540 int signbit_known
= signbit_known_p (lhs_lb
, lhs_ub
, op2_lb
, op2_ub
);
2541 zero_to_inf_range (lb
, ub
, signbit_known
);
2542 r
.set (type
, lb
, ub
);
2544 // Otherwise, if op2 is a singleton INF and lhs doesn't include INF,
2545 // or if lhs must be zero and op2 doesn't include zero, it would be
2546 // UNDEFINED, while rdiv.fold_range computes a zero or singleton INF
2547 // range. Those are supersets of UNDEFINED, so let's keep that way.
2548 return float_binary_op_range_finish (ret
, r
, type
, wlhs
);
2552 operator_mult::op2_range (frange
&r
, tree type
,
2553 const frange
&lhs
, const frange
&op1
,
2554 relation_trio
) const
2556 return op1_range (r
, type
, lhs
, op1
);
2560 operator_mult::rv_fold (REAL_VALUE_TYPE
&lb
, REAL_VALUE_TYPE
&ub
,
2561 bool &maybe_nan
, tree type
,
2562 const REAL_VALUE_TYPE
&lh_lb
,
2563 const REAL_VALUE_TYPE
&lh_ub
,
2564 const REAL_VALUE_TYPE
&rh_lb
,
2565 const REAL_VALUE_TYPE
&rh_ub
,
2566 relation_kind kind
) const
2570 && real_equal (&lh_lb
, &rh_lb
)
2571 && real_equal (&lh_ub
, &rh_ub
)
2572 && real_isneg (&lh_lb
) == real_isneg (&rh_lb
)
2573 && real_isneg (&lh_ub
) == real_isneg (&rh_ub
));
2576 // x * x never produces a new NAN and we only multiply the same
2577 // values, so the 0 * INF problematic cases never appear there.
2580 // [+-0, +-0] * [+INF,+INF] (or [-INF,-INF] or swapped is a known NAN.
2581 if ((zero_p (lh_lb
, lh_ub
) && singleton_inf_p (rh_lb
, rh_ub
))
2582 || (zero_p (rh_lb
, rh_ub
) && singleton_inf_p (lh_lb
, lh_ub
)))
2584 real_nan (&lb
, "", 0, TYPE_MODE (type
));
2590 // Otherwise, if one range includes zero and the other ends with +-INF,
2591 // it is a maybe NAN.
2592 if ((contains_zero_p (lh_lb
, lh_ub
)
2593 && (real_isinf (&rh_lb
) || real_isinf (&rh_ub
)))
2594 || (contains_zero_p (rh_lb
, rh_ub
)
2595 && (real_isinf (&lh_lb
) || real_isinf (&lh_ub
))))
2599 int signbit_known
= signbit_known_p (lh_lb
, lh_ub
, rh_lb
, rh_ub
);
2601 // If one of the ranges that includes INF is singleton
2602 // and the other range includes zero, the resulting
2603 // range is INF and NAN, because the 0 * INF boundary
2604 // case will be NAN, but already nextafter (0, 1) * INF
2606 if (singleton_inf_p (lh_lb
, lh_ub
)
2607 || singleton_inf_p (rh_lb
, rh_ub
))
2608 return inf_range (lb
, ub
, signbit_known
);
2610 // If one of the multiplicands must be zero, the resulting
2611 // range is +-0 and NAN.
2612 if (zero_p (lh_lb
, lh_ub
) || zero_p (rh_lb
, rh_ub
))
2613 return zero_range (lb
, ub
, signbit_known
);
2615 // Otherwise one of the multiplicands could be
2616 // [0.0, nextafter (0.0, 1.0)] and the [DBL_MAX, INF]
2617 // or similarly with different signs. 0.0 * DBL_MAX
2618 // is still 0.0, nextafter (0.0, 1.0) * INF is still INF,
2619 // so if the signs are always the same or always different,
2620 // result is [+0.0, +INF] or [-INF, -0.0], otherwise VARYING.
2621 return zero_to_inf_range (lb
, ub
, signbit_known
);
2625 REAL_VALUE_TYPE cp
[8];
2626 // Do a cross-product. At this point none of the multiplications
2627 // should produce a NAN.
2628 frange_arithmetic (MULT_EXPR
, type
, cp
[0], lh_lb
, rh_lb
, dconstninf
);
2629 frange_arithmetic (MULT_EXPR
, type
, cp
[4], lh_lb
, rh_lb
, dconstinf
);
2632 // For x * x we can just do max (lh_lb * lh_lb, lh_ub * lh_ub)
2633 // as maximum and -0.0 as minimum if 0.0 is in the range,
2634 // otherwise min (lh_lb * lh_lb, lh_ub * lh_ub).
2635 // -0.0 rather than 0.0 because VREL_EQ doesn't prove that
2636 // x and y are bitwise equal, just that they compare equal.
2637 if (contains_zero_p (lh_lb
, lh_ub
))
2639 if (real_isneg (&lh_lb
) == real_isneg (&lh_ub
))
2652 frange_arithmetic (MULT_EXPR
, type
, cp
[1], lh_lb
, rh_ub
, dconstninf
);
2653 frange_arithmetic (MULT_EXPR
, type
, cp
[5], lh_lb
, rh_ub
, dconstinf
);
2654 frange_arithmetic (MULT_EXPR
, type
, cp
[2], lh_ub
, rh_lb
, dconstninf
);
2655 frange_arithmetic (MULT_EXPR
, type
, cp
[6], lh_ub
, rh_lb
, dconstinf
);
2657 frange_arithmetic (MULT_EXPR
, type
, cp
[3], lh_ub
, rh_ub
, dconstninf
);
2658 frange_arithmetic (MULT_EXPR
, type
, cp
[7], lh_ub
, rh_ub
, dconstinf
);
2660 find_range (lb
, ub
, cp
);
2664 class foperator_div
: public range_operator
2666 using range_operator::op1_range
;
2667 using range_operator::op2_range
;
2669 virtual bool op1_range (frange
&r
, tree type
,
2672 relation_trio
= TRIO_VARYING
) const final override
2674 if (lhs
.undefined_p ())
2676 frange wlhs
= float_widen_lhs_range (type
, lhs
);
2677 bool ret
= range_op_handler (MULT_EXPR
).fold_range (r
, type
, wlhs
, op2
);
2680 if (wlhs
.known_isnan () || op2
.known_isnan () || op2
.undefined_p ())
2681 return float_binary_op_range_finish (ret
, r
, type
, wlhs
);
2682 const REAL_VALUE_TYPE
&lhs_lb
= wlhs
.lower_bound ();
2683 const REAL_VALUE_TYPE
&lhs_ub
= wlhs
.upper_bound ();
2684 const REAL_VALUE_TYPE
&op2_lb
= op2
.lower_bound ();
2685 const REAL_VALUE_TYPE
&op2_ub
= op2
.upper_bound ();
2686 if ((contains_zero_p (lhs_lb
, lhs_ub
)
2687 && (real_isinf (&op2_lb
) || real_isinf (&op2_ub
)))
2688 || ((contains_zero_p (op2_lb
, op2_ub
))
2689 && (real_isinf (&lhs_lb
) || real_isinf (&lhs_ub
))))
2691 // If both lhs could be zero and op2 infinity or vice versa,
2692 // we don't know anything about op1 except maybe for the sign
2693 // and perhaps if it can be NAN or not.
2694 REAL_VALUE_TYPE lb
, ub
;
2695 int signbit_known
= signbit_known_p (lhs_lb
, lhs_ub
, op2_lb
, op2_ub
);
2696 zero_to_inf_range (lb
, ub
, signbit_known
);
2697 r
.set (type
, lb
, ub
);
2699 return float_binary_op_range_finish (ret
, r
, type
, wlhs
);
2701 virtual bool op2_range (frange
&r
, tree type
,
2704 relation_trio
= TRIO_VARYING
) const final override
2706 if (lhs
.undefined_p ())
2708 frange wlhs
= float_widen_lhs_range (type
, lhs
);
2709 bool ret
= fold_range (r
, type
, op1
, wlhs
);
2712 if (wlhs
.known_isnan () || op1
.known_isnan () || op1
.undefined_p ())
2713 return float_binary_op_range_finish (ret
, r
, type
, wlhs
, true);
2714 const REAL_VALUE_TYPE
&lhs_lb
= wlhs
.lower_bound ();
2715 const REAL_VALUE_TYPE
&lhs_ub
= wlhs
.upper_bound ();
2716 const REAL_VALUE_TYPE
&op1_lb
= op1
.lower_bound ();
2717 const REAL_VALUE_TYPE
&op1_ub
= op1
.upper_bound ();
2718 if ((contains_zero_p (lhs_lb
, lhs_ub
) && contains_zero_p (op1_lb
, op1_ub
))
2719 || ((real_isinf (&lhs_lb
) || real_isinf (&lhs_ub
))
2720 && (real_isinf (&op1_lb
) || real_isinf (&op1_ub
))))
2722 // If both lhs and op1 could be zeros or both could be infinities,
2723 // we don't know anything about op2 except maybe for the sign
2724 // and perhaps if it can be NAN or not.
2725 REAL_VALUE_TYPE lb
, ub
;
2726 int signbit_known
= signbit_known_p (lhs_lb
, lhs_ub
, op1_lb
, op1_ub
);
2727 zero_to_inf_range (lb
, ub
, signbit_known
);
2728 r
.set (type
, lb
, ub
);
2730 return float_binary_op_range_finish (ret
, r
, type
, wlhs
, true);
2733 void rv_fold (REAL_VALUE_TYPE
&lb
, REAL_VALUE_TYPE
&ub
, bool &maybe_nan
,
2735 const REAL_VALUE_TYPE
&lh_lb
,
2736 const REAL_VALUE_TYPE
&lh_ub
,
2737 const REAL_VALUE_TYPE
&rh_lb
,
2738 const REAL_VALUE_TYPE
&rh_ub
,
2739 relation_kind
) const final override
2741 // +-0.0 / +-0.0 or +-INF / +-INF is a known NAN.
2742 if ((zero_p (lh_lb
, lh_ub
) && zero_p (rh_lb
, rh_ub
))
2743 || (singleton_inf_p (lh_lb
, lh_ub
) && singleton_inf_p (rh_lb
, rh_ub
)))
2745 real_nan (&lb
, "", 0, TYPE_MODE (type
));
2751 // If +-0.0 is in both ranges, it is a maybe NAN.
2752 if (contains_zero_p (lh_lb
, lh_ub
) && contains_zero_p (rh_lb
, rh_ub
))
2754 // If +-INF is in both ranges, it is a maybe NAN.
2755 else if ((real_isinf (&lh_lb
) || real_isinf (&lh_ub
))
2756 && (real_isinf (&rh_lb
) || real_isinf (&rh_ub
)))
2761 int signbit_known
= signbit_known_p (lh_lb
, lh_ub
, rh_lb
, rh_ub
);
2763 // If dividend must be zero, the range is just +-0
2764 // (including if the divisor is +-INF).
2765 // If divisor must be +-INF, the range is just +-0
2766 // (including if the dividend is zero).
2767 if (zero_p (lh_lb
, lh_ub
) || singleton_inf_p (rh_lb
, rh_ub
))
2768 return zero_range (lb
, ub
, signbit_known
);
2770 // If divisor must be zero, the range is just +-INF
2771 // (including if the dividend is +-INF).
2772 // If dividend must be +-INF, the range is just +-INF
2773 // (including if the dividend is zero).
2774 if (zero_p (rh_lb
, rh_ub
) || singleton_inf_p (lh_lb
, lh_ub
))
2775 return inf_range (lb
, ub
, signbit_known
);
2777 // Otherwise if both operands may be zero, divisor could be
2778 // nextafter(0.0, +-1.0) and dividend +-0.0
2779 // in which case result is going to INF or vice versa and
2780 // result +0.0. So, all we can say for that case is if the
2781 // signs of divisor and dividend are always the same we have
2782 // [+0.0, +INF], if they are always different we have
2783 // [-INF, -0.0]. If they vary, VARYING.
2784 // If both may be +-INF, divisor could be INF and dividend FLT_MAX,
2785 // in which case result is going to INF or vice versa and
2786 // result +0.0. So, all we can say for that case is if the
2787 // signs of divisor and dividend are always the same we have
2788 // [+0.0, +INF], if they are always different we have
2789 // [-INF, -0.0]. If they vary, VARYING.
2791 return zero_to_inf_range (lb
, ub
, signbit_known
);
2793 REAL_VALUE_TYPE cp
[8];
2794 // Do a cross-division. At this point none of the divisions should
2796 frange_arithmetic (RDIV_EXPR
, type
, cp
[0], lh_lb
, rh_lb
, dconstninf
);
2797 frange_arithmetic (RDIV_EXPR
, type
, cp
[1], lh_lb
, rh_ub
, dconstninf
);
2798 frange_arithmetic (RDIV_EXPR
, type
, cp
[2], lh_ub
, rh_lb
, dconstninf
);
2799 frange_arithmetic (RDIV_EXPR
, type
, cp
[3], lh_ub
, rh_ub
, dconstninf
);
2800 frange_arithmetic (RDIV_EXPR
, type
, cp
[4], lh_lb
, rh_lb
, dconstinf
);
2801 frange_arithmetic (RDIV_EXPR
, type
, cp
[5], lh_lb
, rh_ub
, dconstinf
);
2802 frange_arithmetic (RDIV_EXPR
, type
, cp
[6], lh_ub
, rh_lb
, dconstinf
);
2803 frange_arithmetic (RDIV_EXPR
, type
, cp
[7], lh_ub
, rh_ub
, dconstinf
);
2805 find_range (lb
, ub
, cp
);
2807 // If divisor may be zero (but is not known to be only zero),
2808 // and dividend can't be zero, the range can go up to -INF or +INF
2809 // depending on the signs.
2810 if (contains_zero_p (rh_lb
, rh_ub
))
2812 if (signbit_known
<= 0)
2813 real_inf (&lb
, true);
2814 if (signbit_known
>= 0)
2815 real_inf (&ub
, false);
2821 // Initialize any float operators to the primary table
2824 range_op_table::initialize_float_ops ()
2826 set (UNLE_EXPR
, fop_unordered_le
);
2827 set (UNLT_EXPR
, fop_unordered_lt
);
2828 set (UNGE_EXPR
, fop_unordered_ge
);
2829 set (UNGT_EXPR
, fop_unordered_gt
);
2830 set (UNEQ_EXPR
, fop_unordered_equal
);
2831 set (ORDERED_EXPR
, fop_ordered
);
2832 set (UNORDERED_EXPR
, fop_unordered
);
2833 set (LTGT_EXPR
, fop_ltgt
);
2834 set (RDIV_EXPR
, fop_div
);
2838 #include "selftest.h"
2843 // Build an frange from string endpoints.
2845 static inline frange
2846 frange_float (const char *lb
, const char *ub
, tree type
= float_type_node
)
2848 REAL_VALUE_TYPE min
, max
;
2849 gcc_assert (real_from_string (&min
, lb
) == 0);
2850 gcc_assert (real_from_string (&max
, ub
) == 0);
2851 return frange (type
, min
, max
);
2855 range_op_float_tests ()
2858 frange
trange (float_type_node
);
2860 // negate([-5, +10]) => [-10, 5]
2861 r0
= frange_float ("-5", "10");
2862 range_op_handler (NEGATE_EXPR
).fold_range (r
, float_type_node
, r0
, trange
);
2863 ASSERT_EQ (r
, frange_float ("-10", "5"));
2865 // negate([0, 1] -NAN) => [-1, -0] +NAN
2866 r0
= frange_float ("0", "1");
2867 r0
.update_nan (true);
2868 range_op_handler (NEGATE_EXPR
).fold_range (r
, float_type_node
, r0
, trange
);
2869 r1
= frange_float ("-1", "-0");
2870 r1
.update_nan (false);
2873 // [-INF,+INF] + [-INF,+INF] could be a NAN.
2874 range_op_handler
plus (PLUS_EXPR
);
2875 r0
.set_varying (float_type_node
);
2876 r1
.set_varying (float_type_node
);
2879 plus
.fold_range (r
, float_type_node
, r0
, r1
);
2880 if (HONOR_NANS (float_type_node
))
2881 ASSERT_TRUE (r
.maybe_isnan ());
2884 } // namespace selftest
2886 #endif // CHECKING_P