Hi All,

The failures on -m32 on x86 show that the checks at the top level in
tree_ssa_phiopt_worker aren't enough for diamond_p.

In minmax_replacement we perform the additional validation of the shape but by
then it's too late to catch these case.

This patch changes it so we check that for a diamond shape we check that the
edges we're operation on must result in the same destination BB.

We also enforce that for a diamond the middle BBs must have a single successor,
this is because the remainder of the code always follows EDGE_SUCC 0.  If there
are more than 1 successor then the edge we follow could be not part of the
diamond so just reject it early on.

I also remove the assert after the use of gimple_phi_arg_def as this function
can't return NULL. if the index is out of range it already breaks on an assert
inside the gimple_phi_arg_def, so we never hit this assert.

Bootstrapped Regtested on aarch64-none-linux-gnu, x86_64-pc-linux-gnu
and no issues.

Ok for master?

Thanks,
Tamar

gcc/ChangeLog:

        PR middle-end/106519
        * tree-ssa-phiopt.cc (tree_ssa_phiopt_worker): Check final phi edge for
        diamond shapes.

gcc/testsuite/ChangeLog:

        PR middle-end/106519
        * gcc.dg/pr106519.c: New test.

--- inline copy of patch -- 
diff --git a/gcc/testsuite/gcc.dg/pr106519.c b/gcc/testsuite/gcc.dg/pr106519.c
new file mode 100644
index 
0000000000000000000000000000000000000000..3d4662d8a02c6501560abb71ac53320f093620d8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr106519.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+
+int bytestart, bytemem_0_0, modlookup_l_p;
+
+void
+modlookup_l() {
+  long j;
+  while (modlookup_l_p)
+    while (bytestart && j && bytemem_0_0)
+      j = j + 1;
+}
diff --git a/gcc/tree-ssa-phiopt.cc b/gcc/tree-ssa-phiopt.cc
index 
a8e55e040649e17f83a2fc3340e368cf9c4c5e70..1c4942b5b5c18732a8b18789c04e2685437404dd
 100644
--- a/gcc/tree-ssa-phiopt.cc
+++ b/gcc/tree-ssa-phiopt.cc
@@ -268,7 +268,8 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool 
do_hoist_loads, bool early_p)
          continue;
        }
       else if (EDGE_SUCC (bb1, 0)->dest == EDGE_SUCC (bb2, 0)->dest
-              && !empty_block_p (bb1))
+              && !empty_block_p (bb1)
+              && single_succ_p (bb1) && single_succ_p (bb2))
        diamond_p = true;
       else
        continue;
@@ -311,6 +312,12 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool 
do_hoist_loads, bool early_p)
            for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
              {
                phi = as_a <gphi *> (gsi_stmt (gsi));
+
+               /* A diamond must continue to the same destination node, 
otherwise
+                  by definition it's not a diamond.  */
+               if (diamond_p && e1->dest != e2->dest)
+                 continue;
+
                arg0 = gimple_phi_arg_def (phi, e1->dest_idx);
                arg1 = gimple_phi_arg_def (phi, e2->dest_idx);
                if (value_replacement (bb, bb1, e1, e2, phi, arg0, arg1) == 2)
@@ -329,12 +336,15 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool 
do_hoist_loads, bool early_p)
          if (!phi)
            continue;
 
-         arg0 = gimple_phi_arg_def (phi, e1->dest_idx);
-         arg1 = gimple_phi_arg_def (phi, e2->dest_idx);
+         /* A diamond must continue to the same destination node, otherwise
+            by definition it's not a diamond.  */
+         if (diamond_p && e1->dest != e2->dest)
+           continue;
 
          /* Something is wrong if we cannot find the arguments in the PHI
             node.  */
-         gcc_assert (arg0 != NULL_TREE && arg1 != NULL_TREE);
+         arg0 = gimple_phi_arg_def (phi, e1->dest_idx);
+         arg1 = gimple_phi_arg_def (phi, e2->dest_idx);
 
          gphi *newphi;
          if (single_pred_p (bb1)




-- 
diff --git a/gcc/testsuite/gcc.dg/pr106519.c b/gcc/testsuite/gcc.dg/pr106519.c
new file mode 100644
index 
0000000000000000000000000000000000000000..3d4662d8a02c6501560abb71ac53320f093620d8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr106519.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+
+int bytestart, bytemem_0_0, modlookup_l_p;
+
+void
+modlookup_l() {
+  long j;
+  while (modlookup_l_p)
+    while (bytestart && j && bytemem_0_0)
+      j = j + 1;
+}
diff --git a/gcc/tree-ssa-phiopt.cc b/gcc/tree-ssa-phiopt.cc
index 
a8e55e040649e17f83a2fc3340e368cf9c4c5e70..1c4942b5b5c18732a8b18789c04e2685437404dd
 100644
--- a/gcc/tree-ssa-phiopt.cc
+++ b/gcc/tree-ssa-phiopt.cc
@@ -268,7 +268,8 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool 
do_hoist_loads, bool early_p)
          continue;
        }
       else if (EDGE_SUCC (bb1, 0)->dest == EDGE_SUCC (bb2, 0)->dest
-              && !empty_block_p (bb1))
+              && !empty_block_p (bb1)
+              && single_succ_p (bb1) && single_succ_p (bb2))
        diamond_p = true;
       else
        continue;
@@ -311,6 +312,12 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool 
do_hoist_loads, bool early_p)
            for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
              {
                phi = as_a <gphi *> (gsi_stmt (gsi));
+
+               /* A diamond must continue to the same destination node, 
otherwise
+                  by definition it's not a diamond.  */
+               if (diamond_p && e1->dest != e2->dest)
+                 continue;
+
                arg0 = gimple_phi_arg_def (phi, e1->dest_idx);
                arg1 = gimple_phi_arg_def (phi, e2->dest_idx);
                if (value_replacement (bb, bb1, e1, e2, phi, arg0, arg1) == 2)
@@ -329,12 +336,15 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool 
do_hoist_loads, bool early_p)
          if (!phi)
            continue;
 
-         arg0 = gimple_phi_arg_def (phi, e1->dest_idx);
-         arg1 = gimple_phi_arg_def (phi, e2->dest_idx);
+         /* A diamond must continue to the same destination node, otherwise
+            by definition it's not a diamond.  */
+         if (diamond_p && e1->dest != e2->dest)
+           continue;
 
          /* Something is wrong if we cannot find the arguments in the PHI
             node.  */
-         gcc_assert (arg0 != NULL_TREE && arg1 != NULL_TREE);
+         arg0 = gimple_phi_arg_def (phi, e1->dest_idx);
+         arg1 = gimple_phi_arg_def (phi, e2->dest_idx);
 
          gphi *newphi;
          if (single_pred_p (bb1)



Reply via email to