-----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)