00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
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
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
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
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
00127
00128
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
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
00168
00169
00170
00171
00172
00173
00174
00175
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
00184 if (len < 2)
00185 len = 2;
00186
00187
00188 size = sizeof (struct tree_phi_node) + (len - 1) * sizeof (struct phi_arg_d);
00189
00190
00191 log2 = ceil_log2 (size);
00192 new_size = 1 << log2;
00193
00194
00195
00196 new_len = len + (new_size - size) / sizeof (struct phi_arg_d);
00197 return new_len;
00198 }
00199
00200
00201
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
00214
00215
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
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
00263
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
00274
00275
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
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
00328 SSA_NAME_DEF_STMT (PHI_RESULT (*loc)) = *loc;
00329
00330 release_phi_node (old_phi);
00331 }
00332
00333
00334
00335
00336
00337
00338
00339
00340 SET_PHI_ARG_DEF (*loc, len - 1, NULL_TREE);
00341
00342 PHI_NUM_ARGS (*loc)++;
00343 }
00344 }
00345
00346
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
00356 PHI_CHAIN (phi) = phi_nodes (bb);
00357 bb->phi_nodes = phi;
00358
00359
00360 set_bb_for_stmt (phi, bb);
00361
00362 return phi;
00363 }
00364
00365
00366
00367
00368
00369
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
00379
00380 gcc_assert (PHI_NUM_ARGS (phi) <= PHI_ARG_CAPACITY (phi));
00381
00382
00383
00384 gcc_assert (e->dest_idx < (unsigned int) PHI_NUM_ARGS (phi));
00385
00386
00387
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
00398
00399
00400
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
00411 delink_imm_use (&(PHI_ARG_IMM_USE_NODE (phi, i)));
00412
00413
00414
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
00421 *(new_p->use) = *(old_p->use);
00422 relink_imm_use (new_p, old_p);
00423 }
00424
00425
00426
00427
00428 PHI_NUM_ARGS (phi)--;
00429 }
00430
00431
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
00443
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
00463 *loc = PHI_CHAIN (phi);
00464
00465
00466
00467 release_phi_node (phi);
00468 release_ssa_name (PHI_RESULT (phi));
00469 }
00470
00471
00472
00473
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"