aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-threadupdate.c
diff options
context:
space:
mode:
authorJeff Law <law@redhat.com>2011-03-28 12:33:42 -0600
committerJeff Law <law@gcc.gnu.org>2011-03-28 12:33:42 -0600
commit520af9ec9a673351b046e06e91d8f66fa70341d2 (patch)
tree6f6e281ff34d399c1d3ec13acccdbbca92243795 /gcc/tree-ssa-threadupdate.c
parent80ec23acbd7c94b82afc2e53506d5bfa2a049fe8 (diff)
downloadgcc-520af9ec9a673351b046e06e91d8f66fa70341d2.zip
gcc-520af9ec9a673351b046e06e91d8f66fa70341d2.tar.gz
gcc-520af9ec9a673351b046e06e91d8f66fa70341d2.tar.bz2
tree-ssa-threadupdate.c (redirect_edges): Call create_edge_and_update_destination_phis as needed.
* tree-ssa-threadupdate.c (redirect_edges): Call create_edge_and_update_destination_phis as needed. (create_edge_and_update_destination_phis): Accept new BB argument. All callers updated. (thread_block): Do not update the profile when threading around intermediate blocks. (thread_single_edge): Likewise. (determine_bb_domination_status): If BB is not a successor of the loop header, return NONDOMINATING. (register_jump_thread): Note when we register a jump thread around an intermediate block. * tree-ssa-threadedge.c (thread_around_empty_block): New function. (thread_across_edge): Use it. * gcc.dg/tree-ssa/ssa-dom-thread-3.c: New test. From-SVN: r171622
Diffstat (limited to 'gcc/tree-ssa-threadupdate.c')
-rw-r--r--gcc/tree-ssa-threadupdate.c38
1 files changed, 27 insertions, 11 deletions
diff --git a/gcc/tree-ssa-threadupdate.c b/gcc/tree-ssa-threadupdate.c
index 951f47e..efbc5ec 100644
--- a/gcc/tree-ssa-threadupdate.c
+++ b/gcc/tree-ssa-threadupdate.c
@@ -304,14 +304,15 @@ lookup_redirection_data (edge e, edge incoming_edge, enum insert_option insert)
destination. */
static void
-create_edge_and_update_destination_phis (struct redirection_data *rd)
+create_edge_and_update_destination_phis (struct redirection_data *rd,
+ basic_block bb)
{
- edge e = make_edge (rd->dup_block, rd->outgoing_edge->dest, EDGE_FALLTHRU);
+ edge e = make_edge (bb, rd->outgoing_edge->dest, EDGE_FALLTHRU);
gimple_stmt_iterator gsi;
rescan_loop_exit (e, true, false);
e->probability = REG_BR_PROB_BASE;
- e->count = rd->dup_block->count;
+ e->count = bb->count;
e->aux = rd->outgoing_edge->aux;
/* If there are any PHI nodes at the destination of the outgoing edge
@@ -359,7 +360,7 @@ create_duplicates (void **slot, void *data)
/* Go ahead and wire up outgoing edges and update PHIs for the duplicate
block. */
- create_edge_and_update_destination_phis (rd);
+ create_edge_and_update_destination_phis (rd, rd->dup_block);
}
/* Keep walking the hash table. */
@@ -380,7 +381,7 @@ fixup_template_block (void **slot, void *data)
and halt the hash table traversal. */
if (rd->dup_block && rd->dup_block == local_info->template_block)
{
- create_edge_and_update_destination_phis (rd);
+ create_edge_and_update_destination_phis (rd, rd->dup_block);
return 0;
}
@@ -443,6 +444,11 @@ redirect_edges (void **slot, void *data)
remove_ctrl_stmt_and_useless_edges (local_info->bb,
rd->outgoing_edge->dest);
+ /* If we are threading beyond the immediate successors of
+ the duplicate, then BB will have no edges, create one. */
+ if (EDGE_COUNT (local_info->bb->succs) == 0)
+ create_edge_and_update_destination_phis (rd, local_info->bb);
+
/* Fixup the flags on the single remaining edge. */
single_succ_edge (local_info->bb)->flags
&= ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE | EDGE_ABNORMAL);
@@ -565,8 +571,9 @@ thread_block (basic_block bb, bool noloop_only)
continue;
}
- update_bb_profile_for_threading (e->dest, EDGE_FREQUENCY (e),
- e->count, (edge) e->aux);
+ if (e->dest == e2->src)
+ update_bb_profile_for_threading (e->dest, EDGE_FREQUENCY (e),
+ e->count, (edge) e->aux);
/* Insert the outgoing edge into the hash table if it is not
already in the hash table. */
@@ -650,12 +657,13 @@ thread_single_edge (edge e)
}
/* Otherwise, we need to create a copy. */
- update_bb_profile_for_threading (bb, EDGE_FREQUENCY (e), e->count, eto);
+ if (e->dest == eto->src)
+ update_bb_profile_for_threading (bb, EDGE_FREQUENCY (e), e->count, eto);
rd.outgoing_edge = eto;
create_block_for_threading (bb, &rd);
- create_edge_and_update_destination_phis (&rd);
+ create_edge_and_update_destination_phis (&rd, rd.dup_block);
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, " Threaded jump %d --> %d to %d\n",
@@ -704,7 +712,9 @@ determine_bb_domination_status (struct loop *loop, basic_block bb)
edge e;
#ifdef ENABLE_CHECKING
- /* This function assumes BB is a successor of LOOP->header. */
+ /* This function assumes BB is a successor of LOOP->header.
+ If that is not the case return DOMST_NONDOMINATING which
+ is always safe. */
{
bool ok = false;
@@ -717,7 +727,8 @@ determine_bb_domination_status (struct loop *loop, basic_block bb)
}
}
- gcc_assert (ok);
+ if (!ok)
+ return DOMST_NONDOMINATING;
}
#endif
@@ -1099,6 +1110,11 @@ register_jump_thread (edge e, edge e2)
if (threaded_edges == NULL)
threaded_edges = VEC_alloc (edge, heap, 10);
+ if (dump_file && (dump_flags & TDF_DETAILS)
+ && e->dest != e2->src)
+ fprintf (dump_file,
+ " Registering jump thread around one or more intermediate blocks\n");
+
VEC_safe_push (edge, heap, threaded_edges, e);
VEC_safe_push (edge, heap, threaded_edges, e2);
}