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 "expr.h"
00034 #include "function.h"
00035 #include "diagnostic.h"
00036 #include "timevar.h"
00037 #include "tree-dump.h"
00038 #include "tree-flow.h"
00039 #include "tree-pass.h"
00040 #include "tree-ssa-propagate.h"
00041 #include "langhooks.h"
00042 #include "varray.h"
00043 #include "vec.h"
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
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 static ssa_prop_visit_stmt_fn ssa_prop_visit_stmt;
00119 static ssa_prop_visit_phi_fn ssa_prop_visit_phi;
00120
00121
00122
00123
00124
00125
00126
00127 #define STMT_IN_SSA_EDGE_WORKLIST(T) TREE_DEPRECATED (T)
00128
00129
00130 static sbitmap executable_blocks;
00131
00132
00133 static VEC(basic_block,heap) *cfg_blocks;
00134
00135 static unsigned int cfg_blocks_num = 0;
00136 static int cfg_blocks_tail;
00137 static int cfg_blocks_head;
00138
00139 static sbitmap bb_in_list;
00140
00141
00142
00143
00144
00145 static GTY(()) VEC(tree,gc) *interesting_ssa_edges;
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161 static GTY(()) VEC(tree,gc) *varying_ssa_edges;
00162
00163
00164
00165
00166 static inline bool
00167 cfg_blocks_empty_p (void)
00168 {
00169 return (cfg_blocks_num == 0);
00170 }
00171
00172
00173
00174
00175
00176 static void
00177 cfg_blocks_add (basic_block bb)
00178 {
00179 gcc_assert (bb != ENTRY_BLOCK_PTR && bb != EXIT_BLOCK_PTR);
00180 gcc_assert (!TEST_BIT (bb_in_list, bb->index));
00181
00182 if (cfg_blocks_empty_p ())
00183 {
00184 cfg_blocks_tail = cfg_blocks_head = 0;
00185 cfg_blocks_num = 1;
00186 }
00187 else
00188 {
00189 cfg_blocks_num++;
00190 if (cfg_blocks_num > VEC_length (basic_block, cfg_blocks))
00191 {
00192
00193
00194
00195
00196
00197 cfg_blocks_tail = VEC_length (basic_block, cfg_blocks);
00198 cfg_blocks_head = 0;
00199 VEC_safe_grow (basic_block, heap, cfg_blocks, 2 * cfg_blocks_tail);
00200 }
00201 else
00202 cfg_blocks_tail = ((cfg_blocks_tail + 1)
00203 % VEC_length (basic_block, cfg_blocks));
00204 }
00205
00206 VEC_replace (basic_block, cfg_blocks, cfg_blocks_tail, bb);
00207 SET_BIT (bb_in_list, bb->index);
00208 }
00209
00210
00211
00212
00213 static basic_block
00214 cfg_blocks_get (void)
00215 {
00216 basic_block bb;
00217
00218 bb = VEC_index (basic_block, cfg_blocks, cfg_blocks_head);
00219
00220 gcc_assert (!cfg_blocks_empty_p ());
00221 gcc_assert (bb);
00222
00223 cfg_blocks_head = ((cfg_blocks_head + 1)
00224 % VEC_length (basic_block, cfg_blocks));
00225 --cfg_blocks_num;
00226 RESET_BIT (bb_in_list, bb->index);
00227
00228 return bb;
00229 }
00230
00231
00232
00233
00234
00235
00236 static void
00237 add_ssa_edge (tree var, bool is_varying)
00238 {
00239 imm_use_iterator iter;
00240 use_operand_p use_p;
00241
00242 FOR_EACH_IMM_USE_FAST (use_p, iter, var)
00243 {
00244 tree use_stmt = USE_STMT (use_p);
00245
00246 if (!DONT_SIMULATE_AGAIN (use_stmt)
00247 && !STMT_IN_SSA_EDGE_WORKLIST (use_stmt))
00248 {
00249 STMT_IN_SSA_EDGE_WORKLIST (use_stmt) = 1;
00250 if (is_varying)
00251 VEC_safe_push (tree, gc, varying_ssa_edges, use_stmt);
00252 else
00253 VEC_safe_push (tree, gc, interesting_ssa_edges, use_stmt);
00254 }
00255 }
00256 }
00257
00258
00259
00260
00261 static void
00262 add_control_edge (edge e)
00263 {
00264 basic_block bb = e->dest;
00265 if (bb == EXIT_BLOCK_PTR)
00266 return;
00267
00268
00269 if (e->flags & EDGE_EXECUTABLE)
00270 return;
00271
00272 e->flags |= EDGE_EXECUTABLE;
00273
00274
00275 if (TEST_BIT (bb_in_list, bb->index))
00276 return;
00277
00278 cfg_blocks_add (bb);
00279
00280 if (dump_file && (dump_flags & TDF_DETAILS))
00281 fprintf (dump_file, "Adding Destination of edge (%d -> %d) to worklist\n\n",
00282 e->src->index, e->dest->index);
00283 }
00284
00285
00286
00287
00288 static void
00289 simulate_stmt (tree stmt)
00290 {
00291 enum ssa_prop_result val = SSA_PROP_NOT_INTERESTING;
00292 edge taken_edge = NULL;
00293 tree output_name = NULL_TREE;
00294
00295
00296
00297 if (DONT_SIMULATE_AGAIN (stmt))
00298 return;
00299
00300 if (TREE_CODE (stmt) == PHI_NODE)
00301 {
00302 val = ssa_prop_visit_phi (stmt);
00303 output_name = PHI_RESULT (stmt);
00304 }
00305 else
00306 val = ssa_prop_visit_stmt (stmt, &taken_edge, &output_name);
00307
00308 if (val == SSA_PROP_VARYING)
00309 {
00310 DONT_SIMULATE_AGAIN (stmt) = 1;
00311
00312
00313
00314 if (output_name)
00315 add_ssa_edge (output_name, true);
00316
00317
00318
00319 if (stmt_ends_bb_p (stmt))
00320 {
00321 edge e;
00322 edge_iterator ei;
00323 basic_block bb = bb_for_stmt (stmt);
00324 FOR_EACH_EDGE (e, ei, bb->succs)
00325 add_control_edge (e);
00326 }
00327 }
00328 else if (val == SSA_PROP_INTERESTING)
00329 {
00330
00331
00332 if (output_name)
00333 add_ssa_edge (output_name, false);
00334
00335
00336
00337 if (taken_edge)
00338 add_control_edge (taken_edge);
00339 }
00340 }
00341
00342
00343
00344
00345
00346
00347
00348 static void
00349 process_ssa_edge_worklist (VEC(tree,gc) **worklist)
00350 {
00351
00352 while (VEC_length (tree, *worklist) > 0)
00353 {
00354 basic_block bb;
00355
00356
00357 tree stmt = VEC_pop (tree, *worklist);
00358
00359
00360
00361 if (!STMT_IN_SSA_EDGE_WORKLIST (stmt))
00362 continue;
00363
00364
00365 STMT_IN_SSA_EDGE_WORKLIST (stmt) = 0;
00366
00367 if (dump_file && (dump_flags & TDF_DETAILS))
00368 {
00369 fprintf (dump_file, "\nSimulating statement (from ssa_edges): ");
00370 print_generic_stmt (dump_file, stmt, dump_flags);
00371 }
00372
00373 bb = bb_for_stmt (stmt);
00374
00375
00376
00377
00378 if (TREE_CODE (stmt) == PHI_NODE
00379 || TEST_BIT (executable_blocks, bb->index))
00380 simulate_stmt (stmt);
00381 }
00382 }
00383
00384
00385
00386
00387
00388 static void
00389 simulate_block (basic_block block)
00390 {
00391 tree phi;
00392
00393
00394 if (block == EXIT_BLOCK_PTR)
00395 return;
00396
00397 if (dump_file && (dump_flags & TDF_DETAILS))
00398 fprintf (dump_file, "\nSimulating block %d\n", block->index);
00399
00400
00401
00402 for (phi = phi_nodes (block); phi; phi = PHI_CHAIN (phi))
00403 simulate_stmt (phi);
00404
00405
00406
00407 if (!TEST_BIT (executable_blocks, block->index))
00408 {
00409 block_stmt_iterator j;
00410 unsigned int normal_edge_count;
00411 edge e, normal_edge;
00412 edge_iterator ei;
00413
00414
00415 SET_BIT (executable_blocks, block->index);
00416
00417 for (j = bsi_start (block); !bsi_end_p (j); bsi_next (&j))
00418 {
00419 tree stmt = bsi_stmt (j);
00420
00421
00422
00423
00424
00425
00426 if (STMT_IN_SSA_EDGE_WORKLIST (stmt))
00427 STMT_IN_SSA_EDGE_WORKLIST (stmt) = 0;
00428
00429 simulate_stmt (stmt);
00430 }
00431
00432
00433
00434
00435
00436
00437
00438
00439 normal_edge_count = 0;
00440 normal_edge = NULL;
00441 FOR_EACH_EDGE (e, ei, block->succs)
00442 {
00443 if (e->flags & EDGE_ABNORMAL)
00444 add_control_edge (e);
00445 else
00446 {
00447 normal_edge_count++;
00448 normal_edge = e;
00449 }
00450 }
00451
00452 if (normal_edge_count == 1)
00453 add_control_edge (normal_edge);
00454 }
00455 }
00456
00457
00458
00459
00460 static void
00461 ssa_prop_init (void)
00462 {
00463 edge e;
00464 edge_iterator ei;
00465 basic_block bb;
00466 size_t i;
00467
00468
00469 interesting_ssa_edges = VEC_alloc (tree, gc, 20);
00470 varying_ssa_edges = VEC_alloc (tree, gc, 20);
00471
00472 executable_blocks = sbitmap_alloc (last_basic_block);
00473 sbitmap_zero (executable_blocks);
00474
00475 bb_in_list = sbitmap_alloc (last_basic_block);
00476 sbitmap_zero (bb_in_list);
00477
00478 if (dump_file && (dump_flags & TDF_DETAILS))
00479 dump_immediate_uses (dump_file);
00480
00481 cfg_blocks = VEC_alloc (basic_block, heap, 20);
00482 VEC_safe_grow (basic_block, heap, cfg_blocks, 20);
00483
00484
00485 for (i = 1; i < num_ssa_names; i++)
00486 if (ssa_name (i))
00487 SSA_NAME_VALUE (ssa_name (i)) = NULL_TREE;
00488
00489
00490
00491 FOR_ALL_BB (bb)
00492 {
00493 block_stmt_iterator si;
00494
00495 for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si))
00496 STMT_IN_SSA_EDGE_WORKLIST (bsi_stmt (si)) = 0;
00497
00498 FOR_EACH_EDGE (e, ei, bb->succs)
00499 e->flags &= ~EDGE_EXECUTABLE;
00500 }
00501
00502
00503
00504 FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR->succs)
00505 add_control_edge (e);
00506 }
00507
00508
00509
00510
00511 static void
00512 ssa_prop_fini (void)
00513 {
00514 VEC_free (tree, gc, interesting_ssa_edges);
00515 VEC_free (tree, gc, varying_ssa_edges);
00516 VEC_free (basic_block, heap, cfg_blocks);
00517 cfg_blocks = NULL;
00518 sbitmap_free (bb_in_list);
00519 sbitmap_free (executable_blocks);
00520 }
00521
00522
00523
00524
00525 tree
00526 get_rhs (tree stmt)
00527 {
00528 enum tree_code code = TREE_CODE (stmt);
00529
00530 switch (code)
00531 {
00532 case RETURN_EXPR:
00533 stmt = TREE_OPERAND (stmt, 0);
00534 if (!stmt || TREE_CODE (stmt) != MODIFY_EXPR)
00535 return stmt;
00536
00537
00538 case MODIFY_EXPR:
00539 stmt = TREE_OPERAND (stmt, 1);
00540 if (TREE_CODE (stmt) == WITH_SIZE_EXPR)
00541 return TREE_OPERAND (stmt, 0);
00542 else
00543 return stmt;
00544
00545 case COND_EXPR:
00546 return COND_EXPR_COND (stmt);
00547 case SWITCH_EXPR:
00548 return SWITCH_COND (stmt);
00549 case GOTO_EXPR:
00550 return GOTO_DESTINATION (stmt);
00551 case LABEL_EXPR:
00552 return LABEL_EXPR_LABEL (stmt);
00553
00554 default:
00555 return stmt;
00556 }
00557 }
00558
00559
00560
00561
00562
00563
00564 bool
00565 set_rhs (tree *stmt_p, tree expr)
00566 {
00567 tree stmt = *stmt_p, op;
00568 enum tree_code code = TREE_CODE (expr);
00569 stmt_ann_t ann;
00570 tree var;
00571 ssa_op_iter iter;
00572
00573
00574 if (TREE_CODE_CLASS (code) == tcc_binary)
00575 {
00576 if (!is_gimple_val (TREE_OPERAND (expr, 0))
00577 || !is_gimple_val (TREE_OPERAND (expr, 1)))
00578 return false;
00579 }
00580 else if (TREE_CODE_CLASS (code) == tcc_unary)
00581 {
00582 if (!is_gimple_val (TREE_OPERAND (expr, 0)))
00583 return false;
00584 }
00585 else if (code == ADDR_EXPR)
00586 {
00587 if (TREE_CODE (TREE_OPERAND (expr, 0)) == ARRAY_REF
00588 && !is_gimple_val (TREE_OPERAND (TREE_OPERAND (expr, 0), 1)))
00589 return false;
00590 }
00591 else if (code == COMPOUND_EXPR
00592 || code == MODIFY_EXPR)
00593 return false;
00594
00595 if (EXPR_HAS_LOCATION (stmt)
00596 && EXPR_P (expr)
00597 && ! EXPR_HAS_LOCATION (expr)
00598 && TREE_SIDE_EFFECTS (expr)
00599 && TREE_CODE (expr) != LABEL_EXPR)
00600 SET_EXPR_LOCATION (expr, EXPR_LOCATION (stmt));
00601
00602 switch (TREE_CODE (stmt))
00603 {
00604 case RETURN_EXPR:
00605 op = TREE_OPERAND (stmt, 0);
00606 if (TREE_CODE (op) != MODIFY_EXPR)
00607 {
00608 TREE_OPERAND (stmt, 0) = expr;
00609 break;
00610 }
00611 stmt = op;
00612
00613
00614 case MODIFY_EXPR:
00615 op = TREE_OPERAND (stmt, 1);
00616 if (TREE_CODE (op) == WITH_SIZE_EXPR)
00617 stmt = op;
00618 TREE_OPERAND (stmt, 1) = expr;
00619 break;
00620
00621 case COND_EXPR:
00622 if (!is_gimple_condexpr (expr))
00623 return false;
00624 COND_EXPR_COND (stmt) = expr;
00625 break;
00626 case SWITCH_EXPR:
00627 SWITCH_COND (stmt) = expr;
00628 break;
00629 case GOTO_EXPR:
00630 GOTO_DESTINATION (stmt) = expr;
00631 break;
00632 case LABEL_EXPR:
00633 LABEL_EXPR_LABEL (stmt) = expr;
00634 break;
00635
00636 default:
00637
00638
00639 ann = stmt_ann (stmt);
00640 *stmt_p = TREE_SIDE_EFFECTS (expr) ? expr : build_empty_stmt ();
00641 (*stmt_p)->common.ann = (tree_ann_t) ann;
00642
00643 if (in_ssa_p
00644 && TREE_SIDE_EFFECTS (expr))
00645 {
00646
00647
00648 FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, SSA_OP_ALL_DEFS)
00649 {
00650 if (TREE_CODE (var) == SSA_NAME)
00651 SSA_NAME_DEF_STMT (var) = *stmt_p;
00652 }
00653 }
00654 break;
00655 }
00656
00657 return true;
00658 }
00659
00660
00661
00662
00663
00664
00665
00666 void
00667 ssa_propagate (ssa_prop_visit_stmt_fn visit_stmt,
00668 ssa_prop_visit_phi_fn visit_phi)
00669 {
00670 ssa_prop_visit_stmt = visit_stmt;
00671 ssa_prop_visit_phi = visit_phi;
00672
00673 ssa_prop_init ();
00674
00675
00676 while (!cfg_blocks_empty_p ()
00677 || VEC_length (tree, interesting_ssa_edges) > 0
00678 || VEC_length (tree, varying_ssa_edges) > 0)
00679 {
00680 if (!cfg_blocks_empty_p ())
00681 {
00682
00683 basic_block dest_block = cfg_blocks_get ();
00684 simulate_block (dest_block);
00685 }
00686
00687
00688
00689 process_ssa_edge_worklist (&varying_ssa_edges);
00690
00691
00692 process_ssa_edge_worklist (&interesting_ssa_edges);
00693 }
00694
00695 ssa_prop_fini ();
00696 }
00697
00698
00699
00700
00701 tree
00702 first_vdef (tree stmt)
00703 {
00704 ssa_op_iter iter;
00705 tree op;
00706
00707
00708 FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_VIRTUAL_DEFS)
00709 return (op);
00710
00711 gcc_unreachable ();
00712 }
00713
00714
00715
00716
00717
00718
00719
00720 bool
00721 stmt_makes_single_load (tree stmt)
00722 {
00723 tree rhs;
00724
00725 if (TREE_CODE (stmt) != MODIFY_EXPR)
00726 return false;
00727
00728 if (ZERO_SSA_OPERANDS (stmt, SSA_OP_VMAYDEF|SSA_OP_VUSE))
00729 return false;
00730
00731 rhs = TREE_OPERAND (stmt, 1);
00732 STRIP_NOPS (rhs);
00733
00734 return (!TREE_THIS_VOLATILE (rhs)
00735 && (DECL_P (rhs)
00736 || REFERENCE_CLASS_P (rhs)));
00737 }
00738
00739
00740
00741
00742
00743
00744
00745 bool
00746 stmt_makes_single_store (tree stmt)
00747 {
00748 tree lhs;
00749
00750 if (TREE_CODE (stmt) != MODIFY_EXPR)
00751 return false;
00752
00753 if (ZERO_SSA_OPERANDS (stmt, SSA_OP_VMAYDEF|SSA_OP_VMUSTDEF))
00754 return false;
00755
00756 lhs = TREE_OPERAND (stmt, 0);
00757 STRIP_NOPS (lhs);
00758
00759 return (!TREE_THIS_VOLATILE (lhs)
00760 && (DECL_P (lhs)
00761 || REFERENCE_CLASS_P (lhs)));
00762 }
00763
00764
00765
00766
00767
00768
00769 prop_value_t *
00770 get_value_loaded_by (tree stmt, prop_value_t *values)
00771 {
00772 ssa_op_iter i;
00773 tree vuse;
00774 prop_value_t *prev_val = NULL;
00775 prop_value_t *val = NULL;
00776
00777 FOR_EACH_SSA_TREE_OPERAND (vuse, stmt, i, SSA_OP_VIRTUAL_USES)
00778 {
00779 val = &values[SSA_NAME_VERSION (vuse)];
00780 if (prev_val && prev_val->value != val->value)
00781 return NULL;
00782 prev_val = val;
00783 }
00784
00785 return val;
00786 }
00787
00788
00789
00790 struct prop_stats_d
00791 {
00792 long num_const_prop;
00793 long num_copy_prop;
00794 long num_pred_folded;
00795 };
00796
00797 static struct prop_stats_d prop_stats;
00798
00799
00800
00801
00802
00803
00804 bool
00805 replace_uses_in (tree stmt, bool *replaced_addresses_p,
00806 prop_value_t *prop_value)
00807 {
00808 bool replaced = false;
00809 use_operand_p use;
00810 ssa_op_iter iter;
00811
00812 FOR_EACH_SSA_USE_OPERAND (use, stmt, iter, SSA_OP_USE)
00813 {
00814 tree tuse = USE_FROM_PTR (use);
00815 tree val = prop_value[SSA_NAME_VERSION (tuse)].value;
00816
00817 if (val == tuse || val == NULL_TREE)
00818 continue;
00819
00820 if (TREE_CODE (stmt) == ASM_EXPR
00821 && !may_propagate_copy_into_asm (tuse))
00822 continue;
00823
00824 if (!may_propagate_copy (tuse, val))
00825 continue;
00826
00827 if (TREE_CODE (val) != SSA_NAME)
00828 prop_stats.num_const_prop++;
00829 else
00830 prop_stats.num_copy_prop++;
00831
00832 propagate_value (use, val);
00833
00834 replaced = true;
00835 if (POINTER_TYPE_P (TREE_TYPE (tuse)) && replaced_addresses_p)
00836 *replaced_addresses_p = true;
00837 }
00838
00839 return replaced;
00840 }
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904 static bool
00905 replace_vuses_in (tree stmt, bool *replaced_addresses_p,
00906 prop_value_t *prop_value)
00907 {
00908 bool replaced = false;
00909 ssa_op_iter iter;
00910 use_operand_p vuse;
00911
00912 if (stmt_makes_single_load (stmt))
00913 {
00914
00915
00916
00917 prop_value_t *val = get_value_loaded_by (stmt, prop_value);
00918 tree rhs = TREE_OPERAND (stmt, 1);
00919
00920 if (val
00921 && val->value
00922 && (is_gimple_reg (val->value)
00923 || is_gimple_min_invariant (val->value))
00924 && simple_cst_equal (rhs, val->mem_ref) == 1)
00925
00926 {
00927
00928
00929 if (TREE_CODE (val->value) != SSA_NAME
00930 && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (stmt, 1)))
00931 && replaced_addresses_p)
00932 *replaced_addresses_p = true;
00933
00934
00935
00936
00937
00938
00939
00940 TREE_OPERAND (stmt, 1) = val->value;
00941
00942 if (TREE_CODE (val->value) != SSA_NAME)
00943 prop_stats.num_const_prop++;
00944 else
00945 prop_stats.num_copy_prop++;
00946
00947
00948
00949
00950 return true;
00951 }
00952 }
00953
00954
00955
00956 FOR_EACH_SSA_USE_OPERAND (vuse, stmt, iter, SSA_OP_VIRTUAL_USES)
00957 {
00958 tree var = USE_FROM_PTR (vuse);
00959 tree val = prop_value[SSA_NAME_VERSION (var)].value;
00960
00961 if (val == NULL_TREE || var == val)
00962 continue;
00963
00964
00965
00966
00967 if (is_gimple_min_invariant (val) || is_gimple_reg (val))
00968 continue;
00969
00970 propagate_value (vuse, val);
00971 prop_stats.num_copy_prop++;
00972 replaced = true;
00973 }
00974
00975 return replaced;
00976 }
00977
00978
00979
00980
00981
00982 static void
00983 replace_phi_args_in (tree phi, prop_value_t *prop_value)
00984 {
00985 int i;
00986 bool replaced = false;
00987 tree prev_phi = NULL;
00988
00989 if (dump_file && (dump_flags & TDF_DETAILS))
00990 prev_phi = unshare_expr (phi);
00991
00992 for (i = 0; i < PHI_NUM_ARGS (phi); i++)
00993 {
00994 tree arg = PHI_ARG_DEF (phi, i);
00995
00996 if (TREE_CODE (arg) == SSA_NAME)
00997 {
00998 tree val = prop_value[SSA_NAME_VERSION (arg)].value;
00999
01000 if (val && val != arg && may_propagate_copy (arg, val))
01001 {
01002 if (TREE_CODE (val) != SSA_NAME)
01003 prop_stats.num_const_prop++;
01004 else
01005 prop_stats.num_copy_prop++;
01006
01007 propagate_value (PHI_ARG_DEF_PTR (phi, i), val);
01008 replaced = true;
01009
01010
01011
01012
01013 if (TREE_CODE (val) == SSA_NAME
01014 && PHI_ARG_EDGE (phi, i)->flags & EDGE_ABNORMAL)
01015 SSA_NAME_OCCURS_IN_ABNORMAL_PHI (val) = 1;
01016 }
01017 }
01018 }
01019
01020 if (replaced && dump_file && (dump_flags & TDF_DETAILS))
01021 {
01022 fprintf (dump_file, "Folded PHI node: ");
01023 print_generic_stmt (dump_file, prev_phi, TDF_SLIM);
01024 fprintf (dump_file, " into: ");
01025 print_generic_stmt (dump_file, phi, TDF_SLIM);
01026 fprintf (dump_file, "\n");
01027 }
01028 }
01029
01030
01031
01032
01033
01034
01035 static bool
01036 fold_predicate_in (tree stmt)
01037 {
01038 tree *pred_p = NULL;
01039 bool modify_expr_p = false;
01040 tree val;
01041
01042 if (TREE_CODE (stmt) == MODIFY_EXPR
01043 && COMPARISON_CLASS_P (TREE_OPERAND (stmt, 1)))
01044 {
01045 modify_expr_p = true;
01046 pred_p = &TREE_OPERAND (stmt, 1);
01047 }
01048 else if (TREE_CODE (stmt) == COND_EXPR)
01049 pred_p = &COND_EXPR_COND (stmt);
01050 else
01051 return false;
01052
01053 val = vrp_evaluate_conditional (*pred_p, stmt);
01054 if (val)
01055 {
01056 if (modify_expr_p)
01057 val = fold_convert (TREE_TYPE (*pred_p), val);
01058
01059 if (dump_file)
01060 {
01061 fprintf (dump_file, "Folding predicate ");
01062 print_generic_expr (dump_file, *pred_p, 0);
01063 fprintf (dump_file, " to ");
01064 print_generic_expr (dump_file, val, 0);
01065 fprintf (dump_file, "\n");
01066 }
01067
01068 prop_stats.num_pred_folded++;
01069 *pred_p = val;
01070 return true;
01071 }
01072
01073 return false;
01074 }
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089 void
01090 substitute_and_fold (prop_value_t *prop_value, bool use_ranges_p)
01091 {
01092 basic_block bb;
01093
01094 if (prop_value == NULL && !use_ranges_p)
01095 return;
01096
01097 if (dump_file && (dump_flags & TDF_DETAILS))
01098 fprintf (dump_file, "\nSubstituing values and folding statements\n\n");
01099
01100 memset (&prop_stats, 0, sizeof (prop_stats));
01101
01102
01103 FOR_EACH_BB (bb)
01104 {
01105 block_stmt_iterator i;
01106 tree phi;
01107
01108
01109 if (prop_value)
01110 for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
01111 replace_phi_args_in (phi, prop_value);
01112
01113 for (i = bsi_start (bb); !bsi_end_p (i); bsi_next (&i))
01114 {
01115 bool replaced_address, did_replace;
01116 tree prev_stmt = NULL;
01117 tree stmt = bsi_stmt (i);
01118
01119
01120
01121
01122 if (TREE_CODE (stmt) == MODIFY_EXPR
01123 && TREE_CODE (TREE_OPERAND (stmt, 1)) == ASSERT_EXPR)
01124 continue;
01125
01126
01127
01128 did_replace = false;
01129 replaced_address = false;
01130 if (dump_file && (dump_flags & TDF_DETAILS))
01131 prev_stmt = unshare_expr (stmt);
01132
01133
01134
01135 if (use_ranges_p)
01136 did_replace = fold_predicate_in (stmt);
01137
01138 if (prop_value)
01139 {
01140
01141
01142
01143
01144 if (!did_replace)
01145 did_replace |= replace_uses_in (stmt, &replaced_address,
01146 prop_value);
01147
01148 did_replace |= replace_vuses_in (stmt, &replaced_address,
01149 prop_value);
01150 }
01151
01152
01153 if (did_replace)
01154 {
01155 tree old_stmt = stmt;
01156 tree rhs;
01157
01158 fold_stmt (bsi_stmt_ptr (i));
01159 stmt = bsi_stmt (i);
01160
01161
01162
01163 mark_new_vars_to_rename (stmt);
01164
01165
01166
01167 if (maybe_clean_or_replace_eh_stmt (old_stmt, stmt))
01168 tree_purge_dead_eh_edges (bb);
01169
01170 rhs = get_rhs (stmt);
01171 if (TREE_CODE (rhs) == ADDR_EXPR)
01172 recompute_tree_invariant_for_addr_expr (rhs);
01173
01174 if (dump_file && (dump_flags & TDF_DETAILS))
01175 {
01176 fprintf (dump_file, "Folded statement: ");
01177 print_generic_stmt (dump_file, prev_stmt, TDF_SLIM);
01178 fprintf (dump_file, " into: ");
01179 print_generic_stmt (dump_file, stmt, TDF_SLIM);
01180 fprintf (dump_file, "\n");
01181 }
01182 }
01183
01184
01185
01186
01187
01188
01189
01190 if (use_ranges_p)
01191 simplify_stmt_using_ranges (stmt);
01192
01193 }
01194 }
01195
01196 if (dump_file && (dump_flags & TDF_STATS))
01197 {
01198 fprintf (dump_file, "Constants propagated: %6ld\n",
01199 prop_stats.num_const_prop);
01200 fprintf (dump_file, "Copies propagated: %6ld\n",
01201 prop_stats.num_copy_prop);
01202 fprintf (dump_file, "Predicates folded: %6ld\n",
01203 prop_stats.num_pred_folded);
01204 }
01205 }
01206
01207 #include "gt-tree-ssa-propagate.h"