00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "config.h"
00023 #include "system.h"
00024 #include "coretypes.h"
00025 #include "tm.h"
00026 #include "tree.h"
00027 #include "flags.h"
00028 #include "rtl.h"
00029 #include "tm_p.h"
00030 #include "ggc.h"
00031 #include "langhooks.h"
00032 #include "hard-reg-set.h"
00033 #include "basic-block.h"
00034 #include "output.h"
00035 #include "expr.h"
00036 #include "function.h"
00037 #include "diagnostic.h"
00038 #include "bitmap.h"
00039 #include "tree-flow.h"
00040 #include "tree-gimple.h"
00041 #include "tree-inline.h"
00042 #include "varray.h"
00043 #include "timevar.h"
00044 #include "hashtab.h"
00045 #include "tree-dump.h"
00046 #include "tree-ssa-live.h"
00047 #include "tree-pass.h"
00048 #include "toplev.h"
00049 #include "vecprim.h"
00050
00051
00052
00053 #define SSANORM_PERFORM_TER 0x1
00054 #define SSANORM_COMBINE_TEMPS 0x2
00055 #define SSANORM_COALESCE_PARTITIONS 0x4
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078 typedef struct _elim_graph {
00079
00080 int size;
00081
00082
00083 VEC(tree,heap) *nodes;
00084
00085
00086 VEC(int,heap) *edge_list;
00087
00088
00089 sbitmap visited;
00090
00091
00092 VEC(int,heap) *stack;
00093
00094
00095 var_map map;
00096
00097
00098 edge e;
00099
00100
00101 VEC(tree,heap) *const_copies;
00102 } *elim_graph;
00103
00104
00105
00106 static tree create_temp (tree);
00107 static void insert_copy_on_edge (edge, tree, tree);
00108 static elim_graph new_elim_graph (int);
00109 static inline void delete_elim_graph (elim_graph);
00110 static inline void clear_elim_graph (elim_graph);
00111 static inline int elim_graph_size (elim_graph);
00112 static inline void elim_graph_add_node (elim_graph, tree);
00113 static inline void elim_graph_add_edge (elim_graph, int, int);
00114 static inline int elim_graph_remove_succ_edge (elim_graph, int);
00115
00116 static inline void eliminate_name (elim_graph, tree);
00117 static void eliminate_build (elim_graph, basic_block);
00118 static void elim_forward (elim_graph, int);
00119 static int elim_unvisited_predecessor (elim_graph, int);
00120 static void elim_backward (elim_graph, int);
00121 static void elim_create (elim_graph, int);
00122 static void eliminate_phi (edge, elim_graph);
00123 static tree_live_info_p coalesce_ssa_name (var_map, int);
00124 static void assign_vars (var_map);
00125 static bool replace_use_variable (var_map, use_operand_p, tree *);
00126 static bool replace_def_variable (var_map, def_operand_p, tree *);
00127 static void eliminate_virtual_phis (void);
00128 static void coalesce_abnormal_edges (var_map, conflict_graph, root_var_p);
00129 static void print_exprs (FILE *, const char *, tree, const char *, tree,
00130 const char *);
00131 static void print_exprs_edge (FILE *, edge, const char *, tree, const char *,
00132 tree);
00133
00134
00135
00136
00137
00138 static tree
00139 create_temp (tree t)
00140 {
00141 tree tmp;
00142 const char *name = NULL;
00143 tree type;
00144
00145 if (TREE_CODE (t) == SSA_NAME)
00146 t = SSA_NAME_VAR (t);
00147
00148 gcc_assert (TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == PARM_DECL);
00149
00150 type = TREE_TYPE (t);
00151 tmp = DECL_NAME (t);
00152 if (tmp)
00153 name = IDENTIFIER_POINTER (tmp);
00154
00155 if (name == NULL)
00156 name = "temp";
00157 tmp = create_tmp_var (type, name);
00158
00159 if (DECL_DEBUG_EXPR_IS_FROM (t) && DECL_DEBUG_EXPR (t))
00160 {
00161 SET_DECL_DEBUG_EXPR (tmp, DECL_DEBUG_EXPR (t));
00162 DECL_DEBUG_EXPR_IS_FROM (tmp) = 1;
00163 }
00164 else if (!DECL_IGNORED_P (t))
00165 {
00166 SET_DECL_DEBUG_EXPR (tmp, t);
00167 DECL_DEBUG_EXPR_IS_FROM (tmp) = 1;
00168 }
00169 DECL_ARTIFICIAL (tmp) = DECL_ARTIFICIAL (t);
00170 DECL_IGNORED_P (tmp) = DECL_IGNORED_P (t);
00171 add_referenced_var (tmp);
00172
00173
00174
00175
00176 var_ann (tmp)->symbol_mem_tag = var_ann (t)->symbol_mem_tag;
00177 if (is_call_clobbered (t))
00178 mark_call_clobbered (tmp, var_ann (t)->escape_mask);
00179
00180 return tmp;
00181 }
00182
00183
00184
00185
00186
00187 static void
00188 insert_copy_on_edge (edge e, tree dest, tree src)
00189 {
00190 tree copy;
00191
00192 copy = build2 (MODIFY_EXPR, TREE_TYPE (dest), dest, src);
00193 set_is_used (dest);
00194
00195 if (TREE_CODE (src) == ADDR_EXPR)
00196 src = TREE_OPERAND (src, 0);
00197 if (TREE_CODE (src) == VAR_DECL || TREE_CODE (src) == PARM_DECL)
00198 set_is_used (src);
00199
00200 if (dump_file && (dump_flags & TDF_DETAILS))
00201 {
00202 fprintf (dump_file,
00203 "Inserting a copy on edge BB%d->BB%d :",
00204 e->src->index,
00205 e->dest->index);
00206 print_generic_expr (dump_file, copy, dump_flags);
00207 fprintf (dump_file, "\n");
00208 }
00209
00210 bsi_insert_on_edge (e, copy);
00211 }
00212
00213
00214
00215
00216
00217 static elim_graph
00218 new_elim_graph (int size)
00219 {
00220 elim_graph g = (elim_graph) xmalloc (sizeof (struct _elim_graph));
00221
00222 g->nodes = VEC_alloc (tree, heap, 30);
00223 g->const_copies = VEC_alloc (tree, heap, 20);
00224 g->edge_list = VEC_alloc (int, heap, 20);
00225 g->stack = VEC_alloc (int, heap, 30);
00226
00227 g->visited = sbitmap_alloc (size);
00228
00229 return g;
00230 }
00231
00232
00233
00234
00235 static inline void
00236 clear_elim_graph (elim_graph g)
00237 {
00238 VEC_truncate (tree, g->nodes, 0);
00239 VEC_truncate (int, g->edge_list, 0);
00240 }
00241
00242
00243
00244
00245 static inline void
00246 delete_elim_graph (elim_graph g)
00247 {
00248 sbitmap_free (g->visited);
00249 VEC_free (int, heap, g->stack);
00250 VEC_free (int, heap, g->edge_list);
00251 VEC_free (tree, heap, g->const_copies);
00252 VEC_free (tree, heap, g->nodes);
00253 free (g);
00254 }
00255
00256
00257
00258
00259 static inline int
00260 elim_graph_size (elim_graph g)
00261 {
00262 return VEC_length (tree, g->nodes);
00263 }
00264
00265
00266
00267
00268 static inline void
00269 elim_graph_add_node (elim_graph g, tree node)
00270 {
00271 int x;
00272 tree t;
00273
00274 for (x = 0; VEC_iterate (tree, g->nodes, x, t); x++)
00275 if (t == node)
00276 return;
00277 VEC_safe_push (tree, heap, g->nodes, node);
00278 }
00279
00280
00281
00282
00283 static inline void
00284 elim_graph_add_edge (elim_graph g, int pred, int succ)
00285 {
00286 VEC_safe_push (int, heap, g->edge_list, pred);
00287 VEC_safe_push (int, heap, g->edge_list, succ);
00288 }
00289
00290
00291
00292
00293
00294 static inline int
00295 elim_graph_remove_succ_edge (elim_graph g, int node)
00296 {
00297 int y;
00298 unsigned x;
00299 for (x = 0; x < VEC_length (int, g->edge_list); x += 2)
00300 if (VEC_index (int, g->edge_list, x) == node)
00301 {
00302 VEC_replace (int, g->edge_list, x, -1);
00303 y = VEC_index (int, g->edge_list, x + 1);
00304 VEC_replace (int, g->edge_list, x + 1, -1);
00305 return y;
00306 }
00307 return -1;
00308 }
00309
00310
00311
00312
00313
00314
00315 #define FOR_EACH_ELIM_GRAPH_SUCC(GRAPH, NODE, VAR, CODE) \
00316 do { \
00317 unsigned x_; \
00318 int y_; \
00319 for (x_ = 0; x_ < VEC_length (int, (GRAPH)->edge_list); x_ += 2) \
00320 { \
00321 y_ = VEC_index (int, (GRAPH)->edge_list, x_); \
00322 if (y_ != (NODE)) \
00323 continue; \
00324 (VAR) = VEC_index (int, (GRAPH)->edge_list, x_ + 1); \
00325 CODE; \
00326 } \
00327 } while (0)
00328
00329
00330
00331
00332
00333
00334 #define FOR_EACH_ELIM_GRAPH_PRED(GRAPH, NODE, VAR, CODE) \
00335 do { \
00336 unsigned x_; \
00337 int y_; \
00338 for (x_ = 0; x_ < VEC_length (int, (GRAPH)->edge_list); x_ += 2) \
00339 { \
00340 y_ = VEC_index (int, (GRAPH)->edge_list, x_ + 1); \
00341 if (y_ != (NODE)) \
00342 continue; \
00343 (VAR) = VEC_index (int, (GRAPH)->edge_list, x_); \
00344 CODE; \
00345 } \
00346 } while (0)
00347
00348
00349
00350
00351 static inline void
00352 eliminate_name (elim_graph g, tree T)
00353 {
00354 elim_graph_add_node (g, T);
00355 }
00356
00357
00358
00359
00360
00361 static void
00362 eliminate_build (elim_graph g, basic_block B)
00363 {
00364 tree phi;
00365 tree T0, Ti;
00366 int p0, pi;
00367
00368 clear_elim_graph (g);
00369
00370 for (phi = phi_nodes (B); phi; phi = PHI_CHAIN (phi))
00371 {
00372 T0 = var_to_partition_to_var (g->map, PHI_RESULT (phi));
00373
00374
00375 if (T0 == NULL_TREE)
00376 continue;
00377
00378 Ti = PHI_ARG_DEF (phi, g->e->dest_idx);
00379
00380
00381
00382
00383 if (!phi_ssa_name_p (Ti)
00384 || (TREE_CODE (Ti) == SSA_NAME
00385 && var_to_partition (g->map, Ti) == NO_PARTITION))
00386 {
00387
00388
00389 VEC_safe_push (tree, heap, g->const_copies, T0);
00390 VEC_safe_push (tree, heap, g->const_copies, Ti);
00391 }
00392 else
00393 {
00394 Ti = var_to_partition_to_var (g->map, Ti);
00395 if (T0 != Ti)
00396 {
00397 eliminate_name (g, T0);
00398 eliminate_name (g, Ti);
00399 p0 = var_to_partition (g->map, T0);
00400 pi = var_to_partition (g->map, Ti);
00401 elim_graph_add_edge (g, p0, pi);
00402 }
00403 }
00404 }
00405 }
00406
00407
00408
00409
00410 static void
00411 elim_forward (elim_graph g, int T)
00412 {
00413 int S;
00414 SET_BIT (g->visited, T);
00415 FOR_EACH_ELIM_GRAPH_SUCC (g, T, S,
00416 {
00417 if (!TEST_BIT (g->visited, S))
00418 elim_forward (g, S);
00419 });
00420 VEC_safe_push (int, heap, g->stack, T);
00421 }
00422
00423
00424
00425
00426 static int
00427 elim_unvisited_predecessor (elim_graph g, int T)
00428 {
00429 int P;
00430 FOR_EACH_ELIM_GRAPH_PRED (g, T, P,
00431 {
00432 if (!TEST_BIT (g->visited, P))
00433 return 1;
00434 });
00435 return 0;
00436 }
00437
00438
00439
00440 static void
00441 elim_backward (elim_graph g, int T)
00442 {
00443 int P;
00444 SET_BIT (g->visited, T);
00445 FOR_EACH_ELIM_GRAPH_PRED (g, T, P,
00446 {
00447 if (!TEST_BIT (g->visited, P))
00448 {
00449 elim_backward (g, P);
00450 insert_copy_on_edge (g->e,
00451 partition_to_var (g->map, P),
00452 partition_to_var (g->map, T));
00453 }
00454 });
00455 }
00456
00457
00458
00459
00460 static void
00461 elim_create (elim_graph g, int T)
00462 {
00463 tree U;
00464 int P, S;
00465
00466 if (elim_unvisited_predecessor (g, T))
00467 {
00468 U = create_temp (partition_to_var (g->map, T));
00469 insert_copy_on_edge (g->e, U, partition_to_var (g->map, T));
00470 FOR_EACH_ELIM_GRAPH_PRED (g, T, P,
00471 {
00472 if (!TEST_BIT (g->visited, P))
00473 {
00474 elim_backward (g, P);
00475 insert_copy_on_edge (g->e, partition_to_var (g->map, P), U);
00476 }
00477 });
00478 }
00479 else
00480 {
00481 S = elim_graph_remove_succ_edge (g, T);
00482 if (S != -1)
00483 {
00484 SET_BIT (g->visited, T);
00485 insert_copy_on_edge (g->e,
00486 partition_to_var (g->map, T),
00487 partition_to_var (g->map, S));
00488 }
00489 }
00490
00491 }
00492
00493
00494
00495 static void
00496 eliminate_phi (edge e, elim_graph g)
00497 {
00498 int x;
00499 basic_block B = e->dest;
00500
00501 gcc_assert (VEC_length (tree, g->const_copies) == 0);
00502
00503
00504 if (e->flags & EDGE_ABNORMAL)
00505 return;
00506
00507 g->e = e;
00508
00509 eliminate_build (g, B);
00510
00511 if (elim_graph_size (g) != 0)
00512 {
00513 tree var;
00514
00515 sbitmap_zero (g->visited);
00516 VEC_truncate (int, g->stack, 0);
00517
00518 for (x = 0; VEC_iterate (tree, g->nodes, x, var); x++)
00519 {
00520 int p = var_to_partition (g->map, var);
00521 if (!TEST_BIT (g->visited, p))
00522 elim_forward (g, p);
00523 }
00524
00525 sbitmap_zero (g->visited);
00526 while (VEC_length (int, g->stack) > 0)
00527 {
00528 x = VEC_pop (int, g->stack);
00529 if (!TEST_BIT (g->visited, x))
00530 elim_create (g, x);
00531 }
00532 }
00533
00534
00535 while (VEC_length (tree, g->const_copies) > 0)
00536 {
00537 tree src, dest;
00538 src = VEC_pop (tree, g->const_copies);
00539 dest = VEC_pop (tree, g->const_copies);
00540 insert_copy_on_edge (e, dest, src);
00541 }
00542 }
00543
00544
00545
00546
00547
00548 static void
00549 print_exprs (FILE *f, const char *str1, tree expr1, const char *str2,
00550 tree expr2, const char *str3)
00551 {
00552 fprintf (f, "%s", str1);
00553 print_generic_expr (f, expr1, TDF_SLIM);
00554 fprintf (f, "%s", str2);
00555 print_generic_expr (f, expr2, TDF_SLIM);
00556 fprintf (f, "%s", str3);
00557 }
00558
00559
00560
00561
00562
00563 static void
00564 print_exprs_edge (FILE *f, edge e, const char *str1, tree expr1,
00565 const char *str2, tree expr2)
00566 {
00567 print_exprs (f, str1, expr1, str2, expr2, " across an abnormal edge");
00568 fprintf (f, " from BB%d->BB%d\n", e->src->index,
00569 e->dest->index);
00570 }
00571
00572
00573
00574
00575
00576
00577
00578 static void
00579 coalesce_abnormal_edges (var_map map, conflict_graph graph, root_var_p rv)
00580 {
00581 basic_block bb;
00582 edge e;
00583 tree phi, var, tmp;
00584 int x, y, z;
00585 edge_iterator ei;
00586
00587
00588
00589
00590
00591 FOR_EACH_BB (bb)
00592 FOR_EACH_EDGE (e, ei, bb->succs)
00593 if (e->dest != EXIT_BLOCK_PTR && e->flags & EDGE_ABNORMAL)
00594 for (phi = phi_nodes (e->dest); phi; phi = PHI_CHAIN (phi))
00595 {
00596
00597
00598 var = PHI_RESULT (phi);
00599 x = var_to_partition (map, var);
00600
00601
00602 if (x == NO_PARTITION)
00603 continue;
00604
00605 tmp = PHI_ARG_DEF (phi, e->dest_idx);
00606 #ifdef ENABLE_CHECKING
00607 if (!phi_ssa_name_p (tmp))
00608 {
00609 print_exprs_edge (stderr, e,
00610 "\nConstant argument in PHI. Can't insert :",
00611 var, " = ", tmp);
00612 internal_error ("SSA corruption");
00613 }
00614 #else
00615 gcc_assert (phi_ssa_name_p (tmp));
00616 #endif
00617 y = var_to_partition (map, tmp);
00618 gcc_assert (x != NO_PARTITION);
00619 gcc_assert (y != NO_PARTITION);
00620 #ifdef ENABLE_CHECKING
00621 if (root_var_find (rv, x) != root_var_find (rv, y))
00622 {
00623 print_exprs_edge (stderr, e, "\nDifferent root vars: ",
00624 root_var (rv, root_var_find (rv, x)),
00625 " and ",
00626 root_var (rv, root_var_find (rv, y)));
00627 internal_error ("SSA corruption");
00628 }
00629 #else
00630 gcc_assert (root_var_find (rv, x) == root_var_find (rv, y));
00631 #endif
00632
00633 if (x != y)
00634 {
00635 #ifdef ENABLE_CHECKING
00636 if (conflict_graph_conflict_p (graph, x, y))
00637 {
00638 print_exprs_edge (stderr, e, "\n Conflict ",
00639 partition_to_var (map, x),
00640 " and ", partition_to_var (map, y));
00641 internal_error ("SSA corruption");
00642 }
00643 #else
00644 gcc_assert (!conflict_graph_conflict_p (graph, x, y));
00645 #endif
00646
00647
00648 var = partition_to_var (map, x);
00649 tmp = partition_to_var (map, y);
00650 if (dump_file && (dump_flags & TDF_DETAILS))
00651 {
00652 print_exprs_edge (dump_file, e,
00653 "ABNORMAL: Coalescing ",
00654 var, " and ", tmp);
00655 }
00656 z = var_union (map, var, tmp);
00657 #ifdef ENABLE_CHECKING
00658 if (z == NO_PARTITION)
00659 {
00660 print_exprs_edge (stderr, e, "\nUnable to coalesce",
00661 partition_to_var (map, x), " and ",
00662 partition_to_var (map, y));
00663 internal_error ("SSA corruption");
00664 }
00665 #else
00666 gcc_assert (z != NO_PARTITION);
00667 #endif
00668 gcc_assert (z == x || z == y);
00669 if (z == x)
00670 conflict_graph_merge_regs (graph, x, y);
00671 else
00672 conflict_graph_merge_regs (graph, y, x);
00673 }
00674 }
00675 }
00676
00677
00678
00679 static void
00680 coalesce_phi_operands (var_map map, coalesce_list_p cl)
00681 {
00682 basic_block bb;
00683 tree phi;
00684
00685 FOR_EACH_BB (bb)
00686 {
00687 for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
00688 {
00689 tree res = PHI_RESULT (phi);
00690 int p = var_to_partition (map, res);
00691 int x;
00692
00693 if (p == NO_PARTITION)
00694 continue;
00695
00696 for (x = 0; x < PHI_NUM_ARGS (phi); x++)
00697 {
00698 tree arg = PHI_ARG_DEF (phi, x);
00699 int p2;
00700
00701 if (TREE_CODE (arg) != SSA_NAME)
00702 continue;
00703 if (SSA_NAME_VAR (res) != SSA_NAME_VAR (arg))
00704 continue;
00705 p2 = var_to_partition (map, PHI_ARG_DEF (phi, x));
00706 if (p2 != NO_PARTITION)
00707 {
00708 edge e = PHI_ARG_EDGE (phi, x);
00709 add_coalesce (cl, p, p2,
00710 coalesce_cost (EDGE_FREQUENCY (e),
00711 maybe_hot_bb_p (bb),
00712 EDGE_CRITICAL_P (e)));
00713 }
00714 }
00715 }
00716 }
00717 }
00718
00719
00720
00721 static void
00722 coalesce_result_decls (var_map map, coalesce_list_p cl)
00723 {
00724 unsigned int i, x;
00725 tree var = NULL;
00726
00727 for (i = x = 0; x < num_var_partitions (map); x++)
00728 {
00729 tree p = partition_to_var (map, x);
00730 if (TREE_CODE (SSA_NAME_VAR (p)) == RESULT_DECL)
00731 {
00732 if (var == NULL_TREE)
00733 {
00734 var = p;
00735 i = x;
00736 }
00737 else
00738 add_coalesce (cl, i, x,
00739 coalesce_cost (EXIT_BLOCK_PTR->frequency,
00740 maybe_hot_bb_p (EXIT_BLOCK_PTR),
00741 false));
00742 }
00743 }
00744 }
00745
00746
00747
00748 static void
00749 coalesce_asm_operands (var_map map, coalesce_list_p cl)
00750 {
00751 basic_block bb;
00752
00753 FOR_EACH_BB (bb)
00754 {
00755 block_stmt_iterator bsi;
00756 for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
00757 {
00758 tree stmt = bsi_stmt (bsi);
00759 unsigned long noutputs, i;
00760 tree *outputs, link;
00761
00762 if (TREE_CODE (stmt) != ASM_EXPR)
00763 continue;
00764
00765 noutputs = list_length (ASM_OUTPUTS (stmt));
00766 outputs = (tree *) alloca (noutputs * sizeof (tree));
00767 for (i = 0, link = ASM_OUTPUTS (stmt); link;
00768 ++i, link = TREE_CHAIN (link))
00769 outputs[i] = TREE_VALUE (link);
00770
00771 for (link = ASM_INPUTS (stmt); link; link = TREE_CHAIN (link))
00772 {
00773 const char *constraint
00774 = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
00775 tree input = TREE_VALUE (link);
00776 char *end;
00777 unsigned long match;
00778 int p1, p2;
00779
00780 if (TREE_CODE (input) != SSA_NAME && !DECL_P (input))
00781 continue;
00782
00783 match = strtoul (constraint, &end, 10);
00784 if (match >= noutputs || end == constraint)
00785 continue;
00786
00787 if (TREE_CODE (outputs[match]) != SSA_NAME
00788 && !DECL_P (outputs[match]))
00789 continue;
00790
00791 p1 = var_to_partition (map, outputs[match]);
00792 if (p1 == NO_PARTITION)
00793 continue;
00794 p2 = var_to_partition (map, input);
00795 if (p2 == NO_PARTITION)
00796 continue;
00797
00798 add_coalesce (cl, p1, p2, coalesce_cost (REG_BR_PROB_BASE,
00799 maybe_hot_bb_p (bb),
00800 false));
00801 }
00802 }
00803 }
00804 }
00805
00806
00807
00808
00809
00810
00811
00812 static tree_live_info_p
00813 coalesce_ssa_name (var_map map, int flags)
00814 {
00815 unsigned num, x;
00816 sbitmap live;
00817 root_var_p rv;
00818 tree_live_info_p liveinfo;
00819 conflict_graph graph;
00820 coalesce_list_p cl = NULL;
00821 sbitmap_iterator sbi;
00822
00823 if (num_var_partitions (map) <= 1)
00824 return NULL;
00825
00826 liveinfo = calculate_live_on_entry (map);
00827 calculate_live_on_exit (liveinfo);
00828 rv = root_var_init (map);
00829
00830
00831 root_var_compact (rv);
00832
00833 cl = create_coalesce_list (map);
00834
00835 coalesce_phi_operands (map, cl);
00836 coalesce_result_decls (map, cl);
00837 coalesce_asm_operands (map, cl);
00838
00839
00840 graph = build_tree_conflict_graph (liveinfo, rv, cl);
00841
00842 if (cl)
00843 {
00844 if (dump_file && (dump_flags & TDF_DETAILS))
00845 {
00846 fprintf (dump_file, "Before sorting:\n");
00847 dump_coalesce_list (dump_file, cl);
00848 }
00849
00850 sort_coalesce_list (cl);
00851
00852 if (dump_file && (dump_flags & TDF_DETAILS))
00853 {
00854 fprintf (dump_file, "\nAfter sorting:\n");
00855 dump_coalesce_list (dump_file, cl);
00856 }
00857 }
00858
00859
00860 root_var_decompact (rv);
00861
00862
00863
00864
00865 num = num_var_partitions (map);
00866 live = sbitmap_alloc (num);
00867 sbitmap_zero (live);
00868
00869
00870 for (x = 0 ; x < num; x++)
00871 {
00872 tree var = partition_to_var (map, x);
00873 if (default_def (SSA_NAME_VAR (var)) == var)
00874 SET_BIT (live, x);
00875 }
00876
00877 if ((flags & SSANORM_COMBINE_TEMPS) == 0)
00878 {
00879 delete_tree_live_info (liveinfo);
00880 liveinfo = NULL;
00881 }
00882
00883
00884
00885 EXECUTE_IF_SET_IN_SBITMAP (live, 0, x, sbi)
00886 {
00887 tree var = root_var (rv, root_var_find (rv, x));
00888 var_ann_t ann = var_ann (var);
00889
00890 if (partition_to_var (map, x) != var)
00891 {
00892
00893
00894 gcc_assert (!ann->out_of_ssa_tag);
00895
00896 if (dump_file && (dump_flags & TDF_DETAILS))
00897 {
00898 print_exprs (dump_file, "Must coalesce ",
00899 partition_to_var (map, x),
00900 " with the root variable ", var, ".\n");
00901 }
00902
00903 change_partition_var (map, var, x);
00904 }
00905 }
00906
00907 sbitmap_free (live);
00908
00909
00910 coalesce_abnormal_edges (map, graph, rv);
00911
00912 if (dump_file && (dump_flags & TDF_DETAILS))
00913 dump_var_map (dump_file, map);
00914
00915
00916 coalesce_tpa_members (rv, graph, map, cl,
00917 ((dump_flags & TDF_DETAILS) ? dump_file
00918 : NULL));
00919
00920 if (flags & SSANORM_COALESCE_PARTITIONS)
00921 coalesce_tpa_members (rv, graph, map, NULL,
00922 ((dump_flags & TDF_DETAILS) ? dump_file
00923 : NULL));
00924 if (cl)
00925 delete_coalesce_list (cl);
00926 root_var_delete (rv);
00927 conflict_graph_delete (graph);
00928
00929 return liveinfo;
00930 }
00931
00932
00933
00934
00935
00936 static void
00937 assign_vars (var_map map)
00938 {
00939 int x, i, num, rep;
00940 tree t, var;
00941 var_ann_t ann;
00942 root_var_p rv;
00943
00944 rv = root_var_init (map);
00945 if (!rv)
00946 return;
00947
00948
00949
00950
00951 num = num_var_partitions (map);
00952 for (x = 0; x < num; x++)
00953 {
00954 var = partition_to_var (map, x);
00955 if (TREE_CODE (var) != SSA_NAME)
00956 {
00957
00958
00959
00960 ann = var_ann (var);
00961 ann->out_of_ssa_tag = 1;
00962 if (dump_file && (dump_flags & TDF_DETAILS))
00963 {
00964 fprintf (dump_file, "partition %d has variable ", x);
00965 print_generic_expr (dump_file, var, TDF_SLIM);
00966 fprintf (dump_file, " assigned to it.\n");
00967 }
00968
00969 }
00970 }
00971
00972 num = root_var_num (rv);
00973 for (x = 0; x < num; x++)
00974 {
00975 var = root_var (rv, x);
00976 ann = var_ann (var);
00977 for (i = root_var_first_partition (rv, x);
00978 i != ROOT_VAR_NONE;
00979 i = root_var_next_partition (rv, i))
00980 {
00981 t = partition_to_var (map, i);
00982
00983 if (t == var || TREE_CODE (t) != SSA_NAME)
00984 continue;
00985
00986 rep = var_to_partition (map, t);
00987
00988 if (!ann->out_of_ssa_tag)
00989 {
00990 if (dump_file && (dump_flags & TDF_DETAILS))
00991 print_exprs (dump_file, "", t, " --> ", var, "\n");
00992 change_partition_var (map, var, rep);
00993 continue;
00994 }
00995
00996 if (dump_file && (dump_flags & TDF_DETAILS))
00997 print_exprs (dump_file, "", t, " not coalesced with ", var,
00998 "");
00999
01000 var = create_temp (t);
01001 change_partition_var (map, var, rep);
01002 ann = var_ann (var);
01003
01004 if (dump_file && (dump_flags & TDF_DETAILS))
01005 {
01006 fprintf (dump_file, " --> New temp: '");
01007 print_generic_expr (dump_file, var, TDF_SLIM);
01008 fprintf (dump_file, "'\n");
01009 }
01010 }
01011 }
01012
01013 root_var_delete (rv);
01014 }
01015
01016
01017
01018
01019
01020
01021
01022 static inline bool
01023 replace_use_variable (var_map map, use_operand_p p, tree *expr)
01024 {
01025 tree new_var;
01026 tree var = USE_FROM_PTR (p);
01027
01028
01029 if (expr)
01030 {
01031 int version = SSA_NAME_VERSION (var);
01032 if (expr[version])
01033 {
01034 tree new_expr = TREE_OPERAND (expr[version], 1);
01035 SET_USE (p, new_expr);
01036
01037 TREE_OPERAND (expr[version], 1) = NULL_TREE;
01038 return true;
01039 }
01040 }
01041
01042 new_var = var_to_partition_to_var (map, var);
01043 if (new_var)
01044 {
01045 SET_USE (p, new_var);
01046 set_is_used (new_var);
01047 return true;
01048 }
01049 return false;
01050 }
01051
01052
01053
01054
01055
01056
01057
01058 static inline bool
01059 replace_def_variable (var_map map, def_operand_p def_p, tree *expr)
01060 {
01061 tree new_var;
01062 tree var = DEF_FROM_PTR (def_p);
01063
01064
01065 if (expr)
01066 {
01067 int version = SSA_NAME_VERSION (var);
01068 if (expr[version])
01069 {
01070 tree new_expr = TREE_OPERAND (expr[version], 1);
01071 SET_DEF (def_p, new_expr);
01072
01073 TREE_OPERAND (expr[version], 1) = NULL_TREE;
01074 return true;
01075 }
01076 }
01077
01078 new_var = var_to_partition_to_var (map, var);
01079 if (new_var)
01080 {
01081 SET_DEF (def_p, new_var);
01082 set_is_used (new_var);
01083 return true;
01084 }
01085 return false;
01086 }
01087
01088
01089
01090
01091 static void
01092 eliminate_virtual_phis (void)
01093 {
01094 basic_block bb;
01095 tree phi, next;
01096
01097 FOR_EACH_BB (bb)
01098 {
01099 for (phi = phi_nodes (bb); phi; phi = next)
01100 {
01101 next = PHI_CHAIN (phi);
01102 if (!is_gimple_reg (SSA_NAME_VAR (PHI_RESULT (phi))))
01103 {
01104 #ifdef ENABLE_CHECKING
01105 int i;
01106
01107
01108 for (i = 0; i < PHI_NUM_ARGS (phi); i++)
01109 {
01110 tree arg = PHI_ARG_DEF (phi, i);
01111 if (TREE_CODE (arg) == SSA_NAME
01112 && is_gimple_reg (SSA_NAME_VAR (arg)))
01113 {
01114 fprintf (stderr, "Argument of PHI is not virtual (");
01115 print_generic_expr (stderr, arg, TDF_SLIM);
01116 fprintf (stderr, "), but the result is :");
01117 print_generic_stmt (stderr, phi, TDF_SLIM);
01118 internal_error ("SSA corruption");
01119 }
01120 }
01121 #endif
01122 remove_phi_node (phi, NULL_TREE);
01123 }
01124 }
01125 }
01126 }
01127
01128
01129
01130
01131
01132
01133
01134
01135 static void
01136 coalesce_vars (var_map map, tree_live_info_p liveinfo)
01137 {
01138 basic_block bb;
01139 type_var_p tv;
01140 tree var;
01141 unsigned x, p, p2;
01142 coalesce_list_p cl;
01143 conflict_graph graph;
01144
01145 cl = create_coalesce_list (map);
01146
01147
01148 for (x = 0; x < num_var_partitions (map); x++)
01149 {
01150 var = partition_to_var (map, x);
01151 p = var_to_partition (map, var);
01152 if (p != x)
01153 live_merge_and_clear (liveinfo, p, x);
01154 }
01155
01156
01157
01158 FOR_EACH_BB (bb)
01159 {
01160 tree phi, arg;
01161 unsigned p;
01162
01163 for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
01164 {
01165 p = var_to_partition (map, PHI_RESULT (phi));
01166
01167
01168 if (p == (unsigned)NO_PARTITION)
01169 continue;
01170
01171 make_live_on_entry (liveinfo, bb, p);
01172
01173
01174
01175 for (x = 0; x < (unsigned)PHI_NUM_ARGS (phi); x++)
01176 {
01177 arg = PHI_ARG_DEF (phi, x);
01178 if (!phi_ssa_name_p (arg))
01179 continue;
01180 p2 = var_to_partition (map, arg);
01181 if (p2 == (unsigned)NO_PARTITION)
01182 continue;
01183 if (p != p2)
01184 {
01185 edge e = PHI_ARG_EDGE (phi, x);
01186
01187 add_coalesce (cl, p, p2,
01188 coalesce_cost (EDGE_FREQUENCY (e),
01189 maybe_hot_bb_p (bb),
01190 EDGE_CRITICAL_P (e)));
01191 }
01192 }
01193 }
01194 }
01195
01196
01197
01198 calculate_live_on_exit (liveinfo);
01199
01200 if (dump_file && (dump_flags & TDF_DETAILS))
01201 {
01202 fprintf (dump_file, "Live range info for variable memory coalescing.\n");
01203 dump_live_info (dump_file, liveinfo, LIVEDUMP_ALL);
01204
01205 fprintf (dump_file, "Coalesce list from phi nodes:\n");
01206 dump_coalesce_list (dump_file, cl);
01207 }
01208
01209
01210 tv = type_var_init (map);
01211 if (dump_file)
01212 type_var_dump (dump_file, tv);
01213 type_var_compact (tv);
01214 if (dump_file)
01215 type_var_dump (dump_file, tv);
01216
01217 graph = build_tree_conflict_graph (liveinfo, tv, cl);
01218
01219 type_var_decompact (tv);
01220 if (dump_file && (dump_flags & TDF_DETAILS))
01221 {
01222 fprintf (dump_file, "type var list now looks like:n");
01223 type_var_dump (dump_file, tv);
01224
01225 fprintf (dump_file, "Coalesce list after conflict graph build:\n");
01226 dump_coalesce_list (dump_file, cl);
01227 }
01228
01229 sort_coalesce_list (cl);
01230 if (dump_file && (dump_flags & TDF_DETAILS))
01231 {
01232 fprintf (dump_file, "Coalesce list after sorting:\n");
01233 dump_coalesce_list (dump_file, cl);
01234 }
01235
01236 coalesce_tpa_members (tv, graph, map, cl,
01237 ((dump_flags & TDF_DETAILS) ? dump_file : NULL));
01238
01239 type_var_delete (tv);
01240 delete_coalesce_list (cl);
01241 }
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288 typedef struct value_expr_d
01289 {
01290 int value;
01291 struct value_expr_d *next;
01292 } *value_expr_p;
01293
01294
01295
01296
01297 typedef struct temp_expr_table_d
01298 {
01299 var_map map;
01300 void **version_info;
01301 bitmap *expr_vars;
01302 value_expr_p *partition_dep_list;
01303 bitmap replaceable;
01304 bool saw_replaceable;
01305 int virtual_partition;
01306 bitmap partition_in_use;
01307 value_expr_p free_list;
01308 value_expr_p pending_dependence;
01309 } *temp_expr_table_p;
01310
01311
01312 #define VIRTUAL_PARTITION(table) (table->virtual_partition)
01313
01314 static temp_expr_table_p new_temp_expr_table (var_map);
01315 static tree *free_temp_expr_table (temp_expr_table_p);
01316 static inline value_expr_p new_value_expr (temp_expr_table_p);
01317 static inline void free_value_expr (temp_expr_table_p, value_expr_p);
01318 static inline value_expr_p find_value_in_list (value_expr_p, int,
01319 value_expr_p *);
01320 static inline void add_value_to_list (temp_expr_table_p, value_expr_p *, int);
01321 static inline void add_info_to_list (temp_expr_table_p, value_expr_p *,
01322 value_expr_p);
01323 static value_expr_p remove_value_from_list (value_expr_p *, int);
01324 static void add_dependence (temp_expr_table_p, int, tree);
01325 static bool check_replaceable (temp_expr_table_p, tree);
01326 static void finish_expr (temp_expr_table_p, int, bool);
01327 static void mark_replaceable (temp_expr_table_p, tree);
01328 static inline void kill_expr (temp_expr_table_p, int, bool);
01329 static inline void kill_virtual_exprs (temp_expr_table_p, bool);
01330 static void find_replaceable_in_bb (temp_expr_table_p, basic_block);
01331 static tree *find_replaceable_exprs (var_map);
01332 static void dump_replaceable_exprs (FILE *, tree *);
01333
01334
01335
01336
01337 static temp_expr_table_p
01338 new_temp_expr_table (var_map map)
01339 {
01340 temp_expr_table_p t;
01341
01342 t = XNEW (struct temp_expr_table_d);
01343 t->map = map;
01344
01345 t->version_info = XCNEWVEC (void *, num_ssa_names + 1);
01346 t->expr_vars = XCNEWVEC (bitmap, num_ssa_names + 1);
01347 t->partition_dep_list = XCNEWVEC (value_expr_p,
01348 num_var_partitions (map) + 1);
01349
01350 t->replaceable = BITMAP_ALLOC (NULL);
01351 t->partition_in_use = BITMAP_ALLOC (NULL);
01352
01353 t->saw_replaceable = false;
01354 t->virtual_partition = num_var_partitions (map);
01355 t->free_list = NULL;
01356 t->pending_dependence = NULL;
01357
01358 return t;
01359 }
01360
01361
01362
01363
01364
01365 static tree *
01366 free_temp_expr_table (temp_expr_table_p t)
01367 {
01368 value_expr_p p;
01369 tree *ret = NULL;
01370 unsigned i;
01371
01372 #ifdef ENABLE_CHECKING
01373 unsigned x;
01374 for (x = 0; x <= num_var_partitions (t->map); x++)
01375 gcc_assert (!t->partition_dep_list[x]);
01376 #endif
01377
01378 while ((p = t->free_list))
01379 {
01380 t->free_list = p->next;
01381 free (p);
01382 }
01383
01384 BITMAP_FREE (t->partition_in_use);
01385 BITMAP_FREE (t->replaceable);
01386
01387 for (i = 0; i <= num_ssa_names; i++)
01388 if (t->expr_vars[i])
01389 BITMAP_FREE (t->expr_vars[i]);
01390 free (t->expr_vars);
01391
01392 free (t->partition_dep_list);
01393 if (t->saw_replaceable)
01394 ret = (tree *)t->version_info;
01395 else
01396 free (t->version_info);
01397
01398 free (t);
01399 return ret;
01400 }
01401
01402
01403
01404
01405
01406 static inline value_expr_p
01407 new_value_expr (temp_expr_table_p table)
01408 {
01409 value_expr_p p;
01410 if (table->free_list)
01411 {
01412 p = table->free_list;
01413 table->free_list = p->next;
01414 }
01415 else
01416 p = (value_expr_p) xmalloc (sizeof (struct value_expr_d));
01417
01418 return p;
01419 }
01420
01421
01422
01423
01424 static inline void
01425 free_value_expr (temp_expr_table_p table, value_expr_p p)
01426 {
01427 p->next = table->free_list;
01428 table->free_list = p;
01429 }
01430
01431
01432
01433
01434
01435
01436 static inline value_expr_p
01437 find_value_in_list (value_expr_p list, int value, value_expr_p *last_ptr)
01438 {
01439 value_expr_p curr;
01440 value_expr_p last = NULL;
01441
01442 for (curr = list; curr; last = curr, curr = curr->next)
01443 {
01444 if (curr->value == value)
01445 break;
01446 }
01447 if (last_ptr)
01448 *last_ptr = last;
01449 return curr;
01450 }
01451
01452
01453
01454
01455
01456 static inline void
01457 add_value_to_list (temp_expr_table_p tab, value_expr_p *list, int value)
01458 {
01459 value_expr_p info;
01460
01461 if (!find_value_in_list (*list, value, NULL))
01462 {
01463 info = new_value_expr (tab);
01464 info->value = value;
01465 info->next = *list;
01466 *list = info;
01467 }
01468 }
01469
01470
01471
01472
01473
01474 static inline void
01475 add_info_to_list (temp_expr_table_p tab, value_expr_p *list, value_expr_p info)
01476 {
01477 if (find_value_in_list (*list, info->value, NULL))
01478 free_value_expr (tab, info);
01479 else
01480 {
01481 info->next = *list;
01482 *list = info;
01483 }
01484 }
01485
01486
01487
01488
01489
01490 static value_expr_p
01491 remove_value_from_list (value_expr_p *list, int value)
01492 {
01493 value_expr_p info, last;
01494
01495 info = find_value_in_list (*list, value, &last);
01496 if (!info)
01497 return NULL;
01498 if (!last)
01499 *list = info->next;
01500 else
01501 last->next = info->next;
01502
01503 return info;
01504 }
01505
01506
01507
01508
01509
01510
01511
01512 static void
01513 add_dependence (temp_expr_table_p tab, int version, tree var)
01514 {
01515 int i, x;
01516 value_expr_p info;
01517
01518 i = SSA_NAME_VERSION (var);
01519 if (bitmap_bit_p (tab->replaceable, i))
01520 {
01521
01522
01523 while ((info = tab->pending_dependence))
01524 {
01525 tab->pending_dependence = info->next;
01526
01527
01528 x = info->value;
01529 info->value = version;
01530 add_info_to_list (tab, &(tab->partition_dep_list[x]), info);
01531 add_value_to_list (tab,
01532 (value_expr_p *)&(tab->version_info[version]), x);
01533 bitmap_set_bit (tab->partition_in_use, x);
01534 }
01535 }
01536 else
01537 {
01538 i = var_to_partition (tab->map, var);
01539 gcc_assert (i != NO_PARTITION);
01540 add_value_to_list (tab, &(tab->partition_dep_list[i]), version);
01541 add_value_to_list (tab,
01542 (value_expr_p *)&(tab->version_info[version]), i);
01543 bitmap_set_bit (tab->partition_in_use, i);
01544 }
01545 }
01546
01547
01548
01549
01550
01551 static bool
01552 check_replaceable (temp_expr_table_p tab, tree stmt)
01553 {
01554 tree var, def, basevar;
01555 int version;
01556 var_map map = tab->map;
01557 ssa_op_iter iter;
01558 tree call_expr;
01559 bitmap def_vars, use_vars;
01560
01561 if (TREE_CODE (stmt) != MODIFY_EXPR)
01562 return false;
01563
01564
01565 def = SINGLE_SSA_TREE_OPERAND (stmt, SSA_OP_DEF);
01566 if (!def)
01567 return false;
01568
01569 if (version_ref_count (map, def) != 1)
01570 return false;
01571
01572
01573 if (!(ZERO_SSA_OPERANDS (stmt, (SSA_OP_VMAYDEF | SSA_OP_VMUSTDEF))))
01574 return false;
01575
01576
01577 if (flag_float_store && FLOAT_TYPE_P (TREE_TYPE (TREE_OPERAND (stmt, 1))))
01578 return false;
01579
01580
01581
01582 if (TREE_CODE (TREE_OPERAND (stmt, 1)) == VAR_DECL
01583 && DECL_HARD_REGISTER (TREE_OPERAND (stmt, 1)))
01584 return false;
01585
01586
01587 if ((call_expr = get_call_expr_in (stmt)) != NULL_TREE)
01588 {
01589 int call_flags = call_expr_flags (call_expr);
01590 if (TREE_SIDE_EFFECTS (call_expr)
01591 && !(call_flags & (ECF_PURE | ECF_CONST | ECF_NORETURN)))
01592 return false;
01593 }
01594
01595 version = SSA_NAME_VERSION (def);
01596 basevar = SSA_NAME_VAR (def);
01597 def_vars = BITMAP_ALLOC (NULL);
01598 bitmap_set_bit (def_vars, DECL_UID (basevar));
01599
01600
01601 FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, SSA_OP_USE)
01602 {
01603 add_dependence (tab, version, var);
01604
01605 use_vars = tab->expr_vars[SSA_NAME_VERSION (var)];
01606 if (use_vars)
01607 bitmap_ior_into (def_vars, use_vars);
01608 }
01609 tab->expr_vars[version] = def_vars;
01610
01611
01612 if (!ZERO_SSA_OPERANDS (stmt, SSA_OP_VUSE))
01613 {
01614 add_value_to_list (tab, (value_expr_p *)&(tab->version_info[version]),
01615 VIRTUAL_PARTITION (tab));
01616 add_value_to_list (tab,
01617 &(tab->partition_dep_list[VIRTUAL_PARTITION (tab)]),
01618 version);
01619 bitmap_set_bit (tab->partition_in_use, VIRTUAL_PARTITION (tab));
01620 }
01621
01622 return true;
01623 }
01624
01625
01626
01627
01628
01629
01630 static void
01631 finish_expr (temp_expr_table_p tab, int version, bool replace)
01632 {
01633 value_expr_p info, tmp;
01634 int partition;
01635
01636
01637
01638 for (info = (value_expr_p) tab->version_info[version]; info; info = tmp)
01639 {
01640 partition = info->value;
01641 gcc_assert (tab->partition_dep_list[partition]);
01642 tmp = remove_value_from_list (&(tab->partition_dep_list[partition]),
01643 version);
01644 gcc_assert (tmp);
01645 free_value_expr (tab, tmp);
01646
01647
01648 if (!(tab->partition_dep_list[partition]) && replace)
01649 bitmap_clear_bit (tab->partition_in_use, partition);
01650 tmp = info->next;
01651 if (!replace)
01652 free_value_expr (tab, info);
01653 }
01654
01655 if (replace)
01656 {
01657 tab->saw_replaceable = true;
01658 bitmap_set_bit (tab->replaceable, version);
01659 }
01660 else
01661 {
01662 gcc_assert (!bitmap_bit_p (tab->replaceable, version));
01663 tab->version_info[version] = NULL;
01664 }
01665 }
01666
01667
01668
01669
01670
01671 static void
01672 mark_replaceable (temp_expr_table_p tab, tree var)
01673 {
01674 value_expr_p info;
01675 int version = SSA_NAME_VERSION (var);
01676 finish_expr (tab, version, true);
01677
01678
01679 if (tab->version_info[version])
01680 {
01681 info = (value_expr_p) tab->version_info[version];
01682 for ( ; info->next; info = info->next)
01683 continue;
01684 info->next = tab->pending_dependence;
01685 tab->pending_dependence = (value_expr_p)tab->version_info[version];
01686 }
01687
01688 tab->version_info[version] = SSA_NAME_DEF_STMT (var);
01689 }
01690
01691
01692
01693
01694
01695
01696
01697 static inline void
01698 kill_expr (temp_expr_table_p tab, int partition, bool clear_bit)
01699 {
01700 value_expr_p ptr;
01701
01702
01703 while ((ptr = tab->partition_dep_list[partition]) != NULL)
01704 finish_expr (tab, ptr->value, false);
01705
01706 if (clear_bit)
01707 bitmap_clear_bit (tab->partition_in_use, partition);
01708 }
01709
01710
01711
01712
01713
01714 static inline void
01715 kill_virtual_exprs (temp_expr_table_p tab, bool clear_bit)
01716 {
01717 kill_expr (tab, VIRTUAL_PARTITION (tab), clear_bit);
01718 }
01719
01720
01721
01722
01723
01724 static void
01725 find_replaceable_in_bb (temp_expr_table_p tab, basic_block bb)
01726 {
01727 block_stmt_iterator bsi;
01728 tree stmt, def, use;
01729 stmt_ann_t ann;
01730 int partition;
01731 var_map map = tab->map;
01732 value_expr_p p;
01733 ssa_op_iter iter;
01734
01735 for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
01736 {
01737 stmt = bsi_stmt (bsi);
01738 ann = stmt_ann (stmt);
01739
01740
01741 FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE)
01742 {
01743 unsigned ver = SSA_NAME_VERSION (use);
01744
01745 if (tab->version_info[ver])
01746 {
01747 bool same_root_var = false;
01748 ssa_op_iter iter2;
01749 bitmap vars = tab->expr_vars[ver];
01750
01751
01752
01753
01754 FOR_EACH_SSA_TREE_OPERAND (def, stmt, iter2, SSA_OP_DEF)
01755 {
01756 if (bitmap_bit_p (vars, DECL_UID (SSA_NAME_VAR (def))))
01757 {
01758 same_root_var = true;
01759 break;
01760 }
01761 }
01762
01763
01764
01765 if (!ann->has_volatile_ops && !same_root_var)
01766 mark_replaceable (tab, use);
01767 else
01768 finish_expr (tab, ver, false);
01769 }
01770 }
01771
01772
01773 FOR_EACH_SSA_TREE_OPERAND (def, stmt, iter, SSA_OP_DEF)
01774 {
01775 partition = var_to_partition (map, def);
01776 if (partition != NO_PARTITION && tab->partition_dep_list[partition])
01777 kill_expr (tab, partition, true);
01778 }
01779
01780
01781 if (!ann->has_volatile_ops)
01782 check_replaceable (tab, stmt);
01783
01784
01785 while ((p = tab->pending_dependence))
01786 {
01787 tab->pending_dependence = p->next;
01788 free_value_expr (tab, p);
01789 }
01790
01791
01792 if (!ZERO_SSA_OPERANDS (stmt, SSA_OP_VIRTUAL_DEFS))
01793 kill_virtual_exprs (tab, true);
01794 }
01795 }
01796
01797
01798
01799
01800
01801
01802
01803
01804
01805
01806 static tree *
01807 find_replaceable_exprs (var_map map)
01808 {
01809 basic_block bb;
01810 unsigned i;
01811 temp_expr_table_p table;
01812 tree *ret;
01813
01814 table = new_temp_expr_table (map);
01815 FOR_EACH_BB (bb)
01816 {
01817 bitmap_iterator bi;
01818
01819 find_replaceable_in_bb (table, bb);
01820 EXECUTE_IF_SET_IN_BITMAP ((table->partition_in_use), 0, i, bi)
01821 {
01822 kill_expr (table, i, false);
01823 }
01824 }
01825
01826 ret = free_temp_expr_table (table);
01827 return ret;
01828 }
01829
01830
01831
01832
01833 static void
01834 dump_replaceable_exprs (FILE *f, tree *expr)
01835 {
01836 tree stmt, var;
01837 int x;
01838 fprintf (f, "\nReplacing Expressions\n");
01839 for (x = 0; x < (int)num_ssa_names + 1; x++)
01840 if (expr[x])
01841 {
01842 stmt = expr[x];
01843 var = SINGLE_SSA_TREE_OPERAND (stmt, SSA_OP_DEF);
01844 gcc_assert (var != NULL_TREE);
01845 print_generic_expr (f, var, TDF_SLIM);
01846 fprintf (f, " replace with --> ");
01847 print_generic_expr (f, TREE_OPERAND (stmt, 1), TDF_SLIM);
01848 fprintf (f, "\n");
01849 }
01850 fprintf (f, "\n");
01851 }
01852
01853
01854
01855
01856
01857
01858
01859
01860 static void
01861 rewrite_trees (var_map map, tree *values)
01862 {
01863 elim_graph g;
01864 basic_block bb;
01865 block_stmt_iterator si;
01866 edge e;
01867 tree phi;
01868 bool changed;
01869
01870 #ifdef ENABLE_CHECKING
01871
01872
01873
01874 FOR_EACH_BB (bb)
01875 {
01876 tree phi;
01877
01878 for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
01879 {
01880 tree T0 = var_to_partition_to_var (map, PHI_RESULT (phi));
01881
01882 if (T0 == NULL_TREE)
01883 {
01884 int i;
01885
01886 for (i = 0; i < PHI_NUM_ARGS (phi); i++)
01887 {
01888 tree arg = PHI_ARG_DEF (phi, i);
01889
01890 if (TREE_CODE (arg) == SSA_NAME
01891 && var_to_partition (map, arg) != NO_PARTITION)
01892 {
01893 fprintf (stderr, "Argument of PHI is in a partition :(");
01894 print_generic_expr (stderr, arg, TDF_SLIM);
01895 fprintf (stderr, "), but the result is not :");
01896 print_generic_stmt (stderr, phi, TDF_SLIM);
01897 internal_error ("SSA corruption");
01898 }
01899 }
01900 }
01901 }
01902 }
01903 #endif
01904
01905
01906 g = new_elim_graph (map->num_partitions);
01907 g->map = map;
01908 FOR_EACH_BB (bb)
01909 {
01910 for (si = bsi_start (bb); !bsi_end_p (si); )
01911 {
01912 tree stmt = bsi_stmt (si);
01913 use_operand_p use_p, copy_use_p;
01914 def_operand_p def_p;
01915 bool remove = false, is_copy = false;
01916 int num_uses = 0;
01917 stmt_ann_t ann;
01918 ssa_op_iter iter;
01919
01920 ann = stmt_ann (stmt);
01921 changed = false;
01922
01923 if (TREE_CODE (stmt) == MODIFY_EXPR
01924 && (TREE_CODE (TREE_OPERAND (stmt, 1)) == SSA_NAME))
01925 is_copy = true;
01926
01927 copy_use_p = NULL_USE_OPERAND_P;
01928 FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_USE)
01929 {
01930 if (replace_use_variable (map, use_p, values))
01931 changed = true;
01932 copy_use_p = use_p;
01933 num_uses++;
01934 }
01935
01936 if (num_uses != 1)
01937 is_copy = false;
01938
01939 def_p = SINGLE_SSA_DEF_OPERAND (stmt, SSA_OP_DEF);
01940
01941 if (def_p != NULL)
01942 {
01943
01944
01945 if (values && values[SSA_NAME_VERSION (DEF_FROM_PTR (def_p))])
01946 remove = true;
01947 else
01948 {
01949 if (replace_def_variable (map, def_p, NULL))
01950 changed = true;
01951
01952
01953 if (is_copy)
01954 {
01955 gcc_assert (copy_use_p != NULL_USE_OPERAND_P);
01956 if (DEF_FROM_PTR (def_p) == USE_FROM_PTR (copy_use_p))
01957 remove = true;
01958 }
01959 }
01960 }
01961 else
01962 FOR_EACH_SSA_DEF_OPERAND (def_p, stmt, iter, SSA_OP_DEF)
01963 if (replace_def_variable (map, def_p, NULL))
01964 changed = true;
01965
01966
01967 if (remove)
01968 bsi_remove (&si, true);
01969 else
01970 bsi_next (&si);
01971 }
01972
01973 phi = phi_nodes (bb);
01974 if (phi)
01975 {
01976 edge_iterator ei;
01977 FOR_EACH_EDGE (e, ei, bb->preds)
01978 eliminate_phi (e, g);
01979 }
01980 }
01981
01982 delete_elim_graph (g);
01983 }
01984
01985
01986 DEF_VEC_ALLOC_P(edge,heap);
01987
01988
01989
01990 static VEC(edge,heap) *edge_leader;
01991 static VEC(tree,heap) *stmt_list;
01992 static bitmap leader_has_match = NULL;
01993 static edge leader_match = NULL;
01994
01995
01996
01997
01998 static bool
01999 same_stmt_list_p (edge e)
02000 {
02001 return (e->aux == (PTR) leader_match) ? true : false;
02002 }
02003
02004
02005
02006 static inline bool
02007 identical_copies_p (tree s1, tree s2)
02008 {
02009 #ifdef ENABLE_CHECKING
02010 gcc_assert (TREE_CODE (s1) == MODIFY_EXPR);
02011 gcc_assert (TREE_CODE (s2) == MODIFY_EXPR);
02012 gcc_assert (DECL_P (TREE_OPERAND (s1, 0)));
02013 gcc_assert (DECL_P (TREE_OPERAND (s2, 0)));
02014 #endif
02015
02016 if (TREE_OPERAND (s1, 0) != TREE_OPERAND (s2, 0))
02017 return false;
02018
02019 s1 = TREE_OPERAND (s1, 1);
02020 s2 = TREE_OPERAND (s2, 1);
02021
02022 if (s1 != s2)
02023 return false;
02024
02025 return true;
02026 }
02027
02028
02029
02030
02031
02032 static inline bool
02033 identical_stmt_lists_p (edge e1, edge e2)
02034 {
02035 tree t1 = PENDING_STMT (e1);
02036 tree t2 = PENDING_STMT (e2);
02037 tree_stmt_iterator tsi1, tsi2;
02038
02039 gcc_assert (TREE_CODE (t1) == STATEMENT_LIST);
02040 gcc_assert (TREE_CODE (t2) == STATEMENT_LIST);
02041
02042 for (tsi1 = tsi_start (t1), tsi2 = tsi_start (t2);
02043 !tsi_end_p (tsi1) && !tsi_end_p (tsi2);
02044 tsi_next (&tsi1), tsi_next (&tsi2))
02045 {
02046 if (!identical_copies_p (tsi_stmt (tsi1), tsi_stmt (tsi2)))
02047 break;
02048 }
02049
02050 if (!tsi_end_p (tsi1) || ! tsi_end_p (tsi2))
02051 return false;
02052
02053 return true;
02054 }
02055
02056
02057
02058
02059 static void
02060 init_analyze_edges_for_bb (void)
02061 {
02062 edge_leader = VEC_alloc (edge, heap, 25);
02063 stmt_list = VEC_alloc (tree, heap, 25);
02064 leader_has_match = BITMAP_ALLOC (NULL);
02065 }
02066
02067
02068
02069
02070 static void
02071 fini_analyze_edges_for_bb (void)
02072 {
02073 VEC_free (edge, heap, edge_leader);
02074 VEC_free (tree, heap, stmt_list);
02075 BITMAP_FREE (leader_has_match);
02076 }
02077
02078
02079
02080
02081
02082 static void
02083 analyze_edges_for_bb (basic_block bb)
02084 {
02085 edge e;
02086 edge_iterator ei;
02087 int count;
02088 unsigned int x;
02089 bool have_opportunity;
02090 block_stmt_iterator bsi;
02091 tree stmt;
02092 edge single_edge = NULL;
02093 bool is_label;
02094 edge leader;
02095
02096 count = 0;
02097
02098
02099
02100
02101 have_opportunity = true;
02102 FOR_EACH_EDGE (e, ei, bb->preds)
02103 if (e->flags & EDGE_ABNORMAL)
02104 {
02105 have_opportunity = false;
02106 break;
02107 }
02108
02109 if (!have_opportunity)
02110 {
02111 FOR_EACH_EDGE (e, ei, bb->preds)
02112 if (PENDING_STMT (e))
02113 bsi_commit_one_edge_insert (e, NULL);
02114 return;
02115 }
02116
02117
02118 FOR_EACH_EDGE (e, ei, bb->preds)
02119 {
02120 if (PENDING_STMT (e))
02121 {
02122 gcc_assert (!(e->flags & EDGE_ABNORMAL));
02123 if (e->flags & EDGE_FALLTHRU)
02124 {
02125 bsi = bsi_start (e->src);
02126 if (!bsi_end_p (bsi))
02127 {
02128 stmt = bsi_stmt (bsi);
02129 bsi_next (&bsi);
02130 gcc_assert (stmt != NULL_TREE);
02131 is_label = (TREE_CODE (stmt) == LABEL_EXPR);
02132
02133 if (!is_label || DECL_NONLOCAL (TREE_OPERAND (stmt, 0))
02134 || !bsi_end_p (bsi))
02135 {
02136 bsi_commit_one_edge_insert (e, NULL);
02137 continue;
02138 }
02139 }
02140 }
02141 single_edge = e;
02142 count++;
02143 }
02144 }
02145
02146
02147 if (count < 2)
02148 {
02149 if (single_edge)
02150 bsi_commit_one_edge_insert (single_edge, NULL);
02151 return;
02152 }
02153
02154
02155 #ifdef ENABLE_CHECKING
02156 gcc_assert (VEC_length (edge, edge_leader) == 0);
02157 gcc_assert (VEC_length (tree, stmt_list) == 0);
02158 gcc_assert (bitmap_empty_p (leader_has_match));
02159 #endif
02160
02161
02162
02163
02164
02165 have_opportunity = false;
02166 FOR_EACH_EDGE (e, ei, bb->preds)
02167 {
02168 if (PENDING_STMT (e))
02169 {
02170 bool found = false;
02171
02172
02173 for (x = 0; VEC_iterate (edge, edge_leader, x, leader); x++)
02174 {
02175 if (identical_stmt_lists_p (leader, e))
02176 {
02177
02178 PENDING_STMT (e) = NULL;
02179 e->aux = leader;
02180 bitmap_set_bit (leader_has_match, x);
02181 have_opportunity = found = true;
02182 break;
02183 }
02184 }
02185
02186
02187 if (!found)
02188 {
02189 VEC_safe_push (edge, heap, edge_leader, e);
02190 VEC_safe_push (tree, heap, stmt_list, PENDING_STMT (e));
02191 }
02192 }
02193 }
02194
02195
02196 if (!have_opportunity)
02197 {
02198 for (x = 0; VEC_iterate (edge, edge_leader, x, leader); x++)
02199 bsi_commit_one_edge_insert (leader, NULL);
02200 VEC_truncate (edge, edge_leader, 0);
02201 VEC_truncate (tree, stmt_list, 0);
02202 bitmap_clear (leader_has_match);
02203 return;
02204 }
02205
02206
02207 if (dump_file)
02208 fprintf (dump_file, "\nOpportunities in BB %d for stmt/block reduction:\n",
02209 bb->index);
02210
02211
02212
02213
02214 for (x = 0; VEC_iterate (edge, edge_leader, x, leader); x++)
02215 if (bitmap_bit_p (leader_has_match, x))
02216 {
02217 edge new_edge;
02218 block_stmt_iterator bsi;
02219 tree curr_stmt_list;
02220
02221 leader_match = leader;
02222
02223
02224
02225
02226
02227 PENDING_STMT (leader) = NULL;
02228 leader->aux = leader;
02229 curr_stmt_list = VEC_index (tree, stmt_list, x);
02230
02231 new_edge = make_forwarder_block (leader->dest, same_stmt_list_p,
02232 NULL);
02233 bb = new_edge->dest;
02234 if (dump_file)
02235 {
02236 fprintf (dump_file, "Splitting BB %d for Common stmt list. ",
02237 leader->dest->index);
02238 fprintf (dump_file, "Original block is now BB%d.\n", bb->index);
02239 print_generic_stmt (dump_file, curr_stmt_list, TDF_VOPS);
02240 }
02241
02242 FOR_EACH_EDGE (e, ei, new_edge->src->preds)
02243 {
02244 e->aux = NULL;
02245 if (dump_file)
02246 fprintf (dump_file, " Edge (%d->%d) lands here.\n",
02247 e->src->index, e->dest->index);
02248 }
02249
02250 bsi = bsi_last (leader->dest);
02251 bsi_insert_after (&bsi, curr_stmt_list, BSI_NEW_STMT);
02252
02253 leader_match = NULL;
02254
02255 }
02256 else
02257 {
02258 PENDING_STMT (leader) = VEC_index (tree, stmt_list, x);
02259 bsi_commit_one_edge_insert (leader, NULL);
02260 }
02261
02262
02263
02264 VEC_truncate (edge, edge_leader, 0);
02265 VEC_truncate (tree, stmt_list, 0);
02266 bitmap_clear (leader_has_match);
02267 }
02268
02269
02270
02271
02272
02273
02274
02275 static void
02276 perform_edge_inserts (void)
02277 {
02278 basic_block bb;
02279
02280 if (dump_file)
02281 fprintf(dump_file, "Analyzing Edge Insertions.\n");
02282
02283
02284
02285
02286
02287 free_dominance_info (CDI_DOMINATORS);
02288 free_dominance_info (CDI_POST_DOMINATORS);
02289
02290
02291 init_analyze_edges_for_bb ();
02292
02293 FOR_EACH_BB (bb)
02294 analyze_edges_for_bb (bb);
02295
02296 analyze_edges_for_bb (EXIT_BLOCK_PTR);
02297
02298
02299 fini_analyze_edges_for_bb ();
02300
02301 #ifdef ENABLE_CHECKING
02302 {
02303 edge_iterator ei;
02304 edge e;
02305 FOR_EACH_BB (bb)
02306 {
02307 FOR_EACH_EDGE (e, ei, bb->preds)
02308 {
02309 if (PENDING_STMT (e))
02310 error (" Pending stmts not issued on PRED edge (%d, %d)\n",
02311 e->src->index, e->dest->index);
02312 }
02313 FOR_EACH_EDGE (e, ei, bb->succs)
02314 {
02315 if (PENDING_STMT (e))
02316 error (" Pending stmts not issued on SUCC edge (%d, %d)\n",
02317 e->src->index, e->dest->index);
02318 }
02319 }
02320 FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR->succs)
02321 {
02322 if (PENDING_STMT (e))
02323 error (" Pending stmts not issued on ENTRY edge (%d, %d)\n",
02324 e->src->index, e->dest->index);
02325 }
02326 FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR->preds)
02327 {
02328 if (PENDING_STMT (e))
02329 error (" Pending stmts not issued on EXIT edge (%d, %d)\n",
02330 e->src->index, e->dest->index);
02331 }
02332 }
02333 #endif
02334 }
02335
02336
02337
02338
02339
02340 static void
02341 remove_ssa_form (var_map map, int flags)
02342 {
02343 tree_live_info_p liveinfo;
02344 basic_block bb;
02345 tree phi, next;
02346 tree *values = NULL;
02347
02348
02349
02350 if ((flags & SSANORM_COMBINE_TEMPS) == 0)
02351 compact_var_map (map, VARMAP_NO_SINGLE_DEFS);
02352 else
02353 compact_var_map (map, VARMAP_NORMAL);
02354
02355 if (dump_file && (dump_flags & TDF_DETAILS))
02356 dump_var_map (dump_file, map);
02357
02358 liveinfo = coalesce_ssa_name (map, flags);
02359
02360
02361 if ((flags & SSANORM_COMBINE_TEMPS) == 0)
02362 compact_var_map (map, VARMAP_NORMAL);
02363
02364 if (dump_file && (dump_flags & TDF_DETAILS))
02365 {
02366 fprintf (dump_file, "After Coalescing:\n");
02367 dump_var_map (dump_file, map);
02368 }
02369
02370 if (flags & SSANORM_PERFORM_TER)
02371 {
02372 values = find_replaceable_exprs (map);
02373 if (values && dump_file && (dump_flags & TDF_DETAILS))
02374 dump_replaceable_exprs (dump_file, values);
02375 }
02376
02377
02378 assign_vars (map);
02379
02380 if (dump_file && (dump_flags & TDF_DETAILS))
02381 {
02382 fprintf (dump_file, "After Root variable replacement:\n");
02383 dump_var_map (dump_file, map);
02384 }
02385
02386 if ((flags & SSANORM_COMBINE_TEMPS) && liveinfo)
02387 {
02388 coalesce_vars (map, liveinfo);
02389 if (dump_file && (dump_flags & TDF_DETAILS))
02390 {
02391 fprintf (dump_file, "After variable memory coalescing:\n");
02392 dump_var_map (dump_file, map);
02393 }
02394 }
02395
02396 if (liveinfo)
02397 delete_tree_live_info (liveinfo);
02398
02399 rewrite_trees (map, values);
02400
02401 if (values)
02402 free (values);
02403
02404
02405 FOR_EACH_BB (bb)
02406 {
02407 for (phi = phi_nodes (bb); phi; phi = next)
02408 {
02409 next = PHI_CHAIN (phi);
02410 remove_phi_node (phi, NULL_TREE);
02411 }
02412 }
02413
02414
02415 fini_ssa_operands ();
02416
02417
02418 perform_edge_inserts ();
02419 }
02420
02421
02422
02423
02424
02425
02426
02427
02428
02429
02430 static void
02431 insert_backedge_copies (void)
02432 {
02433 basic_block bb;
02434
02435 FOR_EACH_BB (bb)
02436 {
02437 tree phi;
02438
02439 for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
02440 {
02441 tree result = PHI_RESULT (phi);
02442 tree result_var;
02443 int i;
02444
02445 if (!is_gimple_reg (result))
02446 continue;
02447
02448 result_var = SSA_NAME_VAR (result);
02449 for (i = 0; i < PHI_NUM_ARGS (phi); i++)
02450 {
02451 tree arg = PHI_ARG_DEF (phi, i);
02452 edge e = PHI_ARG_EDGE (phi, i);
02453
02454
02455
02456
02457
02458
02459 if ((e->flags & EDGE_DFS_BACK)
02460 && (TREE_CODE (arg) != SSA_NAME
02461 || (!flag_tree_combine_temps
02462 && SSA_NAME_VAR (arg) != result_var)))
02463 {
02464 tree stmt, name, last = NULL;
02465 block_stmt_iterator bsi;
02466
02467 bsi = bsi_last (PHI_ARG_EDGE (phi, i)->src);
02468 if (!bsi_end_p (bsi))
02469 last = bsi_stmt (bsi);
02470
02471
02472
02473
02474
02475
02476
02477
02478
02479 if (last && stmt_ends_bb_p (last))
02480 {
02481
02482
02483
02484 if (TREE_CODE (arg) == SSA_NAME
02485 && SSA_NAME_DEF_STMT (arg) == last)
02486 continue;
02487 }
02488
02489
02490
02491 stmt = build2 (MODIFY_EXPR, TREE_TYPE (result_var),
02492 NULL_TREE, PHI_ARG_DEF (phi, i));
02493 name = make_ssa_name (result_var, stmt);
02494 TREE_OPERAND (stmt, 0) = name;
02495
02496
02497
02498 if (last && stmt_ends_bb_p (last))
02499 bsi_insert_before (&bsi, stmt, BSI_NEW_STMT);
02500 else
02501 bsi_insert_after (&bsi, stmt, BSI_NEW_STMT);
02502 SET_PHI_ARG_DEF (phi, i, name);
02503 }
02504 }
02505 }
02506 }
02507 }
02508
02509
02510
02511
02512
02513 static unsigned int
02514 rewrite_out_of_ssa (void)
02515 {
02516 var_map map;
02517 int var_flags = 0;
02518 int ssa_flags = 0;
02519
02520
02521
02522
02523
02524
02525
02526 insert_backedge_copies ();
02527
02528 if (!flag_tree_live_range_split)
02529 ssa_flags |= SSANORM_COALESCE_PARTITIONS;
02530
02531 eliminate_virtual_phis ();
02532
02533 if (dump_file && (dump_flags & TDF_DETAILS))
02534 dump_tree_cfg (dump_file, dump_flags & ~TDF_DETAILS);
02535
02536
02537 if (flag_tree_ter && !flag_mudflap)
02538 var_flags = SSA_VAR_MAP_REF_COUNT;
02539
02540 map = create_ssa_var_map (var_flags);
02541
02542 if (flag_tree_combine_temps)
02543 ssa_flags |= SSANORM_COMBINE_TEMPS;
02544 if (flag_tree_ter && !flag_mudflap)
02545 ssa_flags |= SSANORM_PERFORM_TER;
02546
02547 remove_ssa_form (map, ssa_flags);
02548
02549 if (dump_file && (dump_flags & TDF_DETAILS))
02550 dump_tree_cfg (dump_file, dump_flags & ~TDF_DETAILS);
02551
02552
02553 delete_var_map (map);
02554
02555 in_ssa_p = false;
02556 return 0;
02557 }
02558
02559
02560
02561
02562 struct tree_opt_pass pass_del_ssa =
02563 {
02564 "optimized",
02565 NULL,
02566 rewrite_out_of_ssa,
02567 NULL,
02568 NULL,
02569 0,
02570 TV_TREE_SSA_TO_NORMAL,
02571 PROP_cfg | PROP_ssa | PROP_alias,
02572 0,
02573
02574 PROP_ssa,
02575 TODO_verify_ssa | TODO_verify_flow
02576 | TODO_verify_stmts,
02577 TODO_dump_func
02578 | TODO_ggc_collect
02579 | TODO_remove_unused_locals,
02580 0
02581 };