aboutsummaryrefslogtreecommitdiff
path: root/gcc/range-op-float.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/range-op-float.cc')
-rw-r--r--gcc/range-op-float.cc79
1 files changed, 58 insertions, 21 deletions
diff --git a/gcc/range-op-float.cc b/gcc/range-op-float.cc
index ff9fe31..ca41136 100644
--- a/gcc/range-op-float.cc
+++ b/gcc/range-op-float.cc
@@ -150,6 +150,18 @@ range_operator_float::op1_op2_relation (const irange &lhs ATTRIBUTE_UNUSED) cons
return VREL_VARYING;
}
+// Set R to [NAN, NAN].
+
+static inline void
+frange_set_nan (frange &r, tree type)
+{
+ REAL_VALUE_TYPE rv;
+ bool res = real_nan (&rv, "", 1, TYPE_MODE (type));
+ if (flag_checking)
+ gcc_assert (res);
+ r.set (type, rv, rv);
+}
+
// Return TRUE if OP1 and OP2 are known to be free of NANs.
static inline bool
@@ -178,6 +190,40 @@ frelop_early_resolve (irange &r, tree type,
&& relop_early_resolve (r, type, op1, op2, rel, my_rel));
}
+// Crop R to [-INF, MAX] where MAX is the maximum representable number
+// for TYPE.
+
+static inline void
+frange_drop_inf (frange &r, tree type)
+{
+ // FIXME: build_real() bails on decimal float modes when called with
+ // a max representable endpoint.
+ if (DECIMAL_FLOAT_MODE_P (TYPE_MODE (type)))
+ return;
+
+ REAL_VALUE_TYPE max;
+ real_max_representable (&max, type);
+ frange tmp (type, r.lower_bound (), max);
+ r.intersect (tmp);
+}
+
+// Crop R to [MIN, +INF] where MIN is the minimum representable number
+// for TYPE.
+
+static inline void
+frange_drop_ninf (frange &r, tree type)
+{
+ // FIXME: build_real() bails on decimal float modes when called with
+ // a max representable endpoint.
+ if (DECIMAL_FLOAT_MODE_P (TYPE_MODE (type)))
+ return;
+
+ REAL_VALUE_TYPE min;
+ real_min_representable (&min, type);
+ frange tmp (type, min, r.upper_bound ());
+ r.intersect (tmp);
+}
+
// Default implementation of fold_range for relational operators.
// This amounts to passing on any known relations from the oracle, iff
// we know the operands are not NAN or -ffinite-math-only holds.
@@ -252,21 +298,8 @@ foperator_equal::op1_range (frange &r, tree type,
switch (get_bool_state (r, lhs, type))
{
case BRS_TRUE:
- if (HONOR_SIGNED_ZEROS (type)
- && op2.contains_p (build_zero_cst (type)))
- {
- // With signed zeros, x == -0.0 does not mean we can replace
- // x with -0.0, because x may be either +0.0 or -0.0.
- r.set_varying (type);
- }
- else
- {
- // If it's true, the result is the same as OP2.
- //
- // If the range does not actually contain zeros, this should
- // always be OK.
- r = op2;
- }
+ // If it's true, the result is the same as OP2.
+ r = op2;
// The TRUE side of op1 == op2 implies op1 is !NAN.
r.set_nan (fp_prop::NO);
break;
@@ -275,7 +308,7 @@ foperator_equal::op1_range (frange &r, tree type,
r.set_varying (type);
// The FALSE side of op1 == op1 implies op1 is a NAN.
if (rel == VREL_EQ)
- r.set_nan (fp_prop::YES);
+ frange_set_nan (r, type);
break;
default:
@@ -365,7 +398,8 @@ foperator_lt::op1_range (frange &r,
r.set_varying (type);
// The TRUE side of op1 < op2 implies op1 is !NAN and !INF.
r.set_nan (fp_prop::NO);
- r.set_inf (fp_prop::NO);
+ // x < y implies x is not +INF.
+ frange_drop_inf (r, type);
break;
case BRS_FALSE:
@@ -391,7 +425,8 @@ foperator_lt::op2_range (frange &r,
r.set_varying (type);
// The TRUE side of op1 < op2 implies op2 is !NAN and !NINF.
r.set_nan (fp_prop::NO);
- r.set_ninf (fp_prop::NO);
+ // x < y implies y is not -INF.
+ frange_drop_ninf (r, type);
break;
case BRS_FALSE:
@@ -493,7 +528,8 @@ foperator_gt::op1_range (frange &r,
r.set_varying (type);
// The TRUE side of op1 > op2 implies op1 is !NAN and !NINF.
r.set_nan (fp_prop::NO);
- r.set_ninf (fp_prop::NO);
+ // x > y implies x is not -INF.
+ frange_drop_ninf (r, type);
break;
case BRS_FALSE:
@@ -519,7 +555,8 @@ foperator_gt::op2_range (frange &r,
r.set_varying (type);
// The TRUE side of op1 > op2 implies op2 is !NAN and !INF.
r.set_nan (fp_prop::NO);
- r.set_inf (fp_prop::NO);
+ // x > y implies y is not +INF.
+ frange_drop_inf (r, type);
break;
case BRS_FALSE:
@@ -636,7 +673,7 @@ foperator_unordered::op1_range (frange &r, tree type,
// Since at least one operand must be NAN, if one of them is
// not, the other must be.
if (op2.get_nan ().no_p ())
- r.set_nan (fp_prop::YES);
+ frange_set_nan (r, type);
break;
case BRS_FALSE: