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
, tree type
,
53 const frange
&op1
, const frange
&op2
,
54 relation_trio trio
) const
56 if (empty_range_varying (r
, type
, op1
, op2
))
58 if (op1
.known_isnan () || op2
.known_isnan ())
60 r
.set_nan (op1
.type ());
64 REAL_VALUE_TYPE lb
, ub
;
66 rv_fold (lb
, ub
, maybe_nan
, type
,
67 op1
.lower_bound (), op1
.upper_bound (),
68 op2
.lower_bound (), op2
.upper_bound (), trio
.op1_op2 ());
70 // Handle possible NANs by saturating to the appropriate INF if only
71 // one end is a NAN. If both ends are a NAN, just return a NAN.
72 bool lb_nan
= real_isnan (&lb
);
73 bool ub_nan
= real_isnan (&ub
);
86 if (lb_nan
|| ub_nan
|| maybe_nan
88 || op2
.maybe_isnan ())
89 // Keep the default NAN (with a varying sign) set by the setter.
97 // For a given operation, fold two sets of ranges into [lb, ub].
98 // MAYBE_NAN is set to TRUE if, in addition to any result in LB or
99 // UB, the final range has the possiblity of a NAN.
101 range_operator_float::rv_fold (REAL_VALUE_TYPE
&lb
,
104 tree type ATTRIBUTE_UNUSED
,
105 const REAL_VALUE_TYPE
&lh_lb ATTRIBUTE_UNUSED
,
106 const REAL_VALUE_TYPE
&lh_ub ATTRIBUTE_UNUSED
,
107 const REAL_VALUE_TYPE
&rh_lb ATTRIBUTE_UNUSED
,
108 const REAL_VALUE_TYPE
&rh_ub ATTRIBUTE_UNUSED
,
117 range_operator_float::fold_range (irange
&r ATTRIBUTE_UNUSED
,
118 tree type ATTRIBUTE_UNUSED
,
119 const frange
&lh ATTRIBUTE_UNUSED
,
120 const irange
&rh ATTRIBUTE_UNUSED
,
127 range_operator_float::fold_range (irange
&r ATTRIBUTE_UNUSED
,
128 tree type ATTRIBUTE_UNUSED
,
129 const frange
&lh ATTRIBUTE_UNUSED
,
130 const frange
&rh ATTRIBUTE_UNUSED
,
137 range_operator_float::op1_range (frange
&r ATTRIBUTE_UNUSED
,
138 tree type ATTRIBUTE_UNUSED
,
139 const frange
&lhs ATTRIBUTE_UNUSED
,
140 const frange
&op2 ATTRIBUTE_UNUSED
,
147 range_operator_float::op1_range (frange
&r ATTRIBUTE_UNUSED
,
148 tree type ATTRIBUTE_UNUSED
,
149 const irange
&lhs ATTRIBUTE_UNUSED
,
150 const frange
&op2 ATTRIBUTE_UNUSED
,
157 range_operator_float::op2_range (frange
&r ATTRIBUTE_UNUSED
,
158 tree type ATTRIBUTE_UNUSED
,
159 const frange
&lhs ATTRIBUTE_UNUSED
,
160 const frange
&op1 ATTRIBUTE_UNUSED
,
167 range_operator_float::op2_range (frange
&r ATTRIBUTE_UNUSED
,
168 tree type ATTRIBUTE_UNUSED
,
169 const irange
&lhs ATTRIBUTE_UNUSED
,
170 const frange
&op1 ATTRIBUTE_UNUSED
,
177 range_operator_float::lhs_op1_relation (const frange
&lhs ATTRIBUTE_UNUSED
,
178 const frange
&op1 ATTRIBUTE_UNUSED
,
179 const frange
&op2 ATTRIBUTE_UNUSED
,
186 range_operator_float::lhs_op1_relation (const irange
&lhs ATTRIBUTE_UNUSED
,
187 const frange
&op1 ATTRIBUTE_UNUSED
,
188 const frange
&op2 ATTRIBUTE_UNUSED
,
195 range_operator_float::lhs_op2_relation (const irange
&lhs ATTRIBUTE_UNUSED
,
196 const frange
&op1 ATTRIBUTE_UNUSED
,
197 const frange
&op2 ATTRIBUTE_UNUSED
,
204 range_operator_float::lhs_op2_relation (const frange
&lhs ATTRIBUTE_UNUSED
,
205 const frange
&op1 ATTRIBUTE_UNUSED
,
206 const frange
&op2 ATTRIBUTE_UNUSED
,
213 range_operator_float::op1_op2_relation (const irange
&lhs ATTRIBUTE_UNUSED
) const
219 range_operator_float::op1_op2_relation (const frange
&lhs ATTRIBUTE_UNUSED
) const
224 // Return TRUE if OP1 and OP2 may be a NAN.
227 maybe_isnan (const frange
&op1
, const frange
&op2
)
229 return op1
.maybe_isnan () || op2
.maybe_isnan ();
232 // Floating version of relop_early_resolve that takes into account NAN
233 // and -ffinite-math-only.
236 frelop_early_resolve (irange
&r
, tree type
,
237 const frange
&op1
, const frange
&op2
,
238 relation_trio rel
, relation_kind my_rel
)
240 // If either operand is undefined, return VARYING.
241 if (empty_range_varying (r
, type
, op1
, op2
))
244 // We can fold relations from the oracle when we know both operands
245 // are free of NANs, or when -ffinite-math-only.
246 return (!maybe_isnan (op1
, op2
)
247 && relop_early_resolve (r
, type
, op1
, op2
, rel
, my_rel
));
250 // Set VALUE to its next real value, or INF if the operation overflows.
253 frange_nextafter (enum machine_mode mode
,
254 REAL_VALUE_TYPE
&value
,
255 const REAL_VALUE_TYPE
&inf
)
257 if (MODE_COMPOSITE_P (mode
)
258 && (real_isdenormal (&value
, mode
) || real_iszero (&value
)))
260 // IBM extended denormals only have DFmode precision.
261 REAL_VALUE_TYPE tmp
, tmp2
;
262 real_convert (&tmp2
, DFmode
, &value
);
263 real_nextafter (&tmp
, REAL_MODE_FORMAT (DFmode
), &tmp2
, &inf
);
264 real_convert (&value
, mode
, &tmp
);
269 real_nextafter (&tmp
, REAL_MODE_FORMAT (mode
), &value
, &inf
);
274 // Like real_arithmetic, but round the result to INF if the operation
275 // produced inexact results.
277 // ?? There is still one problematic case, i387. With
278 // -fexcess-precision=standard we perform most SF/DFmode arithmetic in
279 // XFmode (long_double_type_node), so that case is OK. But without
280 // -mfpmath=sse, all the SF/DFmode computations are in XFmode
281 // precision (64-bit mantissa) and only occassionally rounded to
282 // SF/DFmode (when storing into memory from the 387 stack). Maybe
283 // this is ok as well though it is just occassionally more precise. ??
286 frange_arithmetic (enum tree_code code
, tree type
,
287 REAL_VALUE_TYPE
&result
,
288 const REAL_VALUE_TYPE
&op1
,
289 const REAL_VALUE_TYPE
&op2
,
290 const REAL_VALUE_TYPE
&inf
)
292 REAL_VALUE_TYPE value
;
293 enum machine_mode mode
= TYPE_MODE (type
);
294 bool mode_composite
= MODE_COMPOSITE_P (mode
);
296 bool inexact
= real_arithmetic (&value
, code
, &op1
, &op2
);
297 real_convert (&result
, mode
, &value
);
299 // Be extra careful if there may be discrepancies between the
300 // compile and runtime results.
306 bool low
= real_isneg (&inf
);
307 round
= (low
? !real_less (&result
, &value
)
308 : !real_less (&value
, &result
));
309 if (real_isinf (&result
, !low
)
310 && !real_isinf (&value
)
311 && !flag_rounding_math
)
313 // Use just [+INF, +INF] rather than [MAX, +INF]
314 // even if value is larger than MAX and rounds to
315 // nearest to +INF. Similarly just [-INF, -INF]
316 // rather than [-INF, +MAX] even if value is smaller
317 // than -MAX and rounds to nearest to -INF.
318 // Unless INEXACT is true, in that case we need some
324 REAL_VALUE_TYPE tmp
= result
, tmp2
;
325 frange_nextafter (mode
, tmp
, inf
);
326 // TMP is at this point the maximum representable
328 real_arithmetic (&tmp2
, MINUS_EXPR
, &value
, &tmp
);
329 if (real_isneg (&tmp2
) != low
330 && (REAL_EXP (&tmp2
) - REAL_EXP (&tmp
)
331 >= 2 - REAL_MODE_FORMAT (mode
)->p
))
336 if (round
&& (inexact
|| !real_identical (&result
, &value
)))
339 && (real_isdenormal (&result
, mode
) || real_iszero (&result
)))
341 // IBM extended denormals only have DFmode precision.
342 REAL_VALUE_TYPE tmp
, tmp2
;
343 real_convert (&tmp2
, DFmode
, &value
);
344 real_nextafter (&tmp
, REAL_MODE_FORMAT (DFmode
), &tmp2
, &inf
);
345 real_convert (&result
, mode
, &tmp
);
348 frange_nextafter (mode
, result
, inf
);
355 // ibm-ldouble-format documents 1ulp for + and -.
356 frange_nextafter (mode
, result
, inf
);
359 // ibm-ldouble-format documents 2ulps for *.
360 frange_nextafter (mode
, result
, inf
);
361 frange_nextafter (mode
, result
, inf
);
364 // ibm-ldouble-format documents 3ulps for /.
365 frange_nextafter (mode
, result
, inf
);
366 frange_nextafter (mode
, result
, inf
);
367 frange_nextafter (mode
, result
, inf
);
374 // Crop R to [-INF, MAX] where MAX is the maximum representable number
378 frange_drop_inf (frange
&r
, tree type
)
380 REAL_VALUE_TYPE max
= real_max_representable (type
);
381 frange
tmp (type
, r
.lower_bound (), max
);
385 // Crop R to [MIN, +INF] where MIN is the minimum representable number
389 frange_drop_ninf (frange
&r
, tree type
)
391 REAL_VALUE_TYPE min
= real_min_representable (type
);
392 frange
tmp (type
, min
, r
.upper_bound ());
396 // Crop R to [MIN, MAX] where MAX is the maximum representable number
397 // for TYPE and MIN the minimum representable number for TYPE.
400 frange_drop_infs (frange
&r
, tree type
)
402 REAL_VALUE_TYPE max
= real_max_representable (type
);
403 REAL_VALUE_TYPE min
= real_min_representable (type
);
404 frange
tmp (type
, min
, max
);
408 // If zero is in R, make sure both -0.0 and +0.0 are in the range.
411 frange_add_zeros (frange
&r
, tree type
)
413 if (r
.undefined_p () || r
.known_isnan ())
416 if (HONOR_SIGNED_ZEROS (type
)
417 && (real_iszero (&r
.lower_bound ()) || real_iszero (&r
.upper_bound ())))
420 zero
.set_zero (type
);
425 // Build a range that is <= VAL and store it in R. Return TRUE if
426 // further changes may be needed for R, or FALSE if R is in its final
430 build_le (frange
&r
, tree type
, const frange
&val
)
432 gcc_checking_assert (!val
.known_isnan ());
434 REAL_VALUE_TYPE ninf
= frange_val_min (type
);
435 r
.set (type
, ninf
, val
.upper_bound ());
437 // Add both zeros if there's the possibility of zero equality.
438 frange_add_zeros (r
, type
);
443 // Build a range that is < VAL and store it in R. Return TRUE if
444 // further changes may be needed for R, or FALSE if R is in its final
448 build_lt (frange
&r
, tree type
, const frange
&val
)
450 gcc_checking_assert (!val
.known_isnan ());
452 // < -INF is outside the range.
453 if (real_isinf (&val
.upper_bound (), 1))
455 if (HONOR_NANS (type
))
462 REAL_VALUE_TYPE ninf
= frange_val_min (type
);
463 REAL_VALUE_TYPE prev
= val
.upper_bound ();
464 machine_mode mode
= TYPE_MODE (type
);
465 // Default to the conservatively correct closed ranges for
466 // MODE_COMPOSITE_P, otherwise use nextafter. Note that for
467 // !HONOR_INFINITIES, nextafter will yield -INF, but frange::set()
468 // will crop the range appropriately.
469 if (!MODE_COMPOSITE_P (mode
))
470 frange_nextafter (mode
, prev
, ninf
);
471 r
.set (type
, ninf
, prev
);
475 // Build a range that is >= VAL and store it in R. Return TRUE if
476 // further changes may be needed for R, or FALSE if R is in its final
480 build_ge (frange
&r
, tree type
, const frange
&val
)
482 gcc_checking_assert (!val
.known_isnan ());
484 REAL_VALUE_TYPE inf
= frange_val_max (type
);
485 r
.set (type
, val
.lower_bound (), inf
);
487 // Add both zeros if there's the possibility of zero equality.
488 frange_add_zeros (r
, type
);
493 // Build a range that is > VAL and store it in R. Return TRUE if
494 // further changes may be needed for R, or FALSE if R is in its final
498 build_gt (frange
&r
, tree type
, const frange
&val
)
500 gcc_checking_assert (!val
.known_isnan ());
502 // > +INF is outside the range.
503 if (real_isinf (&val
.lower_bound (), 0))
505 if (HONOR_NANS (type
))
512 REAL_VALUE_TYPE inf
= frange_val_max (type
);
513 REAL_VALUE_TYPE next
= val
.lower_bound ();
514 machine_mode mode
= TYPE_MODE (type
);
515 // Default to the conservatively correct closed ranges for
516 // MODE_COMPOSITE_P, otherwise use nextafter. Note that for
517 // !HONOR_INFINITIES, nextafter will yield +INF, but frange::set()
518 // will crop the range appropriately.
519 if (!MODE_COMPOSITE_P (mode
))
520 frange_nextafter (mode
, next
, inf
);
521 r
.set (type
, next
, inf
);
526 class foperator_identity
: public range_operator_float
528 using range_operator_float::fold_range
;
529 using range_operator_float::op1_range
;
531 bool fold_range (frange
&r
, tree type ATTRIBUTE_UNUSED
,
532 const frange
&op1
, const frange
&op2 ATTRIBUTE_UNUSED
,
533 relation_trio
= TRIO_VARYING
) const final override
538 bool op1_range (frange
&r
, tree type ATTRIBUTE_UNUSED
,
539 const frange
&lhs
, const frange
&op2 ATTRIBUTE_UNUSED
,
540 relation_trio
= TRIO_VARYING
) const final override
548 class foperator_equal
: public range_operator_float
550 using range_operator_float::fold_range
;
551 using range_operator_float::op1_range
;
552 using range_operator_float::op2_range
;
553 using range_operator_float::op1_op2_relation
;
555 bool fold_range (irange
&r
, tree type
,
556 const frange
&op1
, const frange
&op2
,
557 relation_trio
= TRIO_VARYING
) const final override
;
558 relation_kind
op1_op2_relation (const irange
&lhs
) const final override
560 return equal_op1_op2_relation (lhs
);
562 bool op1_range (frange
&r
, tree type
,
563 const irange
&lhs
, const frange
&op2
,
564 relation_trio
= TRIO_VARYING
) const final override
;
565 bool op2_range (frange
&r
, tree type
,
566 const irange
&lhs
, const frange
&op1
,
567 relation_trio rel
= TRIO_VARYING
) const final override
569 return op1_range (r
, type
, lhs
, op1
, rel
.swap_op1_op2 ());
574 foperator_equal::fold_range (irange
&r
, tree type
,
575 const frange
&op1
, const frange
&op2
,
576 relation_trio rel
) const
578 if (frelop_early_resolve (r
, type
, op1
, op2
, rel
, VREL_EQ
))
581 if (op1
.known_isnan () || op2
.known_isnan ())
582 r
= range_false (type
);
583 // We can be sure the values are always equal or not if both ranges
584 // consist of a single value, and then compare them.
585 else if (op1
.singleton_p () && op2
.singleton_p ())
588 r
= range_true (type
);
590 r
= range_false (type
);
592 else if (!maybe_isnan (op1
, op2
))
594 // If ranges do not intersect, we know the range is not equal,
595 // otherwise we don't know anything for sure.
598 if (tmp
.undefined_p ())
599 r
= range_false (type
);
601 r
= range_true_and_false (type
);
604 r
= range_true_and_false (type
);
609 foperator_equal::op1_range (frange
&r
, tree type
,
612 relation_trio trio
) const
614 relation_kind rel
= trio
.op1_op2 ();
615 switch (get_bool_state (r
, lhs
, type
))
618 // The TRUE side of x == NAN is unreachable.
619 if (op2
.known_isnan ())
623 // If it's true, the result is the same as OP2.
625 // Add both zeros if there's the possibility of zero equality.
626 frange_add_zeros (r
, type
);
627 // The TRUE side of op1 == op2 implies op1 is !NAN.
633 // The FALSE side of op1 == op1 implies op1 is a NAN.
636 // On the FALSE side of x == NAN, we know nothing about x.
637 else if (op2
.known_isnan ())
638 r
.set_varying (type
);
639 // If the result is false, the only time we know anything is
640 // if OP2 is a constant.
641 else if (op2
.singleton_p ()
642 || (!op2
.maybe_isnan () && op2
.zero_p ()))
644 REAL_VALUE_TYPE tmp
= op2
.lower_bound ();
645 r
.set (type
, tmp
, tmp
, VR_ANTI_RANGE
);
648 r
.set_varying (type
);
657 class foperator_not_equal
: public range_operator_float
659 using range_operator_float::fold_range
;
660 using range_operator_float::op1_range
;
661 using range_operator_float::op1_op2_relation
;
663 bool fold_range (irange
&r
, tree type
,
664 const frange
&op1
, const frange
&op2
,
665 relation_trio rel
= TRIO_VARYING
) const final override
;
666 relation_kind
op1_op2_relation (const irange
&lhs
) const final override
668 return not_equal_op1_op2_relation (lhs
);
670 bool op1_range (frange
&r
, tree type
,
671 const irange
&lhs
, const frange
&op2
,
672 relation_trio
= TRIO_VARYING
) const final override
;
676 foperator_not_equal::fold_range (irange
&r
, tree type
,
677 const frange
&op1
, const frange
&op2
,
678 relation_trio rel
) const
680 if (frelop_early_resolve (r
, type
, op1
, op2
, rel
, VREL_NE
))
683 // x != NAN is always TRUE.
684 if (op1
.known_isnan () || op2
.known_isnan ())
685 r
= range_true (type
);
686 // We can be sure the values are always equal or not if both ranges
687 // consist of a single value, and then compare them.
688 else if (op1
.singleton_p () && op2
.singleton_p ())
691 r
= range_true (type
);
693 r
= range_false (type
);
695 else if (!maybe_isnan (op1
, op2
))
697 // If ranges do not intersect, we know the range is not equal,
698 // otherwise we don't know anything for sure.
701 if (tmp
.undefined_p ())
702 r
= range_true (type
);
704 r
= range_true_and_false (type
);
707 r
= range_true_and_false (type
);
712 foperator_not_equal::op1_range (frange
&r
, tree type
,
715 relation_trio trio
) const
717 relation_kind rel
= trio
.op1_op2 ();
718 switch (get_bool_state (r
, lhs
, type
))
721 // If the result is true, the only time we know anything is if
722 // OP2 is a constant.
723 if (op2
.singleton_p ())
725 // This is correct even if op1 is NAN, because the following
726 // range would be ~[tmp, tmp] with the NAN property set to
728 REAL_VALUE_TYPE tmp
= op2
.lower_bound ();
729 r
.set (type
, tmp
, tmp
, VR_ANTI_RANGE
);
731 // The TRUE side of op1 != op1 implies op1 is NAN.
732 else if (rel
== VREL_EQ
)
735 r
.set_varying (type
);
739 // The FALSE side of x != NAN is impossible.
740 if (op2
.known_isnan ())
744 // If it's false, the result is the same as OP2.
746 // Add both zeros if there's the possibility of zero equality.
747 frange_add_zeros (r
, type
);
748 // The FALSE side of op1 != op2 implies op1 is !NAN.
759 class foperator_lt
: public range_operator_float
761 using range_operator_float::fold_range
;
762 using range_operator_float::op1_range
;
763 using range_operator_float::op2_range
;
764 using range_operator_float::op1_op2_relation
;
766 bool fold_range (irange
&r
, tree type
,
767 const frange
&op1
, const frange
&op2
,
768 relation_trio
= TRIO_VARYING
) const final override
;
769 relation_kind
op1_op2_relation (const irange
&lhs
) const final override
771 return lt_op1_op2_relation (lhs
);
773 bool op1_range (frange
&r
, tree type
,
774 const irange
&lhs
, const frange
&op2
,
775 relation_trio
= TRIO_VARYING
) const final override
;
776 bool op2_range (frange
&r
, tree type
,
777 const irange
&lhs
, const frange
&op1
,
778 relation_trio
= TRIO_VARYING
) const final override
;
782 foperator_lt::fold_range (irange
&r
, tree type
,
783 const frange
&op1
, const frange
&op2
,
784 relation_trio rel
) const
786 if (frelop_early_resolve (r
, type
, op1
, op2
, rel
, VREL_LT
))
789 if (op1
.known_isnan () || op2
.known_isnan ())
790 r
= range_false (type
);
791 else if (!maybe_isnan (op1
, op2
))
793 if (real_less (&op1
.upper_bound (), &op2
.lower_bound ()))
794 r
= range_true (type
);
795 else if (!real_less (&op1
.lower_bound (), &op2
.upper_bound ()))
796 r
= range_false (type
);
798 r
= range_true_and_false (type
);
801 r
= range_true_and_false (type
);
806 foperator_lt::op1_range (frange
&r
,
812 switch (get_bool_state (r
, lhs
, type
))
815 // The TRUE side of x < NAN is unreachable.
816 if (op2
.known_isnan ())
818 else if (build_lt (r
, type
, op2
))
821 // x < y implies x is not +INF.
822 frange_drop_inf (r
, type
);
827 // On the FALSE side of x < NAN, we know nothing about x.
828 if (op2
.known_isnan ())
829 r
.set_varying (type
);
831 build_ge (r
, type
, op2
);
841 foperator_lt::op2_range (frange
&r
,
847 switch (get_bool_state (r
, lhs
, type
))
850 // The TRUE side of NAN < x is unreachable.
851 if (op1
.known_isnan ())
853 else if (build_gt (r
, type
, op1
))
856 // x < y implies y is not -INF.
857 frange_drop_ninf (r
, type
);
862 // On the FALSE side of NAN < x, we know nothing about x.
863 if (op1
.known_isnan ())
864 r
.set_varying (type
);
866 build_le (r
, type
, op1
);
875 class foperator_le
: public range_operator_float
877 using range_operator_float::fold_range
;
878 using range_operator_float::op1_range
;
879 using range_operator_float::op2_range
;
880 using range_operator_float::op1_op2_relation
;
882 bool fold_range (irange
&r
, tree type
,
883 const frange
&op1
, const frange
&op2
,
884 relation_trio rel
= TRIO_VARYING
) const final override
;
885 relation_kind
op1_op2_relation (const irange
&lhs
) const final override
887 return le_op1_op2_relation (lhs
);
889 bool op1_range (frange
&r
, tree type
,
890 const irange
&lhs
, const frange
&op2
,
891 relation_trio rel
= TRIO_VARYING
) const final override
;
892 bool op2_range (frange
&r
, tree type
,
893 const irange
&lhs
, const frange
&op1
,
894 relation_trio rel
= TRIO_VARYING
) const final override
;
898 foperator_le::fold_range (irange
&r
, tree type
,
899 const frange
&op1
, const frange
&op2
,
900 relation_trio rel
) const
902 if (frelop_early_resolve (r
, type
, op1
, op2
, rel
, VREL_LE
))
905 if (op1
.known_isnan () || op2
.known_isnan ())
906 r
= range_false (type
);
907 else if (!maybe_isnan (op1
, op2
))
909 if (real_compare (LE_EXPR
, &op1
.upper_bound (), &op2
.lower_bound ()))
910 r
= range_true (type
);
911 else if (!real_compare (LE_EXPR
, &op1
.lower_bound (), &op2
.upper_bound ()))
912 r
= range_false (type
);
914 r
= range_true_and_false (type
);
917 r
= range_true_and_false (type
);
922 foperator_le::op1_range (frange
&r
,
928 switch (get_bool_state (r
, lhs
, type
))
931 // The TRUE side of x <= NAN is unreachable.
932 if (op2
.known_isnan ())
934 else if (build_le (r
, type
, op2
))
939 // On the FALSE side of x <= NAN, we know nothing about x.
940 if (op2
.known_isnan ())
941 r
.set_varying (type
);
943 build_gt (r
, type
, op2
);
953 foperator_le::op2_range (frange
&r
,
959 switch (get_bool_state (r
, lhs
, type
))
962 // The TRUE side of NAN <= x is unreachable.
963 if (op1
.known_isnan ())
965 else if (build_ge (r
, type
, op1
))
970 // On the FALSE side of NAN <= x, we know nothing about x.
971 if (op1
.known_isnan ())
972 r
.set_varying (type
);
974 build_lt (r
, type
, op1
);
983 class foperator_gt
: public range_operator_float
985 using range_operator_float::fold_range
;
986 using range_operator_float::op1_range
;
987 using range_operator_float::op2_range
;
988 using range_operator_float::op1_op2_relation
;
990 bool fold_range (irange
&r
, tree type
,
991 const frange
&op1
, const frange
&op2
,
992 relation_trio
= TRIO_VARYING
) const final override
;
993 relation_kind
op1_op2_relation (const irange
&lhs
) const final override
995 return gt_op1_op2_relation (lhs
);
997 bool op1_range (frange
&r
, tree type
,
998 const irange
&lhs
, const frange
&op2
,
999 relation_trio
= TRIO_VARYING
) const final override
;
1000 bool op2_range (frange
&r
, tree type
,
1001 const irange
&lhs
, const frange
&op1
,
1002 relation_trio
= TRIO_VARYING
) const final override
;
1006 foperator_gt::fold_range (irange
&r
, tree type
,
1007 const frange
&op1
, const frange
&op2
,
1008 relation_trio rel
) const
1010 if (frelop_early_resolve (r
, type
, op1
, op2
, rel
, VREL_GT
))
1013 if (op1
.known_isnan () || op2
.known_isnan ())
1014 r
= range_false (type
);
1015 else if (!maybe_isnan (op1
, op2
))
1017 if (real_compare (GT_EXPR
, &op1
.lower_bound (), &op2
.upper_bound ()))
1018 r
= range_true (type
);
1019 else if (!real_compare (GT_EXPR
, &op1
.upper_bound (), &op2
.lower_bound ()))
1020 r
= range_false (type
);
1022 r
= range_true_and_false (type
);
1025 r
= range_true_and_false (type
);
1030 foperator_gt::op1_range (frange
&r
,
1034 relation_trio
) const
1036 switch (get_bool_state (r
, lhs
, type
))
1039 // The TRUE side of x > NAN is unreachable.
1040 if (op2
.known_isnan ())
1042 else if (build_gt (r
, type
, op2
))
1045 // x > y implies x is not -INF.
1046 frange_drop_ninf (r
, type
);
1051 // On the FALSE side of x > NAN, we know nothing about x.
1052 if (op2
.known_isnan ())
1053 r
.set_varying (type
);
1055 build_le (r
, type
, op2
);
1065 foperator_gt::op2_range (frange
&r
,
1069 relation_trio
) const
1071 switch (get_bool_state (r
, lhs
, type
))
1074 // The TRUE side of NAN > x is unreachable.
1075 if (op1
.known_isnan ())
1077 else if (build_lt (r
, type
, op1
))
1080 // x > y implies y is not +INF.
1081 frange_drop_inf (r
, type
);
1086 // On The FALSE side of NAN > x, we know nothing about x.
1087 if (op1
.known_isnan ())
1088 r
.set_varying (type
);
1090 build_ge (r
, type
, op1
);
1099 class foperator_ge
: public range_operator_float
1101 using range_operator_float::fold_range
;
1102 using range_operator_float::op1_range
;
1103 using range_operator_float::op2_range
;
1104 using range_operator_float::op1_op2_relation
;
1106 bool fold_range (irange
&r
, tree type
,
1107 const frange
&op1
, const frange
&op2
,
1108 relation_trio
= TRIO_VARYING
) const final override
;
1109 relation_kind
op1_op2_relation (const irange
&lhs
) const final override
1111 return ge_op1_op2_relation (lhs
);
1113 bool op1_range (frange
&r
, tree type
,
1114 const irange
&lhs
, const frange
&op2
,
1115 relation_trio
= TRIO_VARYING
) const final override
;
1116 bool op2_range (frange
&r
, tree type
,
1117 const irange
&lhs
, const frange
&op1
,
1118 relation_trio
= TRIO_VARYING
) const final override
;
1122 foperator_ge::fold_range (irange
&r
, tree type
,
1123 const frange
&op1
, const frange
&op2
,
1124 relation_trio rel
) const
1126 if (frelop_early_resolve (r
, type
, op1
, op2
, rel
, VREL_GE
))
1129 if (op1
.known_isnan () || op2
.known_isnan ())
1130 r
= range_false (type
);
1131 else if (!maybe_isnan (op1
, op2
))
1133 if (real_compare (GE_EXPR
, &op1
.lower_bound (), &op2
.upper_bound ()))
1134 r
= range_true (type
);
1135 else if (!real_compare (GE_EXPR
, &op1
.upper_bound (), &op2
.lower_bound ()))
1136 r
= range_false (type
);
1138 r
= range_true_and_false (type
);
1141 r
= range_true_and_false (type
);
1146 foperator_ge::op1_range (frange
&r
,
1150 relation_trio
) const
1152 switch (get_bool_state (r
, lhs
, type
))
1155 // The TRUE side of x >= NAN is unreachable.
1156 if (op2
.known_isnan ())
1158 else if (build_ge (r
, type
, op2
))
1163 // On the FALSE side of x >= NAN, we know nothing about x.
1164 if (op2
.known_isnan ())
1165 r
.set_varying (type
);
1167 build_lt (r
, type
, op2
);
1177 foperator_ge::op2_range (frange
&r
, tree type
,
1180 relation_trio
) const
1182 switch (get_bool_state (r
, lhs
, type
))
1185 // The TRUE side of NAN >= x is unreachable.
1186 if (op1
.known_isnan ())
1188 else if (build_le (r
, type
, op1
))
1193 // On the FALSE side of NAN >= x, we know nothing about x.
1194 if (op1
.known_isnan ())
1195 r
.set_varying (type
);
1197 build_gt (r
, type
, op1
);
1206 // UNORDERED_EXPR comparison.
1208 class foperator_unordered
: public range_operator_float
1210 using range_operator_float::fold_range
;
1211 using range_operator_float::op1_range
;
1212 using range_operator_float::op2_range
;
1214 bool fold_range (irange
&r
, tree type
,
1215 const frange
&op1
, const frange
&op2
,
1216 relation_trio
= TRIO_VARYING
) const final override
;
1217 bool op1_range (frange
&r
, tree type
,
1218 const irange
&lhs
, const frange
&op2
,
1219 relation_trio
= TRIO_VARYING
) const final override
;
1220 bool op2_range (frange
&r
, tree type
,
1221 const irange
&lhs
, const frange
&op1
,
1222 relation_trio rel
= TRIO_VARYING
) const final override
1224 return op1_range (r
, type
, lhs
, op1
, rel
.swap_op1_op2 ());
1229 foperator_unordered::fold_range (irange
&r
, tree type
,
1230 const frange
&op1
, const frange
&op2
,
1231 relation_trio
) const
1233 // UNORDERED is TRUE if either operand is a NAN.
1234 if (op1
.known_isnan () || op2
.known_isnan ())
1235 r
= range_true (type
);
1236 // UNORDERED is FALSE if neither operand is a NAN.
1237 else if (!op1
.maybe_isnan () && !op2
.maybe_isnan ())
1238 r
= range_false (type
);
1240 r
= range_true_and_false (type
);
1245 foperator_unordered::op1_range (frange
&r
, tree type
,
1248 relation_trio trio
) const
1250 relation_kind rel
= trio
.op1_op2 ();
1251 switch (get_bool_state (r
, lhs
, type
))
1254 // Since at least one operand must be NAN, if one of them is
1255 // not, the other must be.
1256 if (rel
== VREL_EQ
|| !op2
.maybe_isnan ())
1259 r
.set_varying (type
);
1263 // A false UNORDERED means both operands are !NAN, so it's
1264 // impossible for op2 to be a NAN.
1265 if (op2
.known_isnan ())
1269 r
.set_varying (type
);
1280 // ORDERED_EXPR comparison.
1282 class foperator_ordered
: public range_operator_float
1284 using range_operator_float::fold_range
;
1285 using range_operator_float::op1_range
;
1286 using range_operator_float::op2_range
;
1288 bool fold_range (irange
&r
, tree type
,
1289 const frange
&op1
, const frange
&op2
,
1290 relation_trio
= TRIO_VARYING
) const final override
;
1291 bool op1_range (frange
&r
, tree type
,
1292 const irange
&lhs
, const frange
&op2
,
1293 relation_trio
= TRIO_VARYING
) const final override
;
1294 bool op2_range (frange
&r
, tree type
,
1295 const irange
&lhs
, const frange
&op1
,
1296 relation_trio rel
= TRIO_VARYING
) const final override
1298 return op1_range (r
, type
, lhs
, op1
, rel
.swap_op1_op2 ());
1303 foperator_ordered::fold_range (irange
&r
, tree type
,
1304 const frange
&op1
, const frange
&op2
,
1305 relation_trio
) const
1307 if (op1
.known_isnan () || op2
.known_isnan ())
1308 r
= range_false (type
);
1309 else if (!op1
.maybe_isnan () && !op2
.maybe_isnan ())
1310 r
= range_true (type
);
1312 r
= range_true_and_false (type
);
1317 foperator_ordered::op1_range (frange
&r
, tree type
,
1320 relation_trio trio
) const
1322 relation_kind rel
= trio
.op1_op2 ();
1323 switch (get_bool_state (r
, lhs
, type
))
1326 // The TRUE side of ORDERED means both operands are !NAN, so
1327 // it's impossible for op2 to be a NAN.
1328 if (op2
.known_isnan ())
1332 r
.set_varying (type
);
1338 // The FALSE side of op1 ORDERED op1 implies op1 is NAN.
1342 r
.set_varying (type
);
1351 class foperator_negate
: public range_operator_float
1353 using range_operator_float::fold_range
;
1354 using range_operator_float::op1_range
;
1356 bool fold_range (frange
&r
, tree type
,
1357 const frange
&op1
, const frange
&op2
,
1358 relation_trio
= TRIO_VARYING
) const final override
1360 if (empty_range_varying (r
, type
, op1
, op2
))
1362 if (op1
.known_isnan ())
1365 if (op1
.nan_signbit_p (sign
))
1366 r
.set_nan (type
, !sign
);
1372 REAL_VALUE_TYPE lh_lb
= op1
.lower_bound ();
1373 REAL_VALUE_TYPE lh_ub
= op1
.upper_bound ();
1374 lh_lb
= real_value_negate (&lh_lb
);
1375 lh_ub
= real_value_negate (&lh_ub
);
1376 r
.set (type
, lh_ub
, lh_lb
);
1377 if (op1
.maybe_isnan ())
1380 if (op1
.nan_signbit_p (sign
))
1381 r
.update_nan (!sign
);
1389 bool op1_range (frange
&r
, tree type
,
1390 const frange
&lhs
, const frange
&op2
,
1391 relation_trio rel
= TRIO_VARYING
) const final override
1393 return fold_range (r
, type
, lhs
, op2
, rel
);
1397 class foperator_abs
: public range_operator_float
1399 using range_operator_float::fold_range
;
1400 using range_operator_float::op1_range
;
1402 bool fold_range (frange
&r
, tree type
,
1403 const frange
&op1
, const frange
&,
1404 relation_trio
= TRIO_VARYING
) const final override
;
1405 bool op1_range (frange
&r
, tree type
,
1406 const frange
&lhs
, const frange
&op2
,
1407 relation_trio rel
= TRIO_VARYING
) const final override
;
1411 foperator_abs::fold_range (frange
&r
, tree type
,
1412 const frange
&op1
, const frange
&op2
,
1413 relation_trio
) const
1415 if (empty_range_varying (r
, type
, op1
, op2
))
1417 if (op1
.known_isnan ())
1419 r
.set_nan (type
, /*sign=*/false);
1423 const REAL_VALUE_TYPE lh_lb
= op1
.lower_bound ();
1424 const REAL_VALUE_TYPE lh_ub
= op1
.upper_bound ();
1425 // Handle the easy case where everything is positive.
1426 if (real_compare (GE_EXPR
, &lh_lb
, &dconst0
)
1427 && !real_iszero (&lh_lb
, /*sign=*/true)
1428 && !op1
.maybe_isnan (/*sign=*/true))
1434 REAL_VALUE_TYPE min
= real_value_abs (&lh_lb
);
1435 REAL_VALUE_TYPE max
= real_value_abs (&lh_ub
);
1436 // If the range contains zero then we know that the minimum value in the
1437 // range will be zero.
1438 if (real_compare (LE_EXPR
, &lh_lb
, &dconst0
)
1439 && real_compare (GE_EXPR
, &lh_ub
, &dconst0
))
1441 if (real_compare (GT_EXPR
, &min
, &max
))
1447 // If the range was reversed, swap MIN and MAX.
1448 if (real_compare (GT_EXPR
, &min
, &max
))
1449 std::swap (min
, max
);
1452 r
.set (type
, min
, max
);
1453 if (op1
.maybe_isnan ())
1454 r
.update_nan (/*sign=*/false);
1461 foperator_abs::op1_range (frange
&r
, tree type
,
1462 const frange
&lhs
, const frange
&op2
,
1463 relation_trio
) const
1465 if (empty_range_varying (r
, type
, lhs
, op2
))
1467 if (lhs
.known_isnan ())
1473 // Start with the positives because negatives are an impossible result.
1474 frange
positives (type
, dconst0
, frange_val_max (type
));
1475 positives
.update_nan (/*sign=*/false);
1476 positives
.intersect (lhs
);
1478 // Add -NAN if relevant.
1479 if (r
.maybe_isnan ())
1482 neg_nan
.set_nan (type
, true);
1485 if (r
.known_isnan () || r
.undefined_p ())
1487 // Then add the negative of each pair:
1488 // ABS(op1) = [5,20] would yield op1 => [-20,-5][5,20].
1489 frange
negatives (type
, real_value_negate (&positives
.upper_bound ()),
1490 real_value_negate (&positives
.lower_bound ()));
1491 negatives
.clear_nan ();
1492 r
.union_ (negatives
);
1496 class foperator_unordered_lt
: public range_operator_float
1498 using range_operator_float::fold_range
;
1499 using range_operator_float::op1_range
;
1500 using range_operator_float::op2_range
;
1502 bool fold_range (irange
&r
, tree type
,
1503 const frange
&op1
, const frange
&op2
,
1504 relation_trio rel
= TRIO_VARYING
) const final override
1506 if (op1
.known_isnan () || op2
.known_isnan ())
1508 r
= range_true (type
);
1511 if (!fop_lt
.fold_range (r
, type
, op1
, op2
, rel
))
1513 // The result is the same as the ordered version when the
1514 // comparison is true or when the operands cannot be NANs.
1515 if (!maybe_isnan (op1
, op2
) || r
== range_true (type
))
1519 r
= range_true_and_false (type
);
1523 bool op1_range (frange
&r
, tree type
,
1526 relation_trio trio
) const final override
;
1527 bool op2_range (frange
&r
, tree type
,
1530 relation_trio trio
) const final override
;
1534 foperator_unordered_lt::op1_range (frange
&r
, tree type
,
1537 relation_trio
) const
1539 switch (get_bool_state (r
, lhs
, type
))
1542 if (op2
.known_isnan ())
1543 r
.set_varying (type
);
1545 build_lt (r
, type
, op2
);
1549 // A false UNORDERED_LT means both operands are !NAN, so it's
1550 // impossible for op2 to be a NAN.
1551 if (op2
.known_isnan ())
1553 else if (build_ge (r
, type
, op2
))
1564 foperator_unordered_lt::op2_range (frange
&r
, tree type
,
1567 relation_trio
) const
1569 switch (get_bool_state (r
, lhs
, type
))
1572 if (op1
.known_isnan ())
1573 r
.set_varying (type
);
1575 build_gt (r
, type
, op1
);
1579 // A false UNORDERED_LT means both operands are !NAN, so it's
1580 // impossible for op1 to be a NAN.
1581 if (op1
.known_isnan ())
1583 else if (build_le (r
, type
, op1
))
1593 class foperator_unordered_le
: public range_operator_float
1595 using range_operator_float::fold_range
;
1596 using range_operator_float::op1_range
;
1597 using range_operator_float::op2_range
;
1599 bool fold_range (irange
&r
, tree type
,
1600 const frange
&op1
, const frange
&op2
,
1601 relation_trio rel
= TRIO_VARYING
) const final override
1603 if (op1
.known_isnan () || op2
.known_isnan ())
1605 r
= range_true (type
);
1608 if (!fop_le
.fold_range (r
, type
, op1
, op2
, rel
))
1610 // The result is the same as the ordered version when the
1611 // comparison is true or when the operands cannot be NANs.
1612 if (!maybe_isnan (op1
, op2
) || r
== range_true (type
))
1616 r
= range_true_and_false (type
);
1620 bool op1_range (frange
&r
, tree type
,
1621 const irange
&lhs
, const frange
&op2
,
1622 relation_trio
= TRIO_VARYING
) const final override
;
1623 bool op2_range (frange
&r
, tree type
,
1624 const irange
&lhs
, const frange
&op1
,
1625 relation_trio
= TRIO_VARYING
) const final override
;
1629 foperator_unordered_le::op1_range (frange
&r
, tree type
,
1630 const irange
&lhs
, const frange
&op2
,
1631 relation_trio
) const
1633 switch (get_bool_state (r
, lhs
, type
))
1636 if (op2
.known_isnan ())
1637 r
.set_varying (type
);
1639 build_le (r
, type
, op2
);
1643 // A false UNORDERED_LE means both operands are !NAN, so it's
1644 // impossible for op2 to be a NAN.
1645 if (op2
.known_isnan ())
1647 else if (build_gt (r
, type
, op2
))
1658 foperator_unordered_le::op2_range (frange
&r
,
1662 relation_trio
) const
1664 switch (get_bool_state (r
, lhs
, type
))
1667 if (op1
.known_isnan ())
1668 r
.set_varying (type
);
1670 build_ge (r
, type
, op1
);
1674 // A false UNORDERED_LE means both operands are !NAN, so it's
1675 // impossible for op1 to be a NAN.
1676 if (op1
.known_isnan ())
1678 else if (build_lt (r
, type
, op1
))
1688 class foperator_unordered_gt
: public range_operator_float
1690 using range_operator_float::fold_range
;
1691 using range_operator_float::op1_range
;
1692 using range_operator_float::op2_range
;
1694 bool fold_range (irange
&r
, tree type
,
1695 const frange
&op1
, const frange
&op2
,
1696 relation_trio rel
= TRIO_VARYING
) const final override
1698 if (op1
.known_isnan () || op2
.known_isnan ())
1700 r
= range_true (type
);
1703 if (!fop_gt
.fold_range (r
, type
, op1
, op2
, rel
))
1705 // The result is the same as the ordered version when the
1706 // comparison is true or when the operands cannot be NANs.
1707 if (!maybe_isnan (op1
, op2
) || r
== range_true (type
))
1711 r
= range_true_and_false (type
);
1715 bool op1_range (frange
&r
, tree type
,
1716 const irange
&lhs
, const frange
&op2
,
1717 relation_trio
= TRIO_VARYING
) const final override
;
1718 bool op2_range (frange
&r
, tree type
,
1719 const irange
&lhs
, const frange
&op1
,
1720 relation_trio
= TRIO_VARYING
) const final override
;
1724 foperator_unordered_gt::op1_range (frange
&r
,
1728 relation_trio
) const
1730 switch (get_bool_state (r
, lhs
, type
))
1733 if (op2
.known_isnan ())
1734 r
.set_varying (type
);
1736 build_gt (r
, type
, op2
);
1740 // A false UNORDERED_GT means both operands are !NAN, so it's
1741 // impossible for op2 to be a NAN.
1742 if (op2
.known_isnan ())
1744 else if (build_le (r
, type
, op2
))
1755 foperator_unordered_gt::op2_range (frange
&r
,
1759 relation_trio
) const
1761 switch (get_bool_state (r
, lhs
, type
))
1764 if (op1
.known_isnan ())
1765 r
.set_varying (type
);
1767 build_lt (r
, type
, op1
);
1771 // A false UNORDERED_GT means both operands are !NAN, so it's
1772 // impossible for op1 to be a NAN.
1773 if (op1
.known_isnan ())
1775 else if (build_ge (r
, type
, op1
))
1785 class foperator_unordered_ge
: public range_operator_float
1787 using range_operator_float::fold_range
;
1788 using range_operator_float::op1_range
;
1789 using range_operator_float::op2_range
;
1791 bool fold_range (irange
&r
, tree type
,
1792 const frange
&op1
, const frange
&op2
,
1793 relation_trio rel
= TRIO_VARYING
) const final override
1795 if (op1
.known_isnan () || op2
.known_isnan ())
1797 r
= range_true (type
);
1800 if (!fop_ge
.fold_range (r
, type
, op1
, op2
, rel
))
1802 // The result is the same as the ordered version when the
1803 // comparison is true or when the operands cannot be NANs.
1804 if (!maybe_isnan (op1
, op2
) || r
== range_true (type
))
1808 r
= range_true_and_false (type
);
1812 bool op1_range (frange
&r
, tree type
,
1813 const irange
&lhs
, const frange
&op2
,
1814 relation_trio
= TRIO_VARYING
) const final override
;
1815 bool op2_range (frange
&r
, tree type
,
1816 const irange
&lhs
, const frange
&op1
,
1817 relation_trio
= TRIO_VARYING
) const final override
;
1821 foperator_unordered_ge::op1_range (frange
&r
,
1825 relation_trio
) const
1827 switch (get_bool_state (r
, lhs
, type
))
1830 if (op2
.known_isnan ())
1831 r
.set_varying (type
);
1833 build_ge (r
, type
, op2
);
1837 // A false UNORDERED_GE means both operands are !NAN, so it's
1838 // impossible for op2 to be a NAN.
1839 if (op2
.known_isnan ())
1841 else if (build_lt (r
, type
, op2
))
1852 foperator_unordered_ge::op2_range (frange
&r
, tree type
,
1855 relation_trio
) const
1857 switch (get_bool_state (r
, lhs
, type
))
1860 if (op1
.known_isnan ())
1861 r
.set_varying (type
);
1863 build_le (r
, type
, op1
);
1867 // A false UNORDERED_GE means both operands are !NAN, so it's
1868 // impossible for op1 to be a NAN.
1869 if (op1
.known_isnan ())
1871 else if (build_gt (r
, type
, op1
))
1881 class foperator_unordered_equal
: public range_operator_float
1883 using range_operator_float::fold_range
;
1884 using range_operator_float::op1_range
;
1885 using range_operator_float::op2_range
;
1887 bool fold_range (irange
&r
, tree type
,
1888 const frange
&op1
, const frange
&op2
,
1889 relation_trio rel
= TRIO_VARYING
) const final override
1891 if (op1
.known_isnan () || op2
.known_isnan ())
1893 r
= range_true (type
);
1896 if (!fop_equal
.fold_range (r
, type
, op1
, op2
, rel
))
1898 // The result is the same as the ordered version when the
1899 // comparison is true or when the operands cannot be NANs.
1900 if (!maybe_isnan (op1
, op2
) || r
== range_true (type
))
1904 r
= range_true_and_false (type
);
1908 bool op1_range (frange
&r
, tree type
,
1909 const irange
&lhs
, const frange
&op2
,
1910 relation_trio
= TRIO_VARYING
) const final override
;
1911 bool op2_range (frange
&r
, tree type
,
1912 const irange
&lhs
, const frange
&op1
,
1913 relation_trio rel
= TRIO_VARYING
) const final override
1915 return op1_range (r
, type
, lhs
, op1
, rel
.swap_op1_op2 ());
1917 } fop_unordered_equal
;
1920 foperator_unordered_equal::op1_range (frange
&r
, tree type
,
1923 relation_trio
) const
1925 switch (get_bool_state (r
, lhs
, type
))
1928 // If it's true, the result is the same as OP2 plus a NAN.
1930 // Add both zeros if there's the possibility of zero equality.
1931 frange_add_zeros (r
, type
);
1932 // Add the posibility of a NAN.
1937 // A false UNORDERED_EQ means both operands are !NAN, so it's
1938 // impossible for op2 to be a NAN.
1939 if (op2
.known_isnan ())
1943 // The false side indictates !NAN and not equal. We can at least
1945 r
.set_varying (type
);
1956 // Final tweaks for float binary op op1_range/op2_range.
1957 // Return TRUE if the operation is performed and a valid range is available.
1960 float_binary_op_range_finish (bool ret
, frange
&r
, tree type
,
1961 const frange
&lhs
, bool div_op2
= false)
1966 // If we get a known NAN from reverse op, it means either that
1967 // the other operand was known NAN (in that case we know nothing),
1968 // or the reverse operation introduced a known NAN.
1969 // Say for lhs = op1 * op2 if lhs is [-0, +0] and op2 is too,
1970 // 0 / 0 is known NAN. Just punt in that case.
1971 // If NANs aren't honored, we get for 0 / 0 UNDEFINED, so punt as well.
1972 // Or if lhs is a known NAN, we also don't know anything.
1973 if (r
.known_isnan () || lhs
.known_isnan () || r
.undefined_p ())
1975 r
.set_varying (type
);
1979 // If lhs isn't NAN, then neither operand could be NAN,
1980 // even if the reverse operation does introduce a maybe_nan.
1981 if (!lhs
.maybe_isnan ())
1985 ? !(real_compare (LE_EXPR
, &lhs
.lower_bound (), &dconst0
)
1986 && real_compare (GE_EXPR
, &lhs
.upper_bound (), &dconst0
))
1987 : !(real_isinf (&lhs
.lower_bound ())
1988 || real_isinf (&lhs
.upper_bound ())))
1989 // For reverse + or - or * or op1 of /, if result is finite, then
1990 // r must be finite too, as X + INF or X - INF or X * INF or
1991 // INF / X is always +-INF or NAN. For op2 of /, if result is
1992 // non-zero and not NAN, r must be finite, as X / INF is always
1994 frange_drop_infs (r
, type
);
1996 // If lhs is a maybe or known NAN, the operand could be
2003 // True if [lb, ub] is [+-0, +-0].
2005 zero_p (const REAL_VALUE_TYPE
&lb
, const REAL_VALUE_TYPE
&ub
)
2007 return real_iszero (&lb
) && real_iszero (&ub
);
2010 // True if +0 or -0 is in [lb, ub] range.
2012 contains_zero_p (const REAL_VALUE_TYPE
&lb
, const REAL_VALUE_TYPE
&ub
)
2014 return (real_compare (LE_EXPR
, &lb
, &dconst0
)
2015 && real_compare (GE_EXPR
, &ub
, &dconst0
));
2018 // True if [lb, ub] is [-INF, -INF] or [+INF, +INF].
2020 singleton_inf_p (const REAL_VALUE_TYPE
&lb
, const REAL_VALUE_TYPE
&ub
)
2022 return real_isinf (&lb
) && real_isinf (&ub
, real_isneg (&lb
));
2025 // Return -1 if binary op result must have sign bit set,
2026 // 1 if binary op result must have sign bit clear,
2028 // Sign bit of binary op result is exclusive or of the
2029 // operand's sign bits.
2031 signbit_known_p (const REAL_VALUE_TYPE
&lh_lb
, const REAL_VALUE_TYPE
&lh_ub
,
2032 const REAL_VALUE_TYPE
&rh_lb
, const REAL_VALUE_TYPE
&rh_ub
)
2034 if (real_isneg (&lh_lb
) == real_isneg (&lh_ub
)
2035 && real_isneg (&rh_lb
) == real_isneg (&rh_ub
))
2037 if (real_isneg (&lh_lb
) == real_isneg (&rh_ub
))
2045 // Set [lb, ub] to [-0, -0], [-0, +0] or [+0, +0] depending on
2048 zero_range (REAL_VALUE_TYPE
&lb
, REAL_VALUE_TYPE
&ub
, int signbit_known
)
2051 if (signbit_known
<= 0)
2052 lb
= real_value_negate (&dconst0
);
2053 if (signbit_known
< 0)
2057 // Set [lb, ub] to [-INF, -INF], [-INF, +INF] or [+INF, +INF] depending on
2060 inf_range (REAL_VALUE_TYPE
&lb
, REAL_VALUE_TYPE
&ub
, int signbit_known
)
2062 if (signbit_known
> 0)
2063 ub
= lb
= dconstinf
;
2064 else if (signbit_known
< 0)
2065 ub
= lb
= dconstninf
;
2073 // Set [lb, ub] to [-INF, -0], [-INF, +INF] or [+0, +INF] depending on
2076 zero_to_inf_range (REAL_VALUE_TYPE
&lb
, REAL_VALUE_TYPE
&ub
, int signbit_known
)
2078 if (signbit_known
> 0)
2083 else if (signbit_known
< 0)
2086 ub
= real_value_negate (&dconst0
);
2095 class foperator_plus
: public range_operator_float
2097 using range_operator_float::op1_range
;
2098 using range_operator_float::op2_range
;
2100 virtual bool op1_range (frange
&r
, tree type
,
2103 relation_trio
= TRIO_VARYING
) const final override
2105 if (lhs
.undefined_p ())
2107 range_op_handler
minus (MINUS_EXPR
, type
);
2110 return float_binary_op_range_finish (minus
.fold_range (r
, type
, lhs
, op2
),
2113 virtual bool op2_range (frange
&r
, tree type
,
2116 relation_trio
= TRIO_VARYING
) const final override
2118 return op1_range (r
, type
, lhs
, op1
);
2121 void rv_fold (REAL_VALUE_TYPE
&lb
, REAL_VALUE_TYPE
&ub
, bool &maybe_nan
,
2123 const REAL_VALUE_TYPE
&lh_lb
,
2124 const REAL_VALUE_TYPE
&lh_ub
,
2125 const REAL_VALUE_TYPE
&rh_lb
,
2126 const REAL_VALUE_TYPE
&rh_ub
,
2127 relation_kind
) const final override
2129 frange_arithmetic (PLUS_EXPR
, type
, lb
, lh_lb
, rh_lb
, dconstninf
);
2130 frange_arithmetic (PLUS_EXPR
, type
, ub
, lh_ub
, rh_ub
, dconstinf
);
2132 // [-INF] + [+INF] = NAN
2133 if (real_isinf (&lh_lb
, true) && real_isinf (&rh_ub
, false))
2135 // [+INF] + [-INF] = NAN
2136 else if (real_isinf (&lh_ub
, false) && real_isinf (&rh_lb
, true))
2144 class foperator_minus
: public range_operator_float
2146 using range_operator_float::op1_range
;
2147 using range_operator_float::op2_range
;
2149 virtual bool op1_range (frange
&r
, tree type
,
2152 relation_trio
= TRIO_VARYING
) const final override
2154 if (lhs
.undefined_p ())
2156 return float_binary_op_range_finish (fop_plus
.fold_range (r
, type
, lhs
,
2160 virtual bool op2_range (frange
&r
, tree type
,
2163 relation_trio
= TRIO_VARYING
) const final override
2165 if (lhs
.undefined_p ())
2167 return float_binary_op_range_finish (fold_range (r
, type
, op1
, lhs
),
2171 void rv_fold (REAL_VALUE_TYPE
&lb
, REAL_VALUE_TYPE
&ub
, bool &maybe_nan
,
2173 const REAL_VALUE_TYPE
&lh_lb
,
2174 const REAL_VALUE_TYPE
&lh_ub
,
2175 const REAL_VALUE_TYPE
&rh_lb
,
2176 const REAL_VALUE_TYPE
&rh_ub
,
2177 relation_kind
) const final override
2179 frange_arithmetic (MINUS_EXPR
, type
, lb
, lh_lb
, rh_ub
, dconstninf
);
2180 frange_arithmetic (MINUS_EXPR
, type
, ub
, lh_ub
, rh_lb
, dconstinf
);
2182 // [+INF] - [+INF] = NAN
2183 if (real_isinf (&lh_ub
, false) && real_isinf (&rh_ub
, false))
2185 // [-INF] - [-INF] = NAN
2186 else if (real_isinf (&lh_lb
, true) && real_isinf (&rh_lb
, true))
2194 class foperator_mult_div_base
: public range_operator_float
2197 // Given CP[0] to CP[3] floating point values rounded to -INF,
2198 // set LB to the smallest of them (treating -0 as smaller to +0).
2199 // Given CP[4] to CP[7] floating point values rounded to +INF,
2200 // set UB to the largest of them (treating -0 as smaller to +0).
2201 static void find_range (REAL_VALUE_TYPE
&lb
, REAL_VALUE_TYPE
&ub
,
2202 const REAL_VALUE_TYPE (&cp
)[8])
2206 for (int i
= 1; i
< 4; ++i
)
2208 if (real_less (&cp
[i
], &lb
)
2209 || (real_iszero (&lb
) && real_isnegzero (&cp
[i
])))
2211 if (real_less (&ub
, &cp
[i
+ 4])
2212 || (real_isnegzero (&ub
) && real_iszero (&cp
[i
+ 4])))
2219 class foperator_mult
: public foperator_mult_div_base
2221 using range_operator_float::op1_range
;
2222 using range_operator_float::op2_range
;
2224 virtual bool op1_range (frange
&r
, tree type
,
2227 relation_trio
= TRIO_VARYING
) const final override
2229 if (lhs
.undefined_p ())
2231 range_op_handler
rdiv (RDIV_EXPR
, type
);
2234 bool ret
= rdiv
.fold_range (r
, type
, lhs
, op2
);
2237 if (lhs
.known_isnan () || op2
.known_isnan () || op2
.undefined_p ())
2238 return float_binary_op_range_finish (ret
, r
, type
, lhs
);
2239 const REAL_VALUE_TYPE
&lhs_lb
= lhs
.lower_bound ();
2240 const REAL_VALUE_TYPE
&lhs_ub
= lhs
.upper_bound ();
2241 const REAL_VALUE_TYPE
&op2_lb
= op2
.lower_bound ();
2242 const REAL_VALUE_TYPE
&op2_ub
= op2
.upper_bound ();
2243 if ((contains_zero_p (lhs_lb
, lhs_ub
) && contains_zero_p (op2_lb
, op2_ub
))
2244 || ((real_isinf (&lhs_lb
) || real_isinf (&lhs_ub
))
2245 && (real_isinf (&op2_lb
) || real_isinf (&op2_ub
))))
2247 // If both lhs and op2 could be zeros or both could be infinities,
2248 // we don't know anything about op1 except maybe for the sign
2249 // and perhaps if it can be NAN or not.
2250 REAL_VALUE_TYPE lb
, ub
;
2251 int signbit_known
= signbit_known_p (lhs_lb
, lhs_ub
, op2_lb
, op2_ub
);
2252 zero_to_inf_range (lb
, ub
, signbit_known
);
2253 r
.set (type
, lb
, ub
);
2255 // Otherwise, if op2 is a singleton INF and lhs doesn't include INF,
2256 // or if lhs must be zero and op2 doesn't include zero, it would be
2257 // UNDEFINED, while rdiv.fold_range computes a zero or singleton INF
2258 // range. Those are supersets of UNDEFINED, so let's keep that way.
2259 return float_binary_op_range_finish (ret
, r
, type
, lhs
);
2261 virtual bool op2_range (frange
&r
, tree type
,
2264 relation_trio
= TRIO_VARYING
) const final override
2266 return op1_range (r
, type
, lhs
, op1
);
2269 void rv_fold (REAL_VALUE_TYPE
&lb
, REAL_VALUE_TYPE
&ub
, bool &maybe_nan
,
2271 const REAL_VALUE_TYPE
&lh_lb
,
2272 const REAL_VALUE_TYPE
&lh_ub
,
2273 const REAL_VALUE_TYPE
&rh_lb
,
2274 const REAL_VALUE_TYPE
&rh_ub
,
2275 relation_kind kind
) const final override
2279 && real_equal (&lh_lb
, &rh_lb
)
2280 && real_equal (&lh_ub
, &rh_ub
)
2281 && real_isneg (&lh_lb
) == real_isneg (&rh_lb
)
2282 && real_isneg (&lh_ub
) == real_isneg (&rh_ub
));
2285 // x * x never produces a new NAN and we only multiply the same
2286 // values, so the 0 * INF problematic cases never appear there.
2289 // [+-0, +-0] * [+INF,+INF] (or [-INF,-INF] or swapped is a known NAN.
2290 if ((zero_p (lh_lb
, lh_ub
) && singleton_inf_p (rh_lb
, rh_ub
))
2291 || (zero_p (rh_lb
, rh_ub
) && singleton_inf_p (lh_lb
, lh_ub
)))
2293 real_nan (&lb
, "", 0, TYPE_MODE (type
));
2299 // Otherwise, if one range includes zero and the other ends with +-INF,
2300 // it is a maybe NAN.
2301 if ((contains_zero_p (lh_lb
, lh_ub
)
2302 && (real_isinf (&rh_lb
) || real_isinf (&rh_ub
)))
2303 || (contains_zero_p (rh_lb
, rh_ub
)
2304 && (real_isinf (&lh_lb
) || real_isinf (&lh_ub
))))
2308 int signbit_known
= signbit_known_p (lh_lb
, lh_ub
, rh_lb
, rh_ub
);
2310 // If one of the ranges that includes INF is singleton
2311 // and the other range includes zero, the resulting
2312 // range is INF and NAN, because the 0 * INF boundary
2313 // case will be NAN, but already nextafter (0, 1) * INF
2315 if (singleton_inf_p (lh_lb
, lh_ub
)
2316 || singleton_inf_p (rh_lb
, rh_ub
))
2317 return inf_range (lb
, ub
, signbit_known
);
2319 // If one of the multiplicands must be zero, the resulting
2320 // range is +-0 and NAN.
2321 if (zero_p (lh_lb
, lh_ub
) || zero_p (rh_lb
, rh_ub
))
2322 return zero_range (lb
, ub
, signbit_known
);
2324 // Otherwise one of the multiplicands could be
2325 // [0.0, nextafter (0.0, 1.0)] and the [DBL_MAX, INF]
2326 // or similarly with different signs. 0.0 * DBL_MAX
2327 // is still 0.0, nextafter (0.0, 1.0) * INF is still INF,
2328 // so if the signs are always the same or always different,
2329 // result is [+0.0, +INF] or [-INF, -0.0], otherwise VARYING.
2330 return zero_to_inf_range (lb
, ub
, signbit_known
);
2334 REAL_VALUE_TYPE cp
[8];
2335 // Do a cross-product. At this point none of the multiplications
2336 // should produce a NAN.
2337 frange_arithmetic (MULT_EXPR
, type
, cp
[0], lh_lb
, rh_lb
, dconstninf
);
2338 frange_arithmetic (MULT_EXPR
, type
, cp
[4], lh_lb
, rh_lb
, dconstinf
);
2341 // For x * x we can just do max (lh_lb * lh_lb, lh_ub * lh_ub)
2342 // as maximum and -0.0 as minimum if 0.0 is in the range,
2343 // otherwise min (lh_lb * lh_lb, lh_ub * lh_ub).
2344 // -0.0 rather than 0.0 because VREL_EQ doesn't prove that
2345 // x and y are bitwise equal, just that they compare equal.
2346 if (contains_zero_p (lh_lb
, lh_ub
))
2348 if (real_isneg (&lh_lb
) == real_isneg (&lh_ub
))
2351 cp
[1] = real_value_negate (&dconst0
);
2361 frange_arithmetic (MULT_EXPR
, type
, cp
[1], lh_lb
, rh_ub
, dconstninf
);
2362 frange_arithmetic (MULT_EXPR
, type
, cp
[5], lh_lb
, rh_ub
, dconstinf
);
2363 frange_arithmetic (MULT_EXPR
, type
, cp
[2], lh_ub
, rh_lb
, dconstninf
);
2364 frange_arithmetic (MULT_EXPR
, type
, cp
[6], lh_ub
, rh_lb
, dconstinf
);
2366 frange_arithmetic (MULT_EXPR
, type
, cp
[3], lh_ub
, rh_ub
, dconstninf
);
2367 frange_arithmetic (MULT_EXPR
, type
, cp
[7], lh_ub
, rh_ub
, dconstinf
);
2369 find_range (lb
, ub
, cp
);
2374 class foperator_div
: public foperator_mult_div_base
2376 using range_operator_float::op1_range
;
2377 using range_operator_float::op2_range
;
2379 virtual bool op1_range (frange
&r
, tree type
,
2382 relation_trio
= TRIO_VARYING
) const final override
2384 if (lhs
.undefined_p ())
2386 bool ret
= fop_mult
.fold_range (r
, type
, lhs
, op2
);
2389 if (lhs
.known_isnan () || op2
.known_isnan () || op2
.undefined_p ())
2390 return float_binary_op_range_finish (ret
, r
, type
, lhs
);
2391 const REAL_VALUE_TYPE
&lhs_lb
= lhs
.lower_bound ();
2392 const REAL_VALUE_TYPE
&lhs_ub
= lhs
.upper_bound ();
2393 const REAL_VALUE_TYPE
&op2_lb
= op2
.lower_bound ();
2394 const REAL_VALUE_TYPE
&op2_ub
= op2
.upper_bound ();
2395 if ((contains_zero_p (lhs_lb
, lhs_ub
)
2396 && (real_isinf (&op2_lb
) || real_isinf (&op2_ub
)))
2397 || ((contains_zero_p (op2_lb
, op2_ub
))
2398 && (real_isinf (&lhs_lb
) || real_isinf (&lhs_ub
))))
2400 // If both lhs could be zero and op2 infinity or vice versa,
2401 // we don't know anything about op1 except maybe for the sign
2402 // and perhaps if it can be NAN or not.
2403 REAL_VALUE_TYPE lb
, ub
;
2404 int signbit_known
= signbit_known_p (lhs_lb
, lhs_ub
, op2_lb
, op2_ub
);
2405 zero_to_inf_range (lb
, ub
, signbit_known
);
2406 r
.set (type
, lb
, ub
);
2408 return float_binary_op_range_finish (ret
, r
, type
, lhs
);
2410 virtual bool op2_range (frange
&r
, tree type
,
2413 relation_trio
= TRIO_VARYING
) const final override
2415 if (lhs
.undefined_p ())
2417 bool ret
= fold_range (r
, type
, op1
, lhs
);
2420 if (lhs
.known_isnan () || op1
.known_isnan () || op1
.undefined_p ())
2421 return float_binary_op_range_finish (ret
, r
, type
, lhs
, true);
2422 const REAL_VALUE_TYPE
&lhs_lb
= lhs
.lower_bound ();
2423 const REAL_VALUE_TYPE
&lhs_ub
= lhs
.upper_bound ();
2424 const REAL_VALUE_TYPE
&op1_lb
= op1
.lower_bound ();
2425 const REAL_VALUE_TYPE
&op1_ub
= op1
.upper_bound ();
2426 if ((contains_zero_p (lhs_lb
, lhs_ub
) && contains_zero_p (op1_lb
, op1_ub
))
2427 || ((real_isinf (&lhs_lb
) || real_isinf (&lhs_ub
))
2428 && (real_isinf (&op1_lb
) || real_isinf (&op1_ub
))))
2430 // If both lhs and op1 could be zeros or both could be infinities,
2431 // we don't know anything about op2 except maybe for the sign
2432 // and perhaps if it can be NAN or not.
2433 REAL_VALUE_TYPE lb
, ub
;
2434 int signbit_known
= signbit_known_p (lhs_lb
, lhs_ub
, op1_lb
, op1_ub
);
2435 zero_to_inf_range (lb
, ub
, signbit_known
);
2436 r
.set (type
, lb
, ub
);
2438 return float_binary_op_range_finish (ret
, r
, type
, lhs
, true);
2441 void rv_fold (REAL_VALUE_TYPE
&lb
, REAL_VALUE_TYPE
&ub
, bool &maybe_nan
,
2443 const REAL_VALUE_TYPE
&lh_lb
,
2444 const REAL_VALUE_TYPE
&lh_ub
,
2445 const REAL_VALUE_TYPE
&rh_lb
,
2446 const REAL_VALUE_TYPE
&rh_ub
,
2447 relation_kind
) const final override
2449 // +-0.0 / +-0.0 or +-INF / +-INF is a known NAN.
2450 if ((zero_p (lh_lb
, lh_ub
) && zero_p (rh_lb
, rh_ub
))
2451 || (singleton_inf_p (lh_lb
, lh_ub
) && singleton_inf_p (rh_lb
, rh_ub
)))
2453 real_nan (&lb
, "", 0, TYPE_MODE (type
));
2459 // If +-0.0 is in both ranges, it is a maybe NAN.
2460 if (contains_zero_p (lh_lb
, lh_ub
) && contains_zero_p (rh_lb
, rh_ub
))
2462 // If +-INF is in both ranges, it is a maybe NAN.
2463 else if ((real_isinf (&lh_lb
) || real_isinf (&lh_ub
))
2464 && (real_isinf (&rh_lb
) || real_isinf (&rh_ub
)))
2469 int signbit_known
= signbit_known_p (lh_lb
, lh_ub
, rh_lb
, rh_ub
);
2471 // If dividend must be zero, the range is just +-0
2472 // (including if the divisor is +-INF).
2473 // If divisor must be +-INF, the range is just +-0
2474 // (including if the dividend is zero).
2475 if (zero_p (lh_lb
, lh_ub
) || singleton_inf_p (rh_lb
, rh_ub
))
2476 return zero_range (lb
, ub
, signbit_known
);
2478 // If divisor must be zero, the range is just +-INF
2479 // (including if the dividend is +-INF).
2480 // If dividend must be +-INF, the range is just +-INF
2481 // (including if the dividend is zero).
2482 if (zero_p (rh_lb
, rh_ub
) || singleton_inf_p (lh_lb
, lh_ub
))
2483 return inf_range (lb
, ub
, signbit_known
);
2485 // Otherwise if both operands may be zero, divisor could be
2486 // nextafter(0.0, +-1.0) and dividend +-0.0
2487 // in which case result is going to INF or vice versa and
2488 // result +0.0. So, all we can say for that case is if the
2489 // signs of divisor and dividend are always the same we have
2490 // [+0.0, +INF], if they are always different we have
2491 // [-INF, -0.0]. If they vary, VARING.
2492 // If both may be +-INF, divisor could be INF and dividend FLT_MAX,
2493 // in which case result is going to INF or vice versa and
2494 // result +0.0. So, all we can say for that case is if the
2495 // signs of divisor and dividend are always the same we have
2496 // [+0.0, +INF], if they are always different we have
2497 // [-INF, -0.0]. If they vary, VARYING.
2499 return zero_to_inf_range (lb
, ub
, signbit_known
);
2501 REAL_VALUE_TYPE cp
[8];
2502 // Do a cross-division. At this point none of the divisions should
2504 frange_arithmetic (RDIV_EXPR
, type
, cp
[0], lh_lb
, rh_lb
, dconstninf
);
2505 frange_arithmetic (RDIV_EXPR
, type
, cp
[1], lh_lb
, rh_ub
, dconstninf
);
2506 frange_arithmetic (RDIV_EXPR
, type
, cp
[2], lh_ub
, rh_lb
, dconstninf
);
2507 frange_arithmetic (RDIV_EXPR
, type
, cp
[3], lh_ub
, rh_ub
, dconstninf
);
2508 frange_arithmetic (RDIV_EXPR
, type
, cp
[4], lh_lb
, rh_lb
, dconstinf
);
2509 frange_arithmetic (RDIV_EXPR
, type
, cp
[5], lh_lb
, rh_ub
, dconstinf
);
2510 frange_arithmetic (RDIV_EXPR
, type
, cp
[6], lh_ub
, rh_lb
, dconstinf
);
2511 frange_arithmetic (RDIV_EXPR
, type
, cp
[7], lh_ub
, rh_ub
, dconstinf
);
2513 find_range (lb
, ub
, cp
);
2515 // If divisor may be zero (but is not known to be only zero),
2516 // and dividend can't be zero, the range can go up to -INF or +INF
2517 // depending on the signs.
2518 if (contains_zero_p (rh_lb
, rh_ub
))
2520 if (signbit_known
<= 0)
2521 real_inf (&lb
, true);
2522 if (signbit_known
>= 0)
2523 real_inf (&ub
, false);
2528 // Instantiate a range_op_table for floating point operations.
2529 static floating_op_table global_floating_table
;
2531 // Pointer to the float table so the dispatch code can access it.
2532 floating_op_table
*floating_tree_table
= &global_floating_table
;
2534 floating_op_table::floating_op_table ()
2536 set (SSA_NAME
, fop_identity
);
2537 set (PAREN_EXPR
, fop_identity
);
2538 set (OBJ_TYPE_REF
, fop_identity
);
2539 set (REAL_CST
, fop_identity
);
2541 // All the relational operators are expected to work, because the
2542 // calculation of ranges on outgoing edges expect the handlers to be
2544 set (EQ_EXPR
, fop_equal
);
2545 set (NE_EXPR
, fop_not_equal
);
2546 set (LT_EXPR
, fop_lt
);
2547 set (LE_EXPR
, fop_le
);
2548 set (GT_EXPR
, fop_gt
);
2549 set (GE_EXPR
, fop_ge
);
2550 set (UNLE_EXPR
, fop_unordered_le
);
2551 set (UNLT_EXPR
, fop_unordered_lt
);
2552 set (UNGE_EXPR
, fop_unordered_ge
);
2553 set (UNGT_EXPR
, fop_unordered_gt
);
2554 set (UNEQ_EXPR
, fop_unordered_equal
);
2555 set (ORDERED_EXPR
, fop_ordered
);
2556 set (UNORDERED_EXPR
, fop_unordered
);
2558 set (ABS_EXPR
, fop_abs
);
2559 set (NEGATE_EXPR
, fop_negate
);
2560 set (PLUS_EXPR
, fop_plus
);
2561 set (MINUS_EXPR
, fop_minus
);
2562 set (MULT_EXPR
, fop_mult
);
2563 set (RDIV_EXPR
, fop_div
);
2566 // Return a pointer to the range_operator_float instance, if there is
2567 // one associated with tree_code CODE.
2569 range_operator_float
*
2570 floating_op_table::operator[] (enum tree_code code
)
2572 return m_range_tree
[code
];
2575 // Add OP to the handler table for CODE.
2578 floating_op_table::set (enum tree_code code
, range_operator_float
&op
)
2580 gcc_checking_assert (m_range_tree
[code
] == NULL
);
2581 m_range_tree
[code
] = &op
;
2585 #include "selftest.h"
2590 // Build an frange from string endpoints.
2593 frange_float (const char *lb
, const char *ub
, tree type
= float_type_node
)
2595 REAL_VALUE_TYPE min
, max
;
2596 gcc_assert (real_from_string (&min
, lb
) == 0);
2597 gcc_assert (real_from_string (&max
, ub
) == 0);
2598 return frange (type
, min
, max
);
2602 range_op_float_tests ()
2605 frange
trange (float_type_node
);
2607 // negate([-5, +10]) => [-10, 5]
2608 r0
= frange_float ("-5", "10");
2609 fop_negate
.fold_range (r
, float_type_node
, r0
, trange
);
2610 ASSERT_EQ (r
, frange_float ("-10", "5"));
2612 // negate([0, 1] -NAN) => [-1, -0] +NAN
2613 r0
= frange_float ("0", "1");
2614 r0
.update_nan (true);
2615 fop_negate
.fold_range (r
, float_type_node
, r0
, trange
);
2616 r1
= frange_float ("-1", "-0");
2617 r1
.update_nan (false);
2620 // [-INF,+INF] + [-INF,+INF] could be a NAN.
2621 range_op_handler
plus (PLUS_EXPR
, float_type_node
);
2622 r0
.set_varying (float_type_node
);
2623 r1
.set_varying (float_type_node
);
2626 plus
.fold_range (r
, float_type_node
, r0
, r1
);
2627 if (HONOR_NANS (float_type_node
))
2628 ASSERT_TRUE (r
.maybe_isnan ());
2631 } // namespace selftest
2633 #endif // CHECKING_P