tree-ssa-threadupdate.c (THREAD_TARGET): define.

* tree-ssa-threadupdate.c (THREAD_TARGET): define.
	(remove_ctrl_stmt_and_useless_edges): Clear AUX field of outgoing edges.
	(craete_edge_and_update_destination_phis): Use THREAD_TARGET rather
	than accessing AUX field directly.  Free the AUX field before			clearing it.
	(thread_block, thread_through_loop_header): Likewise.
	(thread_single_edge, mark_threaded_blocks): Likewise.
	(redirect_edges): Delay clearing the AUX field.  Free the AUX field.
	(register_jump_thread): Do not attempt to thread to a NULL edge.

From-SVN: r173305
This commit is contained in:
Jeff Law 2011-05-03 07:12:29 -06:00 committed by Jeff Law
parent 2c7eebae8a
commit 7134c090d2
2 changed files with 69 additions and 19 deletions

View File

@ -1,3 +1,14 @@
2011-05-03 Jeff Law <law@redhat.com>
* tree-ssa-threadupdate.c (THREAD_TARGET): define.
(remove_ctrl_stmt_and_useless_edges): Clear AUX field of outgoing edges.
(craete_edge_and_update_destination_phis): Use THREAD_TARGET rather
than accessing AUX field directly. Free the AUX field before clearing it.
(thread_block, thread_through_loop_header): Likewise.
(thread_single_edge, mark_threaded_blocks): Likewise.
(redirect_edges): Delay clearing the AUX field. Free the AUX field.
(register_jump_thread): Do not attempt to thread to a NULL edge.
2011-05-03 Bernd Schmidt <bernds@codesourcery.com>
* function.c (init_function_start): Call decide_function_section.

View File

