DOM's cprop folds a load from a constant table of doubles like one
of integers, so it threads a comparison the selected element decides:
static const double tab[2] = { 0.5, 2.5 };
if (c) i = 1; else { i = 0; d = d + 1; }
if (d && tab[i] > 1.0) ...
On the other hand, ranger can't because range_from_readonly_var does
not handle floats as the TODO in there notes. This patch implements
this.
Tested on ppc64le Linux. The assembly is identical over a corpus of
.ii files from a stage1 bootstrap and over the LAPACK sources, and
LAPACK's ctests pass.
Pushed.
gcc/ChangeLog:
* gimple-range-fold.cc (range_from_missing_constructor_part):
Allow float types.
(range_from_readonly_load): Add the range of a REAL_CST.
(fold_using_range::range_from_readonly_var): Allow float types.
gcc/testsuite/ChangeLog:
* gcc.dg/tree-ssa/vrp-from-cst-agg-8.c: New test.
---
gcc/gimple-range-fold.cc | 37 +++++++++++++------
.../gcc.dg/tree-ssa/vrp-from-cst-agg-8.c | 28 ++++++++++++++
2 files changed, 53 insertions(+), 12 deletions(-)
create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/vrp-from-cst-agg-8.c
diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc
index 7dd9ddfd796..abe3ade2960 100644
--- a/gcc/gimple-range-fold.cc
+++ b/gcc/gimple-range-fold.cc
@@ -993,28 +993,29 @@ fold_using_range::range_of_address (prange &r, gimple
*stmt, fur_source &src)
}
/* If TYPE is a pointer, return false. Otherwise, add zero of TYPE (which must
- be an integer) to R and return true. */
+ be an integer or a float) to R and return true. */
static bool
range_from_missing_constructor_part (vrange &r, tree type)
{
if (POINTER_TYPE_P (type))
return false;
- gcc_checking_assert (irange::supports_p (type));
- wide_int zero = wi::zero (TYPE_PRECISION (type));
- r.union_ (int_range<1> (type, zero, zero));
+ gcc_checking_assert (irange::supports_p (type)
+ || frange::supports_p (type));
+ value_range zero (type);
+ zero.set_zero (type);
+ r.union_ (zero);
return true;
}
// One step of fold_using_range::range_from_readonly_var. Process expressions
// in COMPS which together load a value of TYPE, from index I to 0 according to
// the corresponding static initializer in CST which should be either a scalar
-// invariant or a constructor. Currently TYPE must be either a pointer or an
-// integer. If TYPE is a pointer, return true if all potentially loaded values
-// are known not to be zero and false if any of them can be zero. Otherwise
-// return true if it is possible to add all constants which can be loaded from
-// CST (which must be storable to TYPE) to R and do so.
-// TODO: Add support for franges.
+// invariant or a constructor. Currently TYPE must be a pointer, an integer
+// or a float. If TYPE is a pointer, return true if all potentially loaded
+// values are known not to be zero and false if any of them can be zero.
+// Otherwise return true if it is possible to add all constants which can be
+// loaded from CST (which must be storable to TYPE) to R and do so.
static bool
range_from_readonly_load (vrange &r, tree type, tree cst,
@@ -1030,6 +1031,18 @@ range_from_readonly_load (vrange &r, tree type, tree cst,
return tree_single_nonzero_p (cst);
}
+ if (TREE_CODE (cst) == REAL_CST)
+ {
+ const REAL_VALUE_TYPE *rv = TREE_REAL_CST_PTR (cst);
+ frange elt;
+ if (real_isnan (rv))
+ elt.set_nan (type, real_isneg (rv));
+ else
+ elt.set (type, *rv, *rv, nan_state (false));
+ r.union_ (elt);
+ return true;
+ }
+
if (TREE_CODE (cst) != INTEGER_CST)
return false;
@@ -1118,9 +1131,9 @@ fold_using_range::range_from_readonly_var (vrange &r,
gimple *stmt)
{
gcc_checking_assert (gimple_code (stmt) == GIMPLE_ASSIGN);
tree type = TREE_TYPE (gimple_assign_lhs (stmt));
- /* TODO: Add support for frange. */
if (!irange::supports_p (type)
- && !prange::supports_p (type))
+ && !prange::supports_p (type)
+ && !frange::supports_p (type))
return false;
unsigned HOST_WIDE_INT limit = param_vrp_cstload_limit;
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp-from-cst-agg-8.c
b/gcc/testsuite/gcc.dg/tree-ssa/vrp-from-cst-agg-8.c
new file mode 100644
index 00000000000..6e37badeea8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp-from-cst-agg-8.c
@@ -0,0 +1,28 @@
+/* { dg-do link } */
+/* { dg-options "-O2" } */
+
+volatile double gd;
+
+static const double values[4] = {0.5, 1.5, 2.5, 3.5};
+
+void link_error (void);
+
+void foo (int index)
+{
+ if (index < 0 || index > 3)
+ return;
+ const double v = values[index];
+ if (v < 0.5 || v > 3.5)
+ link_error ();
+ if (v != v)
+ link_error ();
+ gd = v;
+}
+
+__attribute__((noipa)) int get_index (void) { return 2; }
+
+int main (void)
+{
+ foo (get_index ());
+ return 0;
+}
--
2.53.0