When a partial equivalency record is merged, the existing members are updated.  The resulting PE size for each member should be the minimum of what it was, and the size of the object it is now based on.  The code was simply setting it to the new size, which sometimes overwrote the correct result.

Bootstrapped on x86_64-pc-linux-gnu with no regressions.  Pushed.

Andrew
commit 0205fbb91be022055c632973caa95e398b33db39
Author: Andrew MacLeod <amacl...@redhat.com>
Date:   Mon Oct 17 19:00:49 2022 -0400

    Merge partial relation precisions properly
    
    When merging 2 groups of PE's, one group was simply being set to the
    other instead of properly merging them.
    
            PR tree-optimization/107273
            gcc/
            * value-relation.cc (equiv_oracle::add_partial_equiv): Merge
            instead of copying precison of each member.
    
            gcc/testsuite/
            * gcc.dg/tree-ssa/pr107273-1.c: New.
            * gcc.dg/tree-ssa/pr107273-2.c: New.

diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr107273-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr107273-1.c
new file mode 100644
index 00000000000..db2e2c0da55
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr107273-1.c
@@ -0,0 +1,31 @@
+/* { dg-do run } */
+/* { dg-options "-O3" } */
+
+int printf(const char *, ...);
+int a[1] = {1};
+short b, c = 5500;
+int d;
+long e;
+char f = 1;
+int main() {
+  while (1) {
+    long g = b < 1;
+    e = g;
+    break;
+  }
+  for (; f; f--) {
+    if (e) {
+      d = -(6L | -(c & 1000));
+    }
+    char h = d;
+    if (b)
+      b = 0;
+    if (d < 200)
+      while (1)
+        printf("%d", a[c]);
+    short i = h * 210;
+    c = i;
+  }
+  return 0;
+}
+
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr107273-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr107273-2.c
new file mode 100644
index 00000000000..337450782d9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr107273-2.c
@@ -0,0 +1,27 @@
+/* { dg-do run } */
+/* { dg-options "-Os" } */
+
+int a, d, f;
+char b, g;
+unsigned i;
+int main() {
+  int c = 300, h = 40;
+  char e = 1;
+  for (; a < 1; a++) {
+    c = ~((i - ~c) | e);
+  L1:
+    e = f = c;
+    if (c)
+      if (c > -200)
+        e = g % (1 << h);
+    char k = 0;
+  L2:;
+  }
+  if (b) {
+    if (d)
+      goto L2;
+    if (!b)
+      goto L1;
+  }
+  return 0;
+}
diff --git a/gcc/value-relation.cc b/gcc/value-relation.cc
index fed8a78723c..178a245f41a 100644
--- a/gcc/value-relation.cc
+++ b/gcc/value-relation.cc
@@ -380,7 +380,7 @@ equiv_oracle::add_partial_equiv (relation_kind r, tree op1, tree op2)
       EXECUTE_IF_SET_IN_BITMAP (pe1.members, 0, x, bi)
 	{
 	  m_partial[x].ssa_base = op2;
-	  m_partial[x].code = pe2.code;
+	  m_partial[x].code = pe_min (m_partial[x].code, pe2.code);
 	}
       bitmap_set_bit (pe1.members, v2);
       return;

Reply via email to