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 (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) --