tree-phinodes.c

Go to the documentation of this file.
00001 /* Generic routines for manipulating PHIs
00002    Copyright (C) 2003, 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, 51 Franklin Street, Fifth Floor,
00019 Boston, MA 02110-1301, USA.  */
00020 
00021 #include "config.h"
00022 #include "system.h"
00023 #include "coretypes.h"
00024 #include "tm.h"
00025 #include "tree.h"
00026 #include "rtl.h"
00027 #include "varray.h"
00028 #include "ggc.h"
00029 #include "basic-block.h"
00030 #include "tree-flow.h"
00031 #include "toplev.h"
00032 
00033 /* Rewriting a function into SSA form can create a huge number of PHIs
00034    many of which may be thrown away shortly after their creation if jumps
00035    were threaded through PHI nodes.
00036 
00037    While our garbage collection mechanisms will handle this situation, it
00038    is extremely wasteful to create nodes and throw them away, especially
00039    when the nodes can be reused.
00040 
00041    For PR 8361, we can significantly reduce the number of nodes allocated
00042    and thus the total amount of memory allocated by managing PHIs a
00043    little.  This additionally helps reduce the amount of work done by the
00044    garbage collector.  Similar results have been seen on a wider variety
00045    of tests (such as the compiler itself).
00046 
00047    Right now we maintain our free list on a per-function basis.  It may
00048    or may not make sense to maintain the free list for the duration of
00049    a compilation unit.
00050 
00051    We could also use a zone allocator for these objects since they have
00052    a very well defined lifetime.  If someone wants to experiment with that
00053    this is the place to try it.
00054 
00055    PHI nodes have different sizes, so we can't have a single list of all
00056    the PHI nodes as it would be too expensive to walk down that list to
00057    find a PHI of a suitable size.
00058 
00059    Instead we have an array of lists of free PHI nodes.  The array is
00060    indexed by the number of PHI alternatives that PHI node can hold.
00061    Except for the last array member, which holds all remaining PHI
00062    nodes.
00063 
00064    So to find a free PHI node, we compute its index into the free PHI
00065    node array and see if there are any elements with an exact match.
00066    If so, then we are done.  Otherwise, we test the next larger size
00067    up and continue until we are in the last array element.
00068 
00069    We do not actually walk members of the last array element.  While it
00070    might allow us to pick up a few reusable PHI nodes, it could potentially
00071    be very expensive if the program has released a bunch of large PHI nodes,
00072    but keeps asking for even larger PHI nodes.  Experiments have shown that
00073    walking the elements of the last array entry would result in finding less
00074    than .1% additional reusable PHI nodes.
00075 
00076    Note that we can never have less than two PHI argument slots.  Thus,
00077    the -2 on all the calculations below.  */
00078 
00079 #define NUM_BUCKETS 10
00080 static GTY ((deletable (""))) tree free_phinodes[NUM_BUCKETS - 2];
00081 static unsigned long free_phinode_count;
00082 
00083 static int ideal_phi_node_len (int);
00084 static void resize_phi_node (tree *, int);
00085 
00086 #ifdef GATHER_STATISTICS
00087 unsigned int phi_nodes_reused;
00088 unsigned int phi_nodes_created;
00089 #endif
00090 
00091 /* Initialize management of PHIs.  */
00092 
00093 void
00094 init_phinodes (void)
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 }
00102 
00103 /* Finalize management of PHIs.  */
00104 
00105 void
00106 fini_phinodes (void)
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 }
00114 
00115 /* Dump some simple statistics regarding the re-use of PHI nodes.  */
00116 
00117 #ifdef GATHER_STATISTICS
00118 void
00119 phinodes_print_statistics (void)
00120 {
00121   fprintf (stderr, "PHI nodes allocated: %u\n", phi_nodes_created);
00122   fprintf (stderr, "PHI nodes reused: %u\n", phi_nodes_reused);
00123 }
00124 #endif
00125 
00126 /* Allocate a PHI node with at least LEN arguments.  If the free list
00127    happens to contain a PHI node with LEN arguments or more, return
00128    that one.  */
00129 
00130 static inline tree
00131 allocate_phi_node (int len)
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 }
00166 
00167 /* Given LEN, the original number of requested PHI arguments, return
00168    a new, "ideal" length for the PHI node.  The "ideal" length rounds
00169    the total size of the PHI node up to the next power of two bytes.
00170 
00171    Rounding up will not result in wasting any memory since the size request
00172    will be rounded up by the GC system anyway.  [ Note this is not entirely
00173    true since the original length might have fit on one of the special
00174    GC pages. ]  By rounding up, we may avoid the need to reallocate the
00175    PHI node later if we increase the number of arguments for the PHI.  */
00176 
00177 static int
00178 ideal_phi_node_len (int len)
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 }
00199 
00200 
00201 /* Return a PHI node with LEN argument slots for variable VAR.  */
00202 
00203 static tree
00204 make_phi_node (tree var, int len)
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 }
00238 
00239 /* We no longer need PHI, release it so that it may be reused.  */
00240 
00241 void
00242 release_phi_node (tree phi)
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 }
00261 
00262 /* Resize an existing PHI node.  The only way is up.  Return the
00263    possibly relocated phi.  */
00264 
00265 static void
00266 resize_phi_node (tree *phi, int len)
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 }
00307 
00308 /* Reserve PHI arguments for a new edge to basic block BB.  */
00309 
00310 void
00311 reserve_phi_args_for_new_edge (basic_block bb)
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 }
00345 
00346 /* Create a new PHI node for variable VAR at basic block BB.  */
00347 
00348 tree
00349 create_phi_node (tree var, basic_block bb)
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 }
00364 
00365 /* Add a new argument to PHI node PHI.  DEF is the incoming reaching
00366    definition and E is the edge through which DEF reaches PHI.  The new
00367    argument is added at the end of the argument list.
00368    If PHI has reached its maximum capacity, add a few slots.  In this case,
00369    PHI points to the reallocated phi node when we return.  */
00370 
00371 void
00372 add_phi_arg (tree phi, tree def, edge e)
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 }
00396 
00397 /* Remove the Ith argument from PHI's argument list.  This routine
00398    implements removal by swapping the last alternative with the
00399    alternative we want to delete and then shrinking the vector, which
00400    is consistent with how we remove an edge from the edge vector.  */
00401 
00402 static void
00403 remove_phi_arg_num (tree phi, int i)
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 }
00430 
00431 /* Remove all PHI arguments associated with edge E.  */
00432 
00433 void
00434 remove_phi_args (edge e)
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 }
00441 
00442 /* Remove PHI node PHI from basic block BB.  If PREV is non-NULL, it is
00443    used as the node immediately before PHI in the linked list.  */
00444 
00445 void
00446 remove_phi_node (tree phi, tree prev)
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 }
00470 
00471 
00472 /* Reverse the order of PHI nodes in the chain PHI.
00473    Return the new head of the chain (old last PHI node).  */
00474 
00475 tree
00476 phi_reverse (tree phi)
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 }
00487 
00488 #include "gt-tree-phinodes.h"

Generated on Sun Sep 17 18:03:30 2006 for Tree SSA by  doxygen 1.4.6