00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "config.h"
00022 #include "system.h"
00023 #include "coretypes.h"
00024 #include "tm.h"
00025 #include "ggc.h"
00026 #include "tree.h"
00027 #include "rtl.h"
00028 #include "tm_p.h"
00029 #include "basic-block.h"
00030 #include "timevar.h"
00031 #include "diagnostic.h"
00032 #include "tree-flow.h"
00033 #include "tree-pass.h"
00034 #include "tree-dump.h"
00035 #include "langhooks.h"
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
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
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154 static bool cfg_changed;
00155
00156
00157
00158
00159
00160 static bool
00161 ssa_name_defined_by_comparison_p (tree var)
00162 {
00163 tree def = SSA_NAME_DEF_STMT (var);
00164
00165 if (TREE_CODE (def) == MODIFY_EXPR)
00166 {
00167 tree rhs = TREE_OPERAND (def, 1);
00168 return COMPARISON_CLASS_P (rhs);
00169 }
00170
00171 return 0;
00172 }
00173
00174
00175
00176
00177 static tree
00178 forward_propagate_into_cond_1 (tree cond, tree *test_var_p)
00179 {
00180 tree new_cond = NULL_TREE;
00181 enum tree_code cond_code = TREE_CODE (cond);
00182 tree test_var = NULL_TREE;
00183 tree def;
00184 tree def_rhs;
00185
00186
00187
00188
00189
00190
00191
00192 if (cond_code != SSA_NAME
00193 && !((cond_code == EQ_EXPR || cond_code == NE_EXPR)
00194 && TREE_CODE (TREE_OPERAND (cond, 0)) == SSA_NAME
00195 && CONSTANT_CLASS_P (TREE_OPERAND (cond, 1))
00196 && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (cond, 1)))))
00197 return NULL_TREE;
00198
00199
00200 if (cond_code == SSA_NAME)
00201 test_var = cond;
00202 else
00203 test_var = TREE_OPERAND (cond, 0);
00204
00205
00206
00207 def = SSA_NAME_DEF_STMT (test_var);
00208 if (TREE_CODE (def) != MODIFY_EXPR)
00209 return NULL_TREE;
00210
00211 def_rhs = TREE_OPERAND (def, 1);
00212
00213
00214
00215
00216
00217 if (TREE_CODE (def_rhs) == PLUS_EXPR
00218 || TREE_CODE (def_rhs) == MINUS_EXPR)
00219 {
00220 tree op0 = TREE_OPERAND (def_rhs, 0);
00221 tree op1 = TREE_OPERAND (def_rhs, 1);
00222
00223
00224
00225 if (TREE_CODE (op0) != SSA_NAME
00226 || !CONSTANT_CLASS_P (op1)
00227 || !INTEGRAL_TYPE_P (TREE_TYPE (op1)))
00228 return NULL_TREE;
00229
00230
00231
00232 if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op0))
00233 return NULL_TREE;
00234
00235 if (has_single_use (test_var))
00236 {
00237 enum tree_code new_code;
00238 tree t;
00239
00240
00241
00242
00243
00244
00245 new_code = (TREE_CODE (def_rhs) == PLUS_EXPR
00246 ? MINUS_EXPR : PLUS_EXPR);
00247 t = int_const_binop (new_code, TREE_OPERAND (cond, 1), op1, 0);
00248 if (!is_gimple_val (t))
00249 return NULL_TREE;
00250
00251 new_cond = build2 (cond_code, boolean_type_node, op0, t);
00252 }
00253 }
00254
00255
00256
00257 else if (TREE_CODE (cond) == SSA_NAME
00258 || integer_zerop (TREE_OPERAND (cond, 1))
00259 || integer_onep (TREE_OPERAND (cond, 1)))
00260 {
00261
00262
00263
00264 if (COMPARISON_CLASS_P (def_rhs))
00265 {
00266 tree op0 = TREE_OPERAND (def_rhs, 0);
00267 tree op1 = TREE_OPERAND (def_rhs, 1);
00268
00269
00270
00271 if ((TREE_CODE (op0) != SSA_NAME
00272 && !is_gimple_min_invariant (op0))
00273 || (TREE_CODE (op1) != SSA_NAME
00274 && !is_gimple_min_invariant (op1)))
00275 return NULL_TREE;
00276
00277
00278
00279 if (TREE_CODE (op0) == SSA_NAME
00280 && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op0))
00281 return NULL_TREE;
00282
00283
00284
00285 if (TREE_CODE (op1) == SSA_NAME
00286 && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op1))
00287 return NULL_TREE;
00288
00289 if (has_single_use (test_var))
00290 {
00291
00292 new_cond = build2 (TREE_CODE (def_rhs),
00293 boolean_type_node, op0, op1);
00294
00295
00296 if ((cond_code == EQ_EXPR
00297 && integer_zerop (TREE_OPERAND (cond, 1)))
00298 || (cond_code == NE_EXPR
00299 && integer_onep (TREE_OPERAND (cond, 1))))
00300 {
00301 new_cond = invert_truthvalue (new_cond);
00302
00303
00304
00305
00306 if (!COMPARISON_CLASS_P (new_cond)
00307 && TREE_CODE (new_cond) != SSA_NAME)
00308 new_cond = NULL_TREE;
00309 }
00310 }
00311 }
00312
00313
00314
00315 else if (TREE_CODE (def_rhs) == TRUTH_NOT_EXPR)
00316 {
00317 enum tree_code new_code;
00318
00319 def_rhs = TREE_OPERAND (def_rhs, 0);
00320
00321
00322 if (TREE_CODE (def_rhs) != SSA_NAME
00323 && !is_gimple_min_invariant (def_rhs))
00324 return NULL_TREE;
00325
00326
00327
00328 if (TREE_CODE (def_rhs) == SSA_NAME
00329 && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (def_rhs))
00330 return NULL_TREE;
00331
00332 if (cond_code == SSA_NAME
00333 || (cond_code == NE_EXPR
00334 && integer_zerop (TREE_OPERAND (cond, 1)))
00335 || (cond_code == EQ_EXPR
00336 && integer_onep (TREE_OPERAND (cond, 1))))
00337 new_code = EQ_EXPR;
00338 else
00339 new_code = NE_EXPR;
00340
00341 new_cond = build2 (new_code, boolean_type_node, def_rhs,
00342 fold_convert (TREE_TYPE (def_rhs),
00343 integer_zero_node));
00344 }
00345
00346
00347
00348
00349 else if (TREE_CODE (def_rhs) == NOP_EXPR
00350 || TREE_CODE (def_rhs) == CONVERT_EXPR)
00351 {
00352 tree outer_type;
00353 tree inner_type;
00354
00355 outer_type = TREE_TYPE (def_rhs);
00356 inner_type = TREE_TYPE (TREE_OPERAND (def_rhs, 0));
00357
00358 if ((TREE_CODE (outer_type) == BOOLEAN_TYPE
00359 && INTEGRAL_TYPE_P (inner_type))
00360 || (TREE_CODE (inner_type) == BOOLEAN_TYPE
00361 && INTEGRAL_TYPE_P (outer_type)))
00362 ;
00363 else if (INTEGRAL_TYPE_P (outer_type)
00364 && INTEGRAL_TYPE_P (inner_type)
00365 && TREE_CODE (TREE_OPERAND (def_rhs, 0)) == SSA_NAME
00366 && ssa_name_defined_by_comparison_p (TREE_OPERAND (def_rhs,
00367 0)))
00368 ;
00369 else
00370 return NULL_TREE;
00371
00372
00373
00374 if (TREE_CODE (TREE_OPERAND (def_rhs, 0)) == SSA_NAME
00375 && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (TREE_OPERAND
00376 (def_rhs, 0)))
00377 return NULL_TREE;
00378
00379 if (has_single_use (test_var))
00380 {
00381 enum tree_code new_code;
00382 tree new_arg;
00383
00384 if (cond_code == SSA_NAME
00385 || (cond_code == NE_EXPR
00386 && integer_zerop (TREE_OPERAND (cond, 1)))
00387 || (cond_code == EQ_EXPR
00388 && integer_onep (TREE_OPERAND (cond, 1))))
00389 new_code = NE_EXPR;
00390 else
00391 new_code = EQ_EXPR;
00392
00393 new_arg = TREE_OPERAND (def_rhs, 0);
00394 new_cond = build2 (new_code, boolean_type_node, new_arg,
00395 fold_convert (TREE_TYPE (new_arg),
00396 integer_zero_node));
00397 }
00398 }
00399 }
00400
00401 *test_var_p = test_var;
00402 return new_cond;
00403 }
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424 static tree
00425 find_equivalent_equality_comparison (tree cond)
00426 {
00427 tree op0 = TREE_OPERAND (cond, 0);
00428 tree op1 = TREE_OPERAND (cond, 1);
00429 tree def_stmt = SSA_NAME_DEF_STMT (op0);
00430
00431 while (def_stmt
00432 && TREE_CODE (def_stmt) == MODIFY_EXPR
00433 && TREE_CODE (TREE_OPERAND (def_stmt, 1)) == SSA_NAME)
00434 def_stmt = SSA_NAME_DEF_STMT (TREE_OPERAND (def_stmt, 1));
00435
00436
00437
00438 if (def_stmt && TREE_CODE (def_stmt) == MODIFY_EXPR)
00439 {
00440 tree def_rhs = TREE_OPERAND (def_stmt, 1);
00441
00442
00443
00444
00445
00446
00447 if ((POINTER_TYPE_P (TREE_TYPE (op0))
00448 && TREE_CODE (TREE_TYPE (TREE_TYPE (op0))) == FUNCTION_TYPE)
00449 || (POINTER_TYPE_P (TREE_TYPE (op1))
00450 && TREE_CODE (TREE_TYPE (TREE_TYPE (op1))) == FUNCTION_TYPE))
00451 return NULL;
00452
00453
00454 if ((TREE_CODE (def_rhs) == NOP_EXPR
00455 || TREE_CODE (def_rhs) == CONVERT_EXPR)
00456 && TREE_CODE (TREE_OPERAND (def_rhs, 0)) == SSA_NAME)
00457 {
00458 tree def_rhs_inner = TREE_OPERAND (def_rhs, 0);
00459 tree def_rhs_inner_type = TREE_TYPE (def_rhs_inner);
00460 tree new;
00461
00462 if (TYPE_PRECISION (def_rhs_inner_type)
00463 > TYPE_PRECISION (TREE_TYPE (def_rhs)))
00464 return NULL;
00465
00466
00467
00468
00469
00470
00471
00472 if (POINTER_TYPE_P (def_rhs_inner_type)
00473 && TREE_CODE (TREE_TYPE (def_rhs_inner_type)) == FUNCTION_TYPE)
00474 return NULL;
00475
00476
00477
00478
00479
00480
00481
00482
00483 new = fold_build1 (TREE_CODE (def_rhs), def_rhs_inner_type, op1);
00484 STRIP_USELESS_TYPE_CONVERSION (new);
00485 if (is_gimple_val (new) && tree_int_cst_equal (new, op1))
00486 return build2 (TREE_CODE (cond), TREE_TYPE (cond),
00487 def_rhs_inner, new);
00488 }
00489 }
00490 return NULL;
00491 }
00492
00493
00494
00495
00496
00497
00498 static void
00499 simplify_cond (tree stmt)
00500 {
00501 tree cond = COND_EXPR_COND (stmt);
00502
00503 if (COMPARISON_CLASS_P (cond))
00504 {
00505 tree op0 = TREE_OPERAND (cond, 0);
00506 tree op1 = TREE_OPERAND (cond, 1);
00507
00508 if (TREE_CODE (op0) == SSA_NAME && is_gimple_min_invariant (op1))
00509 {
00510
00511
00512
00513
00514 if (TREE_CODE (cond) == EQ_EXPR || TREE_CODE (cond) == NE_EXPR)
00515 {
00516 tree new_cond = find_equivalent_equality_comparison (cond);
00517
00518 if (new_cond)
00519 {
00520 COND_EXPR_COND (stmt) = new_cond;
00521 update_stmt (stmt);
00522 }
00523 }
00524 }
00525 }
00526 }
00527
00528
00529
00530
00531 static void
00532 forward_propagate_into_cond (tree cond_expr)
00533 {
00534 gcc_assert (TREE_CODE (cond_expr) == COND_EXPR);
00535
00536 while (1)
00537 {
00538 tree test_var = NULL_TREE;
00539 tree cond = COND_EXPR_COND (cond_expr);
00540 tree new_cond = forward_propagate_into_cond_1 (cond, &test_var);
00541
00542
00543 if (new_cond == NULL_TREE)
00544 break;
00545
00546
00547 if (dump_file && (dump_flags & TDF_DETAILS))
00548 {
00549 fprintf (dump_file, " Replaced '");
00550 print_generic_expr (dump_file, cond, dump_flags);
00551 fprintf (dump_file, "' with '");
00552 print_generic_expr (dump_file, new_cond, dump_flags);
00553 fprintf (dump_file, "'\n");
00554 }
00555
00556 COND_EXPR_COND (cond_expr) = new_cond;
00557 update_stmt (cond_expr);
00558
00559 if (has_zero_uses (test_var))
00560 {
00561 tree def = SSA_NAME_DEF_STMT (test_var);
00562 block_stmt_iterator bsi = bsi_for_stmt (def);
00563 bsi_remove (&bsi, true);
00564 }
00565 }
00566
00567
00568
00569
00570
00571
00572 simplify_cond (cond_expr);
00573 }
00574
00575
00576
00577
00578 static void
00579 tidy_after_forward_propagate_addr (tree stmt)
00580 {
00581
00582 if (maybe_clean_or_replace_eh_stmt (stmt, stmt)
00583 && tree_purge_dead_eh_edges (bb_for_stmt (stmt)))
00584 cfg_changed = true;
00585
00586 if (TREE_CODE (TREE_OPERAND (stmt, 1)) == ADDR_EXPR)
00587 recompute_tree_invariant_for_addr_expr (TREE_OPERAND (stmt, 1));
00588
00589 mark_new_vars_to_rename (stmt);
00590 }
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607 static bool
00608 forward_propagate_addr_into_variable_array_index (tree offset, tree lhs,
00609 tree stmt, tree use_stmt)
00610 {
00611 tree index;
00612
00613
00614 if (TREE_CODE (offset) != MODIFY_EXPR)
00615 return false;
00616
00617
00618
00619 offset = TREE_OPERAND (offset, 1);
00620 if (!is_gimple_cast (offset))
00621 return false;
00622
00623 offset = TREE_OPERAND (offset, 0);
00624 if (TREE_CODE (offset) != SSA_NAME)
00625 return false;
00626
00627
00628
00629 offset = SSA_NAME_DEF_STMT (offset);
00630
00631
00632
00633 if (TREE_CODE (offset) != MODIFY_EXPR)
00634 return false;
00635
00636
00637
00638
00639
00640 offset = TREE_OPERAND (offset, 1);
00641 if (TREE_CODE (offset) != MULT_EXPR
00642 || TREE_CODE (TREE_OPERAND (offset, 1)) != INTEGER_CST
00643 || !simple_cst_equal (TREE_OPERAND (offset, 1),
00644 TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (lhs)))))
00645 return false;
00646
00647
00648 index = TREE_OPERAND (offset, 0);
00649
00650
00651 TREE_OPERAND (use_stmt, 1) = unshare_expr (TREE_OPERAND (stmt, 1));
00652 TREE_OPERAND (TREE_OPERAND (TREE_OPERAND (use_stmt, 1), 0), 1) = index;
00653
00654
00655
00656 fold_stmt_inplace (use_stmt);
00657 tidy_after_forward_propagate_addr (use_stmt);
00658 return true;
00659 }
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673 static bool
00674 forward_propagate_addr_expr_1 (tree stmt, tree use_stmt, bool *changed)
00675 {
00676 tree name = TREE_OPERAND (stmt, 0);
00677 tree lhs, rhs, array_ref;
00678
00679
00680
00681 lhs = TREE_OPERAND (use_stmt, 0);
00682 while (TREE_CODE (lhs) == COMPONENT_REF || TREE_CODE (lhs) == ARRAY_REF)
00683 lhs = TREE_OPERAND (lhs, 0);
00684
00685
00686
00687 if (TREE_CODE (lhs) == INDIRECT_REF && TREE_OPERAND (lhs, 0) == name)
00688 {
00689
00690
00691 TREE_OPERAND (lhs, 0) = unshare_expr (TREE_OPERAND (stmt, 1));
00692 fold_stmt_inplace (use_stmt);
00693 tidy_after_forward_propagate_addr (use_stmt);
00694 if (changed)
00695 *changed = true;
00696 }
00697
00698
00699
00700
00701
00702
00703
00704
00705 else if (TREE_CODE (lhs) == SSA_NAME && TREE_OPERAND (use_stmt, 1) == name)
00706 {
00707 TREE_OPERAND (use_stmt, 1) = unshare_expr (TREE_OPERAND (stmt, 1));
00708 tidy_after_forward_propagate_addr (use_stmt);
00709 if (changed)
00710 *changed = true;
00711 return true;
00712 }
00713
00714
00715
00716 rhs = TREE_OPERAND (use_stmt, 1);
00717 while (TREE_CODE (rhs) == COMPONENT_REF
00718 || TREE_CODE (rhs) == ARRAY_REF
00719 || TREE_CODE (rhs) == ADDR_EXPR)
00720 rhs = TREE_OPERAND (rhs, 0);
00721
00722
00723
00724 if (TREE_CODE (rhs) == INDIRECT_REF && TREE_OPERAND (rhs, 0) == name)
00725 {
00726
00727
00728 TREE_OPERAND (rhs, 0) = unshare_expr (TREE_OPERAND (stmt, 1));
00729 fold_stmt_inplace (use_stmt);
00730 tidy_after_forward_propagate_addr (use_stmt);
00731 if (changed)
00732 *changed = true;
00733 return true;
00734 }
00735
00736
00737
00738
00739
00740 array_ref = TREE_OPERAND (TREE_OPERAND (stmt, 1), 0);
00741 if (TREE_CODE (array_ref) != ARRAY_REF
00742 || TREE_CODE (TREE_TYPE (TREE_OPERAND (array_ref, 0))) != ARRAY_TYPE
00743 || !integer_zerop (TREE_OPERAND (array_ref, 1)))
00744 return false;
00745
00746
00747
00748 if (TREE_CODE (rhs) != PLUS_EXPR)
00749 return false;
00750
00751
00752
00753 if (TREE_OPERAND (rhs, 0) == name
00754 && TREE_CODE (TREE_OPERAND (rhs, 1)) == INTEGER_CST)
00755 {
00756 tree orig = unshare_expr (rhs);
00757 TREE_OPERAND (rhs, 0) = unshare_expr (TREE_OPERAND (stmt, 1));
00758
00759
00760
00761
00762 if (fold_stmt_inplace (use_stmt))
00763 {
00764 tidy_after_forward_propagate_addr (use_stmt);
00765 if (changed)
00766 *changed = true;
00767 return true;
00768 }
00769 else
00770 {
00771 TREE_OPERAND (use_stmt, 1) = orig;
00772 update_stmt (use_stmt);
00773 return false;
00774 }
00775 }
00776
00777
00778
00779
00780
00781 if (TREE_OPERAND (rhs, 0) == name
00782 && TREE_CODE (TREE_OPERAND (rhs, 1)) == SSA_NAME
00783
00784
00785 && lang_hooks.types_compatible_p (TREE_TYPE (name), TREE_TYPE (rhs)))
00786 {
00787 bool res;
00788 tree offset_stmt = SSA_NAME_DEF_STMT (TREE_OPERAND (rhs, 1));
00789
00790 res = forward_propagate_addr_into_variable_array_index (offset_stmt, lhs,
00791 stmt, use_stmt);
00792 if (res && changed)
00793 *changed = true;
00794 return res;
00795 }
00796
00797
00798
00799 if (TREE_OPERAND (rhs, 1) == name
00800 && TREE_CODE (TREE_OPERAND (rhs, 0)) == SSA_NAME
00801
00802
00803 && lang_hooks.types_compatible_p (TREE_TYPE (name), TREE_TYPE (rhs)))
00804 {
00805 bool res;
00806 tree offset_stmt = SSA_NAME_DEF_STMT (TREE_OPERAND (rhs, 0));
00807 res = forward_propagate_addr_into_variable_array_index (offset_stmt, lhs,
00808 stmt, use_stmt);
00809 if (res && changed)
00810 *changed = true;
00811 return res;
00812 }
00813 return false;
00814 }
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825 static bool
00826 forward_propagate_addr_expr (tree stmt, bool *some)
00827 {
00828 int stmt_loop_depth = bb_for_stmt (stmt)->loop_depth;
00829 tree name = TREE_OPERAND (stmt, 0);
00830 imm_use_iterator iter;
00831 tree use_stmt;
00832 bool all = true;
00833
00834 FOR_EACH_IMM_USE_STMT (use_stmt, iter, name)
00835 {
00836 bool result;
00837
00838
00839
00840 if (TREE_CODE (use_stmt) != MODIFY_EXPR)
00841 {
00842 all = false;
00843 continue;
00844 }
00845
00846
00847
00848
00849 if (bb_for_stmt (use_stmt)->loop_depth > stmt_loop_depth)
00850 {
00851 all = false;
00852 continue;
00853 }
00854
00855
00856 if (stmt_ann (use_stmt)->has_volatile_ops)
00857 {
00858 all = false;
00859 continue;
00860 }
00861
00862 result = forward_propagate_addr_expr_1 (stmt, use_stmt, some);
00863 *some |= result;
00864 all &= result;
00865 }
00866
00867 return all;
00868 }
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884 static void
00885 simplify_not_neg_expr (tree stmt)
00886 {
00887 tree rhs = TREE_OPERAND (stmt, 1);
00888 tree rhs_def_stmt = SSA_NAME_DEF_STMT (TREE_OPERAND (rhs, 0));
00889
00890
00891 if (TREE_CODE (rhs_def_stmt) == MODIFY_EXPR
00892 && TREE_CODE (TREE_OPERAND (rhs_def_stmt, 1)) == TREE_CODE (rhs))
00893 {
00894 tree rhs_def_operand = TREE_OPERAND (TREE_OPERAND (rhs_def_stmt, 1), 0);
00895
00896
00897 if (TREE_CODE (rhs_def_operand) == SSA_NAME
00898 && ! SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rhs_def_operand))
00899 {
00900 TREE_OPERAND (stmt, 1) = rhs_def_operand;
00901 update_stmt (stmt);
00902 }
00903 }
00904 }
00905
00906
00907
00908
00909 static void
00910 simplify_switch_expr (tree stmt)
00911 {
00912 tree cond = SWITCH_COND (stmt);
00913 tree def, to, ti;
00914
00915
00916
00917
00918 if (TREE_CODE (cond) == SSA_NAME)
00919 {
00920 def = SSA_NAME_DEF_STMT (cond);
00921 if (TREE_CODE (def) == MODIFY_EXPR)
00922 {
00923 def = TREE_OPERAND (def, 1);
00924 if (TREE_CODE (def) == NOP_EXPR)
00925 {
00926 int need_precision;
00927 bool fail;
00928
00929 def = TREE_OPERAND (def, 0);
00930
00931 #ifdef ENABLE_CHECKING
00932
00933 gcc_assert (is_gimple_val (def));
00934 #endif
00935
00936 to = TREE_TYPE (cond);
00937 ti = TREE_TYPE (def);
00938
00939
00940
00941
00942 need_precision = TYPE_PRECISION (ti);
00943 fail = false;
00944 if (! INTEGRAL_TYPE_P (ti))
00945 fail = true;
00946 else if (TYPE_UNSIGNED (to) && !TYPE_UNSIGNED (ti))
00947 fail = true;
00948 else if (!TYPE_UNSIGNED (to) && TYPE_UNSIGNED (ti))
00949 need_precision += 1;
00950 if (TYPE_PRECISION (to) < need_precision)
00951 fail = true;
00952
00953 if (!fail)
00954 {
00955 SWITCH_COND (stmt) = def;
00956 update_stmt (stmt);
00957 }
00958 }
00959 }
00960 }
00961 }
00962
00963
00964
00965 static unsigned int
00966 tree_ssa_forward_propagate_single_use_vars (void)
00967 {
00968 basic_block bb;
00969 unsigned int todoflags = 0;
00970
00971 cfg_changed = false;
00972
00973 FOR_EACH_BB (bb)
00974 {
00975 block_stmt_iterator bsi;
00976
00977
00978 for (bsi = bsi_start (bb); !bsi_end_p (bsi); )
00979 {
00980 tree stmt = bsi_stmt (bsi);
00981
00982
00983
00984 if (TREE_CODE (stmt) == MODIFY_EXPR)
00985 {
00986 tree lhs = TREE_OPERAND (stmt, 0);
00987 tree rhs = TREE_OPERAND (stmt, 1);
00988
00989
00990 if (TREE_CODE (lhs) != SSA_NAME)
00991 {
00992 bsi_next (&bsi);
00993 continue;
00994 }
00995
00996 if (TREE_CODE (rhs) == ADDR_EXPR)
00997 {
00998 bool some = false;
00999 if (forward_propagate_addr_expr (stmt, &some))
01000 bsi_remove (&bsi, true);
01001 else
01002 bsi_next (&bsi);
01003 if (some)
01004 todoflags |= TODO_update_smt_usage;
01005 }
01006 else if ((TREE_CODE (rhs) == BIT_NOT_EXPR
01007 || TREE_CODE (rhs) == NEGATE_EXPR)
01008 && TREE_CODE (TREE_OPERAND (rhs, 0)) == SSA_NAME)
01009 {
01010 simplify_not_neg_expr (stmt);
01011 bsi_next (&bsi);
01012 }
01013 else
01014 bsi_next (&bsi);
01015 }
01016 else if (TREE_CODE (stmt) == SWITCH_EXPR)
01017 {
01018 simplify_switch_expr (stmt);
01019 bsi_next (&bsi);
01020 }
01021 else if (TREE_CODE (stmt) == COND_EXPR)
01022 {
01023 forward_propagate_into_cond (stmt);
01024 bsi_next (&bsi);
01025 }
01026 else
01027 bsi_next (&bsi);
01028 }
01029 }
01030
01031 if (cfg_changed)
01032 cleanup_tree_cfg ();
01033 return todoflags;
01034 }
01035
01036
01037 static bool
01038 gate_forwprop (void)
01039 {
01040 return 1;
01041 }
01042
01043 struct tree_opt_pass pass_forwprop = {
01044 "forwprop",
01045 gate_forwprop,
01046 tree_ssa_forward_propagate_single_use_vars,
01047 NULL,
01048 NULL,
01049 0,
01050 TV_TREE_FORWPROP,
01051 PROP_cfg | PROP_ssa
01052 | PROP_alias,
01053 0,
01054 PROP_smt_usage,
01055 0,
01056 TODO_dump_func
01057 | TODO_ggc_collect
01058 | TODO_update_ssa | TODO_verify_ssa,
01059 0
01060 };