aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-threadupdate.c
diff options
context:
space:
mode:
authorJeff Law <law@redhat.com>2013-09-17 11:27:41 -0600
committerJeff Law <law@gcc.gnu.org>2013-09-17 11:27:41 -0600
commit8d34e421a5668e25a992bd0b349cb81e91ee3e49 (patch)
tree94bfe22f7d19095ab53bd28cb6fb75e78e2f9196 /gcc/tree-ssa-threadupdate.c
parentc152901f5e1082de4ede3bc98c7ede2dea361e8d (diff)
downloadgcc-8d34e421a5668e25a992bd0b349cb81e91ee3e49.zip
gcc-8d34e421a5668e25a992bd0b349cb81e91ee3e49.tar.gz
gcc-8d34e421a5668e25a992bd0b349cb81e91ee3e49.tar.bz2
pr58387.c: New test.
* gcc.c-torture/execute/pr58387.c: New test. * tree-ssa-dom.c (cprop_into_successor_phis): Also propagate edge implied equivalences into successor phis. * tree-ssa-threadupdate.c (phi_args_equal_on_edges): Moved into here from tree-ssa-threadedge.c. (mark_threaded_blocks): When threading through a joiner, if both successors of the joiner's clone reach the same block, verify the PHI arguments are equal. If not, cancel the jump threading request. * tree-ssa-threadedge.c (phi_args_equal_on_edges): Moved into tree-ssa-threadupdate.c (thread_across_edge): Don't check PHI argument equality when threading through joiner block here. From-SVN: r202660
Diffstat (limited to 'gcc/tree-ssa-threadupdate.c')
-rw-r--r--gcc/tree-ssa-threadupdate.c62
1 files changed, 62 insertions, 0 deletions
diff --git a/gcc/tree-ssa-threadupdate.c b/gcc/tree-ssa-threadupdate.c
index d755266..4131128 100644
--- a/gcc/tree-ssa-threadupdate.c
+++ b/gcc/tree-ssa-threadupdate.c
@@ -1147,6 +1147,28 @@ fail:
return false;
}
+/* E1 and E2 are edges into the same basic block. Return TRUE if the
+ PHI arguments associated with those edges are equal or there are no
+ PHI arguments, otherwise return FALSE. */
+
+static bool
+phi_args_equal_on_edges (edge e1, edge e2)
+{
+ gimple_stmt_iterator gsi;
+ int indx1 = e1->dest_idx;
+ int indx2 = e2->dest_idx;
+
+ for (gsi = gsi_start_phis (e1->dest); !gsi_end_p (gsi); gsi_next (&gsi))
+ {
+ gimple phi = gsi_stmt (gsi);
+
+ if (!operand_equal_p (gimple_phi_arg_def (phi, indx1),
+ gimple_phi_arg_def (phi, indx2), 0))
+ return false;
+ }
+ return true;
+}
+
/* Walk through the registered jump threads and convert them into a
form convenient for this pass.
@@ -1219,6 +1241,46 @@ mark_threaded_blocks (bitmap threaded_blocks)
}
}
+ /* If we have a joiner block (J) which has two successors S1 and S2 and
+ we are threading though S1 and the final destination of the thread
+ is S2, then we must verify that any PHI nodes in S2 have the same
+ PHI arguments for the edge J->S2 and J->S1->...->S2.
+
+ We used to detect this prior to registering the jump thread, but
+ that prohibits propagation of edge equivalences into non-dominated
+ PHI nodes as the equivalency test might occur before propagation.
+
+ This works for now, but will need improvement as part of the FSA
+ optimization.
+
+ Note since we've moved the thread request data to the edges,
+ we have to iterate on those rather than the threaded_edges vector. */
+ EXECUTE_IF_SET_IN_BITMAP (tmp, 0, i, bi)
+ {
+ bb = BASIC_BLOCK (i);
+ FOR_EACH_EDGE (e, ei, bb->preds)
+ {
+ if (e->aux)
+ {
+ bool have_joiner = THREAD_TARGET2 (e) != NULL;
+
+ if (have_joiner)
+ {
+ basic_block joiner = e->dest;
+ edge final_edge = THREAD_TARGET2 (e);
+ basic_block final_dest = final_edge->dest;
+ edge e2 = find_edge (joiner, final_dest);
+
+ if (e2 && !phi_args_equal_on_edges (e2, final_edge))
+ {
+ free (e->aux);
+ e->aux = NULL;
+ }
+ }
+ }
+ }
+ }
+
/* If optimizing for size, only thread through block if we don't have
to duplicate it or it's an otherwise empty redirection block. */