aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Sandiford <richard.sandiford@arm.com>2020-07-11 13:25:26 +0100
committerRichard Sandiford <richard.sandiford@arm.com>2020-07-11 13:25:26 +0100
commit505032d97d0593d5e9a6f51b107650e27fcf6b23 (patch)
tree7c1f47b339701787e6a10082e7516f40a3ee562d
parentc19f95fb1b8f15090eb1d1682e86de425fbd3c78 (diff)
downloadgcc-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.c20
-rw-r--r--gcc/value-range.cc47
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)