00001 /* Thread edges through blocks and update the control flow and SSA graphs. 00002 Copyright (C) 2004, 2005 Free Software Foundation, Inc. 00003 00004 This file is part of GCC. 00005 00006 GCC is free software; you can redistribute it and/or modify 00007 it under the terms of the GNU General Public License as published by 00008 the Free Software Foundation; either version 2, or (at your option) 00009 any later version. 00010 00011 GCC is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 GNU General Public License for more details. 00015 00016 You should have received a copy of the GNU General Public License 00017 along with GCC; see the file COPYING. If not, write to 00018 the Free Software Foundation, 59 Temple Place - Suite 330, 00019 Boston, MA 02111-1307, USA. */ 00020 00021 #include "config.h" 00022 #include "system.h" 00023 #include "coretypes.h" 00024 #include "tm.h" 00025 #include "tree.h" 00026 #include "flags.h" 00027 #include "rtl.h" 00028 #include "tm_p.h" 00029 #include "ggc.h" 00030 #include "basic-block.h" 00031 #include "output.h" 00032 #include "errors.h" 00033 #include "expr.h" 00034 #include "function.h" 00035 #include "diagnostic.h" 00036 #include "tree-flow.h" 00037 #include "tree-dump.h" 00038 #include "tree-pass.h" 00039 00040 /* Given a block B, update the CFG and SSA graph to reflect redirecting 00041 one or more in-edges to B to instead reach the destination of an 00042 out-edge from B while preserving any side effects in B. 00043 00044 i.e., given A->B and B->C, change A->B to be A->C yet still preserve the 00045 side effects of executing B. 00046 00047 1. Make a copy of B (including its outgoing edges and statements). Call 00048 the copy B'. Note B' has no incoming edges or PHIs at this time. 00049 00050 2. Remove the control statement at the end of B' and all outgoing edges 00051 except B'->C. 00052 00053 3. Add a new argument to each PHI in C with the same value as the existing 00054 argument associated with edge B->C. Associate the new PHI arguments 00055 with the edge B'->C. 00056 00057 4. For each PHI in B, find or create a PHI in B' with an identical 00058 PHI_RESULT. Add an argument to the PHI in B' which has the same 00059 value as the PHI in B associated with the edge A->B. Associate 00060 the new argument in the PHI in B' with the edge A->B. 00061 00062 5. Change the edge A->B to A->B'. 00063 00064 5a. This automatically deletes any PHI arguments associated with the 00065 edge A->B in B. 00066 00067 5b. This automatically associates each new argument added in step 4 00068 with the edge A->B'. 00069 00070 6. Repeat for other incoming edges into B. 00071 00072 7. Put the duplicated resources in B and all the B' blocks into SSA form. 00073 00074 Note that block duplication can be minimized by first collecting the 00075 the set of unique destination blocks that the incoming edges should 00076 be threaded to. Block duplication can be further minimized by using 00077 B instead of creating B' for one destination if all edges into B are 00078 going to be threaded to a successor of B. 00079 00080 We further reduce the number of edges and statements we create by 00081 not copying all the outgoing edges and the control statement in 00082 step #1. We instead create a template block without the outgoing 00083 edges and duplicate the template. */ 00084 00085 00086 /* Steps #5 and #6 of the above algorithm are best implemented by walking 00087 all the incoming edges which thread to the same destination edge at 00088 the same time. That avoids lots of table lookups to get information 00089 for the destination edge. 00090 00091 To realize that implementation we create a list of incoming edges 00092 which thread to the same outgoing edge. Thus to implement steps 00093 #5 and #6 we traverse our hash table of outgoing edge information. 00094 For each entry we walk the list of incoming edges which thread to 00095 the current outgoing edge. */ 00096 00097 struct el 00098 { 00099 edge e; 00100 struct el *next; 00101 }; 00102 00103 /* Main data structure recording information regarding B's duplicate 00104 blocks. */ 00105 00106 /* We need to efficiently record the unique thread destinations of this 00107 block and specific information associated with those destinations. We 00108 may have many incoming edges threaded to the same outgoing edge. This 00109 can be naturally implemented with a hash table. */ 00110 00111 struct redirection_data 00112 { 00113 /* A duplicate of B with the trailing control statement removed and which 00114 targets a single successor of B. */ 00115 basic_block dup_block; 00116 00117 /* An outgoing edge from B. DUP_BLOCK will have OUTGOING_EDGE->dest as 00118 its single successor. */ 00119 edge outgoing_edge; 00120 00121 /* A list of incoming edges which we want to thread to 00122 OUTGOING_EDGE->dest. */ 00123 struct el *incoming_edges; 00124 00125 /* Flag indicating whether or not we should create a duplicate block 00126 for this thread destination. This is only true if we are threading 00127 all incoming edges and thus are using BB itself as a duplicate block. */ 00128 bool do_not_duplicate; 00129 }; 00130 00131 /* Main data structure to hold information for duplicates of BB. */ 00132 static htab_t redirection_data; 00133 00134 /* Data structure of information to pass to hash table traversal routines. */ 00135 struct local_info 00136 { 00137 /* The current block we are working on. */ 00138 basic_block bb; 00139 00140 /* A template copy of BB with no outgoing edges or control statement that 00141 we use for creating copies. */ 00142 basic_block template_block; 00143 }; 00144 00145 /* Remove the last statement in block BB if it is a control statement 00146 Also remove all outgoing edges except the edge which reaches DEST_BB. 00147 If DEST_BB is NULL, then remove all outgoing edges. */ 00148 00149 static void 00150 remove_ctrl_stmt_and_useless_edges (basic_block bb, basic_block dest_bb) 00151 { 00152 block_stmt_iterator bsi; 00153 edge e; 00154 edge_iterator ei; 00155 00156 bsi = bsi_last (bb); 00157 00158 /* If the duplicate ends with a control statement, then remove it. 00159 00160 Note that if we are duplicating the template block rather than the 00161 original basic block, then the duplicate might not have any real 00162 statements in it. */ 00163 if (!bsi_end_p (bsi) 00164 && bsi_stmt (bsi) 00165 && (TREE_CODE (bsi_stmt (bsi)) == COND_EXPR 00166 || TREE_CODE (bsi_stmt (bsi)) == SWITCH_EXPR)) 00167 bsi_remove (&bsi); 00168 00169 for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); ) 00170 { 00171 if (e->dest != dest_bb) 00172 remove_edge (e); 00173 else 00174 ei_next (&ei); 00175 } 00176 } 00177 00178 /* Create a duplicate of BB which only reaches the destination of the edge 00179 stored in RD. Record the duplicate block in RD. */ 00180 00181 static void 00182 create_block_for_threading (basic_block bb, struct redirection_data *rd) 00183 { 00184 /* We can use the generic block duplication code and simply remove 00185 the stuff we do not need. */ 00186 rd->dup_block = duplicate_block (bb, NULL); 00187 00188 /* Zero out the profile, since the block is unreachable for now. */ 00189 rd->dup_block->frequency = 0; 00190 rd->dup_block->count = 0; 00191 00192 /* The call to duplicate_block will copy everything, including the 00193 useless COND_EXPR or SWITCH_EXPR at the end of BB. We just remove 00194 the useless COND_EXPR or SWITCH_EXPR here rather than having a 00195 specialized block copier. We also remove all outgoing edges 00196 from the duplicate block. The appropriate edge will be created 00197 later. */ 00198 remove_ctrl_stmt_and_useless_edges (rd->dup_block, NULL); 00199 } 00200 00201 /* Hashing and equality routines for our hash table. */ 00202 static hashval_t 00203 redirection_data_hash (const void *p) 00204 { 00205 edge e = ((struct redirection_data *)p)->outgoing_edge; 00206 return e->dest->index; 00207 } 00208 00209 static int 00210 redirection_data_eq (const void *p1, const void *p2) 00211 { 00212 edge e1 = ((struct redirection_data *)p1)->outgoing_edge; 00213 edge e2 = ((struct redirection_data *)p2)->outgoing_edge; 00214 00215 return e1 == e2; 00216 } 00217 00218 /* Given an outgoing edge E lookup and return its entry in our hash table. 00219 00220 If INSERT is true, then we insert the entry into the hash table if 00221 it is not already present. INCOMING_EDGE is added to the list of incoming 00222 edges associated with E in the hash table. */ 00223 00224 static struct redirection_data * 00225 lookup_redirection_data (edge e, edge incoming_edge, bool insert) 00226 { 00227 void **slot; 00228 struct redirection_data *elt; 00229 00230 /* Build a hash table element so we can see if E is already 00231 in the table. */ 00232 elt = xmalloc (sizeof (struct redirection_data)); 00233 elt->outgoing_edge = e; 00234 elt->dup_block = NULL; 00235 elt->do_not_duplicate = false; 00236 elt->incoming_edges = NULL; 00237 00238 slot = htab_find_slot (redirection_data, elt, insert); 00239 00240 /* This will only happen if INSERT is false and the entry is not 00241 in the hash table. */ 00242 if (slot == NULL) 00243 { 00244 free (elt); 00245 return NULL; 00246 } 00247 00248 /* This will only happen if E was not in the hash table and 00249 INSERT is true. */ 00250 if (*slot == NULL) 00251 { 00252 *slot = (void *)elt; 00253 elt->incoming_edges = xmalloc (sizeof (struct el)); 00254 elt->incoming_edges->e = incoming_edge; 00255 elt->incoming_edges->next = NULL; 00256 return elt; 00257 } 00258 /* E was in the hash table. */ 00259 else 00260 { 00261 /* Free ELT as we do not need it anymore, we will extract the 00262 relevant entry from the hash table itself. */ 00263 free (elt); 00264 00265 /* Get the entry stored in the hash table. */ 00266 elt = (struct redirection_data *) *slot; 00267 00268 /* If insertion was requested, then we need to add INCOMING_EDGE 00269 to the list of incoming edges associated with E. */ 00270 if (insert) 00271 { 00272 struct el *el = xmalloc (sizeof (struct el)); 00273 el->next = elt->incoming_edges; 00274 el->e = incoming_edge; 00275 elt->incoming_edges = el; 00276 } 00277 00278 return elt; 00279 } 00280 } 00281 00282 /* Given a duplicate block and its single destination (both stored 00283 in RD). Create an edge between the duplicate and its single 00284 destination. 00285 00286 Add an additional argument to any PHI nodes at the single 00287 destination. */ 00288 00289 static void 00290 create_edge_and_update_destination_phis (struct redirection_data *rd) 00291 { 00292 edge e = make_edge (rd->dup_block, rd->outgoing_edge->dest, EDGE_FALLTHRU); 00293 tree phi; 00294 00295 /* If there are any PHI nodes at the destination of the outgoing edge 00296 from the duplicate block, then we will need to add a new argument 00297 to them. The argument should have the same value as the argument 00298 associated with the outgoing edge stored in RD. */ 00299 for (phi = phi_nodes (e->dest); phi; phi = PHI_CHAIN (phi)) 00300 { 00301 int indx = rd->outgoing_edge->dest_idx; 00302 add_phi_arg (phi, PHI_ARG_DEF_TREE (phi, indx), e); 00303 } 00304 } 00305 00306 /* Hash table traversal callback routine to create duplicate blocks. */ 00307 00308 static int 00309 create_duplicates (void **slot, void *data) 00310 { 00311 struct redirection_data *rd = (struct redirection_data *) *slot; 00312 struct local_info *local_info = (struct local_info *)data; 00313 00314 /* If this entry should not have a duplicate created, then there's 00315 nothing to do. */ 00316 if (rd->do_not_duplicate) 00317 return 1; 00318 00319 /* Create a template block if we have not done so already. Otherwise 00320 use the template to create a new block. */ 00321 if (local_info->template_block == NULL) 00322 { 00323 create_block_for_threading (local_info->bb, rd); 00324 local_info->template_block = rd->dup_block; 00325 00326 /* We do not create any outgoing edges for the template. We will 00327 take care of that in a later traversal. That way we do not 00328 create edges that are going to just be deleted. */ 00329 } 00330 else 00331 { 00332 create_block_for_threading (local_info->template_block, rd); 00333 00334 /* Go ahead and wire up outgoing edges and update PHIs for the duplicate 00335 block. */ 00336 create_edge_and_update_destination_phis (rd); 00337 } 00338 00339 /* Keep walking the hash table. */ 00340 return 1; 00341 } 00342 00343 /* We did not create any outgoing edges for the template block during 00344 block creation. This hash table traversal callback creates the 00345 outgoing edge for the template block. */ 00346 00347 static int 00348 fixup_template_block (void **slot, void *data) 00349 { 00350 struct redirection_data *rd = (struct redirection_data *) *slot; 00351 struct local_info *local_info = (struct local_info *)data; 00352 00353 /* If this is the template block, then create its outgoing edges 00354 and halt the hash table traversal. */ 00355 if (rd->dup_block && rd->dup_block == local_info->template_block) 00356 { 00357 create_edge_and_update_destination_phis (rd); 00358 return 0; 00359 } 00360 00361 return 1; 00362 } 00363 00364 /* Hash table traversal callback to redirect each incoming edge 00365 associated with this hash table element to its new destination. */ 00366 00367 static int 00368 redirect_edges (void **slot, void *data) 00369 { 00370 struct redirection_data *rd = (struct redirection_data *) *slot; 00371 struct local_info *local_info = (struct local_info *)data; 00372 struct el *next, *el; 00373 00374 /* Walk over all the incoming edges associated associated with this 00375 hash table entry. */ 00376 for (el = rd->incoming_edges; el; el = next) 00377 { 00378 edge e = el->e; 00379 00380 /* Go ahead and free this element from the list. Doing this now 00381 avoids the need for another list walk when we destroy the hash 00382 table. */ 00383 next = el->next; 00384 free (el); 00385 00386 /* Go ahead and clear E->aux. It's not needed anymore and failure 00387 to clear it will cause all kinds of unpleasant problems later. */ 00388 e->aux = NULL; 00389 00390 if (rd->dup_block) 00391 { 00392 edge e2; 00393 00394 if (dump_file && (dump_flags & TDF_DETAILS)) 00395 fprintf (dump_file, " Threaded jump %d --> %d to %d\n", 00396 e->src->index, e->dest->index, rd->dup_block->index); 00397 00398 /* Redirect the incoming edge to the appropriate duplicate 00399 block. */ 00400 e2 = redirect_edge_and_branch (e, rd->dup_block); 00401 flush_pending_stmts (e2); 00402 00403 if ((dump_file && (dump_flags & TDF_DETAILS)) 00404 && e->src != e2->src) 00405 fprintf (dump_file, " basic block %d created\n", e2->src->index); 00406 } 00407 else 00408 { 00409 if (dump_file && (dump_flags & TDF_DETAILS)) 00410 fprintf (dump_file, " Threaded jump %d --> %d to %d\n", 00411 e->src->index, e->dest->index, local_info->bb->index); 00412 00413 /* We are using BB as the duplicate. Remove the unnecessary 00414 outgoing edges and statements from BB. */ 00415 remove_ctrl_stmt_and_useless_edges (local_info->bb, 00416 rd->outgoing_edge->dest); 00417 00418 /* And fixup the flags on the single remaining edge. */ 00419 EDGE_SUCC (local_info->bb, 0)->flags 00420 &= ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE); 00421 EDGE_SUCC (local_info->bb, 0)->flags |= EDGE_FALLTHRU; 00422 } 00423 } 00424 return 1; 00425 } 00426 00427 /* BB is a block which ends with a COND_EXPR or SWITCH_EXPR and when BB 00428 is reached via one or more specific incoming edges, we know which 00429 outgoing edge from BB will be traversed. 00430 00431 We want to redirect those incoming edges to the target of the 00432 appropriate outgoing edge. Doing so avoids a conditional branch 00433 and may expose new optimization opportunities. Note that we have 00434 to update dominator tree and SSA graph after such changes. 00435 00436 The key to keeping the SSA graph update manageable is to duplicate 00437 the side effects occurring in BB so that those side effects still 00438 occur on the paths which bypass BB after redirecting edges. 00439 00440 We accomplish this by creating duplicates of BB and arranging for 00441 the duplicates to unconditionally pass control to one specific 00442 successor of BB. We then revector the incoming edges into BB to 00443 the appropriate duplicate of BB. 00444 00445 BB and its duplicates will have assignments to the same set of 00446 SSA_NAMEs. Right now, we just call into rewrite_ssa_into_ssa 00447 to update the SSA graph for those names. 00448 00449 We are also going to experiment with a true incremental update 00450 scheme for the duplicated resources. One of the interesting 00451 properties we can exploit here is that all the resources set 00452 in BB will have the same IDFS, so we have one IDFS computation 00453 per block with incoming threaded edges, which can lower the 00454 cost of the true incremental update algorithm. */ 00455 00456 static void 00457 thread_block (basic_block bb) 00458 { 00459 /* E is an incoming edge into BB that we may or may not want to 00460 redirect to a duplicate of BB. */ 00461 edge e; 00462 edge_iterator ei; 00463 struct local_info local_info; 00464 00465 /* ALL indicates whether or not all incoming edges into BB should 00466 be threaded to a duplicate of BB. */ 00467 bool all = true; 00468 00469 /* To avoid scanning a linear array for the element we need we instead 00470 use a hash table. For normal code there should be no noticeable 00471 difference. However, if we have a block with a large number of 00472 incoming and outgoing edges such linear searches can get expensive. */ 00473 redirection_data = htab_create (EDGE_COUNT (bb->succs), 00474 redirection_data_hash, 00475 redirection_data_eq, 00476 free); 00477 00478 /* Record each unique threaded destination into a hash table for 00479 efficient lookups. */ 00480 FOR_EACH_EDGE (e, ei, bb->preds) 00481 { 00482 if (!e->aux) 00483 { 00484 all = false; 00485 } 00486 else 00487 { 00488 edge e2 = e->aux; 00489 00490 /* Insert the outgoing edge into the hash table if it is not 00491 already in the hash table. */ 00492 lookup_redirection_data (e2, e, true); 00493 } 00494 } 00495 00496 /* If we are going to thread all incoming edges to an outgoing edge, then 00497 BB will become unreachable. Rather than just throwing it away, use 00498 it for one of the duplicates. Mark the first incoming edge with the 00499 DO_NOT_DUPLICATE attribute. */ 00500 if (all) 00501 { 00502 edge e = EDGE_PRED (bb, 0)->aux; 00503 lookup_redirection_data (e, NULL, false)->do_not_duplicate = true; 00504 } 00505 00506 /* Now create duplicates of BB. 00507 00508 Note that for a block with a high outgoing degree we can waste 00509 a lot of time and memory creating and destroying useless edges. 00510 00511 So we first duplicate BB and remove the control structure at the 00512 tail of the duplicate as well as all outgoing edges from the 00513 duplicate. We then use that duplicate block as a template for 00514 the rest of the duplicates. */ 00515 local_info.template_block = NULL; 00516 local_info.bb = bb; 00517 htab_traverse (redirection_data, create_duplicates, &local_info); 00518 00519 /* The template does not have an outgoing edge. Create that outgoing 00520 edge and update PHI nodes as the edge's target as necessary. 00521 00522 We do this after creating all the duplicates to avoid creating 00523 unnecessary edges. */ 00524 htab_traverse (redirection_data, fixup_template_block, &local_info); 00525 00526 /* The hash table traversals above created the duplicate blocks (and the 00527 statements within the duplicate blocks). This loop creates PHI nodes for 00528 the duplicated blocks and redirects the incoming edges into BB to reach 00529 the duplicates of BB. */ 00530 htab_traverse (redirection_data, redirect_edges, &local_info); 00531 00532 /* Done with this block. Clear REDIRECTION_DATA. */ 00533 htab_delete (redirection_data); 00534 redirection_data = NULL; 00535 } 00536 00537 /* Walk through all blocks and thread incoming edges to the block's 00538 destinations as requested. This is the only entry point into this 00539 file. 00540 00541 Blocks which have one or more incoming edges have INCOMING_EDGE_THREADED 00542 set in the block's annotation. 00543 00544 Each edge that should be threaded has the new destination edge stored in 00545 the original edge's AUX field. 00546 00547 This routine (or one of its callees) will clear INCOMING_EDGE_THREADED 00548 in the block annotations and the AUX field in the edges. 00549 00550 It is the caller's responsibility to fix the dominance information 00551 and rewrite duplicated SSA_NAMEs back into SSA form. 00552 00553 Returns true if one or more edges were threaded, false otherwise. */ 00554 00555 bool 00556 thread_through_all_blocks (void) 00557 { 00558 basic_block bb; 00559 bool retval = false; 00560 00561 FOR_EACH_BB (bb) 00562 { 00563 if (bb_ann (bb)->incoming_edge_threaded 00564 && EDGE_COUNT (bb->preds) > 0) 00565 { 00566 thread_block (bb); 00567 retval = true; 00568 bb_ann (bb)->incoming_edge_threaded = false; 00569 } 00570 } 00571 return retval; 00572 }
1.5.6