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