aboutsummaryrefslogtreecommitdiff
path: root/gcc/value-range.h
diff options
context:
space:
mode:
authorAldy Hernandez <aldyh@redhat.com>2022-09-22 18:20:39 +0200
committerAldy Hernandez <aldyh@redhat.com>2022-09-23 10:52:21 +0200
commitb7fd7fb5011106c062df9275ca8fddcbce4ebdeb (patch)
treea42c03a68d1a2a8f16bee2a2b6957ea6a1cf3586 /gcc/value-range.h
parent76dbbfe62c0d7f4548cb12e757f67a1b1f84c3df (diff)
downloadgcc-b7fd7fb5011106c062df9275ca8fddcbce4ebdeb.zip
gcc-b7fd7fb5011106c062df9275ca8fddcbce4ebdeb.tar.gz
gcc-b7fd7fb5011106c062df9275ca8fddcbce4ebdeb.tar.bz2
frange: drop endpoints to min/max representable numbers for -ffinite-math-only.
Similarly to how we drop NANs to UNDEFINED when -ffinite-math-only, I think we can drop the numbers outside of the min/max representable numbers to the representable number. This means the endpoings to VR_VARYING for -ffinite-math-only can now be the min/max representable, instead of -INF and +INF. Saturating in the setter means that the upcoming implementation for binary operators no longer have to worry about doing the right thing for -ffinite-math-only. If the range goes outside the limits, it'll get chopped down. Tested on x86-64 Linux. gcc/ChangeLog: * range-op-float.cc (build_le): Use vrp_val_*. (build_lt): Same. (build_ge): Same. (build_gt): Same. * value-range.cc (frange::set): Chop ranges outside of the representable numbers for -ffinite-math-only. (frange::normalize_kind): Use vrp_val*. (frange::verify_range): Same. (frange::set_nonnegative): Same. (range_tests_floats): Remove tests that depend on -INF and +INF. * value-range.h (real_max_representable): Add prototype. (real_min_representable): Same. (vrp_val_max): Set max representable number for -ffinite-math-only. (vrp_val_min): Same but for min. (frange::set_varying): Use vrp_val*.
Diffstat (limited to 'gcc/value-range.h')
-rw-r--r--gcc/value-range.h75
1 files changed, 63 insertions, 12 deletions
diff --git a/gcc/value-range.h b/gcc/value-range.h
index 3668b33..413e54b 100644
--- a/gcc/value-range.h
+++ b/gcc/value-range.h
@@ -593,6 +593,8 @@ extern void dump_value_range (FILE *, const vrange *);
extern bool vrp_val_is_min (const_tree);
extern bool vrp_val_is_max (const_tree);
extern bool vrp_operand_equal_p (const_tree, const_tree);
+inline REAL_VALUE_TYPE frange_val_min (const_tree type);
+inline REAL_VALUE_TYPE frange_val_max (const_tree type);
inline value_range_kind
vrange::kind () const
@@ -1009,7 +1011,10 @@ vrp_val_max (const_tree type)
return wide_int_to_tree (const_cast<tree> (type), max);
}
if (frange::supports_p (type))
- return build_real (const_cast <tree> (type), dconstinf);
+ {
+ REAL_VALUE_TYPE r = frange_val_max (type);
+ return build_real (const_cast <tree> (type), r);
+ }
return NULL_TREE;
}
@@ -1023,7 +1028,10 @@ vrp_val_min (const_tree type)
if (POINTER_TYPE_P (type))
return build_zero_cst (const_cast<tree> (type));
if (frange::supports_p (type))
- return build_real (const_cast <tree> (type), dconstninf);
+ {
+ REAL_VALUE_TYPE r = frange_val_min (type);
+ return build_real (const_cast <tree> (type), r);
+ }
return NULL_TREE;
}
@@ -1073,8 +1081,8 @@ frange::set_varying (tree type)
{
m_kind = VR_VARYING;
m_type = type;
- m_min = dconstninf;
- m_max = dconstinf;
+ m_min = frange_val_min (type);
+ m_max = frange_val_max (type);
m_pos_nan = true;
m_neg_nan = true;
}
@@ -1132,23 +1140,66 @@ frange::clear_nan ()
// Set R to maximum representable value for TYPE.
-inline void
-real_max_representable (REAL_VALUE_TYPE *r, tree type)
+inline REAL_VALUE_TYPE
+real_max_representable (const_tree type)
{
+ REAL_VALUE_TYPE r;
char buf[128];
get_max_float (REAL_MODE_FORMAT (TYPE_MODE (type)),
buf, sizeof (buf), false);
- int res = real_from_string (r, buf);
+ int res = real_from_string (&r, buf);
gcc_checking_assert (!res);
+ return r;
}
-// Set R to minimum representable value for TYPE.
+// Return the minimum representable value for TYPE.
-inline void
-real_min_representable (REAL_VALUE_TYPE *r, tree type)
+inline REAL_VALUE_TYPE
+real_min_representable (const_tree type)
+{
+ REAL_VALUE_TYPE r = real_max_representable (type);
+ r = real_value_negate (&r);
+ return r;
+}
+
+// Return the minimum value for TYPE.
+
+inline REAL_VALUE_TYPE
+frange_val_min (const_tree type)
+{
+ if (flag_finite_math_only)
+ return real_min_representable (type);
+ else
+ return dconstninf;
+}
+
+// Return the maximum value for TYPE.
+
+inline REAL_VALUE_TYPE
+frange_val_max (const_tree type)
+{
+ if (flag_finite_math_only)
+ return real_max_representable (type);
+ else
+ return dconstinf;
+}
+
+// Return TRUE if R is the minimum value for TYPE.
+
+inline bool
+frange_val_is_min (const REAL_VALUE_TYPE &r, const_tree type)
+{
+ REAL_VALUE_TYPE min = frange_val_min (type);
+ return real_identical (&min, &r);
+}
+
+// Return TRUE if R is the max value for TYPE.
+
+inline bool
+frange_val_is_max (const REAL_VALUE_TYPE &r, const_tree type)
{
- real_max_representable (r, type);
- *r = real_value_negate (r);
+ REAL_VALUE_TYPE max = frange_val_max (type);
+ return real_identical (&max, &r);
}
// Build a signless NAN of type TYPE.