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 "basic-block.h"
00032 #include "output.h"
00033 #include "errors.h"
00034 #include "expr.h"
00035 #include "function.h"
00036 #include "diagnostic.h"
00037 #include "timevar.h"
00038 #include "tree-dump.h"
00039 #include "tree-flow.h"
00040 #include "tree-pass.h"
00041 #include "tree-ssa-propagate.h"
00042 #include "langhooks.h"
00043 #include "varray.h"
00044 #include "vec.h"
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119 static ssa_prop_visit_stmt_fn ssa_prop_visit_stmt;
00120 static ssa_prop_visit_phi_fn ssa_prop_visit_phi;
00121
00122
00123
00124
00125
00126
00127
00128 #define STMT_IN_SSA_EDGE_WORKLIST(T) TREE_DEPRECATED (T)
00129
00130
00131 static sbitmap executable_blocks;
00132
00133
00134 static GTY(()) varray_type cfg_blocks = NULL;
00135
00136 static unsigned int cfg_blocks_num = 0;
00137 static int cfg_blocks_tail;
00138 static int cfg_blocks_head;
00139
00140 static sbitmap bb_in_list;
00141
00142
00143
00144
00145
00146 static GTY(()) VEC(tree) *interesting_ssa_edges;
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162 static GTY(()) VEC(tree) *varying_ssa_edges;
00163
00164
00165
00166
00167 static inline bool
00168 cfg_blocks_empty_p (void)
00169 {
00170 return (cfg_blocks_num == 0);
00171 }
00172
00173
00174
00175
00176
00177 static void
00178 cfg_blocks_add (basic_block bb)
00179 {
00180 gcc_assert (bb != ENTRY_BLOCK_PTR && bb != EXIT_BLOCK_PTR);
00181 gcc_assert (!TEST_BIT (bb_in_list, bb->index));
00182
00183 if (cfg_blocks_empty_p ())
00184 {
00185 cfg_blocks_tail = cfg_blocks_head = 0;
00186 cfg_blocks_num = 1;
00187 }
00188 else
00189 {
00190 cfg_blocks_num++;
00191 if (cfg_blocks_num > VARRAY_SIZE (cfg_blocks))
00192 {
00193
00194
00195 cfg_blocks_tail = VARRAY_SIZE (cfg_blocks);
00196 cfg_blocks_head = 0;
00197 VARRAY_GROW (cfg_blocks, 2 * VARRAY_SIZE (cfg_blocks));
00198 }
00199 else
00200 cfg_blocks_tail = (cfg_blocks_tail + 1) % VARRAY_SIZE (cfg_blocks);
00201 }
00202
00203 VARRAY_BB (cfg_blocks, cfg_blocks_tail) = bb;
00204 SET_BIT (bb_in_list, bb->index);
00205 }
00206
00207
00208
00209
00210 static basic_block
00211 cfg_blocks_get (void)
00212 {
00213 basic_block bb;
00214
00215 bb = VARRAY_BB (cfg_blocks, cfg_blocks_head);
00216
00217 gcc_assert (!cfg_blocks_empty_p ());
00218 gcc_assert (bb);
00219
00220 cfg_blocks_head = (cfg_blocks_head + 1) % VARRAY_SIZE (cfg_blocks);
00221 --cfg_blocks_num;
00222 RESET_BIT (bb_in_list, bb->index);
00223
00224 return bb;
00225 }
00226
00227
00228
00229
00230
00231
00232 static void
00233 add_ssa_edge (tree var, bool is_varying)
00234 {
00235 tree stmt = SSA_NAME_DEF_STMT (var);
00236 dataflow_t df = get_immediate_uses (stmt);
00237 int num_uses = num_immediate_uses (df);
00238 int i;
00239
00240 for (i = 0; i < num_uses; i++)
00241 {
00242 tree use_stmt = immediate_use (df, i);
00243
00244 if (!DONT_SIMULATE_AGAIN (use_stmt)
00245 && !STMT_IN_SSA_EDGE_WORKLIST (use_stmt))
00246 {
00247 STMT_IN_SSA_EDGE_WORKLIST (use_stmt) = 1;
00248 if (is_varying)
00249 VEC_safe_push (tree, varying_ssa_edges, use_stmt);
00250 else
00251 VEC_safe_push (tree, interesting_ssa_edges, use_stmt);
00252 }
00253 }
00254 }
00255
00256
00257
00258
00259 static void
00260 add_control_edge (edge e)
00261 {
00262 basic_block bb = e->dest;
00263 if (bb == EXIT_BLOCK_PTR)
00264 return;
00265
00266
00267 if (e->flags & EDGE_EXECUTABLE)
00268 return;
00269
00270 e->flags |= EDGE_EXECUTABLE;
00271
00272
00273 if (TEST_BIT (bb_in_list, bb->index))
00274 return;
00275
00276 cfg_blocks_add (bb);
00277
00278 if (dump_file && (dump_flags & TDF_DETAILS))
00279 fprintf (dump_file, "Adding Destination of edge (%d -> %d) to worklist\n\n",
00280 e->src->index, e->dest->index);
00281 }
00282
00283
00284
00285
00286 static void
00287 simulate_stmt (tree stmt)
00288 {
00289 enum ssa_prop_result val = SSA_PROP_NOT_INTERESTING;
00290 edge taken_edge = NULL;
00291 tree output_name = NULL_TREE;
00292
00293
00294
00295 if (DONT_SIMULATE_AGAIN (stmt))
00296 return;
00297
00298 if (TREE_CODE (stmt) == PHI_NODE)
00299 {
00300 val = ssa_prop_visit_phi (stmt);
00301 output_name = PHI_RESULT (stmt);
00302 }
00303 else
00304 val = ssa_prop_visit_stmt (stmt, &taken_edge, &output_name);
00305
00306 if (val == SSA_PROP_VARYING)
00307 {
00308 DONT_SIMULATE_AGAIN (stmt) = 1;
00309
00310
00311
00312 if (output_name)
00313 add_ssa_edge (output_name, true);
00314
00315
00316
00317 if (stmt_ends_bb_p (stmt))
00318 {
00319 edge e;
00320 edge_iterator ei;
00321 basic_block bb = bb_for_stmt (stmt);
00322 FOR_EACH_EDGE (e, ei, bb->succs)
00323 add_control_edge (e);
00324 }
00325 }
00326 else if (val == SSA_PROP_INTERESTING)
00327 {
00328
00329
00330 if (output_name)
00331 add_ssa_edge (output_name, false);
00332
00333
00334
00335 if (taken_edge)
00336 add_control_edge (taken_edge);
00337 }
00338 }
00339
00340
00341
00342
00343
00344
00345
00346 static void
00347 process_ssa_edge_worklist (VEC(tree) **worklist)
00348 {
00349
00350 while (VEC_length (tree, *worklist) > 0)
00351 {
00352 basic_block bb;
00353
00354
00355 tree stmt = VEC_pop (tree, *worklist);
00356
00357
00358
00359 if (!STMT_IN_SSA_EDGE_WORKLIST (stmt))
00360 continue;
00361
00362
00363 STMT_IN_SSA_EDGE_WORKLIST (stmt) = 0;
00364
00365 if (dump_file && (dump_flags & TDF_DETAILS))
00366 {
00367 fprintf (dump_file, "\nSimulating statement (from ssa_edges): ");
00368 print_generic_stmt (dump_file, stmt, dump_flags);
00369 }
00370
00371 bb = bb_for_stmt (stmt);
00372
00373
00374
00375
00376 if (TREE_CODE (stmt) == PHI_NODE
00377 || TEST_BIT (executable_blocks, bb->index))
00378 simulate_stmt (stmt);
00379 }
00380 }
00381
00382
00383
00384
00385
00386 static void
00387 simulate_block (basic_block block)
00388 {
00389 tree phi;
00390
00391
00392 if (block == EXIT_BLOCK_PTR)
00393 return;
00394
00395 if (dump_file && (dump_flags & TDF_DETAILS))
00396 fprintf (dump_file, "\nSimulating block %d\n", block->index);
00397
00398
00399
00400 for (phi = phi_nodes (block); phi; phi = PHI_CHAIN (phi))
00401 simulate_stmt (phi);
00402
00403
00404
00405 if (!TEST_BIT (executable_blocks, block->index))
00406 {
00407 block_stmt_iterator j;
00408 unsigned int normal_edge_count;
00409 edge e, normal_edge;
00410 edge_iterator ei;
00411
00412
00413 SET_BIT (executable_blocks, block->index);
00414
00415 for (j = bsi_start (block); !bsi_end_p (j); bsi_next (&j))
00416 {
00417 tree stmt = bsi_stmt (j);
00418
00419
00420
00421
00422
00423
00424 if (STMT_IN_SSA_EDGE_WORKLIST (stmt))
00425 STMT_IN_SSA_EDGE_WORKLIST (stmt) = 0;
00426
00427 simulate_stmt (stmt);
00428 }
00429
00430
00431
00432
00433
00434
00435
00436
00437 normal_edge_count = 0;
00438 normal_edge = NULL;
00439 FOR_EACH_EDGE (e, ei, block->succs)
00440 {
00441 if (e->flags & EDGE_ABNORMAL)
00442 add_control_edge (e);
00443 else
00444 {
00445 normal_edge_count++;
00446 normal_edge = e;
00447 }
00448 }
00449
00450 if (normal_edge_count == 1)
00451 add_control_edge (normal_edge);
00452 }
00453 }
00454
00455
00456
00457
00458 static void
00459 ssa_prop_init (void)
00460 {
00461 edge e;
00462 edge_iterator ei;
00463 basic_block bb;
00464
00465
00466 interesting_ssa_edges = VEC_alloc (tree, 20);
00467 varying_ssa_edges = VEC_alloc (tree, 20);
00468
00469 executable_blocks = sbitmap_alloc (last_basic_block);
00470 sbitmap_zero (executable_blocks);
00471
00472 bb_in_list = sbitmap_alloc (last_basic_block);
00473 sbitmap_zero (bb_in_list);
00474
00475 if (dump_file && (dump_flags & TDF_DETAILS))
00476 dump_immediate_uses (dump_file);
00477
00478 VARRAY_BB_INIT (cfg_blocks, 20, "cfg_blocks");
00479
00480
00481
00482 FOR_ALL_BB (bb)
00483 {
00484 block_stmt_iterator si;
00485
00486 for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si))
00487 STMT_IN_SSA_EDGE_WORKLIST (bsi_stmt (si)) = 0;
00488
00489 FOR_EACH_EDGE (e, ei, bb->succs)
00490 e->flags &= ~EDGE_EXECUTABLE;
00491 }
00492
00493
00494
00495 FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR->succs)
00496 add_control_edge (e);
00497 }
00498
00499
00500
00501
00502 static void
00503 ssa_prop_fini (void)
00504 {
00505 VEC_free (tree, interesting_ssa_edges);
00506 VEC_free (tree, varying_ssa_edges);
00507 cfg_blocks = NULL;
00508 sbitmap_free (bb_in_list);
00509 sbitmap_free (executable_blocks);
00510 free_df ();
00511 }
00512
00513
00514
00515
00516 tree
00517 get_rhs (tree stmt)
00518 {
00519 enum tree_code code = TREE_CODE (stmt);
00520
00521 switch (code)
00522 {
00523 case RETURN_EXPR:
00524 stmt = TREE_OPERAND (stmt, 0);
00525 if (!stmt || TREE_CODE (stmt) != MODIFY_EXPR)
00526 return stmt;
00527
00528
00529 case MODIFY_EXPR:
00530 stmt = TREE_OPERAND (stmt, 1);
00531 if (TREE_CODE (stmt) == WITH_SIZE_EXPR)
00532 return TREE_OPERAND (stmt, 0);
00533 else
00534 return stmt;
00535
00536 case COND_EXPR:
00537 return COND_EXPR_COND (stmt);
00538 case SWITCH_EXPR:
00539 return SWITCH_COND (stmt);
00540 case GOTO_EXPR:
00541 return GOTO_DESTINATION (stmt);
00542 case LABEL_EXPR:
00543 return LABEL_EXPR_LABEL (stmt);
00544
00545 default:
00546 return stmt;
00547 }
00548 }
00549
00550
00551
00552
00553
00554
00555 bool
00556 set_rhs (tree *stmt_p, tree expr)
00557 {
00558 tree stmt = *stmt_p, op;
00559 enum tree_code code = TREE_CODE (expr);
00560 stmt_ann_t ann;
00561 tree var;
00562 ssa_op_iter iter;
00563
00564
00565 if (TREE_CODE_CLASS (code) == tcc_binary)
00566 {
00567 if (!is_gimple_val (TREE_OPERAND (expr, 0))
00568 || !is_gimple_val (TREE_OPERAND (expr, 1)))
00569 return false;
00570 }
00571 else if (TREE_CODE_CLASS (code) == tcc_unary)
00572 {
00573 if (!is_gimple_val (TREE_OPERAND (expr, 0)))
00574 return false;
00575 }
00576 else if (code == COMPOUND_EXPR)
00577 return false;
00578
00579 switch (TREE_CODE (stmt))
00580 {
00581 case RETURN_EXPR:
00582 op = TREE_OPERAND (stmt, 0);
00583 if (TREE_CODE (op) != MODIFY_EXPR)
00584 {
00585 TREE_OPERAND (stmt, 0) = expr;
00586 break;
00587 }
00588 stmt = op;
00589
00590
00591 case MODIFY_EXPR:
00592 op = TREE_OPERAND (stmt, 1);
00593 if (TREE_CODE (op) == WITH_SIZE_EXPR)
00594 stmt = op;
00595 TREE_OPERAND (stmt, 1) = expr;
00596 break;
00597
00598 case COND_EXPR:
00599 COND_EXPR_COND (stmt) = expr;
00600 break;
00601 case SWITCH_EXPR:
00602 SWITCH_COND (stmt) = expr;
00603 break;
00604 case GOTO_EXPR:
00605 GOTO_DESTINATION (stmt) = expr;
00606 break;
00607 case LABEL_EXPR:
00608 LABEL_EXPR_LABEL (stmt) = expr;
00609 break;
00610
00611 default:
00612
00613
00614 ann = stmt_ann (stmt);
00615 *stmt_p = TREE_SIDE_EFFECTS (expr) ? expr : build_empty_stmt ();
00616 (*stmt_p)->common.ann = (tree_ann_t) ann;
00617
00618 if (TREE_SIDE_EFFECTS (expr))
00619 {
00620
00621
00622 FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, SSA_OP_ALL_DEFS)
00623 {
00624 if (TREE_CODE (var) == SSA_NAME)
00625 SSA_NAME_DEF_STMT (var) = *stmt_p;
00626 }
00627 }
00628 break;
00629 }
00630
00631 return true;
00632 }
00633
00634
00635
00636
00637
00638
00639
00640 void
00641 ssa_propagate (ssa_prop_visit_stmt_fn visit_stmt,
00642 ssa_prop_visit_phi_fn visit_phi)
00643 {
00644 ssa_prop_visit_stmt = visit_stmt;
00645 ssa_prop_visit_phi = visit_phi;
00646
00647 ssa_prop_init ();
00648
00649
00650 while (!cfg_blocks_empty_p ()
00651 || VEC_length (tree, interesting_ssa_edges) > 0
00652 || VEC_length (tree, varying_ssa_edges) > 0)
00653 {
00654 if (!cfg_blocks_empty_p ())
00655 {
00656
00657 basic_block dest_block = cfg_blocks_get ();
00658 simulate_block (dest_block);
00659 }
00660
00661
00662
00663 process_ssa_edge_worklist (&varying_ssa_edges);
00664
00665
00666 process_ssa_edge_worklist (&interesting_ssa_edges);
00667 }
00668
00669 ssa_prop_fini ();
00670 }
00671
00672 #include "gt-tree-ssa-propagate.h"