diff options
author | Richard Sandiford <richard.sandiford@arm.com> | 2020-07-11 13:25:26 +0100 |
---|---|---|
committer | Richard Sandiford <richard.sandiford@arm.com> | 2020-07-11 13:25:26 +0100 |
commit | 505032d97d0593d5e9a6f51b107650e27fcf6b23 (patch) | |
tree | 7c1f47b339701787e6a10082e7516f40a3ee562d | |
parent | c19f95fb1b8f15090eb1d1682e86de425fbd3c78 (diff) | |
download | gcc-505032d97d0593d5e9a6f51b107650e27fcf6b23.zip gcc-505032d97d0593d5e9a6f51b107650e27fcf6b23.tar.gz gcc-505032d97d0593d5e9a6f51b107650e27fcf6b23.tar.bz2 |
value-range: Fix handling of POLY_INT_CST anti-ranges [PR96146]
The range infrastructure has code to decompose POLY_INT_CST ranges
to worst-case integer bounds. However, it had the fundamental flaw
(obvious in hindsight) that it applied to anti-ranges too, meaning
that a range 2+2X would end up with a range of ~[2, +INF], i.e.
[-INF, 1]. This patch decays to varying in that case instead.
I'm still a bit uneasy about this. ISTM that in terms of
generality:
SSA_NAME => POLY_INT_CST => INTEGER_CST
=> ADDR_EXPR
I.e. an SSA_NAME could store a POLY_INT_CST and a POLY_INT_CST
could store an INTEGER_CST (before canonicalisation). POLY_INT_CST
is also “as constant as” ADDR_EXPR (well, OK, only some ADDR_EXPRs
are run-time rather than link-time constants, whereas all POLY_INT_CSTs
are, but still). So it seems like we should at least be able to treat
POLY_INT_CST as symbolic. On the other hand, I don't have any examples
in which that would be useful.
gcc/
PR tree-optimization/96146
* value-range.cc (value_range::set): Only decompose POLY_INT_CST
bounds to integers for VR_RANGE. Decay to VR_VARYING for anti-ranges
involving POLY_INT_CSTs.
gcc/testsuite/
PR tree-optimization/96146
* gcc.target/aarch64/sve/acle/general/pr96146.c: New test.
-rw-r--r-- | gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr96146.c | 20 | ||||
-rw-r--r-- | gcc/value-range.cc | 47 |
2 files changed, 48 insertions, 19 deletions
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr96146.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr96146.c new file mode 100644 index 0000000..b05fac4 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr96146.c @@ -0,0 +1,20 @@ +/* { dg-do run { target aarch64_sve_hw } } */ +/* { dg-options "-O3" } */ + +#include <arm_sve.h> + +void __attribute__ ((noipa)) +f (volatile int *x) +{ + int i; + for (int i = 0; i < svcntd (); ++i) + *x = i; +} + +int +main (void) +{ + volatile int x; + f (&x); + return 0; +} diff --git a/gcc/value-range.cc b/gcc/value-range.cc index 929a6b5..bc4b061 100644 --- a/gcc/value-range.cc +++ b/gcc/value-range.cc @@ -86,7 +86,34 @@ value_range::set (tree min, tree max, value_range_kind kind) set_undefined (); return; } - else if (kind == VR_VARYING) + + if (kind == VR_RANGE) + { + /* Convert POLY_INT_CST bounds into worst-case INTEGER_CST bounds. */ + if (POLY_INT_CST_P (min)) + { + tree type_min = vrp_val_min (TREE_TYPE (min)); + widest_int lb + = constant_lower_bound_with_limit (wi::to_poly_widest (min), + wi::to_widest (type_min)); + min = wide_int_to_tree (TREE_TYPE (min), lb); + } + if (POLY_INT_CST_P (max)) + { + tree type_max = vrp_val_max (TREE_TYPE (max)); + widest_int ub + = constant_upper_bound_with_limit (wi::to_poly_widest (max), + wi::to_widest (type_max)); + max = wide_int_to_tree (TREE_TYPE (max), ub); + } + } + else if (kind != VR_VARYING) + { + if (POLY_INT_CST_P (min) || POLY_INT_CST_P (max)) + kind = VR_VARYING; + } + + if (kind == VR_VARYING) { gcc_assert (TREE_TYPE (min) == TREE_TYPE (max)); tree typ = TREE_TYPE (min); @@ -99,24 +126,6 @@ value_range::set (tree min, tree max, value_range_kind kind) return; } - /* Convert POLY_INT_CST bounds into worst-case INTEGER_CST bounds. */ - if (POLY_INT_CST_P (min)) - { - tree type_min = vrp_val_min (TREE_TYPE (min)); - widest_int lb - = constant_lower_bound_with_limit (wi::to_poly_widest (min), - wi::to_widest (type_min)); - min = wide_int_to_tree (TREE_TYPE (min), lb); - } - if (POLY_INT_CST_P (max)) - { - tree type_max = vrp_val_max (TREE_TYPE (max)); - widest_int ub - = constant_upper_bound_with_limit (wi::to_poly_widest (max), - wi::to_widest (type_max)); - max = wide_int_to_tree (TREE_TYPE (max), ub); - } - /* Nothing to canonicalize for symbolic ranges. */ if (TREE_CODE (min) != INTEGER_CST || TREE_CODE (max) != INTEGER_CST) |