#include "config.h"#include "system.h"#include "coretypes.h"#include "tm.h"#include "tree.h"#include "rtl.h"#include "varray.h"#include "ggc.h"#include "basic-block.h"#include "tree-flow.h"#include "toplev.h"#include "gt-tree-phinodes.h"Include dependency graph for tree-phinodes.c:

Go to the source code of this file.
Defines | |
| #define | NUM_BUCKETS 10 |
Functions | |
| static int | ideal_phi_node_len (int) |
| static void | resize_phi_node (tree *, int) |
| void | init_phinodes () |
| void | fini_phinodes () |
| static tree | allocate_phi_node () |
| static int | ideal_phi_node_len () |
| static tree | make_phi_node () |
| void | release_phi_node () |
| static void | resize_phi_node () |
| void | reserve_phi_args_for_new_edge () |
| tree | create_phi_node () |
| void | add_phi_arg () |
| static void | remove_phi_arg_num () |
| void | remove_phi_args () |
| void | remove_phi_node () |
| tree | phi_reverse () |
Variables | |
| static tree | free_phinodes [NUM_BUCKETS-2] |
| static unsigned long | free_phinode_count |
|
|
Rewriting a function into SSA form can create a huge number of PHIs many of which may be thrown away shortly after their creation if jumps were threaded through PHI nodes. While our garbage collection mechanisms will handle this situation, it is extremely wasteful to create nodes and throw them away, especially when the nodes can be reused. For PR 8361, we can significantly reduce the number of nodes allocated and thus the total amount of memory allocated by managing PHIs a little. This additionally helps reduce the amount of work done by the garbage collector. Similar results have been seen on a wider variety of tests (such as the compiler itself). Right now we maintain our free list on a per-function basis. It may or may not make sense to maintain the free list for the duration of a compilation unit. We could also use a zone allocator for these objects since they have a very well defined lifetime. If someone wants to experiment with that this is the place to try it. PHI nodes have different sizes, so we can't have a single list of all the PHI nodes as it would be too expensive to walk down that list to find a PHI of a suitable size. Instead we have an array of lists of free PHI nodes. The array is indexed by the number of PHI alternatives that PHI node can hold. Except for the last array member, which holds all remaining PHI nodes. So to find a free PHI node, we compute its index into the free PHI node array and see if there are any elements with an exact match. If so, then we are done. Otherwise, we test the next larger size up and continue until we are in the last array element. We do not actually walk members of the last array element. While it might allow us to pick up a few reusable PHI nodes, it could potentially be very expensive if the program has released a bunch of large PHI nodes, but keeps asking for even larger PHI nodes. Experiments have shown that walking the elements of the last array entry would result in finding less than .1% additional reusable PHI nodes. Note that we can never have less than two PHI argument slots. Thus, the -2 on all the calculations below. Definition at line 79 of file tree-phinodes.c. |
|
|
Add a new argument to PHI node PHI. DEF is the incoming reaching definition and E is the edge through which DEF reaches PHI. The new argument is added at the end of the argument list. If PHI has reached its maximum capacity, add a few slots. In this case, PHI points to the reallocated phi node when we return. Definition at line 372 of file tree-phinodes.c. References bb_for_stmt(), PHI_ARG_CAPACITY, PHI_NUM_ARGS, PHI_RESULT, SET_PHI_ARG_DEF, and SSA_NAME_OCCURS_IN_ABNORMAL_PHI. 00373 { 00374 basic_block bb = e->dest; 00375 00376 gcc_assert (bb == bb_for_stmt (phi)); 00377 00378 /* We resize PHI nodes upon edge creation. We should always have 00379 enough room at this point. */ 00380 gcc_assert (PHI_NUM_ARGS (phi) <= PHI_ARG_CAPACITY (phi)); 00381 00382 /* We resize PHI nodes upon edge creation. We should always have 00383 enough room at this point. */ 00384 gcc_assert (e->dest_idx < (unsigned int) PHI_NUM_ARGS (phi)); 00385 00386 /* Copy propagation needs to know what object occur in abnormal 00387 PHI nodes. This is a convenient place to record such information. */ 00388 if (e->flags & EDGE_ABNORMAL) 00389 { 00390 SSA_NAME_OCCURS_IN_ABNORMAL_PHI (def) = 1; 00391 SSA_NAME_OCCURS_IN_ABNORMAL_PHI (PHI_RESULT (phi)) = 1; 00392 } 00393 00394 SET_PHI_ARG_DEF (phi, e->dest_idx, def); 00395 }
|
|
|
Allocate a PHI node with at least LEN arguments. If the free list happens to contain a PHI node with LEN arguments or more, return that one. Definition at line 131 of file tree-phinodes.c. References free_phinodes, PHI_ARG_CAPACITY, and PHI_CHAIN. Referenced by make_phi_node(), and resize_phi_node(). 00132 { 00133 tree phi; 00134 int bucket = NUM_BUCKETS - 2; 00135 int size = (sizeof (struct tree_phi_node) 00136 + (len - 1) * sizeof (struct phi_arg_d)); 00137 00138 if (free_phinode_count) 00139 for (bucket = len - 2; bucket < NUM_BUCKETS - 2; bucket++) 00140 if (free_phinodes[bucket]) 00141 break; 00142 00143 /* If our free list has an element, then use it. */ 00144 if (bucket < NUM_BUCKETS - 2 00145 && PHI_ARG_CAPACITY (free_phinodes[bucket]) >= len) 00146 { 00147 free_phinode_count--; 00148 phi = free_phinodes[bucket]; 00149 free_phinodes[bucket] = PHI_CHAIN (free_phinodes[bucket]); 00150 #ifdef GATHER_STATISTICS 00151 phi_nodes_reused++; 00152 #endif 00153 } 00154 else 00155 { 00156 phi = ggc_alloc (size); 00157 #ifdef GATHER_STATISTICS 00158 phi_nodes_created++; 00159 tree_node_counts[(int) phi_kind]++; 00160 tree_node_sizes[(int) phi_kind] += size; 00161 #endif 00162 } 00163 00164 return phi; 00165 }
|
|
|
Create a new PHI node for variable VAR at basic block BB. Definition at line 349 of file tree-phinodes.c. References make_phi_node(), PHI_CHAIN, phi_nodes(), and set_bb_for_stmt(). 00350 { 00351 tree phi; 00352 00353 phi = make_phi_node (var, EDGE_COUNT (bb->preds)); 00354 00355 /* Add the new PHI node to the list of PHI nodes for block BB. */ 00356 PHI_CHAIN (phi) = phi_nodes (bb); 00357 bb->phi_nodes = phi; 00358 00359 /* Associate BB to the PHI node. */ 00360 set_bb_for_stmt (phi, bb); 00361 00362 return phi; 00363 }
|
|
|
Finalize management of PHIs. Definition at line 106 of file tree-phinodes.c. References free_phinodes. 00107 { 00108 int i; 00109 00110 for (i = 0; i < NUM_BUCKETS - 2; i++) 00111 free_phinodes[i] = NULL; 00112 free_phinode_count = 0; 00113 }
|
|
|
Given LEN, the original number of requested PHI arguments, return a new, "ideal" length for the PHI node. The "ideal" length rounds the total size of the PHI node up to the next power of two bytes. Rounding up will not result in wasting any memory since the size request will be rounded up by the GC system anyway. [ Note this is not entirely true since the original length might have fit on one of the special GC pages. ] By rounding up, we may avoid the need to reallocate the PHI node later if we increase the number of arguments for the PHI. Definition at line 178 of file tree-phinodes.c. 00179 { 00180 size_t size, new_size; 00181 int log2, new_len; 00182 00183 /* We do not support allocations of less than two PHI argument slots. */ 00184 if (len < 2) 00185 len = 2; 00186 00187 /* Compute the number of bytes of the original request. */ 00188 size = sizeof (struct tree_phi_node) + (len - 1) * sizeof (struct phi_arg_d); 00189 00190 /* Round it up to the next power of two. */ 00191 log2 = ceil_log2 (size); 00192 new_size = 1 << log2; 00193 00194 /* Now compute and return the number of PHI argument slots given an 00195 ideal size allocation. */ 00196 new_len = len + (new_size - size) / sizeof (struct phi_arg_d); 00197 return new_len; 00198 }
|
|
|
Referenced by make_phi_node(), and reserve_phi_args_for_new_edge(). |
|
|
Initialize management of PHIs. Definition at line 94 of file tree-phinodes.c. References free_phinodes. Referenced by init_tree_ssa(). 00095 { 00096 int i; 00097 00098 for (i = 0; i < NUM_BUCKETS - 2; i++) 00099 free_phinodes[i] = NULL; 00100 free_phinode_count = 0; 00101 }
|
|
|
Return a PHI node with LEN argument slots for variable VAR. Definition at line 204 of file tree-phinodes.c. References allocate_phi_node(), ideal_phi_node_len(), make_ssa_name(), PHI_ARG_CAPACITY, PHI_ARG_DEF_TREE, PHI_ARG_IMM_USE_NODE, PHI_NUM_ARGS, SET_PHI_RESULT, TREE_CODE, TREE_SET_CODE, and TREE_TYPE. Referenced by create_phi_node(). 00205 { 00206 tree phi; 00207 int capacity, i; 00208 00209 capacity = ideal_phi_node_len (len); 00210 00211 phi = allocate_phi_node (capacity); 00212 00213 /* We need to clear the entire PHI node, including the argument 00214 portion, because we represent a "missing PHI argument" by placing 00215 NULL_TREE in PHI_ARG_DEF. */ 00216 memset (phi, 0, (sizeof (struct tree_phi_node) - sizeof (struct phi_arg_d) 00217 + sizeof (struct phi_arg_d) * len)); 00218 TREE_SET_CODE (phi, PHI_NODE); 00219 PHI_NUM_ARGS (phi) = len; 00220 PHI_ARG_CAPACITY (phi) = capacity; 00221 TREE_TYPE (phi) = TREE_TYPE (var); 00222 if (TREE_CODE (var) == SSA_NAME) 00223 SET_PHI_RESULT (phi, var); 00224 else 00225 SET_PHI_RESULT (phi, make_ssa_name (var, phi)); 00226 00227 for (i = 0; i < capacity; i++) 00228 { 00229 use_operand_p imm; 00230 imm = &(PHI_ARG_IMM_USE_NODE (phi, i)); 00231 imm->use = &(PHI_ARG_DEF_TREE (phi, i)); 00232 imm->prev = NULL; 00233 imm->next = NULL; 00234 imm->stmt = phi; 00235 } 00236 return phi; 00237 }
|
|
|
Reverse the order of PHI nodes in the chain PHI. Return the new head of the chain (old last PHI node). Definition at line 476 of file tree-phinodes.c. References NULL_TREE, and PHI_CHAIN. 00477 { 00478 tree prev = NULL_TREE, next; 00479 for (; phi; phi = next) 00480 { 00481 next = PHI_CHAIN (phi); 00482 PHI_CHAIN (phi) = prev; 00483 prev = phi; 00484 } 00485 return prev; 00486 }
|
|
|
We no longer need PHI, release it so that it may be reused. Definition at line 242 of file tree-phinodes.c. References delink_imm_use(), PHI_ARG_CAPACITY, PHI_ARG_IMM_USE_NODE, and PHI_NUM_ARGS. Referenced by process_phi_nodes(), remove_phi_node(), and reserve_phi_args_for_new_edge(). 00243 { 00244 int bucket; 00245 int len = PHI_ARG_CAPACITY (phi); 00246 int x; 00247 00248 for (x = 0; x < PHI_NUM_ARGS (phi); x++) 00249 { 00250 use_operand_p imm; 00251 imm = &(PHI_ARG_IMM_USE_NODE (phi, x)); 00252 delink_imm_use (imm); 00253 } 00254 00255 bucket = len > NUM_BUCKETS - 1 ? NUM_BUCKETS - 1 : len; 00256 bucket -= 2; 00257 PHI_CHAIN (phi) = free_phinodes[bucket]; 00258 free_phinodes[bucket] = phi; 00259 free_phinode_count++; 00260 }
|
|
|
Remove the Ith argument from PHI's argument list. This routine implements removal by swapping the last alternative with the alternative we want to delete and then shrinking the vector, which is consistent with how we remove an edge from the edge vector. Definition at line 403 of file tree-phinodes.c. References delink_imm_use(), PHI_ARG_IMM_USE_NODE, PHI_NUM_ARGS, relink_imm_use(), and ssa_use_operand_d::use. Referenced by remove_phi_args(). 00404 { 00405 int num_elem = PHI_NUM_ARGS (phi); 00406 00407 gcc_assert (i < num_elem); 00408 00409 00410 /* Delink the item which is being removed. */ 00411 delink_imm_use (&(PHI_ARG_IMM_USE_NODE (phi, i))); 00412 00413 /* If it is not the last element, move the last element 00414 to the element we want to delete, resetting all the links. */ 00415 if (i != num_elem - 1) 00416 { 00417 use_operand_p old_p, new_p; 00418 old_p = &PHI_ARG_IMM_USE_NODE (phi, num_elem - 1); 00419 new_p = &PHI_ARG_IMM_USE_NODE (phi, i); 00420 /* Set use on new node, and link into last element's place. */ 00421 *(new_p->use) = *(old_p->use); 00422 relink_imm_use (new_p, old_p); 00423 } 00424 00425 /* Shrink the vector and return. Note that we do not have to clear 00426 PHI_ARG_DEF because the garbage collector will not look at those 00427 elements beyond the first PHI_NUM_ARGS elements of the array. */ 00428 PHI_NUM_ARGS (phi)--; 00429 }
|
|
|
Remove all PHI arguments associated with edge E. Definition at line 434 of file tree-phinodes.c. References PHI_CHAIN, phi_nodes(), and remove_phi_arg_num(). 00435 { 00436 tree phi; 00437 00438 for (phi = phi_nodes (e->dest); phi; phi = PHI_CHAIN (phi)) 00439 remove_phi_arg_num (phi, e->dest_idx); 00440 }
|
|
|
Remove PHI node PHI from basic block BB. If PREV is non-NULL, it is used as the node immediately before PHI in the linked list. Definition at line 446 of file tree-phinodes.c. References bb_for_stmt(), PHI_CHAIN, phi_nodes(), PHI_RESULT, release_phi_node(), and release_ssa_name(). 00447 { 00448 tree *loc; 00449 00450 if (prev) 00451 { 00452 loc = &PHI_CHAIN (prev); 00453 } 00454 else 00455 { 00456 for (loc = &(bb_for_stmt (phi)->phi_nodes); 00457 *loc != phi; 00458 loc = &PHI_CHAIN (*loc)) 00459 ; 00460 } 00461 00462 /* Remove PHI from the chain. */ 00463 *loc = PHI_CHAIN (phi); 00464 00465 /* If we are deleting the PHI node, then we should release the 00466 SSA_NAME node so that it can be reused. */ 00467 release_phi_node (phi); 00468 release_ssa_name (PHI_RESULT (phi)); 00469 }
|
|
|
Reserve PHI arguments for a new edge to basic block BB. Definition at line 311 of file tree-phinodes.c. References ideal_phi_node_len(), NULL_TREE, PHI_ARG_CAPACITY, PHI_CHAIN, PHI_NUM_ARGS, PHI_RESULT, release_phi_node(), resize_phi_node(), SET_PHI_ARG_DEF, and SSA_NAME_DEF_STMT. 00312 { 00313 tree *loc; 00314 int len = EDGE_COUNT (bb->preds); 00315 int cap = ideal_phi_node_len (len + 4); 00316 00317 for (loc = &(bb->phi_nodes); 00318 *loc; 00319 loc = &PHI_CHAIN (*loc)) 00320 { 00321 if (len > PHI_ARG_CAPACITY (*loc)) 00322 { 00323 tree old_phi = *loc; 00324 00325 resize_phi_node (loc, cap); 00326 00327 /* The result of the phi is defined by this phi node. */ 00328 SSA_NAME_DEF_STMT (PHI_RESULT (*loc)) = *loc; 00329 00330 release_phi_node (old_phi); 00331 } 00332 00333 /* We represent a "missing PHI argument" by placing NULL_TREE in 00334 the corresponding slot. If PHI arguments were added 00335 immediately after an edge is created, this zeroing would not 00336 be necessary, but unfortunately this is not the case. For 00337 example, the loop optimizer duplicates several basic blocks, 00338 redirects edges, and then fixes up PHI arguments later in 00339 batch. */ 00340 SET_PHI_ARG_DEF (*loc, len - 1, NULL_TREE); 00341 00342 PHI_NUM_ARGS (*loc)++; 00343 } 00344 }
|
|
|
Resize an existing PHI node. The only way is up. Return the possibly relocated phi. Definition at line 266 of file tree-phinodes.c. References allocate_phi_node(), PHI_ARG_CAPACITY, PHI_ARG_DEF_TREE, PHI_ARG_IMM_USE_NODE, PHI_NUM_ARGS, relink_imm_use_stmt(), and ssa_use_operand_d::use. 00267 { 00268 int old_size, i; 00269 tree new_phi; 00270 00271 gcc_assert (len > PHI_ARG_CAPACITY (*phi)); 00272 00273 /* The garbage collector will not look at the PHI node beyond the 00274 first PHI_NUM_ARGS elements. Therefore, all we have to copy is a 00275 portion of the PHI node currently in use. */ 00276 old_size = (sizeof (struct tree_phi_node) 00277 + (PHI_NUM_ARGS (*phi) - 1) * sizeof (struct phi_arg_d)); 00278 00279 new_phi = allocate_phi_node (len); 00280 00281 memcpy (new_phi, *phi, old_size); 00282 00283 for (i = 0; i < PHI_NUM_ARGS (new_phi); i++) 00284 { 00285 use_operand_p imm, old_imm; 00286 imm = &(PHI_ARG_IMM_USE_NODE (new_phi, i)); 00287 old_imm = &(PHI_ARG_IMM_USE_NODE (*phi, i)); 00288 imm->use = &(PHI_ARG_DEF_TREE (new_phi, i)); 00289 relink_imm_use_stmt (imm, old_imm, new_phi); 00290 } 00291 00292 PHI_ARG_CAPACITY (new_phi) = len; 00293 00294 for (i = PHI_NUM_ARGS (new_phi); i < len; i++) 00295 { 00296 use_operand_p imm; 00297 imm = &(PHI_ARG_IMM_USE_NODE (new_phi, i)); 00298 imm->use = &(PHI_ARG_DEF_TREE (new_phi, i)); 00299 imm->prev = NULL; 00300 imm->next = NULL; 00301 imm->stmt = new_phi; 00302 } 00303 00304 00305 *phi = new_phi; 00306 }
|
|
||||||||||||
|
Referenced by reserve_phi_args_for_new_edge(). |
|
|
Definition at line 81 of file tree-phinodes.c. |
|
|
Definition at line 80 of file tree-phinodes.c. Referenced by allocate_phi_node(), fini_phinodes(), and init_phinodes(). |
1.4.6