aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAldy Hernandez <aldyh@redhat.com>2021-11-08 12:13:33 +0100
committerAldy Hernandez <aldyh@redhat.com>2021-11-08 16:08:09 +0100
commit18546941ae4c56cd9240d2dc2ca2806e01eb6fb7 (patch)
treea9ec988e8935f31a537c1fbf194dc0d36fe73067
parenta354b4255b679de45bd3d4d8874a26c89f6c74fc (diff)
downloadgcc-18546941ae4c56cd9240d2dc2ca2806e01eb6fb7.zip
gcc-18546941ae4c56cd9240d2dc2ca2806e01eb6fb7.tar.gz
gcc-18546941ae4c56cd9240d2dc2ca2806e01eb6fb7.tar.bz2
path solver: Avoid recalculating ranges already in the cache.
The problem here is an ordering issue with a path that starts with 19->3: <bb 3> [local count: 916928331]: # value_20 = PHI <value_17(19), value_7(D)(17)> # n_27 = PHI <n_16(19), 1(17)> n_16 = n_27 + 4; value_17 = value_20 / 10000; if (value_20 > 42949672959999) goto <bb 19>; [89.00%] else goto <bb 4>; [11.00%] The problem here is that both value_17 and value_20 are in the set of imports we must pre-calculate. The value_17 name occurs first in the bitmap, so we try to resolve it first, which causes us to recursively solve the value_20 range. We do so correctly and put them both in the cache. However, when we try to solve value_20 from the bitmap, we ignore that it already has a cached entry and try to resolve the PHI with the wrong value of value_17: # value_20 = PHI <value_17(19), value_7(D)(17)> The right thing to do is to avoid recalculating definitions already solved. Regstrapped and checked for # threads before and after on x86-64 Linux. gcc/ChangeLog: PR tree-optimization/103120 * gimple-range-path.cc (path_range_query::range_defined_in_block): Bail if there's a cache entry. gcc/testsuite/ChangeLog: * gcc.dg/pr103120.c: New test.
-rw-r--r--gcc/gimple-range-path.cc3
-rw-r--r--gcc/testsuite/gcc.dg/pr103120.c33
2 files changed, 36 insertions, 0 deletions
diff --git a/gcc/gimple-range-path.cc b/gcc/gimple-range-path.cc
index 9175651..9d3fe89 100644
--- a/gcc/gimple-range-path.cc
+++ b/gcc/gimple-range-path.cc
@@ -300,6 +300,9 @@ path_range_query::range_defined_in_block (irange &r, tree name, basic_block bb)
if (def_bb != bb)
return false;
+ if (get_cache (r, name))
+ return true;
+
if (gimple_code (def_stmt) == GIMPLE_PHI)
ssa_range_in_phi (r, as_a<gphi *> (def_stmt));
else
diff --git a/gcc/testsuite/gcc.dg/pr103120.c b/gcc/testsuite/gcc.dg/pr103120.c
new file mode 100644
index 0000000..b680a6c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr103120.c
@@ -0,0 +1,33 @@
+// { dg-do run }
+// { dg-options "-O2" }
+
+#define radix 10
+__INT32_TYPE__ numDigits(__UINT64_TYPE__ value)
+{
+ __INT32_TYPE__ n = 1;
+ while (value > __UINT32_MAX__)
+ {
+ n += 4;
+ value /= radix * radix * radix * radix;
+ }
+ __UINT32_TYPE__ v = (__UINT32_TYPE__)value;
+ while (1)
+ {
+ if (v < radix)
+ return n;
+ if (v < radix * radix)
+ return n + 1;
+ if (v < radix * radix * radix)
+ return n + 2;
+ if (v < radix * radix * radix * radix)
+ return n + 3;
+ n += 4;
+ v /= radix * radix * radix * radix;
+ }
+}
+
+int main()
+{
+ if (numDigits(__UINT64_MAX__) != 20)
+ __builtin_abort();
+}