@ -149,6 +149,10 @@ struct local_info
(original_edge, target_edge). */
static VEC(edge,heap) *threaded_edges;
/* When we start updating the CFG for threading, data necessary for jump
threading is attached to the AUX field for the incoming edge. Use these
macros to access the underlying structure attached to the AUX field. */
#define THREAD_TARGET(E) ((edge *)(E)->aux)[0]
/* Jump threading statistics. */
@ -200,10 +204,16 @@ remove_ctrl_stmt_and_useless_edges (basic_block bb, basic_block dest_bb)
static void
create_block_for_threading (basic_block bb, struct redirection_data *rd)
{
edge_iterator ei;
edge e;
/* We can use the generic block duplication code and simply remove
the stuff we do not need. */
rd->dup_block = duplicate_block (bb, NULL, NULL);
FOR_EACH_EDGE (e, ei, rd->dup_block->succs)
e->aux = NULL;
/* Zero out the profile, since the block is unreachable for now. */
rd->dup_block->frequency = 0;
rd->dup_block->count = 0;
@ -314,7 +324,16 @@ create_edge_and_update_destination_phis (struct redirection_data *rd,
rescan_loop_exit (e, true, false);
e->probability = REG_BR_PROB_BASE;
e->count = bb->count;
e->aux = rd->outgoing_edge->aux;
if (rd->outgoing_edge->aux)
{
e->aux = (edge *) XNEWVEC (edge, 1);
THREAD_TARGET(e) = THREAD_TARGET (rd->outgoing_edge);
}
else
{
e->aux = NULL;
}
/* If there are any PHI nodes at the destination of the outgoing edge
from the duplicate block, then we will need to add a new argument
@ -406,10 +425,6 @@ redirect_edges (void **slot, void *data)
next = el->next;
free (el);
/* Go ahead and clear E->aux. It's not needed anymore and failure
to clear it will cause all kinds of unpleasant problems later. */
e->aux = NULL;
thread_stats.num_threaded_edges++;
if (rd->dup_block)
@ -429,6 +444,12 @@ redirect_edges (void **slot, void *data)
gcc_assert (e == e2);
flush_pending_stmts (e2);
}
/* Go ahead and clear E->aux. It's not needed anymore and failure
to clear it will cause all kinds of unpleasant problems later. */
free (e->aux);
e->aux = NULL;
}
/* Indicate that we actually threaded one or more jumps. */
@ -512,7 +533,11 @@ thread_block (basic_block bb, bool noloop_only)
if (loop->header == bb)
{
e = loop_latch_edge (loop);
e2 = (edge) e->aux;
if (e->aux)
e2 = THREAD_TARGET (e);
else
e2 = NULL;
if (e2 && loop_exit_edge_p (loop, e2))
{
@ -525,19 +550,22 @@ thread_block (basic_block bb, bool noloop_only)
efficient lookups. */
FOR_EACH_EDGE (e, ei, bb->preds)
{
e2 = (edge) e->aux;
if (e->aux == NULL)
continue;
e2 = THREAD_TARGET (e);
if (!e2
/* If NOLOOP_ONLY is true, we only allow threading through the
header of a loop to exit edges. */
|| (noloop_only
&& bb == bb->loop_father->header
&& !loop_exit_edge_p (bb->loop_father, e2)))
&& (!loop_exit_edge_p (bb->loop_father, e2))))
continue;
if (e->dest == e2->src)
update_bb_profile_for_threading (e->dest, EDGE_FREQUENCY (e),
e->count, (edge) e->aux);
e->count, THREAD_TARGET (e));
/* Insert the outgoing edge into the hash table if it is not
already in the hash table. */
@ -582,17 +610,18 @@ thread_block (basic_block bb, bool noloop_only)
return local_info.jumps_threaded;
}
/* Threads edge E through E->dest to the edge E->aux. Returns the copy
of E->dest created during threading, or E->dest if it was not necessary
/* Threads edge E through E->dest to the edge THREAD_TARGET (E). Returns the
copy of E->dest created during threading, or E->dest if it was not necessary
to copy it (E is its single predecessor). */
static basic_block
thread_single_edge (edge e)
{
basic_block bb = e->dest;
edge eto = (edge) e->aux;
edge eto = THREAD_TARGET (e);
struct redirection_data rd;
free (e->aux);
e->aux = NULL;
thread_stats.num_threaded_edges++;
@ -794,7 +823,7 @@ thread_through_loop_header (struct loop *loop, bool may_peel_loop_headers)
if (latch->aux)
{
tgt_edge = (edge) latch->aux;
tgt_edge = THREAD_TARGET (latch);
tgt_bb = tgt_edge->dest;
}
else if (!may_peel_loop_headers
@ -817,7 +846,7 @@ thread_through_loop_header (struct loop *loop, bool may_peel_loop_headers)
goto fail;
}
tgt_edge = (edge) e->aux;
tgt_edge = THREAD_TARGET (e);
atgt_bb = tgt_edge->dest;
if (!tgt_bb)
tgt_bb = atgt_bb;
@ -883,7 +912,7 @@ thread_through_loop_header (struct loop *loop, bool may_peel_loop_headers)
/* Now consider the case entry edges are redirected to the new entry
block. Remember one entry edge, so that we can find the new
preheader (its destination after threading). */
preheader (its destination after threading). */
FOR_EACH_EDGE (e, ei, header->preds)
{
if (e->aux)
@ -915,6 +944,7 @@ fail:
/* We failed to thread anything. Cancel the requests. */
FOR_EACH_EDGE (e, ei, header->preds)
{
free (e->aux);
e->aux = NULL;
}
return false;
@ -946,9 +976,10 @@ mark_threaded_blocks (bitmap threaded_blocks)
for (i = 0; i < VEC_length (edge, threaded_edges); i += 2)
{
edge e = VEC_index (edge, threaded_edges, i);
edge e2 = VEC_index (edge, threaded_edges, i + 1);
edge *x = (edge *) XNEWVEC (edge, 1);
e->aux = e2;
x[0] = VEC_index (edge, threaded_edges, i + 1);
e->aux = x;
bitmap_set_bit (tmp, e->dest->index);
}
@ -963,7 +994,10 @@ mark_threaded_blocks (bitmap threaded_blocks)
&& !redirection_block_p (bb))
{
FOR_EACH_EDGE (e, ei, bb->preds)
e->aux = NULL;
{
free (e->aux);
e->aux = NULL;
}
}
else
bitmap_set_bit (threaded_blocks, i);
@ -1059,8 +1093,13 @@ thread_through_all_blocks (bool may_peel_loop_headers)
void
register_jump_thread (edge e, edge e2)
{
/* This can occur if we're jumping to a constant address or
or something similar. Just get out now. */
if (e2 == NULL)
return;
if (threaded_edges == NULL)
threaded_edges = VEC_alloc (edge, heap, 10);
threaded_edges = VEC_alloc (edge, heap, 15);
if (dump_file && (dump_flags & TDF_DETAILS)
&& e->dest != e2->src)