diff options
author | law <law@138bc75d-0d04-0410-961f-82ee72b054a4> | 2011-06-16 21:52:00 +0000 |
---|---|---|
committer | law <law@138bc75d-0d04-0410-961f-82ee72b054a4> | 2011-06-16 21:52:00 +0000 |
commit | da81e0c5ad172c146c1fd22f43e8fb4c5529f4df (patch) | |
tree | 3d01a6665a2ef3a33f6ed1eb847b76b1948a165d /gcc/tree-ssa-threadedge.c | |
parent | 68c979bbd0c9dfc2175007b684d59d67f5fc0bd3 (diff) | |
download | gcc-da81e0c5ad172c146c1fd22f43e8fb4c5529f4df.tar.gz |
* tree-ssa-threadupdate.c (struct redirection_data): New field
intermediate_edge.
(THREAD_TARGET2): Define.
(redirection_data_eq): Also check that the intermediate edge is
equal.
(lookup_redirection_data): Drop useless argument. Extract the
outgoing_edge and intermediate edge from E. Callers updated.
(copy_phi_args, update_destination_phis): New functions.
(fix_duplicate_block_edges): Likewise.
(create_edge_and_update_destination_phis): Duplicate all the edges
hung off e->aux. Use copy_phi_args.
(create_duplicates): Use fix_duplicate_block_edges.
(fixup_template_block): Likewise.
(redirect_edges): If necessary, redirect the joiner block's incoming
edge to the duplicate of the joiner block.
(thread_block): Don't muck up loops when threading through a joiner
block.
(thread_through_loop_header): Handle threading through a joiner
block.
(mark_threaded_blocks, register_jump_thread): Likewise.
* tree-flow.h (register_jump_thread): Add new argument. Callers
updated.
* tree-ssa-threadedge.c (phi_args_equal_on_edges): New function.
(thread_across_edge): Handle threading through a joiner block.
* gcc.dg/builtin-object-size-1.c: Update to handle changes from
improved jump threading.
* gcc.dg/builtin-object-size-2.c: Likewise.
* gcc.dg/tree-ssa/20030728-1.c: Likewise.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@175114 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/tree-ssa-threadedge.c')
-rw-r--r-- | gcc/tree-ssa-threadedge.c | 87 |
1 files changed, 85 insertions, 2 deletions
diff --git a/gcc/tree-ssa-threadedge.c b/gcc/tree-ssa-threadedge.c index 24e63977c29..a485b211e59 100644 --- a/gcc/tree-ssa-threadedge.c +++ b/gcc/tree-ssa-threadedge.c @@ -1,5 +1,5 @@ /* SSA Jump Threading - Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 + Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Contributed by Jeff Law <law@redhat.com> @@ -652,6 +652,27 @@ thread_around_empty_block (edge taken_edge, return NULL; } +/* 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; +} /* We are exiting E->src, see if E->dest ends with a conditional jump which has a known value when reached via E. @@ -770,11 +791,73 @@ thread_across_edge (gimple dummy_cond, } remove_temporary_equivalences (stack); - register_jump_thread (e, taken_edge); + register_jump_thread (e, taken_edge, NULL); return; } } + /* We were unable to determine what out edge from E->dest is taken. However, + we might still be able to thread through successors of E->dest. This + often occurs when E->dest is a joiner block which then fans back out + based on redundant tests. + + If so, we'll copy E->dest and redirect the appropriate predecessor to + the copy. Within the copy of E->dest, we'll thread one or more edges + to points deeper in the CFG. + + This is a stopgap until we have a more structured approach to path + isolation. */ + { + edge e2, e3, taken_edge; + edge_iterator ei; + bool found = false; + bitmap visited = BITMAP_ALLOC (NULL); + + /* Look at each successor of E->dest to see if we can thread through it. */ + FOR_EACH_EDGE (taken_edge, ei, e->dest->succs) + { + /* Avoid threading to any block we have already visited. */ + bitmap_clear (visited); + bitmap_set_bit (visited, taken_edge->dest->index); + bitmap_set_bit (visited, e->dest->index); + + /* Record whether or not we were able to thread through a successor + of E->dest. */ + found = false; + e3 = taken_edge; + do + { + e2 = thread_around_empty_block (e3, + dummy_cond, + handle_dominating_asserts, + simplify, + visited); + if (e2) + { + e3 = e2; + found = true; + } + } + while (e2); + + /* If we were able to thread through a successor of E->dest, then + record the jump threading opportunity. */ + if (found) + { + edge tmp; + /* If there is already an edge from the block to be duplicated + (E2->src) to the final target (E3->dest), then make sure that + the PHI args associated with the edges E2 and E3 are the + same. */ + tmp = find_edge (taken_edge->src, e3->dest); + if (!tmp || phi_args_equal_on_edges (tmp, e3)) + register_jump_thread (e, taken_edge, e3); + } + + } + BITMAP_FREE (visited); + } + fail: remove_temporary_equivalences (stack); } |