(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. */
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;
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
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)
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. */
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))
{
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. */
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++;
if (latch->aux)
{
- tgt_edge = (edge) latch->aux;
+ tgt_edge = THREAD_TARGET (latch);
tgt_bb = tgt_edge->dest;
}
else if (!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;
/* 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)
/* We failed to thread anything. Cancel the requests. */
FOR_EACH_EDGE (e, ei, header->preds)
{
+ free (e->aux);
e->aux = NULL;
}
return false;
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);
}
&& !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);
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)