diff options
author | Jeff Law <law@redhat.com> | 2013-09-17 11:27:41 -0600 |
---|---|---|
committer | Jeff Law <law@gcc.gnu.org> | 2013-09-17 11:27:41 -0600 |
commit | 8d34e421a5668e25a992bd0b349cb81e91ee3e49 (patch) | |
tree | 94bfe22f7d19095ab53bd28cb6fb75e78e2f9196 /gcc/tree-ssa-threadupdate.c | |
parent | c152901f5e1082de4ede3bc98c7ede2dea361e8d (diff) | |
download | gcc-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.c | 62 |
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. */ |