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 "rtl.h"
00028 #include "tm_p.h"
00029 #include "hard-reg-set.h"
00030 #include "basic-block.h"
00031 #include "output.h"
00032 #include "toplev.h"
00033 #include "flags.h"
00034 #include "function.h"
00035 #include "expr.h"
00036 #include "ggc.h"
00037 #include "langhooks.h"
00038 #include "diagnostic.h"
00039 #include "tree-flow.h"
00040 #include "timevar.h"
00041 #include "tree-dump.h"
00042 #include "tree-pass.h"
00043 #include "toplev.h"
00044 #include "except.h"
00045 #include "cfgloop.h"
00046 #include "cfglayout.h"
00047 #include "hashtab.h"
00048 #include "tree-ssa-propagate.h"
00049 #include "tree-scalar-evolution.h"
00050
00051
00052
00053 static bool
00054 remove_fallthru_edge (VEC(edge,gc) *ev)
00055 {
00056 edge_iterator ei;
00057 edge e;
00058
00059 FOR_EACH_EDGE (e, ei, ev)
00060 if ((e->flags & EDGE_FALLTHRU) != 0)
00061 {
00062 remove_edge (e);
00063 return true;
00064 }
00065 return false;
00066 }
00067
00068
00069
00070
00071 static bool
00072 cleanup_control_expr_graph (basic_block bb, block_stmt_iterator bsi)
00073 {
00074 edge taken_edge;
00075 bool retval = false;
00076 tree expr = bsi_stmt (bsi), val;
00077
00078 if (!single_succ_p (bb))
00079 {
00080 edge e;
00081 edge_iterator ei;
00082 bool warned;
00083
00084 fold_defer_overflow_warnings ();
00085
00086 switch (TREE_CODE (expr))
00087 {
00088 case COND_EXPR:
00089 val = fold (COND_EXPR_COND (expr));
00090 break;
00091
00092 case SWITCH_EXPR:
00093 val = fold (SWITCH_COND (expr));
00094 if (TREE_CODE (val) != INTEGER_CST)
00095 {
00096 fold_undefer_and_ignore_overflow_warnings ();
00097 return false;
00098 }
00099 break;
00100
00101 default:
00102 gcc_unreachable ();
00103 }
00104
00105 taken_edge = find_taken_edge (bb, val);
00106 if (!taken_edge)
00107 {
00108 fold_undefer_and_ignore_overflow_warnings ();
00109 return false;
00110 }
00111
00112
00113 warned = false;
00114 for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
00115 {
00116 if (e != taken_edge)
00117 {
00118 if (!warned)
00119 {
00120 fold_undefer_overflow_warnings
00121 (true, expr, WARN_STRICT_OVERFLOW_CONDITIONAL);
00122 warned = true;
00123 }
00124
00125 taken_edge->probability += e->probability;
00126 taken_edge->count += e->count;
00127 remove_edge (e);
00128 retval = true;
00129 }
00130 else
00131 ei_next (&ei);
00132 }
00133 if (!warned)
00134 fold_undefer_and_ignore_overflow_warnings ();
00135 if (taken_edge->probability > REG_BR_PROB_BASE)
00136 taken_edge->probability = REG_BR_PROB_BASE;
00137 }
00138 else
00139 taken_edge = single_succ_edge (bb);
00140
00141 bsi_remove (&bsi, true);
00142 taken_edge->flags = EDGE_FALLTHRU;
00143
00144
00145 free_dominance_info (CDI_DOMINATORS);
00146
00147 return retval;
00148 }
00149
00150
00151
00152
00153
00154
00155
00156 VEC(tree,gc) *modified_noreturn_calls;
00157
00158
00159
00160 static bool
00161 cleanup_control_flow (void)
00162 {
00163 basic_block bb;
00164 block_stmt_iterator bsi;
00165 bool retval = false;
00166 tree stmt;
00167
00168
00169 while (VEC_length (tree, modified_noreturn_calls))
00170 {
00171 stmt = VEC_pop (tree, modified_noreturn_calls);
00172 bb = bb_for_stmt (stmt);
00173 if (bb != NULL && last_stmt (bb) != stmt && noreturn_call_p (stmt))
00174 split_block (bb, stmt);
00175 }
00176
00177 FOR_EACH_BB (bb)
00178 {
00179 bsi = bsi_last (bb);
00180
00181
00182
00183 retval |= tree_purge_dead_eh_edges (bb);
00184
00185 if (bsi_end_p (bsi))
00186 continue;
00187
00188 stmt = bsi_stmt (bsi);
00189
00190 if (TREE_CODE (stmt) == COND_EXPR
00191 || TREE_CODE (stmt) == SWITCH_EXPR)
00192 retval |= cleanup_control_expr_graph (bb, bsi);
00193
00194
00195 else if (TREE_CODE (stmt) == GOTO_EXPR
00196 && TREE_CODE (GOTO_DESTINATION (stmt)) == ADDR_EXPR
00197 && (TREE_CODE (TREE_OPERAND (GOTO_DESTINATION (stmt), 0))
00198 == LABEL_DECL))
00199 {
00200 edge e;
00201 tree label;
00202 edge_iterator ei;
00203 basic_block target_block;
00204 bool removed_edge = false;
00205
00206
00207
00208
00209 label = TREE_OPERAND (GOTO_DESTINATION (stmt), 0);
00210 target_block = label_to_block (label);
00211 for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
00212 {
00213 if (e->dest != target_block)
00214 {
00215 removed_edge = true;
00216 remove_edge (e);
00217 }
00218 else
00219 {
00220
00221 e->flags &= ~EDGE_ABNORMAL;
00222
00223
00224 e->flags |= EDGE_FALLTHRU;
00225 ei_next (&ei);
00226 }
00227 }
00228
00229
00230
00231 if (removed_edge)
00232 free_dominance_info (CDI_DOMINATORS);
00233
00234
00235
00236 bsi_remove (&bsi, true);
00237 retval = true;
00238 }
00239
00240
00241
00242 else if (noreturn_call_p (stmt) && remove_fallthru_edge (bb->succs))
00243 {
00244 free_dominance_info (CDI_DOMINATORS);
00245 retval = true;
00246 }
00247 }
00248 return retval;
00249 }
00250
00251
00252
00253
00254
00255
00256
00257
00258 static bool
00259 tree_forwarder_block_p (basic_block bb, bool phi_wanted)
00260 {
00261 block_stmt_iterator bsi;
00262 edge_iterator ei;
00263 edge e, succ;
00264 basic_block dest;
00265
00266
00267 if (single_succ_p (bb) != 1
00268
00269
00270 || (phi_nodes (bb) != NULL_TREE) != phi_wanted
00271
00272 || single_succ (bb) == EXIT_BLOCK_PTR
00273
00274 || single_succ (bb) == bb
00275
00276 || (single_succ_edge (bb)->flags & EDGE_ABNORMAL))
00277 return false;
00278
00279 #if ENABLE_CHECKING
00280 gcc_assert (bb != ENTRY_BLOCK_PTR);
00281 #endif
00282
00283
00284
00285 for (bsi = bsi_last (bb); !bsi_end_p (bsi); bsi_prev (&bsi))
00286 {
00287 tree stmt = bsi_stmt (bsi);
00288
00289 switch (TREE_CODE (stmt))
00290 {
00291 case LABEL_EXPR:
00292 if (DECL_NONLOCAL (LABEL_EXPR_LABEL (stmt)))
00293 return false;
00294 break;
00295
00296 default:
00297 return false;
00298 }
00299 }
00300
00301 if (find_edge (ENTRY_BLOCK_PTR, bb))
00302 return false;
00303
00304 if (current_loops)
00305 {
00306 basic_block dest;
00307
00308 if (bb->loop_father->header == bb)
00309 return false;
00310 dest = EDGE_SUCC (bb, 0)->dest;
00311
00312 if (dest->loop_father->header == dest)
00313 return false;
00314 }
00315
00316
00317
00318
00319
00320
00321 succ = single_succ_edge (bb);
00322 dest = succ->dest;
00323 FOR_EACH_EDGE (e, ei, bb->preds)
00324 {
00325 if (e->flags & EDGE_EH)
00326 {
00327 if (!single_pred_p (dest))
00328 return false;
00329 }
00330 }
00331
00332 return true;
00333 }
00334
00335
00336
00337 static inline bool
00338 has_abnormal_incoming_edge_p (basic_block bb)
00339 {
00340 edge e;
00341 edge_iterator ei;
00342
00343 FOR_EACH_EDGE (e, ei, bb->preds)
00344 if (e->flags & EDGE_ABNORMAL)
00345 return true;
00346
00347 return false;
00348 }
00349
00350
00351
00352
00353
00354 static bool
00355 phi_alternatives_equal (basic_block dest, edge e1, edge e2)
00356 {
00357 int n1 = e1->dest_idx;
00358 int n2 = e2->dest_idx;
00359 tree phi;
00360
00361 for (phi = phi_nodes (dest); phi; phi = PHI_CHAIN (phi))
00362 {
00363 tree val1 = PHI_ARG_DEF (phi, n1);
00364 tree val2 = PHI_ARG_DEF (phi, n2);
00365
00366 gcc_assert (val1 != NULL_TREE);
00367 gcc_assert (val2 != NULL_TREE);
00368
00369 if (!operand_equal_for_phi_arg_p (val1, val2))
00370 return false;
00371 }
00372
00373 return true;
00374 }
00375
00376
00377
00378
00379
00380 static bool
00381 remove_forwarder_block (basic_block bb, basic_block **worklist)
00382 {
00383 edge succ = single_succ_edge (bb), e, s;
00384 basic_block dest = succ->dest;
00385 tree label;
00386 tree phi;
00387 edge_iterator ei;
00388 block_stmt_iterator bsi, bsi_to;
00389 bool seen_abnormal_edge = false;
00390
00391
00392
00393
00394 if (dest == bb)
00395 return false;
00396
00397
00398
00399 label = first_stmt (dest);
00400 if (label
00401 && TREE_CODE (label) == LABEL_EXPR
00402 && DECL_NONLOCAL (LABEL_EXPR_LABEL (label)))
00403 return false;
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416 if (has_abnormal_incoming_edge_p (bb))
00417 {
00418 seen_abnormal_edge = true;
00419
00420 if (has_abnormal_incoming_edge_p (dest)
00421 || phi_nodes (dest) != NULL_TREE)
00422 return false;
00423 }
00424
00425
00426
00427
00428 if (phi_nodes (dest))
00429 {
00430 FOR_EACH_EDGE (e, ei, bb->preds)
00431 {
00432 s = find_edge (e->src, dest);
00433 if (!s)
00434 continue;
00435
00436 if (!phi_alternatives_equal (dest, succ, s))
00437 return false;
00438 }
00439 }
00440
00441
00442 for (ei = ei_start (bb->preds); (e = ei_safe_edge (ei)); )
00443 {
00444 if (e->flags & EDGE_ABNORMAL)
00445 {
00446
00447
00448 s = redirect_edge_succ_nodup (e, dest);
00449 }
00450 else
00451 s = redirect_edge_and_branch (e, dest);
00452
00453 if (s == e)
00454 {
00455
00456
00457 for (phi = phi_nodes (dest); phi; phi = PHI_CHAIN (phi))
00458 add_phi_arg (phi, PHI_ARG_DEF (phi, succ->dest_idx), s);
00459 }
00460 else
00461 {
00462
00463
00464
00465
00466 if (tree_forwarder_block_p (s->src, false))
00467 *(*worklist)++ = s->src;
00468 }
00469 }
00470
00471 if (seen_abnormal_edge)
00472 {
00473
00474
00475
00476 bsi_to = bsi_start (dest);
00477 for (bsi = bsi_start (bb); !bsi_end_p (bsi); )
00478 {
00479 label = bsi_stmt (bsi);
00480 gcc_assert (TREE_CODE (label) == LABEL_EXPR);
00481 bsi_remove (&bsi, false);
00482 bsi_insert_before (&bsi_to, label, BSI_CONTINUE_LINKING);
00483 }
00484 }
00485
00486
00487 if (dom_info_available_p (CDI_DOMINATORS))
00488 {
00489 basic_block dom, dombb, domdest;
00490
00491 dombb = get_immediate_dominator (CDI_DOMINATORS, bb);
00492 domdest = get_immediate_dominator (CDI_DOMINATORS, dest);
00493 if (domdest == bb)
00494 {
00495
00496
00497 dom = dombb;
00498 }
00499 else
00500 dom = nearest_common_dominator (CDI_DOMINATORS, domdest, dombb);
00501
00502 set_immediate_dominator (CDI_DOMINATORS, dest, dom);
00503 }
00504
00505
00506 delete_basic_block (bb);
00507
00508 return true;
00509 }
00510
00511
00512
00513 static bool
00514 cleanup_forwarder_blocks (void)
00515 {
00516 basic_block bb;
00517 bool changed = false;
00518 basic_block *worklist = XNEWVEC (basic_block, n_basic_blocks);
00519 basic_block *current = worklist;
00520
00521 FOR_EACH_BB (bb)
00522 {
00523 if (tree_forwarder_block_p (bb, false))
00524 *current++ = bb;
00525 }
00526
00527 while (current != worklist)
00528 {
00529 bb = *--current;
00530 changed |= remove_forwarder_block (bb, ¤t);
00531 }
00532
00533 free (worklist);
00534 return changed;
00535 }
00536
00537
00538
00539 static bool
00540 cleanup_tree_cfg_1 (void)
00541 {
00542 bool retval;
00543
00544 retval = cleanup_control_flow ();
00545 retval |= delete_unreachable_blocks ();
00546
00547
00548
00549
00550
00551 if (optimize > 0)
00552 {
00553
00554
00555
00556
00557 start_recording_case_labels ();
00558 retval |= cleanup_forwarder_blocks ();
00559 end_recording_case_labels ();
00560 }
00561
00562
00563
00564
00565 retval |= merge_seq_blocks ();
00566
00567 return retval;
00568 }
00569
00570
00571
00572
00573
00574 bool
00575 cleanup_tree_cfg (void)
00576 {
00577 bool retval, changed;
00578
00579 timevar_push (TV_TREE_CLEANUP_CFG);
00580
00581
00582
00583 changed = false;
00584 do
00585 {
00586 retval = cleanup_tree_cfg_1 ();
00587 changed |= retval;
00588 }
00589 while (retval);
00590
00591 compact_blocks ();
00592
00593 #ifdef ENABLE_CHECKING
00594 verify_flow_info ();
00595 #endif
00596
00597 timevar_pop (TV_TREE_CLEANUP_CFG);
00598
00599 return changed;
00600 }
00601
00602
00603
00604 void
00605 cleanup_tree_cfg_loop (void)
00606 {
00607 bool changed = cleanup_tree_cfg ();
00608
00609 if (changed)
00610 {
00611 bitmap changed_bbs = BITMAP_ALLOC (NULL);
00612 fix_loop_structure (current_loops, changed_bbs);
00613 calculate_dominance_info (CDI_DOMINATORS);
00614
00615
00616
00617
00618 rewrite_into_loop_closed_ssa (changed_bbs, TODO_update_ssa);
00619
00620 BITMAP_FREE (changed_bbs);
00621
00622 #ifdef ENABLE_CHECKING
00623 verify_loop_structure (current_loops);
00624 #endif
00625 scev_reset ();
00626 }
00627 }
00628
00629
00630
00631 static void
00632 remove_forwarder_block_with_phi (basic_block bb)
00633 {
00634 edge succ = single_succ_edge (bb);
00635 basic_block dest = succ->dest;
00636 tree label;
00637 basic_block dombb, domdest, dom;
00638
00639
00640
00641
00642 if (dest == bb)
00643 return;
00644
00645
00646
00647 label = first_stmt (dest);
00648 if (label
00649 && TREE_CODE (label) == LABEL_EXPR
00650 && DECL_NONLOCAL (LABEL_EXPR_LABEL (label)))
00651 return;
00652
00653
00654 while (EDGE_COUNT (bb->preds) > 0)
00655 {
00656 edge e = EDGE_PRED (bb, 0), s;
00657 tree phi;
00658
00659 s = find_edge (e->src, dest);
00660 if (s)
00661 {
00662
00663
00664
00665 if (phi_alternatives_equal (dest, s, succ))
00666 {
00667 e = redirect_edge_and_branch (e, dest);
00668 PENDING_STMT (e) = NULL_TREE;
00669 continue;
00670 }
00671
00672
00673
00674
00675 e = single_succ_edge (split_edge (e));
00676 }
00677
00678 s = redirect_edge_and_branch (e, dest);
00679
00680
00681 gcc_assert (s == e);
00682
00683
00684
00685 for (phi = phi_nodes (dest); phi; phi = PHI_CHAIN (phi))
00686 {
00687 tree def = PHI_ARG_DEF (phi, succ->dest_idx);
00688
00689 if (TREE_CODE (def) == SSA_NAME)
00690 {
00691 tree var;
00692
00693
00694
00695
00696 for (var = PENDING_STMT (e); var; var = TREE_CHAIN (var))
00697 {
00698 tree old_arg = TREE_PURPOSE (var);
00699 tree new_arg = TREE_VALUE (var);
00700
00701 if (def == old_arg)
00702 {
00703 def = new_arg;
00704 break;
00705 }
00706 }
00707 }
00708
00709 add_phi_arg (phi, def, s);
00710 }
00711
00712 PENDING_STMT (e) = NULL;
00713 }
00714
00715
00716 dombb = get_immediate_dominator (CDI_DOMINATORS, bb);
00717 domdest = get_immediate_dominator (CDI_DOMINATORS, dest);
00718 if (domdest == bb)
00719 {
00720
00721
00722 dom = dombb;
00723 }
00724 else
00725 dom = nearest_common_dominator (CDI_DOMINATORS, domdest, dombb);
00726
00727 set_immediate_dominator (CDI_DOMINATORS, dest, dom);
00728
00729
00730
00731 delete_basic_block (bb);
00732 }
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759 static unsigned int
00760 merge_phi_nodes (void)
00761 {
00762 basic_block *worklist = XNEWVEC (basic_block, n_basic_blocks);
00763 basic_block *current = worklist;
00764 basic_block bb;
00765
00766 calculate_dominance_info (CDI_DOMINATORS);
00767
00768
00769 FOR_EACH_BB (bb)
00770 {
00771 basic_block dest;
00772
00773
00774 if (!tree_forwarder_block_p (bb, true))
00775 continue;
00776
00777 dest = single_succ (bb);
00778
00779
00780
00781 if (!phi_nodes (dest)
00782
00783
00784 || has_abnormal_incoming_edge_p (bb))
00785 continue;
00786
00787 if (!dominated_by_p (CDI_DOMINATORS, dest, bb))
00788 {
00789
00790
00791
00792 *current++ = bb;
00793 }
00794 else
00795 {
00796 tree phi;
00797 unsigned int dest_idx = single_succ_edge (bb)->dest_idx;
00798
00799
00800
00801
00802
00803
00804 for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
00805 {
00806 tree result = PHI_RESULT (phi);
00807 use_operand_p imm_use;
00808 tree use_stmt;
00809
00810
00811
00812 if (has_zero_uses (result))
00813 continue;
00814
00815
00816 if (!single_imm_use (result, &imm_use, &use_stmt)
00817 || TREE_CODE (use_stmt) != PHI_NODE
00818 || bb_for_stmt (use_stmt) != dest
00819 || PHI_ARG_DEF (use_stmt, dest_idx) != result)
00820 break;
00821 }
00822
00823
00824
00825 if (!phi)
00826 *current++ = bb;
00827 }
00828 }
00829
00830
00831 while (current != worklist)
00832 {
00833 bb = *--current;
00834 remove_forwarder_block_with_phi (bb);
00835 }
00836
00837 free (worklist);
00838 return 0;
00839 }
00840
00841 static bool
00842 gate_merge_phi (void)
00843 {
00844 return 1;
00845 }
00846
00847 struct tree_opt_pass pass_merge_phi = {
00848 "mergephi",
00849 gate_merge_phi,
00850 merge_phi_nodes,
00851 NULL,
00852 NULL,
00853 0,
00854 TV_TREE_MERGE_PHI,
00855 PROP_cfg | PROP_ssa,
00856 0,
00857 0,
00858 0,
00859 TODO_dump_func | TODO_ggc_collect
00860 | TODO_verify_ssa,
00861 0
00862 };