-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
On 05/02/11 15:18, Richard Guenther wrote:
>
>> For (edge *)xmalloc (sizeof (edge) * 1) use XNEWVEC and friends.
>> I wonder if it makes sense to use a VEC instead (will the vector
>> be of variable size?). Maybe wrap accesses to e->aux with
>> a macro or some inline functions.
>
>> Ok with the allocation change.
Attached is the actual patch I checked in. I found a minor goof in the
stats reporting which I fixed, in addition to the stuff Richard pointed out.
Bootstrapped and regression tested on x86_64-unknown-linux-gnu
Jeff
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)
Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org/
iQEcBAEBAgAGBQJNwABQAAoJEBRtltQi2kC7yUkH/3RkOHjEqrTz6C/fnapNQYKx
D/Ts9p7zlIsm66+cVpbM8z2+884QOEv0TjVqd7uDo7/vg9cKw7xRMbNI6+IZTM/H
NdFweso3rC2nZZhqNn0DBkczo7RZcdMhR0DGkpd+xGZBSE4L6gw6W9+3YJ70BZZo
KLuZ0PiYmPcuJEN00O0zmypiVX7z04tvCSSLxPbXT/sHU6odNWvUAdEZhKX6nJ2r
/FljdonBdLbdwEdVoRycZ64F6TrF66zaS2EKWgtdhe9PP6hQ/ovUoyXT5LwkRxDv
VvmLRx/6D1xyDmLus9D41016k9Iog4gn4Kfb9taaX57KkiCfBgyhaQgbOoIZNVM=
=z/nF
-----END PGP SIGNATURE-----
* 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.
Index: tree-ssa-threadupdate.c
===================================================================
*** tree-ssa-threadupdate.c (revision 173302)
--- tree-ssa-threadupdate.c (working copy)
*************** struct local_info
*** 149,154 ****
--- 149,158 ----
(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. */
*************** remove_ctrl_stmt_and_useless_edges (basi
*** 200,209 ****
--- 204,219 ----
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;
*************** create_edge_and_update_destination_phis
*** 314,320 ****
rescan_loop_exit (e, true, false);
e->probability = REG_BR_PROB_BASE;
e->count = bb->count;
! e->aux = rd->outgoing_edge->aux;
/* 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
--- 324,339 ----
rescan_loop_exit (e, true, false);
e->probability = REG_BR_PROB_BASE;
e->count = bb->count;
!
! 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
*************** redirect_edges (void **slot, void *data)
*** 406,415 ****
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)
--- 425,430 ----
*************** redirect_edges (void **slot, void *data)
*** 429,434 ****
--- 444,455 ----
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. */
*************** thread_block (basic_block bb, bool noloo
*** 512,518 ****
if (loop->header == bb)
{
e = loop_latch_edge (loop);
! e2 = (edge) e->aux;
if (e2 && loop_exit_edge_p (loop, e2))
{
--- 533,543 ----
if (loop->header == bb)
{
e = loop_latch_edge (loop);
!
! if (e->aux)
! e2 = THREAD_TARGET (e);
! else
! e2 = NULL;
if (e2 && loop_exit_edge_p (loop, e2))
{
*************** thread_block (basic_block bb, bool noloo
*** 525,543 ****
efficient lookups. */
FOR_EACH_EDGE (e, ei, bb->preds)
{
! e2 = (edge) e->aux;
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)))
continue;
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. */
--- 550,571 ----
efficient lookups. */
FOR_EACH_EDGE (e, ei, bb->preds)
{
! 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))))
continue;
if (e->dest == e2->src)
update_bb_profile_for_threading (e->dest, EDGE_FREQUENCY (e),
! e->count, THREAD_TARGET (e));
/* Insert the outgoing edge into the hash table if it is not
already in the hash table. */
*************** thread_block (basic_block bb, bool noloo
*** 582,598 ****
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
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;
struct redirection_data rd;
e->aux = NULL;
thread_stats.num_threaded_edges++;
--- 610,627 ----
return local_info.jumps_threaded;
}
! /* 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 = THREAD_TARGET (e);
struct redirection_data rd;
+ free (e->aux);
e->aux = NULL;
thread_stats.num_threaded_edges++;
*************** thread_through_loop_header (struct loop
*** 794,800 ****
if (latch->aux)
{
! tgt_edge = (edge) latch->aux;
tgt_bb = tgt_edge->dest;
}
else if (!may_peel_loop_headers
--- 823,829 ----
if (latch->aux)
{
! tgt_edge = THREAD_TARGET (latch);
tgt_bb = tgt_edge->dest;
}
else if (!may_peel_loop_headers
*************** thread_through_loop_header (struct loop
*** 817,823 ****
goto fail;
}
! tgt_edge = (edge) e->aux;
atgt_bb = tgt_edge->dest;
if (!tgt_bb)
tgt_bb = atgt_bb;
--- 846,852 ----
goto fail;
}
! tgt_edge = THREAD_TARGET (e);
atgt_bb = tgt_edge->dest;
if (!tgt_bb)
tgt_bb = atgt_bb;
*************** thread_through_loop_header (struct loop
*** 883,889 ****
/* 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). */
FOR_EACH_EDGE (e, ei, header->preds)
{
if (e->aux)
--- 912,918 ----
/* 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). */
FOR_EACH_EDGE (e, ei, header->preds)
{
if (e->aux)
*************** fail:
*** 915,920 ****
--- 944,950 ----
/* We failed to thread anything. Cancel the requests. */
FOR_EACH_EDGE (e, ei, header->preds)
{
+ free (e->aux);
e->aux = NULL;
}
return false;
*************** mark_threaded_blocks (bitmap threaded_bl
*** 946,954 ****
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);
! e->aux = e2;
bitmap_set_bit (tmp, e->dest->index);
}
--- 976,985 ----
for (i = 0; i < VEC_length (edge, threaded_edges); i += 2)
{
edge e = VEC_index (edge, threaded_edges, i);
! edge *x = (edge *) XNEWVEC (edge, 1);
! x[0] = VEC_index (edge, threaded_edges, i + 1);
! e->aux = x;
bitmap_set_bit (tmp, e->dest->index);
}
*************** mark_threaded_blocks (bitmap threaded_bl
*** 963,969 ****
&& !redirection_block_p (bb))
{
FOR_EACH_EDGE (e, ei, bb->preds)
! e->aux = NULL;
}
else
bitmap_set_bit (threaded_blocks, i);
--- 994,1003 ----
&& !redirection_block_p (bb))
{
FOR_EACH_EDGE (e, ei, bb->preds)
! {
! free (e->aux);
! e->aux = NULL;
! }
}
else
bitmap_set_bit (threaded_blocks, i);
*************** thread_through_all_blocks (bool may_peel
*** 1059,1066 ****
void
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)
--- 1093,1105 ----
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, 15);
if (dump_file && (dump_flags & TDF_DETAILS)
&& e->dest != e2->src)