https://gcc.gnu.org/g:c1b5260244cf532c3702f5054ea0d1a5c6d01f7b
commit r17-4024-gc1b5260244cf532c3702f5054ea0d1a5c6d01f7b Author: Aldy Hernandez <[email protected]> Date: Thu Sep 3 08:33:55 2026 +0000 ranger: give loads from constant tables of floats a range 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. 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. Diff: --- gcc/gimple-range-fold.cc | 37 +++++++++++++++------- gcc/testsuite/gcc.dg/tree-ssa/vrp-from-cst-agg-8.c | 28 ++++++++++++++++ 2 files changed, 53 insertions(+), 12 deletions(-) diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc index 7dd9ddfd7963..abe3ade2960d 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 000000000000..6e37badeea81 --- /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; +}
