00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
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 #ifdef USE_PCH
00065 #include "opt_pch.h"
00066 #endif // USE_PCH
00067 #pragma hdrstop
00068
00069
00070 #ifdef _KEEP_RCS_ID
00071 #define opt_cfg_CXX "opt_cfg.cxx"
00072 static char *rcs_id = opt_cfg_CXX"$Revision: 1.30 $";
00073 #endif
00074
00075 #include "defs.h"
00076 #include "wn_util.h"
00077 #include "wn_simp.h"
00078 #include "wintrinsic.h"
00079 #include "opcode.h"
00080 #include "errors.h"
00081 #include "erglob.h"
00082 #include "tracing.h"
00083 #include "config_targ.h"
00084 #include "config_opt.h"
00085 #include "region_util.h"
00086 #include "fb_whirl.h"
00087 #include "opt_cfg.h"
00088 #include "opt_exc.h"
00089 #include "opt_htable.h"
00090 #include "opt_util.h"
00091 #include "opt_wn.h"
00092 #include "opt_config.h"
00093 #include "opt_alias_class.h"
00094 #include "bb_node_set.h"
00095 #include "opt_ssa.h"
00096 #include "opt_tail.h"
00097 #include "w2op.h"
00098
00099 CFG::CFG(MEM_POOL *pool, MEM_POOL *lpool)
00100 : _bb_vec(pool),
00101 _entry_vec(pool),
00102 _exit_vec(pool),
00103 _notreach_vec(pool),
00104 _agoto_pred_vec(pool),
00105 _agoto_succ_vec(pool),
00106 _mp_rid(pool),
00107 _mp_type(pool),
00108 #if defined(TARG_SL)
00109 _sl2_para_rid(pool),
00110 _sl2_para_type(pool),
00111 #endif
00112 _bb_region(pool)
00113 {
00114 _mem_pool = pool;
00115 _loc_pool = lpool;
00116 _bb_vec.Alloc_array(CFG_BB_TAB_SIZE);
00117 _entry_vec.Alloc_array(CFG_ALTENTRY_TAB_SIZE);
00118 _exit_vec.Alloc_array(CFG_EARLYEXIT_TAB_SIZE);
00119 _notreach_vec.Alloc_array(CFG_EARLYEXIT_TAB_SIZE);
00120 _agoto_pred_vec.Alloc_array(CFG_BB_TAB_SIZE);
00121 _agoto_succ_vec.Alloc_array(CFG_BB_TAB_SIZE);
00122 _dfs_vec = NULL;
00123 _dfs_vec_sz = 0;
00124 _po_vec = NULL;
00125 _po_vec_sz = 0;
00126 _dpo_vec = NULL;
00127 _dpo_vec_sz = 0;
00128 _pdo_vec = NULL;
00129 _pdo_vec_sz = 0;
00130 _entry_bb = NULL;
00131 _exit_bb = NULL;
00132 _first_bb = NULL;
00133 _last_bb = NULL;
00134 _fake_entry_bb = NULL;
00135 _fake_exit_bb = NULL;
00136 _loops = NULL;
00137 _exc = NULL;
00138 _bb_set = NULL;
00139 _non_true_body_set = NULL;
00140 _current_bb = NULL;
00141 _first_bb_id = _last_bb_id = _bb_vec.Newidx();
00142 _label_map = CXX_NEW(MAP(CFG_LAB_HASH_SIZE, pool), pool);
00143 _orig_last_label = _last_label_num = 0;
00144 _cur_loop_depth = 0;
00145 _lower_fully = FALSE;
00146 _calls_break = TRUE;
00147 _rvi_break_stmt = FALSE;
00148 _feedback = NULL;
00149 _rid = NULL;
00150 _rgn_level = RL_UNKNOWN;
00151 _has_regions = FALSE;
00152 _dohead_cnt = 0;
00153 WN_Simplifier_Enable(FALSE);
00154 _trace = Get_Trace(TP_GLOBOPT, CFG_DUMP_FLAG);
00155 _loops_valid = FALSE;
00156 }
00157
00158 CFG::~CFG()
00159 {
00160
00161
00162 _bb_vec.Free_array();
00163 _entry_vec.Free_array();
00164 _exit_vec.Free_array();
00165 _notreach_vec.Free_array();
00166 _agoto_pred_vec.Free_array();
00167 _agoto_succ_vec.Free_array();
00168 }
00169
00170
00171
00172
00173
00174
00175 BB_NODE *
00176 CFG::New_bb( BOOL connect, BB_KIND kind )
00177 {
00178 BB_NODE *newbb = Create_bb(kind);
00179 if ( connect )
00180 Connect_predsucc( _current_bb, newbb );
00181 Append_bb( newbb );
00182
00183 if (Inside_mp_do()) newbb->Set_MP_region();
00184 return newbb;
00185 }
00186
00187
00188
00189
00190
00191 BOOL
00192 CFG::Removable_bb( const BB_NODE *bb ) const
00193 {
00194 if ( bb == Fake_entry_bb() || bb == Fake_exit_bb())
00195 return FALSE;
00196
00197 return TRUE;
00198 }
00199
00200
00201
00202
00203
00204 void
00205 CFG::Remove_bb(BB_NODE *bb)
00206 {
00207 Is_True( Removable_bb( bb ),
00208 ("CFG::Remove_bb: trying to remove unremovable bb:%d", bb->Id()) );
00209
00210
00211 BB_LIST_ITER bb_ps_iter;
00212 BB_NODE *succ,*pred;
00213 FOR_ALL_ELEM( succ, bb_ps_iter, Init(bb->Succ()) ) {
00214 succ->Remove_pred( bb, Mem_pool() );
00215 }
00216 FOR_ALL_ELEM( pred, bb_ps_iter, Init(bb->Pred()) ) {
00217 pred->Remove_succ( bb, Mem_pool() );
00218 }
00219
00220 if (bb->Is_first())
00221 _first_bb = bb->Next();
00222 if (bb->Is_last())
00223 _last_bb = bb->Prev();
00224
00225
00226 for (INT i=0; i <= _exit_vec.Lastidx(); i++) {
00227 if ( _exit_vec[i] == bb ) {
00228
00229 _exit_vec[i] = NULL;
00230 }
00231 }
00232
00233
00234 _bb_vec[bb->Id()] = NULL;
00235
00236
00237 bb->Set_dom_dfs_id(0);
00238 bb->Set_pdom_dfs_id(0);
00239
00240 bb->Remove();
00241
00242
00243 if ( Feedback() ) {
00244 Feedback()->Delete_node( bb->Id() );
00245 }
00246
00247 }
00248
00249
00250
00251
00252
00253
00254 void
00255 CFG::Remove_path(BB_NODE *pred, BB_NODE *succ)
00256 {
00257 succ->Remove_phi_reference( succ->Pred()->Pos(pred) );
00258 pred->Remove_succ( succ, Mem_pool() );
00259 succ->Remove_pred( pred, Mem_pool() );
00260
00261 if ( Trace() ) {
00262 fprintf( TFile, "CFG::Remove_path: Removed bb:%d->bb:%d\n",
00263 pred->Id(), succ->Id() );
00264 }
00265
00266
00267 }
00268
00269 void
00270 CFG::Delete_bbs(BB_LIST *bbs, MOD_PHI_BB_CONTAINER *mod_phis)
00271 {
00272 BB_NODE *last_bb, *succ, *pred;
00273 BB_NODE *bb;
00274 BB_LIST_ITER bb_iter, bb_succ_iter, bb_pred_iter;
00275
00276 FOR_ALL_ELEM( bb, bb_iter, Init(bbs) )
00277 last_bb = bb;
00278
00279
00280 INT num_succs = last_bb->Succ()->Len();
00281 FmtAssert( num_succs <= 1,
00282 ("CFG::Delete_bb: trying to delete BB%d with %d succs",
00283 last_bb->Id(), num_succs) );
00284
00285 mINT32 *pos_array = NULL;
00286 if ( num_succs > 0 ) {
00287 pos_array = TYPE_OPT_POOL_ALLOC_N( mINT32, Loc_pool(), num_succs, -1 );
00288 INT isucc = 0;
00289 FOR_ALL_ELEM( succ, bb_succ_iter, Init(last_bb->Succ()) ) {
00290 Is_True( isucc < num_succs,
00291 ("CFG::Delete_bb: wrong number of successors") );
00292 pos_array[isucc] = succ->Pred()->Pos(last_bb);
00293 isucc++;
00294 }
00295 }
00296 INT32 pred_num = 0;
00297
00298 FOR_ALL_ELEM( bb, bb_iter, Init(bbs) ){
00299 FOR_ALL_ELEM( pred, bb_pred_iter, Init( bb->Pred() ) ) {
00300 if (bbs->Contains(pred))
00301 continue;
00302 pred_num ++;
00303 }
00304 }
00305
00306 if (pred_num == 0) {
00307
00308 FOR_ALL_ELEM( succ, bb_succ_iter, Init(last_bb->Succ()) ) {
00309 succ->Remove_phi_reference(succ->Pred()->Pos(last_bb));
00310 succ->Remove_pred(last_bb, _mem_pool);
00311 }
00312 }
00313
00314 PHI_LIST *preserved_philist = NULL;
00315 BB_NODE *unique_succ = NULL;
00316 if (last_bb->Succ()->Len() == 1 &&
00317 last_bb->Succ()->Node()->Pred()->Len() == 1 &&
00318 last_bb->Succ()->Node()->Phi_list()->Is_Empty() &&
00319 last_bb->Phi_list() != NULL) {
00320 unique_succ = last_bb->Succ()->Node();
00321
00322 preserved_philist = last_bb->Phi_list()->Dup_phi_node(_mem_pool, last_bb);
00323 PHI_NODE *phi;
00324 PHI_LIST_ITER phi_iter;
00325 FOR_ALL_ELEM ( phi, phi_iter, Init(preserved_philist)) {
00326 phi->Set_bb(unique_succ);
00327 }
00328 mod_phis->Add_entry(unique_succ, unique_succ->Phi_list(),
00329 preserved_philist, _mem_pool);
00330 unique_succ->Set_phi_list(preserved_philist);
00331 }
00332
00333 FOR_ALL_ELEM( bb, bb_iter, Init(bbs) ){
00334 FOR_ALL_ELEM( pred, bb_pred_iter, Init( bb->Pred() ) ) {
00335 if (bbs->Contains(pred))
00336 continue;
00337 INT succnum = 0;
00338 FOR_ALL_ELEM( succ, bb_succ_iter, Init(last_bb->Succ()) ) {
00339 if (succ->Pred()->Contains(pred)) {
00340 succ->Remove_phi_reference(succ->Pred()->Pos(last_bb));
00341 succ->Remove_pred(last_bb, _mem_pool);
00342 }
00343 else {
00344 BOOL added = FALSE;
00345 BB_LIST *tmp;
00346 for (tmp = succ->Pred(); tmp != NULL; tmp = tmp->Next()) {
00347 if (tmp->Node() == last_bb) {
00348 tmp->Set_node(pred);
00349 added = TRUE;
00350 break;
00351 }
00352 }
00353 if ( !added ) {
00354 PHI_LIST *new_philist;
00355 succ->Append_pred(pred, _mem_pool);
00356 new_philist = succ->Phi_list()->Dup_phi_node(_mem_pool, succ,
00357 pos_array[succnum]);
00358 mod_phis->Add_entry(succ, succ->Phi_list(), new_philist, _mem_pool);
00359 succ->Set_phi_list(new_philist);
00360 }
00361 }
00362 succnum++;
00363 }
00364 }
00365 }
00366
00367
00368
00369
00370
00371
00372 FOR_ALL_ELEM( succ, bb_succ_iter, Init(last_bb->Succ()) ) {
00373 FOR_ALL_ELEM( bb, bb_iter, Init(bbs) ){
00374 FOR_ALL_ELEM( pred, bb_pred_iter, Init(bb->Pred()) ) {
00375 if (bbs->Contains(pred))
00376 continue;
00377 BB_LIST *tmp;
00378 BOOL added = FALSE;
00379 if (pred->Succ()->Contains(succ)) {
00380 pred->Remove_succ(bb, _mem_pool);
00381 }
00382 else {
00383 for (tmp = pred->Succ(); tmp != NULL; tmp = tmp->Next()) {
00384 if (tmp->Node() == bb) {
00385 tmp->Set_node(succ);
00386 added = TRUE;
00387 break;
00388 }
00389 }
00390 if (!added)
00391 pred->Append_succ(succ, _mem_pool);
00392 }
00393 }
00394 }
00395 }
00396 FOR_ALL_ELEM( bb, bb_iter, Init(bbs) ){
00397 if ( Feedback() && bb->Succ()->Len() == 1 )
00398 Feedback()->Move_incoming_edges_dest( bb->Id(), bb->Succ()->Node()->Id() );
00399 Remove_bb(bb);
00400 }
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416 }
00417
00418
00419
00420
00421
00422
00423 void
00424 CFG::Delete_bb(BB_NODE *bb, MOD_PHI_BB_CONTAINER *mod_phis)
00425 {
00426 BB_NODE *succ, *pred;
00427 BB_LIST_ITER bb_succ_iter, bb_pred_iter;
00428 INT num_succs = bb->Succ()->Len();
00429
00430
00431 if (num_succs > 1) {
00432 FOR_ALL_ELEM( pred, bb_pred_iter, Init(bb->Pred()) ) {
00433 if (pred == bb) {
00434 Remove_path(pred, bb);
00435 num_succs = bb->Succ()->Len();
00436 }
00437 }
00438 if ( Feedback() )
00439 Feedback()->Delete_edge( bb->Id(), bb->Id() );
00440 }
00441
00442 FmtAssert( num_succs <= 1,
00443 ("CFG::Delete_bb: trying to delete BB%d with %d succs",
00444 bb->Id(), num_succs) );
00445
00446
00447
00448 mINT32 *pos_array = NULL;
00449 if ( num_succs > 0 ) {
00450 pos_array = TYPE_OPT_POOL_ALLOC_N( mINT32, Loc_pool(), num_succs, -1 );
00451 INT isucc = 0;
00452 FOR_ALL_ELEM( succ, bb_succ_iter, Init(bb->Succ()) ) {
00453 Is_True( isucc < num_succs,
00454 ("CFG::Delete_bb: wrong number of successors") );
00455 pos_array[isucc] = succ->Pred()->Pos(bb);
00456 isucc++;
00457 }
00458 }
00459
00460 if (bb->Pred() == NULL) {
00461
00462 FOR_ALL_ELEM( succ, bb_succ_iter, Init(bb->Succ()) ) {
00463 succ->Remove_phi_reference(succ->Pred()->Pos(bb));
00464 succ->Remove_pred(bb, _mem_pool);
00465 }
00466 }
00467
00468 PHI_LIST *preserved_philist = NULL;
00469 BB_NODE *unique_succ = NULL;
00470
00471 if (bb->Succ()->Len() == 1 &&
00472 bb->Succ()->Node()->Pred()->Len() == 1 &&
00473 bb->Succ()->Node()->Phi_list()->Is_Empty() &&
00474 bb->Phi_list() != NULL) {
00475 unique_succ = bb->Succ()->Node();
00476 preserved_philist = bb->Phi_list()->Dup_phi_node(_mem_pool, bb, 0);
00477 PHI_NODE *phi;
00478 PHI_LIST_ITER phi_iter;
00479 FOR_ALL_ELEM ( phi, phi_iter, Init(preserved_philist)) {
00480 phi->Set_bb(unique_succ);
00481 }
00482 }
00483
00484 FOR_ALL_ELEM( pred, bb_pred_iter, Init(bb->Pred()) ) {
00485 if (pred == bb)
00486 continue;
00487
00488 INT succnum = 0;
00489 FOR_ALL_ELEM( succ, bb_succ_iter, Init(bb->Succ()) ) {
00490
00491
00492 if (succ->Pred()->Contains(pred)) {
00493
00494 succ->Remove_phi_reference(succ->Pred()->Pos(bb));
00495 succ->Remove_pred(bb, _mem_pool);
00496 }
00497 else {
00498
00499 BOOL added = FALSE;
00500 BB_LIST *tmp;
00501 for (tmp = succ->Pred(); tmp != NULL; tmp = tmp->Next()) {
00502 if (tmp->Node() == bb) {
00503 tmp->Set_node(pred);
00504 added = TRUE;
00505 break;
00506 }
00507 }
00508
00509
00510 if ( !added ) {
00511 PHI_LIST *new_philist;
00512 succ->Append_pred(pred, _mem_pool);
00513 new_philist = succ->Phi_list()->Dup_phi_node(_mem_pool, succ,
00514 pos_array[succnum]);
00515 mod_phis->Add_entry(succ, succ->Phi_list(), new_philist, _mem_pool);
00516 succ->Set_phi_list(new_philist);
00517 }
00518 }
00519 succnum++;
00520 }
00521 }
00522
00523 if (unique_succ) {
00524 Is_Trace(Trace(), (TFile,"CFG::Delete_bb: preserve dead phi from "
00525 "BB%d to BB%d\n", bb->Id(), unique_succ->Id()));
00526 mod_phis->Add_entry(unique_succ, unique_succ->Phi_list(),
00527 preserved_philist, _mem_pool);
00528 unique_succ->Set_phi_list(preserved_philist);
00529 }
00530
00531 FOR_ALL_ELEM( succ, bb_succ_iter, Init(bb->Succ()) ) {
00532
00533 FOR_ALL_ELEM( pred, bb_pred_iter, Init(bb->Pred()) ) {
00534
00535
00536 BB_LIST *tmp;
00537 BOOL added = FALSE;
00538
00539 if (pred->Succ()->Contains(succ)) {
00540 pred->Remove_succ(bb, _mem_pool);
00541 }
00542 else {
00543 for (tmp = pred->Succ(); tmp != NULL; tmp = tmp->Next()) {
00544 if (tmp->Node() == bb) {
00545 tmp->Set_node(succ);
00546 added = TRUE;
00547 break;
00548 }
00549 }
00550
00551 if (!added)
00552 pred->Append_succ(succ, _mem_pool);
00553 }
00554 }
00555 }
00556
00557
00558 if ( Feedback() && bb->Succ()->Len() == 1 )
00559 Feedback()->Move_incoming_edges_dest( bb->Id(), bb->Succ()->Node()->Id() );
00560
00561 Remove_bb(bb);
00562 }
00563
00564
00565
00566
00567
00568 void
00569 CFG::Prepend_wn_in(BB_NODE *bb, WN* wn)
00570 {
00571 if (bb->Firststmt() == NULL) {
00572 Init_stmtlist(bb, wn);
00573 }
00574 else {
00575 WN_prev(bb->Firststmt()) = wn;
00576 WN_next(wn) = bb->Firststmt();
00577 bb->Set_firststmt(wn);
00578 }
00579 }
00580
00581
00582
00583
00584 void
00585 CFG::Append_wn_in(BB_NODE *bb, WN* wn)
00586 {
00587
00588
00589 Is_True(bb->Kind() != BB_REGIONSTART || (bb->Kind() == BB_REGIONSTART &&
00590 (WN_opcode(wn) == OPC_PRAGMA || WN_opcode(wn) == OPC_XPRAGMA ||
00591 WN_opcode(wn) == OPC_VCALL || WN_operator(wn) == OPR_GOTO)),
00592 ("CFG::Append_wn_in(), inserting into a %s",bb->Kind_name()));
00593
00594 if (bb->Firststmt() == NULL) {
00595 Init_stmtlist(bb, wn);
00596 } else {
00597 WN_next(bb->Laststmt()) = wn;
00598 WN_prev(wn) = bb->Laststmt();
00599 bb->Set_laststmt(wn);
00600 }
00601 }
00602
00603
00604
00605
00606
00607 void
00608 CFG::Create_label_stmt( BB_NODE *bb )
00609 {
00610 Is_True( bb->Firststmt() == NULL,
00611 ("CFG::Create_label_stmt: non-empty block to get label") );
00612
00613 LABEL_IDX label = bb->Labnam();
00614
00615 if ( label == 0 )
00616 label = Alloc_label();
00617
00618 WN *new_wn = WN_CreateLabel(0, label, 0, NULL);
00619 Init_stmtlist(bb, new_wn);
00620 Append_label_map(label, bb);
00621 }
00622
00623
00624
00625
00626
00627
00628 BB_NODE *
00629 CFG::Create_labelled_bb( BB_KIND k )
00630 {
00631 BB_NODE *retbb = Create_bb( k );
00632 Create_label_stmt( retbb );
00633 return retbb;
00634 }
00635
00636
00637
00638
00639
00640 BB_NODE *
00641 CFG::Create_conditional(WN *cond,
00642 BB_NODE *true_bb,
00643 BB_NODE *false_bb,
00644 BOOL true_branch,
00645 WN **created_branch)
00646 {
00647 Is_True(cond != NULL, ("CFG::Create_conditional: NULL cond"));
00648 Is_True(true_bb != NULL || false_bb != NULL,
00649 ("CFG::Create_conditional: no target block"));
00650
00651 if ( WN_operator(cond) == OPR_CAND ) {
00652
00653 BB_NODE *short_circuit = Create_labelled_bb();
00654 BOOL append_false_bb = FALSE;
00655
00656
00657 if ( false_bb == NULL && true_branch ) {
00658 false_bb = Create_labelled_bb();
00659 append_false_bb = TRUE;
00660 }
00661
00662
00663
00664 WN *wn_left_branch;
00665 if ( WN_operator(WN_kid0(cond)) == OPR_CAND ||
00666 WN_operator(WN_kid0(cond)) == OPR_CIOR )
00667 {
00668 Create_conditional( WN_kid0(cond), short_circuit, false_bb, FALSE,
00669 &wn_left_branch );
00670 }
00671 else {
00672 Create_conditional( WN_kid0(cond), true_bb, false_bb, FALSE,
00673 &wn_left_branch );
00674 }
00675
00676
00677 Connect_predsucc( _current_bb, short_circuit );
00678 Append_bb( short_circuit );
00679
00680
00681 WN *wn_right_branch;
00682 Create_conditional( WN_kid1(cond), true_bb, false_bb, true_branch,
00683 &wn_right_branch);
00684
00685
00686 if ( append_false_bb ) {
00687 Connect_predsucc( _current_bb, false_bb );
00688 Append_bb( false_bb );
00689 }
00690
00691
00692 if ( Cur_PU_Feedback )
00693 Cur_PU_Feedback->FB_lower_circuit( cond,
00694 wn_left_branch, wn_right_branch );
00695
00696 *created_branch = NULL;
00697 }
00698 else if ( WN_operator(cond) == OPR_CIOR ) {
00699
00700 BB_NODE *short_circuit = Create_labelled_bb();
00701 BOOL append_true_bb = FALSE;
00702
00703 if ( true_bb == NULL && !true_branch ) {
00704 true_bb = Create_labelled_bb();
00705 append_true_bb = TRUE;
00706 }
00707
00708
00709
00710 WN *wn_left_branch;
00711 if ( WN_operator(WN_kid0(cond)) == OPR_CAND ||
00712 WN_operator(WN_kid0(cond)) == OPR_CIOR )
00713 {
00714 Create_conditional( WN_kid0(cond), true_bb, short_circuit, TRUE,
00715 &wn_left_branch );
00716 }
00717 else {
00718 Create_conditional( WN_kid0(cond), true_bb, false_bb, TRUE,
00719 &wn_left_branch );
00720 }
00721
00722
00723
00724 Connect_predsucc( _current_bb, short_circuit );
00725 Append_bb( short_circuit );
00726
00727
00728 WN *wn_right_branch;
00729 Create_conditional( WN_kid1(cond), true_bb, false_bb, true_branch,
00730 &wn_right_branch);
00731
00732
00733 if ( append_true_bb ) {
00734 Connect_predsucc( _current_bb, true_bb );
00735 Append_bb( true_bb );
00736 }
00737
00738
00739 if ( Cur_PU_Feedback )
00740 Cur_PU_Feedback->FB_lower_circuit( cond,
00741 wn_left_branch, wn_right_branch );
00742
00743 *created_branch = NULL;
00744 }
00745 else {
00746
00747 WN *end_cond;
00748 if ( true_branch ) {
00749
00750 if ( true_bb->Labnam() == 0 )
00751 Create_label_stmt( true_bb );
00752
00753 end_cond = WN_CreateTruebr( true_bb->Labnam(), cond );
00754 }
00755 else {
00756
00757
00758 if ( false_bb->Labnam() == 0 )
00759 Create_label_stmt( false_bb );
00760
00761 end_cond = WN_CreateFalsebr( false_bb->Labnam(), cond );
00762 }
00763 WN_Set_Linenum( end_cond, WN_Get_Linenum(cond) );
00764 *created_branch = end_cond;
00765
00766
00767 Add_one_stmt(end_cond, NULL);
00768 }
00769
00770 return _current_bb;
00771 }
00772
00773
00774
00775
00776
00777
00778
00779 BB_NODE *
00780 CFG::Create_entrytest(WN *cond, BB_NODE *target)
00781 {
00782 FmtAssert(cond != NULL, ("CFG::Create_entrytest: NULL cond"));
00783 FmtAssert(target->Labnam() != 0,
00784 ("CFG::Create_entrytest: BB:%d has no label", target->Id()) );
00785
00786 WN *end_cond;
00787 end_cond = WN_CreateFalsebr(target->Labnam(), cond);
00788 WN_Set_Linenum( end_cond, WN_Get_Linenum(cond) );
00789
00790 BB_NODE *retbb = _current_bb;
00791 Add_one_stmt(end_cond, NULL);
00792 return retbb;
00793 }
00794
00795
00796
00797
00798
00799
00800 BB_NODE *
00801 CFG::Create_loopbody( WN *body )
00802 {
00803 BB_NODE *body_bb = Create_labelled_bb();
00804 body_bb->Set_linenum(WN_Get_Linenum(body));
00805 Append_bb(body_bb);
00806
00807 END_BLOCK body_bb_end;
00808 Add_one_stmt(body, &body_bb_end);
00809
00810
00811 if ( body_bb_end == END_FALLTHRU || body_bb_end == END_BREAK ) {
00812
00813 (void) New_bb( body_bb_end == END_FALLTHRU );
00814 }
00815
00816 return body_bb;
00817 }
00818
00819
00820
00821
00822
00823 BB_NODE *
00824 CFG::Create_exittest(WN *cond,
00825 BB_NODE *body_bb,
00826 BB_KIND k)
00827 {
00828 Is_True(cond != NULL, ("CFG::Create_exittest: NULL cond"));
00829 FmtAssert( body_bb->Labnam() != 0,
00830 ("CFG::Create_exittest: body_bb:%d has no label", body_bb->Id()) );
00831
00832 WN *end_cond = WN_CreateTruebr(body_bb->Labnam(), cond);
00833 WN_Set_Linenum( end_cond, WN_Get_Linenum(cond) );
00834
00835
00836 Add_one_stmt(end_cond, NULL);
00837
00838 _current_bb->Set_kind(k);
00839 return _current_bb;
00840 }
00841
00842
00843
00844
00845
00846 void
00847 CFG::Create_loop_info( BB_NODE *body_bb, WN *loop_wn )
00848 {
00849
00850 WN *loop_info = WN_do_loop_info( loop_wn );
00851
00852 if ( loop_info == NULL ) {
00853 WN *index_var = WN_index( loop_wn );
00854
00855
00856
00857
00858 WN *loop_trip = NULL;
00859
00860 loop_info = WN_CreateLoopInfo ( index_var, loop_trip,
00861 0, Cur_loop_depth(), 0 );
00862 }
00863
00864 body_bb->Set_label_loop_info(loop_info);
00865 }
00866
00867
00868
00869
00870
00871 void
00872 CFG::Create_blank_loop_info( BB_NODE *body_bb )
00873 {
00874 WN *index_var = NULL;
00875 WN *loop_trip = NULL;
00876 WN *loop_info = WN_CreateLoopInfo ( index_var, loop_trip, 0 ,
00877 Cur_loop_depth(), 0 );
00878
00879 body_bb->Set_label_loop_info(loop_info);
00880 }
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892 void
00893 CFG::Create_empty_preheader (WN* loop) {
00894 if (_current_bb->Firststmt() != NULL) {
00895 BB_NODE* blk = New_bb (TRUE);
00896 blk->Set_linenum (WN_Get_Linenum(loop));
00897 }
00898 }
00899
00900
00901
00902
00903
00904 void
00905 CFG::Lower_do_loop( WN *wn, END_BLOCK *ends_bb )
00906 {
00907 Is_True(Lower_fully(), ("CFG::Lower_do_loop: Lower_fully not true"));
00908 Set_cur_loop_depth( Cur_loop_depth() + 1 );
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925 WN *start_wn = WN_start(wn);
00926 FmtAssert(start_wn != NULL, ("CFG::Lower_do_loop: NULL start"));
00927
00928
00929 Add_one_stmt( start_wn, NULL );
00930
00931
00932 BB_NODE *exit_bb = Create_labelled_bb();
00933 BB_NODE *dohead_bb = Create_labelled_bb( BB_DOHEAD );
00934
00935
00936
00937 BB_NODE *entry_test_bb = _current_bb;
00938 WN *loop_info = WN_do_loop_info(wn);
00939 WN *wn_top_branch = NULL;
00940 if ( loop_info == NULL || !WN_Loop_Nz_Trip(loop_info) ) {
00941
00942 WN *endcopy = WN_copy(WN_end(wn));
00943 WN_copy_stmap(WN_end(wn), endcopy);
00944 if (Cur_PU_Feedback)
00945 Cur_PU_Feedback->FB_clone_loop_test( WN_end(wn), endcopy, wn );
00946
00947 entry_test_bb = Create_conditional( endcopy, dohead_bb, exit_bb, FALSE,
00948 &wn_top_branch );
00949 }
00950
00951
00952 Connect_predsucc( entry_test_bb, dohead_bb );
00953 Append_bb( dohead_bb );
00954
00955
00956 BB_NODE *body_bb = Create_loopbody(WN_do_body(wn));
00957 Connect_predsucc(dohead_bb, body_bb);
00958
00959
00960 Create_loop_info( body_bb, wn );
00961
00962
00963 FmtAssert(WN_step(wn), ("CFG::Lower_do_loop: NULL do step"));
00964 Add_one_stmt(WN_step(wn), NULL);
00965
00966
00967 BB_NODE *dotail_bb = Create_labelled_bb( BB_DOTAIL );
00968
00969
00970 WN *wn_back_branch;
00971 BB_NODE *cond_bb = Create_conditional( WN_end(wn), body_bb, dotail_bb, TRUE,
00972 &wn_back_branch);
00973 cond_bb->Set_kind(BB_DOEND);
00974
00975
00976 Connect_predsucc( cond_bb, dotail_bb );
00977 Append_bb( dotail_bb );
00978
00979
00980 Connect_predsucc(dotail_bb, exit_bb);
00981 Append_bb(exit_bb);
00982
00983
00984 if (Cur_PU_Feedback) {
00985 Cur_PU_Feedback->FB_lower_loop(wn, wn_top_branch, wn_back_branch);
00986 }
00987
00988 BB_LOOP *loopinfo = CXX_NEW( BB_LOOP( WN_index(wn),
00989 dohead_bb,
00990 cond_bb,
00991 body_bb,
00992 cond_bb,
00993 dotail_bb ),
00994 _mem_pool );
00995 loopinfo->Set_has_entry_guard();
00996 loopinfo->Set_flag(LOOP_DO);
00997 dohead_bb->Set_loop(loopinfo);
00998 cond_bb->Set_loop(loopinfo);
00999 body_bb->Set_loop(loopinfo);
01000
01001
01002
01003
01004 if ( ends_bb )
01005 *ends_bb = END_NOT;
01006
01007 Set_cur_loop_depth( Cur_loop_depth() - 1 );
01008 }
01009
01010
01011
01012
01013
01014 void
01015 CFG::Lower_while_do( WN *wn, END_BLOCK *ends_bb )
01016 {
01017 Is_True(Lower_fully(), ("CFG::Lower_while_do: Lower_fully not true"));
01018 Set_cur_loop_depth( Cur_loop_depth() + 1 );
01019
01020
01021
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033
01034 BB_NODE *exit_bb = Create_labelled_bb();
01035 BB_NODE *dohead_bb = Create_labelled_bb( BB_DOHEAD );
01036
01037
01038 WN *testcopy = WN_copy(WN_while_test(wn));
01039 WN_copy_stmap(WN_while_test(wn), testcopy);
01040 if (Cur_PU_Feedback)
01041 Cur_PU_Feedback->FB_clone_loop_test( WN_while_test(wn), testcopy, wn );
01042
01043 WN *wn_top_branch;
01044 BB_NODE *entry_test_bb =
01045 Create_conditional( testcopy, dohead_bb, exit_bb, FALSE , &wn_top_branch);
01046
01047
01048 Connect_predsucc( entry_test_bb, dohead_bb );
01049 Append_bb( dohead_bb );
01050
01051
01052 BB_NODE *body_bb = Create_loopbody(WN_while_body(wn));
01053 Connect_predsucc(dohead_bb, body_bb);
01054
01055
01056 Create_blank_loop_info(body_bb);
01057
01058
01059 BB_NODE *dotail_bb = Create_labelled_bb( BB_DOTAIL );
01060
01061
01062 WN *wn_back_branch;
01063 BB_NODE *cond_bb = Create_conditional( WN_while_test(wn), body_bb,
01064 dotail_bb, TRUE , &wn_back_branch);
01065 cond_bb->Set_kind(BB_WHILEEND);
01066
01067
01068 Connect_predsucc( cond_bb, dotail_bb );
01069 Append_bb( dotail_bb );
01070
01071
01072 Connect_predsucc(dotail_bb, exit_bb);
01073 Append_bb( exit_bb );
01074
01075
01076
01077 if (Cur_PU_Feedback) {
01078 Cur_PU_Feedback->FB_lower_loop(wn, wn_top_branch, wn_back_branch);
01079 }
01080
01081 BB_LOOP *loopinfo = CXX_NEW( BB_LOOP( NULL,
01082 dohead_bb,
01083 cond_bb,
01084 body_bb,
01085 cond_bb,
01086 dotail_bb ),
01087 _mem_pool );
01088
01089
01090
01091
01092
01093 loopinfo->Set_flag(LOOP_WHILE);
01094 dohead_bb->Set_loop(loopinfo);
01095 cond_bb->Set_loop(loopinfo);
01096 body_bb->Set_loop(loopinfo);
01097
01098
01099
01100 if ( ends_bb )
01101 *ends_bb = END_NOT;
01102
01103 Set_cur_loop_depth( Cur_loop_depth() - 1 );
01104 }
01105
01106
01107
01108
01109
01110 void
01111 CFG::Lower_do_while( WN *wn, END_BLOCK *ends_bb )
01112 {
01113 Is_True(Lower_fully(), ("CFG::Lower_do_while: Lower_fully not true"));
01114 Set_cur_loop_depth( Cur_loop_depth()+1 );
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127 BB_NODE *dohead_bb;
01128
01129
01130 if (_current_bb->Firststmt() == NULL) {
01131 dohead_bb = _current_bb;
01132 dohead_bb->Set_kind( BB_DOHEAD );
01133 Create_label_stmt( dohead_bb );
01134 }
01135 else {
01136 dohead_bb = Create_labelled_bb( BB_DOHEAD );
01137 Connect_predsucc( _current_bb, dohead_bb );
01138 Append_bb( dohead_bb );
01139 }
01140 dohead_bb->Set_linenum(WN_Get_Linenum(wn));
01141
01142
01143 BB_NODE *body_bb = Create_loopbody(WN_while_body(wn));
01144 Connect_predsucc(dohead_bb, body_bb);
01145
01146
01147 Create_blank_loop_info(body_bb);
01148
01149
01150 BB_NODE *dotail_bb = Create_labelled_bb( BB_DOTAIL );
01151
01152
01153 WN *wn_back_branch;
01154 BB_NODE *cond_bb = Create_conditional( WN_while_test(wn), body_bb,
01155 dotail_bb, TRUE , &wn_back_branch);
01156 cond_bb->Set_kind(BB_REPEATEND);
01157
01158
01159 Connect_predsucc( cond_bb, dotail_bb );
01160 Append_bb( dotail_bb );
01161
01162 if (Cur_PU_Feedback) {
01163 Cur_PU_Feedback->FB_lower_loop(wn, NULL, wn_back_branch);
01164 }
01165
01166 BB_LOOP *loopinfo = CXX_NEW( BB_LOOP( NULL,
01167 dohead_bb,
01168 cond_bb,
01169 body_bb,
01170 cond_bb,
01171 dotail_bb ),
01172 _mem_pool );
01173 loopinfo->Set_flag(LOOP_REPEAT);
01174 dohead_bb->Set_loop(loopinfo);
01175 cond_bb->Set_loop(loopinfo);
01176 body_bb->Set_loop(loopinfo);
01177
01178
01179
01180 if ( ends_bb )
01181 *ends_bb = END_NOT;
01182
01183 Set_cur_loop_depth( Cur_loop_depth()-1 );
01184 }
01185
01186
01187
01188
01189
01190 INT
01191 CFG::Is_simple_expr(WN *wn) {
01192 OPERATOR opr = WN_operator(wn);
01193 if (opr == OPR_LDID &&
01194 _opt_stab->Safe_to_speculate(WN_aux(wn)) &&
01195 !_opt_stab->Is_volatile(WN_aux(wn)))
01196 return 1;
01197 if (opr == OPR_INTCONST || opr == OPR_CONST)
01198 return 1;
01199
01200 if (opr == OPR_LDA)
01201 return 1;
01202 #if defined(TARG_IA32) || defined(TARG_X8664)
01203 if (! MTYPE_is_integral(WN_rtype(wn)))
01204 return 0;
01205 #elif defined(TARG_SL)
01206 if (! MTYPE_is_integral(WN_rtype(wn)))
01207 return 0;
01208 if (opr == OPR_SELECT)
01209 return 1;
01210 if (opr == OPR_MIN || opr == OPR_MAX || opr == OPR_ILOAD)
01211 return Is_simple_expr(WN_kid0(wn));
01212 if (opr == OPR_NEG || opr == OPR_MIN || opr == OPR_MAX || opr == OPR_SELECT ||
01213 opr == OPR_CVTL || opr == OPR_ILOAD || opr == OPR_ABS)
01214 return Is_simple_expr(WN_kid0(wn));
01215 #endif
01216 if (opr == OPR_NEG || opr == OPR_ABS || opr == OPR_CVTL)
01217 return Is_simple_expr(WN_kid0(wn));
01218 if (opr == OPR_CVT &&
01219 MTYPE_is_integral(WN_desc(wn)) &&
01220 MTYPE_is_integral(WN_rtype(wn))) {
01221 return Is_simple_expr(WN_kid0(wn));
01222 }
01223
01224
01225
01226 if (opr == OPR_ADD) {
01227 WN *mult = NULL;
01228 WN *non_mult = NULL;
01229 OPERATOR opr0 = WN_operator(WN_kid0(wn));
01230 OPERATOR opr1 = WN_operator(WN_kid1(wn));
01231 if (opr0 == OPR_MPY && opr1 != OPR_MPY) {
01232 mult = WN_kid0(wn);
01233 non_mult = WN_kid1(wn);
01234 } else if (opr0 != OPR_MPY && opr1 == OPR_MPY) {
01235 mult = WN_kid1(wn);
01236 non_mult = WN_kid0(wn);
01237 }
01238 if (mult != NULL) {
01239 WN *mult_opnd;
01240 INT mult_kid_ans, non_mult_kid_ans;
01241 INT val = -1;
01242 if (WN_operator(WN_kid0(mult)) == OPR_INTCONST) {
01243 val = WN_const_val(WN_kid0(mult));
01244 mult_opnd = WN_kid1(mult);
01245 } else if (WN_operator(WN_kid1(mult)) == OPR_INTCONST) {
01246 val = WN_const_val(WN_kid1(mult));
01247 mult_opnd = WN_kid0(mult);
01248 }
01249 if (val != 2 && val != 4 && val != 8)
01250 return 0;
01251 mult_kid_ans = Is_simple_expr(mult_opnd);
01252 if (mult_kid_ans == 0)
01253 return 0;
01254 non_mult_kid_ans = Is_simple_expr(non_mult);
01255 if (non_mult_kid_ans == 0)
01256 return 0;
01257 return mult_kid_ans + non_mult_kid_ans;
01258 }
01259 }
01260
01261 if (opr == OPR_ADD || opr == OPR_SUB || opr == OPR_NEG ||
01262 opr == OPR_SHL || opr == OPR_ASHR || opr == OPR_LSHR ||
01263 #ifdef TARG_NVISA
01264
01265 opr == OPR_MPY ||
01266 #endif
01267 opr == OPR_BAND || opr == OPR_BIOR || opr == OPR_BNOR || opr == OPR_BXOR)
01268 { INT kid0ans, kid1ans;
01269 kid0ans = Is_simple_expr(WN_kid0(wn));
01270 if (kid0ans == 0)
01271 return 0;
01272 kid1ans = Is_simple_expr(WN_kid1(wn));
01273 if (kid1ans == 0)
01274 return 0;
01275 return kid0ans + kid1ans;
01276 }
01277 #ifdef TARG_NVISA
01278 if (opr == OPR_CVT || opr == OPR_RECIP) {
01279 INT kidans = Is_simple_expr(WN_kid0(wn));
01280 return kidans;
01281 }
01282 if (opr == OPR_MADD || opr == OPR_NMADD) {
01283 INT kid0ans = Is_simple_expr(WN_kid0(wn));
01284 INT kid1ans = Is_simple_expr(WN_kid1(wn));
01285 INT kid2ans = Is_simple_expr(WN_kid2(wn));
01286 if (kid0ans == 0 || kid1ans == 0 || kid2ans == 0)
01287 return 0;
01288 return kid0ans + kid1ans + kid2ans;
01289 }
01290 #endif
01291 return 0;
01292 }
01293
01294
01295
01296
01297 static WN *Copy_addr_expr(WN *wn, ALIAS_CLASSIFICATION *ac)
01298 {
01299 if (wn == NULL)
01300 return NULL;
01301 WN *new_wn = WN_CopyNode(wn);
01302 if (OPERATOR_has_aux(WN_operator(wn)))
01303 WN_set_aux(new_wn, WN_aux(wn));
01304 else if (OPERATOR_is_load(WN_operator(wn)) || WN_operator(wn) == OPR_LDA) {
01305 ac->Copy_alias_class(wn, new_wn);
01306 IDTYPE ip_alias_class = WN_MAP32_Get(WN_MAP_ALIAS_CLASS, wn);
01307 if (ip_alias_class != OPTIMISTIC_AC_ID)
01308 WN_MAP32_Set(WN_MAP_ALIAS_CLASS, new_wn, ip_alias_class);
01309 }
01310 for (INT i = 0; i < WN_kid_count(wn); i++) {
01311 WN *kid = WN_kid(wn, i);
01312 if (kid)
01313 WN_kid(new_wn, i) = Copy_addr_expr(kid, ac);
01314 else WN_kid(new_wn, i) = NULL;
01315 }
01316 return new_wn;
01317 }
01318
01319
01320
01321
01322
01323 static BOOL Same_addr_expr(WN *wn1, WN *wn2)
01324 {
01325 if (WN_opcode(wn1) != WN_opcode(wn2))
01326 return FALSE;
01327 switch (WN_operator(wn1)) {
01328 case OPR_INTCONST:
01329 return WN_const_val(wn1) == WN_const_val(wn2);
01330 case OPR_LDA:
01331 if (WN_lda_offset(wn1) != WN_lda_offset(wn2))
01332 return FALSE;
01333 return WN_aux(wn1) == WN_aux(wn2);
01334 case OPR_LDBITS:
01335 if (WN_bit_offset(wn1) != WN_bit_offset(wn2))
01336 return FALSE;
01337 if (WN_bit_size(wn1) != WN_bit_size(wn2))
01338 return FALSE;
01339
01340 case OPR_LDID:
01341 return WN_aux(wn1) == WN_aux(wn2);
01342 case OPR_ILDBITS:
01343 if (WN_bit_offset(wn1) != WN_bit_offset(wn2))
01344 return FALSE;
01345 if (WN_bit_size(wn1) != WN_bit_size(wn2))
01346 return FALSE;
01347
01348 case OPR_ILOAD:
01349 if (WN_load_offset(wn1) != WN_load_offset(wn2))
01350 return FALSE;
01351 return Same_addr_expr(WN_kid0(wn1), WN_kid0(wn2));
01352 case OPR_CVTL:
01353 if (WN_cvtl_bits(wn1) != WN_cvtl_bits(wn2))
01354 return FALSE;
01355
01356 case OPR_CVT: case OPR_NEG: case OPR_ABS:
01357 return Same_addr_expr(WN_kid0(wn1), WN_kid0(wn2));
01358 case OPR_ADD: case OPR_SUB: case OPR_MPY: case OPR_DIV: case OPR_MOD:
01359 case OPR_REM: case OPR_MAX: case OPR_MIN: case OPR_EQ: case OPR_NE:
01360 case OPR_GE: case OPR_GT: case OPR_LE: case OPR_LT: case OPR_BAND:
01361 case OPR_BIOR: case OPR_BNOR: case OPR_BXOR: case OPR_SHL:
01362 case OPR_ASHR: case OPR_LSHR:
01363 return Same_addr_expr(WN_kid0(wn1), WN_kid0(wn2)) &&
01364 Same_addr_expr(WN_kid1(wn1), WN_kid1(wn2));
01365 case OPR_SELECT:
01366 return Same_addr_expr(WN_kid0(wn1), WN_kid0(wn2)) &&
01367 Same_addr_expr(WN_kid1(wn1), WN_kid1(wn2)) &&
01368 Same_addr_expr(WN_kid2(wn1), WN_kid2(wn2));
01369 case OPR_ARRAY:
01370 if (WN_num_dim(wn1) != WN_num_dim(wn2))
01371 return FALSE;
01372 if (WN_element_size(wn1) != WN_element_size(wn2))
01373 return FALSE;
01374 if (!Same_addr_expr(WN_array_base(wn1), WN_array_base(wn2)))
01375 return FALSE;
01376 for (INT i=0; i < WN_num_dim(wn1); i++) {
01377 if (!Same_addr_expr(WN_array_index(wn1, i), WN_array_index(wn2, i)))
01378 return FALSE;
01379 if (!Same_addr_expr(WN_array_dim(wn1, i), WN_array_dim(wn2, i)))
01380 return FALSE;
01381 }
01382 return TRUE;
01383 default:
01384 return FALSE;
01385 }
01386 return FALSE;
01387 }
01388
01389
01390
01391
01392 static BOOL Has_iload_with_same_addr_expr(WN *addr_expr, WN *wn)
01393 {
01394 if (WN_operator(wn) == OPR_ILOAD) {
01395 if (Same_addr_expr(WN_kid0(wn), addr_expr))
01396 return TRUE;
01397 }
01398 else if (WN_operator(wn) == OPR_ISTORE) {
01399 if (Same_addr_expr(WN_kid1(wn), addr_expr))
01400 return TRUE;
01401 }
01402 for (INT i = 0; i < WN_kid_count(wn); i++) {
01403 WN *kid = WN_kid(wn, i);
01404 if (Has_iload_with_same_addr_expr(addr_expr, kid))
01405 return TRUE;
01406 }
01407 return FALSE;
01408 }
01409
01410
01411
01412
01413 static BOOL Same_store_target(WN *wn1, WN *wn2)
01414 {
01415 OPERATOR opr1 = WN_operator(wn1);
01416 OPERATOR opr2 = WN_operator(wn2);
01417 if (opr1 != opr2)
01418 return FALSE;
01419 if (WN_desc(wn1) != WN_desc(wn2))
01420 return FALSE;
01421 if (opr1 == OPR_STID)
01422 return WN_aux(wn1) == WN_aux(wn2);
01423 if (opr1 == OPR_STBITS)
01424 return WN_aux(wn1) == WN_aux(wn2) &&
01425 WN_bit_offset(wn1) == WN_bit_offset(wn2) &&
01426 WN_bit_size(wn1) == WN_bit_size(wn2);
01427
01428 if (WN_store_offset(wn1) != WN_store_offset(wn2))
01429 return FALSE;
01430 if (WN_ty(wn1) != WN_ty(wn2))
01431 return FALSE;
01432 if (opr1 == OPR_ISTBITS &&
01433 (WN_bit_offset(wn1) != WN_bit_offset(wn2) ||
01434 WN_bit_size(wn1) != WN_bit_size(wn2)))
01435 return FALSE;
01436 return Same_addr_expr(WN_kid1(wn1), WN_kid1(wn2));
01437 }
01438
01439 BOOL CFG::Screen_cand(WN* wn, WN* else_wn, WN* then_wn, BOOL empty_else, BOOL empty_then)
01440 {
01441 WN *if_test = WN_if_test(wn);
01442 WN *stmt = WN_first(empty_then ? else_wn : then_wn);
01443
01444 if (WN_operator(stmt) == OPR_MSTORE)
01445 return TRUE;
01446
01447
01448 MTYPE dsctyp = WN_desc(stmt);
01449
01450 if (dsctyp == MTYPE_M) {
01451
01452
01453 return TRUE;
01454 }
01455
01456 if (! WOPT_Enable_If_Conv_For_Istore &&
01457 (WN_operator(stmt) == OPR_ISTORE || WN_operator(stmt) == OPR_ISTBITS))
01458 return TRUE;
01459
01460 if (WN_operator(stmt) == OPR_STID || WN_operator(stmt) == OPR_STBITS) {
01461 if (_opt_stab->Is_volatile(WN_aux(stmt)))
01462 return TRUE;
01463 #ifdef TARG_NVISA
01464
01465
01466 if (ST_in_shared_mem(_opt_stab->St(WN_aux(stmt)))) {
01467 DevWarn("skip if-conversion of shared store");
01468 return TRUE;
01469 }
01470 #endif
01471 }
01472 else {
01473 if (TY_is_volatile(WN_ty(stmt)))
01474 return TRUE;
01475 }
01476
01477 if ((WN_operator(stmt) == OPR_STBITS || WN_operator(stmt) == OPR_ISTBITS) &&
01478 (empty_then || empty_else))
01479 return TRUE;
01480
01481 if (!OPCODE_Can_Be_Speculative(OPC_I4I4ILOAD)) {
01482 if (WN_operator(stmt) == OPR_STID || WN_operator(stmt) == OPR_STBITS) {
01483 if (!empty_then) {
01484 ST *st = _opt_stab->St(WN_aux(WN_first(then_wn)));
01485 if (ST_sclass(st) == SCLASS_FORMAL_REF)
01486 return TRUE;
01487 }
01488 if (!empty_else) {
01489 ST *st = _opt_stab->St(WN_aux(WN_first(else_wn)));
01490 if (ST_sclass(st) == SCLASS_FORMAL_REF)
01491 return TRUE;
01492 }
01493 }
01494 else if (empty_then || empty_else) {
01495 WN *addr_expr = WN_kid1(stmt);
01496
01497
01498
01499 if (OPERATOR_is_compare(WN_operator(if_test)) &&
01500 (Same_addr_expr(WN_kid0(if_test), addr_expr) ||
01501 Same_addr_expr(WN_kid1(if_test), addr_expr)))
01502 return TRUE;
01503
01504
01505
01506
01507 if (! Has_iload_with_same_addr_expr(addr_expr, if_test)) {
01508
01509 if (_current_bb->Laststmt() == NULL)
01510 return TRUE;
01511 if (! Has_iload_with_same_addr_expr(addr_expr, _current_bb->Laststmt()))
01512 {
01513 if (WN_prev(_current_bb->Laststmt()) == NULL)
01514 return TRUE;
01515 if (!Has_iload_with_same_addr_expr(addr_expr, WN_prev(_current_bb->Laststmt())))
01516 return TRUE;
01517 }
01518 }
01519 }
01520 }
01521 #if defined(TARG_X8664) || defined(TARG_SL)
01522 if (MTYPE_is_float(dsctyp))
01523 return TRUE;
01524 #endif
01525 return FALSE;
01526 }
01527
01528
01529 BOOL CFG::If_convertible_cond(WN *wn)
01530 {
01531
01532 FmtAssert((OPCODE_operator(WN_opcode(wn)) == OPR_IF), ("Not an if stmt"));
01533 WN *then_wn = WN_then(wn);
01534 BOOL empty_then = FALSE;
01535 WN *if_test = WN_if_test(wn);
01536
01537 if ( then_wn == NULL )
01538 empty_then = TRUE;
01539 else if ( WN_opcode(then_wn) == OPC_BLOCK &&
01540 WN_first(then_wn) == NULL )
01541 empty_then = TRUE;
01542
01543 WN *else_wn = WN_else(wn);
01544 BOOL empty_else = FALSE;
01545
01546 if ( else_wn == NULL )
01547 empty_else = TRUE;
01548 else if ( WN_opcode(else_wn) == OPC_BLOCK &&
01549 WN_first(else_wn) == NULL )
01550 empty_else = TRUE;
01551
01552 if (If_conv_criteria_met(wn, else_wn, then_wn, empty_else, empty_then)) {
01553 if (Screen_cand(wn, else_wn, then_wn, empty_else, empty_then)) {
01554 return FALSE;
01555 }
01556 return TRUE;
01557 }
01558 return FALSE;
01559 }
01560
01561
01562 BOOL CFG::If_conv_criteria_met(WN* wn, WN* else_wn, WN* then_wn, BOOL empty_else, BOOL empty_then)
01563 {
01564
01565
01566
01567
01568
01569
01570
01571
01572
01573
01574
01575
01576
01577 #ifdef TARG_MIPS
01578 if (!(WOPT_Enable_Simple_If_Conv &&
01579
01580 ! Instrumentation_Enabled
01581
01582 && Is_Target_ISA_M4Plus()))
01583 #else
01584 if (!(WOPT_Enable_Simple_If_Conv &&
01585
01586 ! Instrumentation_Enabled
01587 ))
01588 #endif
01589 return FALSE;
01590
01591 #if defined(TARG_X8664) // do not if-convert if it has either empty then or else part and it
01592 if (
01593
01594 ((empty_else || empty_then) &&
01595 #if defined(TARG_IA64)
01596
01597 WOPT_Enable_If_Conv_Limit <= 6 &&
01598 #else
01599 (WOPT_Enable_Simple_If_Conv <= 1) &&
01600 #endif
01601 (WN_next(wn) == NULL &&
01602 !(_current_bb->Firststmt() != NULL &&
01603 (_current_bb->Firststmt() != _current_bb->Laststmt() ||
01604 (WN_operator(_current_bb->Firststmt()) != OPR_LABEL))))
01605 )
01606 )
01607 return FALSE;
01608 #endif
01609
01610
01611 if (
01612
01613 (empty_else && empty_then)
01614 )
01615 return FALSE;
01616
01617 if (!empty_else) {
01618
01619 if (!(((WN_first(else_wn) == WN_last(else_wn)) &&
01620 OPERATOR_is_store(WN_operator(WN_first(else_wn)))) ||
01621 (WN_operator(else_wn) == OPR_SELECT)))
01622 return FALSE;
01623 }
01624
01625 if (
01626
01627 (!empty_then &&
01628 !(((WN_first(then_wn) == WN_last(then_wn)) &&
01629 OPERATOR_is_store(WN_operator(WN_first(then_wn)))) || (WN_operator(then_wn) == OPR_SELECT)))
01630 )
01631 return FALSE;
01632
01633 if (
01634
01635 !(empty_else ||
01636 empty_then ||
01637 Same_store_target(WN_first(else_wn),
01638 WN_first(then_wn)))
01639 )
01640 return FALSE;
01641 return TRUE;
01642 }
01643
01644
01645 WN*
01646 CFG::Conv_to_select(WN* wn)
01647 {
01648 if (WN_opcode(wn) == OPC_BLOCK) {
01649 wn = WN_first(wn);
01650 }
01651
01652 WN *then_wn = WN_then(wn);
01653 BOOL empty_then = FALSE;
01654 if ( then_wn == NULL )
01655 empty_then = TRUE;
01656 else if ( WN_opcode(then_wn) == OPC_BLOCK &&
01657 WN_first(then_wn) == NULL ) {
01658 empty_then = TRUE;
01659 if (WN_opcode(then_wn) == OPC_BLOCK) {
01660 then_wn = WN_first(then_wn);
01661 }
01662 }
01663
01664 WN *else_wn = WN_else(wn);
01665 BOOL empty_else = FALSE;
01666
01667 if ( else_wn == NULL )
01668 empty_else = TRUE;
01669 else if ( WN_opcode(else_wn) == OPC_BLOCK &&
01670 WN_first(else_wn) == NULL ) {
01671 empty_else = TRUE;
01672 if (WN_opcode(else_wn) == OPC_BLOCK) {
01673 else_wn = WN_first(else_wn);
01674 }
01675 }
01676
01677 if (!If_conv_criteria_met(wn, else_wn, then_wn, empty_else, empty_then))
01678 return NULL;
01679
01680 if (Screen_cand(wn, else_wn, then_wn, empty_else, empty_then))
01681 return NULL;
01682
01683
01684
01685
01686 WN *if_test = WN_if_test(wn);
01687 if ( empty_then && empty_else ) {
01688 WN *eval_stmt = WN_CreateEval( if_test );
01689 return eval_stmt;
01690 }
01691
01692
01693 WN *stmt = WN_first(empty_then ? else_wn : then_wn);
01694
01695 WN *load = NULL;
01696 WN *store = WN_CopyNode(stmt);
01697 WN_set_map_id(store, WN_map_id(stmt));
01698 MTYPE dsctyp = WN_desc(stmt);
01699
01700 if (WN_operator(stmt) == OPR_STID || WN_operator(stmt) == OPR_STBITS)
01701 WN_set_aux(store, WN_aux(stmt));
01702
01703
01704 if (empty_then || empty_else) {
01705 if (WN_operator(stmt) == OPR_STID) {
01706 load = WN_Ldid(dsctyp,
01707 WN_offset(stmt),
01708 (ST_IDX) WN_aux(stmt),
01709 WN_ty(stmt),
01710 WN_field_id(stmt));
01711 WN_set_aux(load, WN_aux(stmt));
01712 }
01713 else {
01714 MTYPE rtype = WN_rtype(WN_kid0(stmt));
01715 if (MTYPE_byte_size(rtype) < MTYPE_byte_size(dsctyp))
01716 rtype = dsctyp;
01717 else rtype = Mtype_TransferSign(dsctyp, rtype);
01718 load = WN_CreateIload(OPR_ILOAD,
01719 rtype,
01720 dsctyp,
01721 WN_offset(stmt), TY_pointed(WN_ty(stmt)),
01722 WN_ty(stmt),
01723 Copy_addr_expr(WN_kid1(stmt), _opt_stab->Alias_classification()),
01724 WN_field_id(stmt));
01725
01726 _opt_stab->Alias_classification()->Copy_alias_class(stmt, load);
01727 IDTYPE ip_alias_class = WN_MAP32_Get(WN_MAP_ALIAS_CLASS, stmt);
01728 if (ip_alias_class != OPTIMISTIC_AC_ID)
01729 WN_MAP32_Set(WN_MAP_ALIAS_CLASS, load, ip_alias_class);
01730 }
01731 }
01732 WN *then_expr = empty_then ? load : WN_kid0(WN_first(then_wn));
01733 WN *else_expr = empty_else ? load : WN_kid0(WN_first(else_wn));
01734 INT lanswer, ranswer;
01735
01736
01737 if (
01738 #if !defined(TARG_IA32) && !defined(TARG_X8664)
01739
01740
01741 Is_simple_expr(then_expr) &&
01742
01743
01744
01745 Is_simple_expr(else_expr)
01746 #else
01747 (lanswer = (empty_then ? 1 : Is_simple_expr(then_expr))) &&
01748
01749 (ranswer = (empty_else ? 1 : Is_simple_expr(else_expr))) &&
01750
01751 (lanswer + ranswer) <= WOPT_Enable_If_Conv_Limit
01752 #endif
01753 ) {
01754
01755 WN *sel = WN_Select( Mtype_comparison(dsctyp),
01756 WN_if_test(wn), then_expr, else_expr );
01757 WN_kid0(store) = sel;
01758 WN_Set_Linenum( store, WN_Get_Linenum(wn) );
01759 return store;
01760 }
01761 return NULL;
01762 }
01763
01764
01765
01766
01767 void
01768 CFG::Lower_if_stmt( WN *wn, END_BLOCK *ends_bb )
01769 {
01770 Is_True(Lower_fully(), ("CFG::Lower_if_stmt: Lower_fully not true"));
01771
01772
01773
01774
01775
01776
01777
01778
01779
01780
01781
01782
01783
01784
01785
01786
01787
01788
01789
01790
01791
01792
01793
01794
01795
01796
01797
01798
01799 WN *then_wn = WN_then(wn);
01800 BOOL empty_then = FALSE;
01801
01802 if ( then_wn == NULL )
01803 empty_then = TRUE;
01804 else {
01805 if ( WN_opcode(then_wn) == OPC_BLOCK &&
01806 WN_first(then_wn) == NULL )
01807 empty_then = TRUE;
01808 }
01809
01810 WN *else_wn = WN_else(wn);
01811 BOOL empty_else = FALSE;
01812
01813 if ( else_wn == NULL )
01814 empty_else = TRUE;
01815 else {
01816 if ( WN_opcode(else_wn) == OPC_BLOCK &&
01817 WN_first(else_wn) == NULL )
01818 empty_else = TRUE;
01819 }
01820
01821
01822
01823
01824 WN *if_test = WN_if_test(wn);
01825 if ( empty_then && empty_else ) {
01826 WN *eval_stmt = WN_CreateEval( if_test );
01827 WN_Set_Linenum( eval_stmt, WN_Get_Linenum(wn) );
01828 Add_one_stmt( eval_stmt, NULL );
01829
01830
01831 if ( Cur_PU_Feedback )
01832 Cur_PU_Feedback->FB_lower_branch( wn, NULL );
01833
01834
01835 if ( ends_bb )
01836 *ends_bb = END_NOT;
01837 return;
01838 }
01839
01840
01841
01842
01843
01844
01845
01846
01847
01848
01849
01850
01851
01852 #if defined(TARG_SL)
01853
01854 if (else_wn && ((WN_first(else_wn) == WN_last(else_wn)) && WN_first(else_wn) && (WN_operator(WN_first(else_wn)) == OPR_IF))) {
01855 WN *sel_stmt = Conv_to_select(else_wn);
01856 if (sel_stmt) {
01857 WN* block = WN_CreateBlock();
01858 WN_first(block) = sel_stmt;
01859 WN_last(block) = sel_stmt;
01860 else_wn = block;
01861 WN_else(wn) = block;
01862 }
01863 }
01864 if (then_wn && ((WN_first(then_wn) == WN_last(then_wn)) && WN_first(then_wn) && (WN_operator(WN_first(then_wn)) == OPR_IF))) {
01865 WN *sel_stmt = Conv_to_select(then_wn);
01866 if (sel_stmt) {
01867 WN* block = WN_CreateBlock();
01868 WN_first(block) = sel_stmt;
01869 WN_last(block) = sel_stmt;
01870 then_wn = block;
01871 WN_then(wn) = block;
01872 }
01873 }
01874 #endif
01875
01876 if (If_conv_criteria_met(wn, else_wn, then_wn, empty_else, empty_then)) {
01877
01878 if (Screen_cand(wn, else_wn, then_wn, empty_else, empty_then))
01879 goto skip_if_conversion;
01880
01881
01882 WN *stmt = WN_first(empty_then ? else_wn : then_wn);
01883
01884 WN *load = NULL;
01885 WN *store = WN_CopyNode(stmt);
01886 WN_set_map_id(store, WN_map_id(stmt));
01887 MTYPE dsctyp = WN_desc(stmt);
01888
01889 if (WN_operator(stmt) == OPR_STID || WN_operator(stmt) == OPR_STBITS)
01890 WN_set_aux(store, WN_aux(stmt));
01891
01892
01893 if (empty_then || empty_else) {
01894 if (WN_operator(stmt) == OPR_STID) {
01895 load = WN_Ldid(dsctyp,
01896 WN_offset(stmt),
01897 (ST_IDX) WN_aux(stmt),
01898 WN_ty(stmt),
01899 WN_field_id(stmt));
01900 WN_set_aux(load, WN_aux(stmt));
01901 }
01902 else {
01903 MTYPE rtype = WN_rtype(WN_kid0(stmt));
01904 if (MTYPE_byte_size(rtype) < MTYPE_byte_size(dsctyp))
01905 rtype = dsctyp;
01906 else rtype = Mtype_TransferSign(dsctyp, rtype);
01907 #ifdef TARG_SL
01908 if (rtype == MTYPE_I2 && dsctyp == MTYPE_I2) {
01909 rtype = MTYPE_I4;
01910 }
01911 #endif
01912 load = WN_CreateIload(OPR_ILOAD,
01913 rtype,
01914 dsctyp,
01915 WN_offset(stmt), TY_pointed(WN_ty(stmt)),
01916 WN_ty(stmt),
01917 Copy_addr_expr(WN_kid1(stmt), _opt_stab->Alias_classification()),
01918 WN_field_id(stmt));
01919
01920 _opt_stab->Alias_classification()->Copy_alias_class(stmt, load);
01921 IDTYPE ip_alias_class = WN_MAP32_Get(WN_MAP_ALIAS_CLASS, stmt);
01922 if (ip_alias_class != OPTIMISTIC_AC_ID)
01923 WN_MAP32_Set(WN_MAP_ALIAS_CLASS, load, ip_alias_class);
01924 }
01925 }
01926 WN *then_expr = empty_then ? load : WN_kid0(WN_first(then_wn));
01927 WN *else_expr = empty_else ? load : WN_kid0(WN_first(else_wn));
01928 INT lanswer, ranswer;
01929
01930
01931 if (
01932 #if !defined(TARG_IA32) && !defined(TARG_X8664)
01933
01934
01935 Is_simple_expr(then_expr) &&
01936
01937
01938
01939 Is_simple_expr(else_expr)
01940 #else
01941 (lanswer = (empty_then ? 1 : Is_simple_expr(then_expr))) &&
01942
01943 (ranswer = (empty_else ? 1 : Is_simple_expr(else_expr))) &&
01944
01945 (lanswer + ranswer) <= WOPT_Enable_If_Conv_Limit
01946 #endif
01947 ) {
01948
01949 #ifdef TARG_SL
01950 WN *cond_kid0 = WN_kid0(if_test);
01951 WN *cond_kid1 = WN_kid1(if_test);
01952 OPERATOR opr = WN_operator(if_test);
01953
01954 WN *then_kid0 = WN_kid0(then_expr);
01955 WN *else_kid0 = WN_kid0(else_expr);
01956
01957 if ((opr == OPR_EQ || opr == OPR_NE || opr == OPR_GE || opr == OPR_GT || opr == OPR_LE || opr == OPR_LT)
01958 && ((WN_operator(cond_kid1) == OPR_INTCONST) && (WN_const_val(cond_kid1) == 0))
01959 && ((WN_operator(then_expr) == OPR_ILOAD) && (WN_Simp_Compare_Trees(cond_kid0, then_kid0) == 0)
01960 || ((WN_operator(else_expr) == OPR_ILOAD) && (WN_Simp_Compare_Trees(cond_kid0, else_kid0)==0))))
01961 goto skip_if_conversion;
01962 #endif
01963
01964 WN *sel = WN_Select( Mtype_comparison(dsctyp),
01965 WN_if_test(wn), then_expr, else_expr );
01966 WN_kid0(store) = sel;
01967 WN_Set_Linenum( store, WN_Get_Linenum(wn) );
01968 Add_one_stmt( store, NULL );
01969
01970
01971 if ( Cur_PU_Feedback )
01972 Cur_PU_Feedback->FB_lower_branch( wn, NULL );
01973
01974
01975 if ( ends_bb )
01976 *ends_bb = END_NOT;
01977 return;
01978 }
01979 }
01980
01981
01982 skip_if_conversion:
01983
01984
01985 BB_NODE *merge_bb = Create_labelled_bb();
01986 BB_NODE *then_bb = NULL, *else_bb = NULL;
01987 BB_NODE *true_bb = NULL, *false_bb = NULL;
01988 BOOL true_branch;
01989 BOOL then_exists = !empty_then;
01990 BOOL else_exists = !empty_else;
01991
01992 if (WOPT_Enable_Edge_Placement) {
01993 then_exists = else_exists = TRUE;
01994 }
01995
01996
01997
01998
01999 if ( !then_exists ) {
02000 Is_True( ! empty_else,
02001 ("CFG::Lower_if_stmt: empty then and else") );
02002 else_bb = Create_bb();
02003
02004 true_bb = merge_bb;
02005 false_bb = else_bb;
02006 true_branch = TRUE;
02007 }
02008 else {
02009
02010 then_bb = Create_bb();
02011 then_bb->Set_linenum( WN_Get_Linenum(then_wn) );
02012
02013 if ( !else_exists ) {
02014 true_bb = then_bb;
02015 false_bb = merge_bb;
02016 true_branch = FALSE;
02017 }
02018 else {
02019 else_bb = Create_labelled_bb();
02020 else_bb->Set_linenum( WN_Get_Linenum(else_wn) );
02021 true_bb = then_bb;
02022 false_bb = else_bb;
02023 true_branch = FALSE;
02024 }
02025 }
02026
02027 WN *wn_branch;
02028 BB_NODE *cond_bb =
02029 Create_conditional( if_test, true_bb, false_bb, true_branch, &wn_branch );
02030
02031
02032 if ( then_exists ) {
02033 Append_bb( then_bb );
02034 Connect_predsucc(cond_bb, then_bb);
02035 END_BLOCK then_end;
02036 Add_one_stmt( then_wn, &then_end );
02037
02038 if ( then_end != END_BREAK ) {
02039
02040
02041 if ( else_exists ) {
02042
02043 if ( then_end == END_FALLTHRU )
02044 (void) New_bb( TRUE );
02045
02046 WN *goto_wn = WN_CreateGoto(merge_bb->Labnam());
02047
02048 Add_one_stmt( goto_wn, NULL );
02049 if(WN_prev(goto_wn) != NULL && (WN_prev(goto_wn)) != NULL) {
02050 WN* prev_wn=WN_prev(goto_wn);
02051 if ( Cur_PU_Feedback ) {
02052 FB_FREQ outgoing_fb=Cur_PU_Feedback->Query_total_out(prev_wn);
02053 Cur_PU_Feedback->Annot(goto_wn, FB_EDGE_OUTGOING, outgoing_fb);
02054 }
02055
02056 }
02057 }
02058 else {
02059 Connect_predsucc( _current_bb, merge_bb );
02060 }
02061 }
02062 }
02063
02064
02065 if ( else_exists ) {
02066 Append_bb( else_bb );
02067 if ( !then_exists )
02068 Connect_predsucc( cond_bb, else_bb );
02069 END_BLOCK else_end;
02070 Add_one_stmt( else_wn, &else_end );
02071
02072 if ( else_end != END_BREAK ) {
02073 Connect_predsucc( _current_bb, merge_bb );
02074 }
02075 }
02076
02077
02078 Append_bb( merge_bb );
02079
02080
02081 if ( Cur_PU_Feedback )
02082 Cur_PU_Feedback->FB_lower_branch( wn, wn_branch );
02083
02084
02085
02086 if ( ends_bb )
02087 *ends_bb = END_NOT;
02088 }
02089
02090
02091
02092
02093
02094 void
02095 CFG::Add_one_do_loop_stmt( WN *wn, END_BLOCK *ends_bb )
02096 {
02097 BOOL process_mp_do = Inside_mp_do();
02098
02099 Set_cur_loop_depth( Cur_loop_depth() + 1 );
02100
02101
02102
02103
02104
02105
02106 BB_NODE *start_bb;
02107 if (_current_bb->Firststmt() != NULL) {
02108 start_bb = New_bb( TRUE, BB_DOSTART );
02109 }
02110 else {
02111 start_bb = _current_bb;
02112 start_bb->Set_kind( BB_DOSTART );
02113 }
02114 start_bb->Set_linenum(WN_Get_Linenum(wn));
02115
02116
02117 WN *start_wn = WN_start(wn);
02118 Is_True(start_wn != NULL, ("CFG::Add_one_do_loop_stmt: NULL start"));
02119 Add_one_stmt( start_wn, NULL );
02120
02121
02122 BB_NODE *merge_bb = Create_bb();
02123
02124 Append_label_map(Alloc_label(), merge_bb);
02125
02126
02127 Is_True(WN_end(wn) != NULL, ("CFG::Add_one_do_loop_stmt: NULL end"));
02128 WN *end_cond = WN_CreateFalsebr(merge_bb->Labnam(), WN_end(wn));
02129 WN_Set_Linenum( end_cond, WN_Get_Linenum(WN_end(wn)) );
02130
02131 BB_NODE *cond_bb = New_bb( TRUE );
02132 Add_one_stmt(end_cond, NULL);
02133 cond_bb->Set_kind(BB_DOEND);
02134 if ( cond_bb->Labnam() == 0 )
02135 Append_label_map(Alloc_label(), cond_bb);
02136
02137
02138 Is_True(WN_do_body(wn) != NULL,
02139 ("CFG::Add_one_do_loop_stmt: NULL do_body pointer"));
02140 BB_NODE *body_bb = New_bb( TRUE );
02141 body_bb->Set_linenum(WN_Get_Linenum(WN_do_body(wn)));
02142 END_BLOCK body_end;
02143 Add_one_stmt(WN_do_body(wn), &body_end);
02144
02145
02146 FmtAssert(WN_step(wn) != NULL,
02147 ("CFG::Add_one_do_loop_stmt: NULL step pointer"));
02148
02149 BB_NODE *step_bb = New_bb( body_end!=END_BREAK, BB_DOSTEP );
02150 Add_one_stmt( WN_step(wn), NULL );
02151 FmtAssert( _current_bb == step_bb,
02152 ("CFG::Add_one_do_loop_stmt: step block not current block") );
02153
02154
02155 WN *gotocond = WN_CreateGoto(cond_bb->Labnam());
02156 Add_one_stmt( gotocond, NULL );
02157
02158
02159 Append_bb( merge_bb );
02160
02161 if (Cur_PU_Feedback)
02162 Cur_PU_Feedback->FB_lower_loop_alt( wn, end_cond );
02163
02164 BB_LOOP *loopinfo = CXX_NEW(BB_LOOP(WN_index(wn),
02165 start_bb,
02166 cond_bb,
02167 body_bb,
02168 step_bb,
02169 merge_bb), _mem_pool);
02170 LOOP_FLAGS flags = LOOP_PRE_DO;
02171 #ifdef Is_True_On
02172
02173 if (Wn_flags(wn) & WN_FLAG_DO_LOOP)
02174 flags = (LOOP_FLAGS) (flags | LOOP_ORIGINAL_DO);
02175 #endif
02176 if (Wn_flags(wn) & WN_FLAG_PROMOTED_DO_LOOP)
02177 loopinfo->Set_promoted_do();
02178 loopinfo->Set_flag(flags);
02179 loopinfo->Set_orig_wn(wn);
02180 start_bb->Set_loop(loopinfo);
02181 cond_bb->Set_loop(loopinfo);
02182 step_bb->Set_loop(loopinfo);
02183
02184
02185
02186 if ( ends_bb )
02187 *ends_bb = END_NOT;
02188
02189 Set_cur_loop_depth( Cur_loop_depth() - 1 );
02190 if (process_mp_do) {
02191
02192 if (Top_mp_type() == MP_DOACROSS) flags = (LOOP_FLAGS)(flags|MP_DOACROSS);
02193 else if (Top_mp_type() == MP_PDO) flags = (LOOP_FLAGS)(flags|MP_PDO);
02194 loopinfo->Set_flag(flags);
02195 merge_bb->Reset_MP_region();
02196 }
02197 }
02198
02199
02200
02201
02202
02203 void
02204 CFG::Add_one_while_do_stmt( WN *wn, END_BLOCK *ends_bb )
02205 {
02206 Set_cur_loop_depth( Cur_loop_depth() + 1 );
02207
02208
02209 BB_NODE *cond_bb = NULL;
02210
02211 cond_bb = New_bb( TRUE );
02212 cond_bb->Set_linenum(WN_Get_Linenum(wn));
02213
02214 if ( cond_bb->Labnam() == 0 )
02215 Append_label_map( Alloc_label(), cond_bb );
02216
02217
02218 BB_NODE *merge_bb = Create_bb();
02219 Append_label_map( Alloc_label(), merge_bb );
02220
02221 WN *end_cond = WN_CreateFalsebr( merge_bb->Labnam(), WN_while_test(wn) );
02222 WN_Set_Linenum( end_cond, WN_Get_Linenum(wn) );
02223 Add_one_stmt( end_cond, NULL );
02224 cond_bb->Set_kind( BB_WHILEEND );
02225
02226
02227 BB_NODE *body_bb = New_bb( TRUE );
02228 END_BLOCK body_end;
02229 Add_one_stmt( WN_while_body(wn), &body_end );
02230
02231
02232 BB_NODE *loop_back = New_bb( body_end != END_BREAK );
02233
02234 WN *gotocond = WN_CreateGoto(cond_bb->Labnam());
02235 Add_one_stmt( gotocond, NULL );
02236
02237
02238 Append_bb( merge_bb );
02239
02240 if (Cur_PU_Feedback)
02241 Cur_PU_Feedback->FB_lower_loop_alt( wn, end_cond );
02242
02243 BB_LOOP *loopinfo = CXX_NEW(BB_LOOP(NULL,
02244 NULL,
02245 cond_bb,
02246 body_bb,
02247 loop_back,
02248 merge_bb),
02249 _mem_pool);
02250 loopinfo->Set_flag(LOOP_PRE_WHILE);
02251 loopinfo->Set_orig_wn(wn);
02252 cond_bb->Set_loop(loopinfo);
02253
02254
02255
02256 if ( ends_bb )
02257 *ends_bb = END_NOT;
02258
02259 Set_cur_loop_depth( Cur_loop_depth() - 1 );
02260 }
02261
02262
02263
02264
02265
02266 void
02267 CFG::Add_one_do_while_stmt( WN *wn, END_BLOCK *ends_bb )
02268 {
02269 Set_cur_loop_depth( Cur_loop_depth()+1 );
02270
02271 BB_NODE *body_bb = NULL;
02272 body_bb = New_bb( TRUE, BB_REPEATBODY );
02273 body_bb->Set_linenum(WN_Get_Linenum(wn));
02274 if ( body_bb->Labnam() == 0 )
02275 Append_label_map(Alloc_label(), body_bb);
02276
02277
02278 BB_NODE *first_block = New_bb( TRUE );
02279 END_BLOCK body_end;
02280 Add_one_stmt( WN_while_body(wn), &body_end );
02281
02282
02283
02284
02285 BB_NODE *cond_bb = New_bb( body_end != END_BREAK );
02286 cond_bb->Set_linenum(WN_Get_Linenum(WN_while_test(wn)));
02287 WN *end_cond = WN_CreateTruebr( body_bb->Labnam(), WN_while_test(wn));
02288 WN_Set_Linenum( end_cond, WN_Get_Linenum(WN_while_test(wn)) );
02289 Add_one_stmt( end_cond, NULL );
02290 cond_bb->Set_kind(BB_REPEATEND);
02291
02292
02293 BB_NODE *merge_bb = New_bb( TRUE );
02294
02295 if (Cur_PU_Feedback)
02296 Cur_PU_Feedback->FB_lower_loop( wn, NULL, end_cond );
02297
02298 BB_LOOP *loopinfo = CXX_NEW(BB_LOOP(NULL,
02299 NULL,
02300 cond_bb,
02301 body_bb,
02302 NULL,
02303 merge_bb),
02304 _mem_pool);
02305 loopinfo->Set_flag(LOOP_PRE_REPEAT);
02306 loopinfo->Set_orig_wn(wn);
02307 body_bb->Set_loop(loopinfo);
02308 cond_bb->Set_loop(loopinfo);
02309
02310
02311
02312 if ( ends_bb )
02313 *ends_bb = END_NOT;
02314
02315 Set_cur_loop_depth( Cur_loop_depth() - 1 );
02316 }
02317
02318
02319
02320
02321
02322 void
02323 CFG::Add_one_if_stmt( WN *wn, END_BLOCK *ends_bb )
02324 {
02325
02326 BB_NODE *else_bb = Create_bb();
02327 Append_label_map(Alloc_label(), else_bb);
02328
02329
02330 WN *end_cond = WN_CreateFalsebr(else_bb->Labnam(), WN_if_test(wn));
02331 WN_Set_Linenum( end_cond, WN_Get_Linenum(wn));
02332 BB_NODE *cond_bb = _current_bb;
02333 Add_one_stmt( end_cond, NULL );
02334
02335
02336 BB_NODE *merge_bb = Create_bb();
02337 merge_bb->Set_ifmerge();
02338
02339
02340 BB_NODE *then_bb = New_bb( TRUE );
02341 END_BLOCK block_end;
02342 Add_one_stmt( WN_then(wn), &block_end );
02343 if ( block_end != END_BREAK ) {
02344 if ( block_end == END_FALLTHRU ) {
02345
02346
02347 BB_NODE *then_fallthru = New_bb( TRUE, BB_GOTO );
02348 }
02349
02350 Connect_predsucc(_current_bb, merge_bb);
02351 }
02352
02353
02354 Append_bb( else_bb );
02355 Add_one_stmt( WN_else(wn), &block_end );
02356 if ( block_end != END_BREAK )
02357 Connect_predsucc(_current_bb, merge_bb);
02358
02359
02360 Append_bb(merge_bb);
02361
02362 if ( Cur_PU_Feedback )
02363 Cur_PU_Feedback->FB_lower_branch( wn, end_cond );
02364
02365 BB_IFINFO *ifinfo = CXX_NEW(BB_IFINFO(WN_Get_Linenum(WN_then(wn)),
02366 WN_Get_Linenum(WN_else(wn)),
02367 cond_bb,
02368 then_bb,
02369 else_bb,
02370 merge_bb),
02371 _mem_pool);
02372
02373 cond_bb->Set_ifinfo(ifinfo);
02374
02375
02376
02377 if ( ends_bb )
02378 *ends_bb = END_NOT;
02379 }
02380
02381
02382
02383
02384
02385 void
02386 CFG::Add_one_compgoto_stmt( WN *wn, END_BLOCK *ends_bb )
02387 {
02388 INT32 new_num_entries = WN_num_entries(wn);
02389 _current_bb->Set_kind(BB_VARGOTO);
02390 _current_bb->Set_hasujp();
02391 Append_wn_in(_current_bb, wn);
02392 _current_bb->Set_switchinfo(CXX_NEW(BB_SWITCH(new_num_entries, _mem_pool),
02393 _mem_pool ) );
02394
02395
02396 if ( WN_kid_count(wn) > 2 ) {
02397
02398 WN *def_goto = WN_kid(wn,2);
02399 Is_True( WN_opcode(def_goto) == OPC_GOTO,
02400 ("Invalid default goto in OPC_COMPGOTO") );
02401
02402 BB_NODE *def_blk = Get_bb_from_label( WN_label_number(def_goto) );
02403 if (def_blk == NULL) {
02404 def_blk = Create_bb();
02405 Append_label_map(WN_label_number(def_goto), def_blk);
02406 }
02407
02408 _current_bb->Set_switchdefault(def_blk);
02409 Connect_predsucc(_current_bb, def_blk);
02410 }
02411
02412
02413 WN *jumptable = WN_kid1(wn);
02414 Is_True( WN_opcode(jumptable) == OPC_BLOCK, ("Invalid kid1 in OPC_GOTO"));
02415
02416 WN *case_wn = WN_first(jumptable);
02417 INT32 case_cnt = 0;
02418 for ( ; case_wn != NULL; case_wn = WN_next(case_wn), case_cnt++ )
02419 {
02420
02421
02422 Is_True( WN_opcode(case_wn) != OPC_REGION_EXIT,
02423 ("CFG::Add_one_compgoto_stmt, found a region exit"));
02424 Is_True( WN_opcode(case_wn) == OPC_GOTO,
02425 ("CFG::Add_one_compgoto__stmt, invalid statement"
02426 " in OPC_COMPGOTO jump table") );
02427 Is_True( case_cnt < new_num_entries,
02428 ("CFG::Add_one_compgoto_stmt, too many entries"
02429 " in jump table block") );
02430
02431 BB_NODE *case_blk = Get_bb_from_label( WN_label_number(case_wn) );
02432 if (case_blk == NULL) {
02433 case_blk = Create_bb();
02434 Append_label_map(WN_label_number(case_wn), case_blk);
02435 }
02436
02437 _current_bb->Set_switchcase(case_blk, case_cnt);
02438 Connect_predsucc(_current_bb, case_blk);
02439 }
02440
02441
02442
02443 if ( ends_bb )
02444 *ends_bb = END_BREAK;
02445 }
02446
02447
02448
02449
02450
02451 void
02452 CFG::Add_one_io_stmt( WN *wn, END_BLOCK *ends_bb )
02453 {
02454 BOOL has_cntl_flow = FALSE;
02455
02456 _current_bb->Set_hascall();
02457 Append_wn_in(_current_bb, wn);
02458
02459 for (INT32 i = 0; i < WN_kid_count(wn); i++) {
02460 WN *kid = WN_kid(wn, i);
02461
02462 OPCODE opcode = WN_opcode(kid);
02463 Is_True(OPCODE_has_inumber(opcode),
02464 ("illegal OPC_IO_ITEM within iostmt"));
02465 if (opcode == OPC_IO_ITEM) {
02466 if (WN_io_item(kid) == IOC_END || WN_io_item(kid) == IOC_ERR ||
02467 WN_io_item(kid) == IOC_EOR) {
02468 WN *kid0 = WN_kid0(kid);
02469
02470 Is_True(WN_operator(kid0) == OPR_GOTO,
02471 ("IOC_END/ERR with non-GOTO kid"));
02472 LABEL_IDX lab = WN_label_number(kid0);
02473
02474 BB_NODE *label_bb = Get_bb_from_label(lab);
02475 if (label_bb == NULL) {
02476 label_bb = Create_bb();
02477
02478 Append_label_map(lab, label_bb);
02479 }
02480 Connect_predsucc(_current_bb, label_bb);
02481 has_cntl_flow = TRUE;
02482
02483 _current_bb->Set_kind( BB_IO );
02484 if ( _current_bb->IOinfo() == NULL ) {
02485 _current_bb->Set_ioinfo( CXX_NEW(
02486 BB_SWITCH(IO_TAB_SIZE, _mem_pool), _mem_pool ) );
02487 _current_bb->Set_io_entries( 0 );
02488 }
02489
02490 _current_bb->Set_io_bb( label_bb, _current_bb->IO_entries() );
02491 _current_bb->Set_io_entries( _current_bb->IO_entries()+1 );
02492 }
02493 }
02494 }
02495
02496 if ( ends_bb ) {
02497
02498
02499 if ( has_cntl_flow || Calls_break() )
02500 *ends_bb = END_FALLTHRU;
02501 else
02502 *ends_bb = END_NOT;
02503 }
02504 }
02505
02506
02507
02508
02509 void
02510 CFG::Copy_xpragmas_into(BB_NODE *bb, WN *pragmas)
02511 {
02512 STMT_ITER stmt_iter;
02513 WN *stmt;
02514
02515
02516 FOR_ALL_ELEM (stmt, stmt_iter, Init(WN_first(pragmas), WN_last(pragmas))) {
02517 Is_True(WN_operator(stmt) == OPR_PRAGMA ||
02518 WN_operator(stmt) == OPR_XPRAGMA ||
02519 WN_opcode(stmt) == OPC_VCALL ||
02520 WN_operator(stmt) == OPR_GOTO,
02521 ("CFG::Copy_pragmas_into: statement is not "
02522 "a pragma, vcall, or goto"));
02523
02524
02525
02526 if (WN_operator(stmt) == OPR_XPRAGMA || WN_operator(stmt) == OPR_PRAGMA) {
02527 Append_wn_in(bb, stmt);
02528 bb->Set_haspragma();
02529 }
02530 }
02531 }
02532
02533
02534
02535
02536
02537 void
02538 CFG::Add_one_region( WN *wn, END_BLOCK *ends_bb )
02539 {
02540 RID *rid = REGION_get_rid(wn);
02541
02542 Is_True(rid != NULL,("CFG::Add_one_region, cannot find RID"));
02543 Is_True(REGION_consistency_check(wn), (""));
02544
02545
02546
02547
02548 if ( RID_level(rid) >= Rgn_level() ) {
02549 WN *wtmp;
02550 BB_NODE *bsave = _current_bb;
02551
02552 Append_wn_in( _current_bb, wn );
02553
02554
02555
02556
02557
02558
02559
02560 BB_NODE *btmp;
02561 btmp = New_bb(TRUE,BB_EXIT);
02562 btmp->Set_hasujp();
02563 _current_bb = bsave;
02564
02565
02566 for (wtmp=WN_first(WN_region_exits(wn)); wtmp!=NULL; wtmp=WN_next(wtmp)) {
02567 INT32 label = WN_label_number(wtmp);
02568 BB_NODE *label_bb = Get_bb_from_label(label);
02569 if (label_bb == NULL) {
02570 label_bb = Create_bb();
02571
02572 Append_label_map(WN_label_number(wtmp), label_bb);
02573 }
02574 Connect_predsucc(bsave, label_bb);
02575 }
02576
02577 if ( ends_bb )
02578 *ends_bb = END_FALLTHRU;
02579
02580 return;
02581 }
02582
02583
02584 Set_has_regions();
02585
02586
02587
02588
02589
02590
02591 BB_NODE *first_region_bb;
02592 if (RID_id(rid) != RID_id(Rid())) {
02593 if (_current_bb->Firststmt() != NULL)
02594 _current_bb = New_bb(TRUE, BB_GOTO);
02595 else
02596 _current_bb->Set_kind(BB_GOTO);
02597 first_region_bb = New_bb(TRUE, BB_REGIONSTART);
02598 } else {
02599
02600 if (_current_bb->Firststmt() != NULL)
02601 (void) New_bb(TRUE, BB_REGIONSTART);
02602 else
02603 _current_bb->Set_kind(BB_REGIONSTART);
02604 first_region_bb = _current_bb;
02605 }
02606 first_region_bb->Set_linenum(WN_Get_Linenum(wn));
02607
02608
02609 BB_REGION *bb_region = CXX_NEW(BB_REGION(first_region_bb, NULL, rid,
02610 NULL, WN_region_pragmas(wn), WN_region_exits(wn),
02611 WN_ereg_supp(wn), WN_Get_Linenum(wn), wn), _mem_pool);
02612 first_region_bb->Set_regioninfo(bb_region);
02613 Push_bb_region(bb_region);
02614
02615 if (REGION_is_mp(wn)) {
02616 if ( Is_region_with_pragma(wn,WN_PRAGMA_DOACROSS) ||
02617 Is_region_with_pragma(wn,WN_PRAGMA_PARALLEL_DO) )
02618 Push_mp_type(MP_DOACROSS);
02619 else if ( Is_region_with_pragma(wn,WN_PRAGMA_PDO_BEGIN) )
02620 Push_mp_type(MP_PDO);
02621 else
02622 Push_mp_type(MP_REGION);
02623 Push_mp_rid(rid);
02624 }
02625
02626 #if defined(TARG_SL)
02627 if (REGION_is_sl2_para(wn)) {
02628 Push_sl2_para_type(SL2_PARA_REGION);
02629 Push_sl2_para_rid(rid);
02630 }
02631 #endif
02632
02633
02634 BB_NODE *first_body_bb = New_bb( TRUE );
02635
02636 END_BLOCK block_end;
02637 Add_one_stmt( WN_region_body(wn), &block_end );
02638
02639 if (REGION_is_mp(wn)) {
02640
02641 if (_current_bb->Kind() != BB_REGIONEXIT)
02642 (void) New_bb(TRUE, BB_REGIONEXIT);
02643 Pop_mp_type();
02644 Pop_mp_rid();
02645 }
02646 #if defined(TARG_SL)
02647 if (REGION_is_sl2_para(wn)) {
02648
02649 if (_current_bb->Kind() != BB_REGIONEXIT)
02650 (void) New_bb(TRUE, BB_REGIONEXIT);
02651 Pop_sl2_para_type();
02652 Pop_sl2_para_rid();
02653 }
02654 #endif
02655 Pop_bb_region();
02656
02657
02658 BB_NODE *last_region_bb = _current_bb;
02659
02660
02661 if (REGION_is_mp(wn) && _rgn_level != RL_MAINOPT &&
02662 Is_region_with_pragma(wn,WN_PRAGMA_SINGLE_PROCESS_BEGIN)) {
02663
02664 Connect_predsucc( first_region_bb, last_region_bb );
02665 }
02666
02667
02668 bb_region->Set_region_end(last_region_bb);
02669 bb_region->Set_parent(Null_bb_region() ? NULL : Top_bb_region());
02670
02671
02672 if (last_region_bb->Kind() == BB_REGIONEXIT ||
02673 last_region_bb->Kind() == BB_EXIT)
02674 last_region_bb->Set_regioninfo(bb_region);
02675
02676
02677
02678 Copy_xpragmas_into(first_region_bb, WN_region_pragmas(wn));
02679
02680
02681 WN_MAP_Set( RID_map, wn, NULL );
02682 RID_rwn(rid) = NULL;
02683
02684
02685 if ( ends_bb ) {
02686 if ( block_end == END_BREAK )
02687 *ends_bb = END_BREAK;
02688 else
02689 *ends_bb = END_FALLTHRU;
02690 }
02691 }
02692
02693 BB_NODE*
02694 CFG::Process_entry( WN *wn, END_BLOCK *ends_bb )
02695 {
02696 BB_NODE *retv;
02697 BB_NODE *last_bb = _current_bb;
02698
02699
02700 if ( _current_bb->Firststmt() != NULL ||
02701 (_current_bb->Pred() && _current_bb->Pred()->Len() > 0) )
02702 {
02703 (void)New_bb( FALSE, BB_ENTRY );
02704 }
02705 else
02706 _current_bb->Set_kind(BB_ENTRY);
02707
02708
02709 Add_altentry(_current_bb);
02710
02711
02712 WN *copy_wn = WN_CopyNode(wn);
02713
02714
02715
02716
02717
02718
02719 WN_COPY_All_Maps(copy_wn, wn);
02720
02721 if ( Cur_PU_Feedback )
02722 Cur_PU_Feedback->FB_duplicate_node( wn, copy_wn );
02723
02724 const OPERATOR opr = WN_operator(wn);
02725
02726
02727 if (opr != OPR_LABEL) {
02728 INT kids_to_copy;
02729 Is_True(opr == OPR_FUNC_ENTRY || opr == OPR_ALTENTRY,
02730 ("CFG::Process_entry, Illegal Operator"));
02731 if ( opr == OPR_FUNC_ENTRY )
02732 kids_to_copy = WN_num_formals(wn);
02733 else
02734 kids_to_copy = WN_kid_count(wn);
02735
02736 for (INT i = 0; i < kids_to_copy; i++)
02737 WN_formal(copy_wn, i) = WN_CopyNode(WN_formal(wn, i));
02738
02739 if (opr == OPR_FUNC_ENTRY) {
02740 WN_func_pragmas(copy_wn) = WN_COPY_Tree_With_Map(WN_func_pragmas(wn));
02741 WN_func_varrefs(copy_wn) = WN_COPY_Tree_With_Map(WN_func_varrefs(wn));
02742 WN_func_body(copy_wn) = WN_CreateBlock();
02743 }
02744 }
02745 else {
02746 WN_label_flag(copy_wn) = WN_label_flag(wn);
02747 Append_label_map(WN_label_number(copy_wn), _current_bb);
02748 }
02749 _current_bb->Set_entrywn(copy_wn);
02750 retv = _current_bb;
02751
02752
02753 (void)New_bb( TRUE );
02754
02755 if ( opr == OPR_FUNC_ENTRY ) {
02756
02757 FmtAssert(WN_func_body(wn) != NULL,
02758 ("CFG::Process_entry: NULL body pointer"));
02759
02760 Add_one_stmt( WN_func_body(wn), NULL );
02761
02762
02763 WN_func_body(wn) = NULL;
02764
02765
02766
02767
02768 if ( ends_bb ) *ends_bb = END_BREAK;
02769 }
02770 else {
02771 if ( ends_bb ) *ends_bb = END_NOT;
02772 #ifdef KEY
02773 if (opr == OPR_LABEL &&
02774 LABEL_target_of_goto_outer_block(WN_label_number(wn)))
02775 Connect_predsucc(last_bb, _current_bb);
02776 #endif
02777 }
02778 return retv;
02779 }
02780
02781
02782
02783
02784
02785
02786
02787
02788 void
02789 CFG::Add_one_stmt( WN *wn, END_BLOCK *ends_bb )
02790 {
02791 BB_NODE *label_bb;
02792
02793 if ( ends_bb )
02794 *ends_bb = END_UNKNOWN;
02795
02796 if (wn == NULL) return;
02797
02798 const OPCODE opc = WN_opcode(wn);
02799 const OPERATOR opr = OPCODE_operator(opc);
02800
02801 switch ( opr ) {
02802
02803 case OPR_BLOCK:
02804 if ( WN_first(wn) != NULL ) {
02805 END_BLOCK endsbb = END_NOT;
02806 WN *nextstmt = NULL;
02807 for ( WN *stmt = WN_first(wn); stmt != NULL; stmt = nextstmt ) {
02808 nextstmt = WN_next(stmt);
02809 WN_next(stmt) = NULL;
02810 WN_prev(stmt) = NULL;
02811 Add_one_stmt( stmt, &endsbb );
02812
02813 if (WN_operator(stmt) == OPR_CALL && WOPT_Enable_Noreturn_Attr_Opt) {
02814 if (PU_has_attr_noreturn(Pu_Table[ST_pu(WN_st(stmt))])) {
02815
02816
02817 if (!nextstmt ||
02818 (WN_operator(nextstmt) != OPR_RETURN &&
02819 WN_operator(nextstmt) != OPR_RETURN_VAL)) {
02820 WN *nextstmt_save = nextstmt;
02821 nextstmt = WN_Create (OPC_RETURN, 0);
02822 WN_next(nextstmt) = nextstmt_save;
02823 if (nextstmt_save)
02824 WN_prev(nextstmt_save) = nextstmt;
02825 }
02826 }
02827 }
02828
02829
02830 if ( endsbb == END_NOT && Rvi_break_stmt() )
02831 endsbb = END_FALLTHRU;
02832
02833 if ( endsbb == END_FALLTHRU || endsbb == END_BREAK ) {
02834
02835 if ( nextstmt != NULL ) {
02836
02837
02838 BOOL need_to_set_callrel = FALSE;
02839 if ( Calls_break() && _current_bb->Hascall() ) {
02840 need_to_set_callrel = TRUE;
02841 }
02842
02843
02844 BB_NODE *label_bb;
02845 if ( WN_opcode(nextstmt) == OPC_LABEL &&
02846 (label_bb = Get_bb_from_label(WN_label_number(nextstmt))) )
02847 {
02848
02849 if ( endsbb == END_FALLTHRU ) {
02850 Connect_predsucc( _current_bb, label_bb );
02851
02852
02853 if ( need_to_set_callrel )
02854 label_bb->Set_callrel();
02855 }
02856 }
02857 else {
02858 (void)New_bb( endsbb == END_FALLTHRU );
02859
02860
02861 if ( need_to_set_callrel )
02862 _current_bb->Set_callrel();
02863 }
02864 }
02865 else {
02866
02867 if ( endsbb == END_FALLTHRU ) {
02868
02869
02870 if ( _current_bb->Kind() == BB_LOGIF ) {
02871 BB_NODE *fallthru = New_bb( TRUE );
02872 endsbb = END_NOT;
02873 }
02874 }
02875 }
02876 }
02877 else {
02878 Is_True( endsbb != END_UNKNOWN,
02879 ("CFG::Add_one_stmt: unknown kind of block ending") );
02880 }
02881 }
02882
02883 if ( ends_bb )
02884 *ends_bb = endsbb;
02885 }
02886 else {
02887 FmtAssert(WN_last(wn) == NULL,
02888 ("CFG::Add_one_stmt: mismatching block statements"));
02889 if ( ends_bb )
02890 *ends_bb = END_NOT;
02891 }
02892
02893
02894 break;
02895
02896 case OPR_FUNC_ENTRY:
02897 case OPR_ALTENTRY:
02898 Process_entry( wn, ends_bb );
02899 break;
02900
02901 case OPR_DO_LOOP:
02902 Create_empty_preheader (wn);
02903 if (Lower_fully())
02904 Lower_do_loop( wn, ends_bb );
02905 else
02906 Add_one_do_loop_stmt( wn, ends_bb );
02907 break;
02908
02909 case OPR_WHILE_DO:
02910 Create_empty_preheader (wn);
02911 if (Lower_fully()) {
02912 Lower_while_do( wn, ends_bb );
02913 }
02914 else {
02915 Add_one_while_do_stmt( wn, ends_bb );
02916 }
02917 break;
02918
02919 case OPR_DO_WHILE:
02920 Create_empty_preheader (wn);
02921 if (Lower_fully())
02922 Lower_do_while( wn, ends_bb );
02923 else
02924 Add_one_do_while_stmt( wn, ends_bb );
02925 break;
02926
02927 case OPR_IF:
02928 if (Lower_fully()) {
02929 Lower_if_stmt( wn, ends_bb );
02930 }
02931 else {
02932 Add_one_if_stmt( wn, ends_bb );
02933 }
02934 break;
02935
02936 case OPR_GOTO:
02937 label_bb = Get_bb_from_label( WN_label_number(wn) );
02938 if (label_bb == NULL) {
02939 label_bb = Create_bb();
02940
02941 Append_label_map(WN_label_number(wn), label_bb);
02942 }
02943 Append_wn_in(_current_bb, wn);
02944 _current_bb->Set_hasujp();
02945 Connect_predsucc(_current_bb, label_bb);
02946 if ( ends_bb )
02947 *ends_bb = END_BREAK;
02948 break;
02949
02950 case OPR_AGOTO:
02951 _agoto_pred_vec.AddElement( _current_bb );
02952 Append_wn_in(_current_bb, wn);
02953 _current_bb->Set_hasujp();
02954 _current_bb->Set_kind(BB_VARGOTO);
02955 if ( ends_bb )
02956 *ends_bb = END_BREAK;
02957 break;
02958
02959 case OPR_FALSEBR:
02960 case OPR_TRUEBR:
02961 label_bb = Get_bb_from_label( WN_label_number(wn) );
02962 if (label_bb == NULL) {
02963 label_bb = Create_bb();
02964
02965 Append_label_map(WN_label_number(wn), label_bb);
02966 }
02967
02968 if ( Lower_fully() &&
02969 (WN_operator(WN_kid0(wn)) == OPR_CAND ||
02970 WN_operator(WN_kid0(wn)) == OPR_CIOR) )
02971 {
02972 WN *wn_branch;
02973 if ( opr == OPR_TRUEBR )
02974 Create_conditional( WN_kid0(wn), label_bb, NULL, TRUE, &wn_branch);
02975 else
02976 Create_conditional( WN_kid0(wn), NULL, label_bb, FALSE, &wn_branch);
02977
02978
02979 if ( Cur_PU_Feedback ) {
02980 Cur_PU_Feedback->FB_lower_branch( wn, wn_branch );
02981 }
02982 }
02983 else {
02984 Connect_predsucc(_current_bb, label_bb);
02985 Append_wn_in(_current_bb, wn);
02986 _current_bb->Set_kind(BB_LOGIF);
02987 }
02988
02989 if ( ends_bb )
02990 *ends_bb = END_FALLTHRU;
02991 break;
02992
02993 case OPR_RETURN:
02994 case OPR_RETURN_VAL:
02995 #ifdef KEY
02996 case OPR_GOTO_OUTER_BLOCK:
02997 #endif
02998 {
02999 Append_wn_in(_current_bb, wn);
03000 _current_bb->Set_hasujp();
03001
03002 _current_bb->Set_kind( BB_EXIT );
03003
03004
03005 BB_REGION *bb_region = Null_bb_region() ? NULL : Top_bb_region();
03006 _current_bb->Set_regioninfo(bb_region);
03007
03008 if ( ends_bb )
03009 *ends_bb = END_BREAK;
03010 }
03011 break;
03012
03013 case OPR_LABEL:
03014 {
03015
03016 if (WN_Label_Is_Handler_Begin(wn)
03017 #ifdef KEY
03018 || LABEL_target_of_goto_outer_block(WN_label_number(wn))
03019 #endif
03020 ) {
03021
03022
03023 FmtAssert( Get_bb_from_label( WN_label_number(wn) ) == NULL,
03024 ("Exception Handler Label is target of goto statement") );
03025
03026 Process_entry( wn, ends_bb );
03027 break;
03028 }
03029
03030 label_bb = Get_bb_from_label( WN_label_number(wn) );
03031 if ( label_bb != NULL ) {
03032 Is_True( label_bb->Firststmt() == NULL,
03033 ("Non-empty block assigned to a label") );
03034
03035
03036 if ( ! _current_bb->Hasujp() )
03037 Connect_predsucc( _current_bb, label_bb );
03038 Append_bb( label_bb );
03039 }
03040 else if ( _current_bb->Firststmt() != NULL ||
03041 _current_bb->Labnam() != 0 ||
03042 First_bb()->Next() == _current_bb )
03043 {
03044
03045
03046 label_bb = New_bb( TRUE );
03047 Append_label_map(WN_label_number(wn), label_bb);
03048 }
03049 else {
03050
03051 Is_True( _current_bb->Labnam() == 0,
03052 ("CFG::Add_one_stmt: empty block has label assigned") );
03053 label_bb = _current_bb;
03054 Append_label_map(WN_label_number(wn), label_bb);
03055 }
03056 Is_True( _current_bb == label_bb,
03057 ("Label block not same as current block") );
03058 label_bb->Set_linenum(WN_Get_Linenum(wn));
03059 if ( WN_label_loop_info(wn) != NULL ) {
03060 WN *loop_info = WN_COPY_Tree_With_Map(WN_label_loop_info(wn));
03061 label_bb->Set_label_loop_info(loop_info);
03062 }
03063
03064
03065 if ( LABEL_addr_saved( label_bb->Labnam() ) ) {
03066 _agoto_succ_vec.AddElement( label_bb );
03067 }
03068
03069 Append_wn_in( label_bb, wn );
03070 if ( ends_bb ) *ends_bb = END_NOT;
03071 }
03072 break;
03073
03074 case OPR_COMPGOTO:
03075 Add_one_compgoto_stmt( wn, ends_bb );
03076 break;
03077
03078 case OPR_CALL:
03079 case OPR_ICALL:
03080 case OPR_PICCALL:
03081 if (_exc)
03082 _exc->Link_top_es(wn);
03083 _current_bb->Set_hascall();
03084 Append_wn_in(_current_bb, wn);
03085 if (ends_bb) {
03086 *ends_bb = Calls_break() ? END_FALLTHRU : END_NOT;
03087 }
03088 break;
03089
03090 case OPR_INTRINSIC_CALL:
03091 _current_bb->Set_hascall();
03092 Append_wn_in(_current_bb, wn);
03093 if (WN_Call_Never_Return(wn)) {
03094 _current_bb->Set_kind( BB_EXIT );
03095 _current_bb->Set_hasujp();
03096 if ( ends_bb )
03097 *ends_bb = END_BREAK;
03098 } else {
03099 if ( ends_bb )
03100 *ends_bb = Calls_break() ? END_FALLTHRU : END_NOT;
03101 }
03102 break;
03103
03104 case OPR_IO:
03105
03106
03107
03108 Add_one_io_stmt( wn, ends_bb );
03109 break;
03110
03111 case OPR_REGION:
03112 { EXC_SCOPE *exc_scope;
03113
03114
03115 if (REGION_is_EH(wn) && _exc) {
03116
03117 exc_scope = _exc->Push_exc_scope(wn);
03118 exc_scope->Set_begin_wn(wn);
03119
03120
03121 _exc->Link_wn_es(wn, exc_scope);
03122 }
03123
03124
03125 Add_one_region( wn, ends_bb );
03126
03127 if (REGION_is_EH(wn) && _exc) {
03128 exc_scope = _exc->Pop_exc_scope();
03129 }
03130 }
03131 break;
03132
03133 case OPR_PRAGMA:
03134 case OPR_XPRAGMA:
03135 _current_bb->Set_haspragma();
03136 Append_wn_in(_current_bb, wn);
03137 if ( ends_bb )
03138 *ends_bb = END_NOT;
03139 break;
03140
03141 case OPR_REGION_EXIT:
03142 {
03143
03144
03145
03146
03147
03148 BB_REGION *bb_region = Null_bb_region() ? NULL : Top_bb_region();
03149 BOOL create_label_bb = TRUE;
03150 if (!RID_TYPE_func_entry(Rid()) && bb_region) {
03151 Is_True(Rid() && RID_rwn(Rid()) &&
03152 WN_opcode(RID_rwn(Rid())) == OPC_REGION &&
03153 WN_region_exits(RID_rwn(Rid())) &&
03154 WN_opcode(WN_region_exits(RID_rwn(Rid()))) == OPC_BLOCK,
03155 ("CFG::Add_one_stmt, invalid assumption about region exit"));
03156 WN *exit_blk;
03157 exit_blk = WN_region_exits(RID_rwn(Rid()));
03158
03159 create_label_bb = !REGION_scan_exits(exit_blk, WN_label_number(wn));
03160 }
03161
03162 label_bb = Get_bb_from_label( WN_label_number(wn) );
03163 if (label_bb == NULL && create_label_bb) {
03164 label_bb = Create_bb();
03165 Append_label_map(WN_label_number(wn), label_bb);
03166 }
03167 if (label_bb)
03168 Connect_predsucc(_current_bb, label_bb);
03169
03170 Append_wn_in(_current_bb, wn);
03171 _current_bb->Set_kind(BB_REGIONEXIT);
03172 _current_bb->Set_regioninfo(bb_region);
03173 _current_bb->Set_hasujp();
03174
03175 if ( ends_bb )
03176 *ends_bb = END_BREAK;
03177 }
03178 break;
03179
03180 default:
03181
03182 FmtAssert(!OPCODE_is_scf(opc),
03183 ("CFG::Add_one_stmt:CTRL opcode %s is not handled yet",
03184 OPCODE_name(opc)) );
03185
03186 Append_wn_in(_current_bb, wn);
03187
03188 if ( ends_bb )
03189 *ends_bb = END_NOT;
03190 break;
03191 }
03192
03193 }
03194
03195
03196
03197
03198
03199 void
03200 CFG::Connect_agotos()
03201 {
03202 INT i, j;
03203
03204
03205 if ( Trace() ) {
03206 fprintf(TFile, "_agoto_pred_vec:");
03207 for (i = 0; i <= _agoto_pred_vec.Lastidx(); i++) {
03208 fprintf(TFile, " %d", _agoto_pred_vec[i]->Id());
03209 }
03210 fprintf(TFile, "\n_agoto_succ_vec:");
03211 for (j = 0; j <= _agoto_succ_vec.Lastidx(); j++) {
03212 fprintf(TFile, " %d", _agoto_succ_vec[j]->Id());
03213 }
03214 fprintf(TFile, "\n");
03215 }
03216
03217
03218 for (i = 0; i <= _agoto_pred_vec.Lastidx(); i++) {
03219 for (j = 0; j <= _agoto_succ_vec.Lastidx(); j++) {
03220 Connect_predsucc(_agoto_pred_vec[i], _agoto_succ_vec[j]);
03221 }
03222 }
03223 }
03224
03225
03226
03227
03228
03229
03230 void
03231 CFG::Remove_agoto_pred( BB_NODE *bb )
03232 {
03233 mUINT32 lastidx = _agoto_pred_vec.Lastidx();
03234 for ( mUINT32 idx = 0; idx <= lastidx; ++idx ) {
03235 if ( _agoto_pred_vec[idx] == bb ) {
03236
03237 _agoto_pred_vec[idx] = _agoto_pred_vec[lastidx];
03238 _agoto_pred_vec.Decidx();
03239 return;
03240 }
03241 }
03242 Is_True( FALSE, ( "CFG::Remove_agoto_pred: bb not found" ) );
03243 }
03244
03245
03246
03247
03248
03249 INT32
03250 CFG::Agoto_succ_entries()
03251 {
03252 return _agoto_succ_vec.Elements();
03253 }
03254
03255
03256
03257
03258
03259 BB_NODE *
03260 CFG::Agoto_succ_bb(INT32 idx)
03261 {
03262 Is_True( idx >= 0 && idx <= _agoto_succ_vec.Lastidx(),
03263 ( "CFG::Agoto_succ_bb found out of range idx %d (range 0...%d)",
03264 idx, _agoto_succ_vec.Lastidx() ) );
03265 return _agoto_succ_vec[idx];
03266 }
03267
03268
03269
03270
03271
03272 void
03273 CFG::Process_multi_entryexit( BOOL is_whirl )
03274 {
03275 Is_Trace(Trace(), (TFile,"CFG::Process_multi_entryexit\n"));
03276
03277
03278
03279 Process_not_reached( is_whirl );
03280
03281 Is_True( _entry_vec.Lastidx() >= 0,
03282 ("CFG::Process_multi_entryexit: No entrypoints") );
03283
03284
03285 if ( Fake_entry_bb() == NULL &&
03286 _entry_vec.Lastidx() == 0 && _notreach_vec.Lastidx() < 0 )
03287 {
03288
03289 _entry_bb = _entry_vec[0];
03290 } else {
03291
03292
03293
03294 if ( Fake_entry_bb() == NULL ) {
03295 _fake_entry_bb = New_bb( FALSE, BB_ENTRY );
03296 _entry_bb = _fake_entry_bb;
03297 } else {
03298 _entry_bb = Fake_entry_bb();
03299 }
03300
03301
03302
03303 INT i;
03304 for ( i=0; i <= _entry_vec.Lastidx(); i++ )
03305 Connect_predsucc(_entry_bb, _entry_vec[i]);
03306 for ( i=0; i <= _notreach_vec.Lastidx(); i++ )
03307 Connect_predsucc(_entry_bb, _notreach_vec[i]);
03308 }
03309
03310 Find_exit_blocks();
03311
03312
03313 Process_no_exit();
03314
03315 Is_True( _exit_vec.Lastidx() >= 0,
03316 ("CFG::Process_multi_entryexit: no exit blocks") );
03317
03318
03319 if ( _exit_vec.Lastidx() == 0 && Fake_exit_bb() == NULL ) {
03320 _exit_bb = _exit_vec[0];
03321
03322 if ( _exit_bb->Willexit() ) {
03323 return;
03324 }
03325 }
03326
03327
03328 if (Fake_exit_bb() == NULL) {
03329 _fake_exit_bb = New_bb( FALSE, BB_EXIT );
03330 _fake_exit_bb->Set_willexit();
03331 _exit_bb = _fake_exit_bb;
03332 } else {
03333
03334 _exit_bb = Fake_exit_bb();
03335 }
03336
03337 for (INT i=0; i <= _exit_vec.Lastidx(); i++) {
03338 Is_True( _exit_vec[i] != _exit_bb,
03339 ("CFG::Process_multi_entryexit: _exit_bb in _exit_vec") );
03340 Connect_predsucc(_exit_vec[i], _exit_bb);
03341 }
03342 }
03343
03344
03345
03346
03347
03348
03349 void
03350 CFG::Ident_mp_regions(void)
03351 {
03352 CFG_ITER cfg_iter(this);
03353 BB_NODE *bb;
03354 BB_REGION *bb_region;
03355
03356 Clear_mp_type();
03357 Clear_mp_rid();
03358 Clear_bb_region();
03359
03360
03361 FOR_ALL_NODE( bb, cfg_iter, Init() ) {
03362 if (bb->Kind() == BB_REGIONSTART) {
03363 bb_region = bb->Regioninfo();
03364 Is_True(bb_region != NULL, ("CFG::Ident_mp_regions, no regioninfo"));
03365 if (RID_TYPE_mp(bb_region->Rid())) {
03366 Push_mp_type(MP_REGION);
03367 Push_mp_rid(bb_region->Rid());
03368 Push_bb_region(bb_region);
03369 }
03370 }
03371
03372 if (! NULL_mp_type()) {
03373 bb->Set_MP_region();
03374 bb->Set_rid_id(RID_id(Top_mp_rid()));
03375 }
03376
03377
03378 if (bb->Kind() == BB_REGIONEXIT) {
03379 bb_region = bb->Regioninfo();
03380 Is_True(bb_region != NULL, ("CFG::Ident_mp_regions, no regioninfo"));
03381 if (RID_TYPE_mp(bb_region->Rid())) {
03382 Pop_mp_type();
03383 Pop_mp_rid();
03384 Pop_bb_region();
03385 }
03386 }
03387 }
03388 }
03389
03390 #if defined(TARG_SL) //PARA_EXTENSION
03391
03392
03393
03394
03395
03396 void
03397 CFG::Ident_sl2_para_regions(void)
03398 {
03399 CFG_ITER cfg_iter(this);
03400 BB_NODE *bb;
03401 BB_REGION *bb_region;
03402
03403 Clear_sl2_para_type();
03404 Clear_sl2_para_rid();
03405 Clear_bb_region();
03406
03407
03408 FOR_ALL_NODE( bb, cfg_iter, Init() ) {
03409 if (bb->Kind() == BB_REGIONSTART) {
03410 bb_region = bb->Regioninfo();
03411 Is_True(bb_region != NULL, ("CFG::Ident_sl2_parallel_regions, no regioninfo"));
03412 if (RID_TYPE_sl2_para(bb_region->Rid())) {
03413 Push_sl2_para_type(SL2_PARA_REGION);
03414 Push_sl2_para_rid(bb_region->Rid());
03415 Push_bb_region(bb_region);
03416 }
03417 }
03418
03419 if (! NULL_sl2_para_type()) {
03420 bb->Set_SL2_para_region();
03421 bb->Set_rid_id(RID_id(Top_sl2_para_rid()));
03422 }
03423
03424
03425 if (bb->Kind() == BB_REGIONEXIT) {
03426 bb_region = bb->Regioninfo();
03427 Is_True(bb_region != NULL, ("CFG::Ident_sl2_parallel_regions, no regioninfo"));
03428 if (RID_TYPE_sl2_para(bb_region->Rid()))
03429 {
03430 Pop_sl2_para_type();
03431 Pop_sl2_para_rid();
03432 Pop_bb_region();
03433 }
03434 }
03435 }
03436 }
03437
03438 #endif
03439
03440
03441
03442
03443
03444 void
03445 CFG::Create(WN *func_wn, BOOL lower_fully, BOOL calls_break,
03446 REGION_LEVEL rgn_level, OPT_STAB *opt_stab, BOOL do_tail )
03447 {
03448 _opt_stab = opt_stab;
03449 _lower_fully = lower_fully;
03450 _calls_break = calls_break;
03451 _rgn_level = rgn_level;
03452
03453 Set_cur_loop_depth( 0 );
03454
03455
03456 _last_bb = NULL;
03457 _first_bb = Create_bb();
03458 Append_bb( _first_bb );
03459
03460 OPERATOR opr = WN_operator(func_wn);
03461 FmtAssert(opr == OPR_FUNC_ENTRY || opr == OPR_REGION,
03462 ("CFG::Create: root wn not FUNC_ENTRY or REGION"));
03463
03464
03465
03466 Is_True(REGION_consistency_check(func_wn),("CFG::Create"));
03467 _rid = REGION_get_rid(func_wn);
03468
03469 END_BLOCK endsbb;
03470 Add_one_stmt(func_wn, &endsbb);
03471 if (opr == OPR_REGION)
03472 Add_altentry(_first_bb);
03473
03474
03475 Connect_agotos();
03476
03477
03478
03479
03480
03481 if ( do_tail ) {
03482 OPT_TAIL opt_tail( this, opt_stab );
03483 opt_tail.Mutate();
03484 }
03485
03486 Process_multi_entryexit( TRUE );
03487
03488 Ident_mp_regions();
03489
03490 #if defined(TARG_SL) //PARA_EXTENSION
03491 Ident_sl2_para_regions();
03492 #endif
03493
03494 if ( Get_Trace(TP_GLOBOPT, CFG_VERF_FLAG)) {
03495 fprintf(TFile, "%sDump after CFG construction %s%d\n%s", DBar,
03496 (opr == OPR_REGION) ? "RGN " : "PU ", RID_id(_rid), DBar);
03497 RID_Tree_Print(TFile,Rid());
03498 Print(TFile);
03499 Validate(TFile);
03500 }
03501 }
03502
03503
03504
03505
03506 static const BB_LOOP *
03507 Common_loop(const BB_LOOP *a, const BB_LOOP *b)
03508 {
03509 const BB_LOOP *p_a = a;
03510 const BB_LOOP *p_b = b;
03511
03512 while (p_a && p_b && p_a != p_b) {
03513 if (p_a->Header()->Loopdepth() > p_b->Header()->Loopdepth()) {
03514 p_a = p_a->Parent();
03515 } else if (p_a->Header()->Loopdepth() < p_b->Header()->Loopdepth()) {
03516 p_b = p_b->Parent();
03517 } else {
03518 p_a = p_a->Parent();
03519 p_b = p_b->Parent();
03520 }
03521 }
03522
03523 if (p_a == NULL || p_b == NULL) return NULL;
03524
03525 return p_a;
03526 }
03527
03528 BB_NODE *
03529 CFG::Add_bb_to_edge( BB_NODE *v, BB_NODE *w)
03530 {
03531 BB_NODE *new_bb;
03532
03533 if (Trace())
03534 fprintf(TFile, "Add_bb_to_edge: BB%d -> BB%d\n", v->Id(), w->Id());
03535
03536 if (v->Next() == w) {
03537 new_bb = Create_and_allocate_bb(BB_GOTO);
03538 v->Insert_After(new_bb);
03539
03540
03541 v->Replace_succ( w, new_bb );
03542 new_bb->Append_pred( v, Mem_pool() );
03543 w->Replace_pred( v, new_bb );
03544 new_bb->Append_succ( w, Mem_pool() );
03545
03546
03547 if ( Feedback() )
03548 Feedback()->Split_edge( v->Id(), new_bb->Id(), w->Id() );
03549
03550 } else {
03551
03552 new_bb = Create_and_allocate_bb(BB_GOTO);
03553
03554 STMTREP *bb_branch = v->Branch_stmtrep();
03555 Is_True(bb_branch != NULL, ("BB has no branch statement."));
03556
03557 OPERATOR opr = bb_branch->Opr();
03558
03559
03560 Is_True(w->Labnam() != 0, ("BB has no label."));
03561 LABEL_IDX new_label = Alloc_label();
03562
03563 Append_label_map(new_label, new_bb);
03564
03565 STMTREP *new_labstmt = CXX_NEW (STMTREP(OPC_LABEL), Mem_pool());
03566 new_labstmt->Init_Label(NULL, new_label, 0);
03567 new_bb->Append_stmtrep( new_labstmt );
03568
03569 if (opr == OPR_TRUEBR || opr == OPR_FALSEBR)
03570 bb_branch->Set_label_number( new_label );
03571 else {
03572 Is_True( opr == OPR_COMPGOTO,
03573 ("don't know how to handle this branch kind.") );
03574 for (INT32 num_entry = 0; num_entry < v->Switchentries(); num_entry++) {
03575 if (v->Switchcase(num_entry) == w)
03576 v->Set_switchcase(new_bb, num_entry);
03577 }
03578 if (v->Switchdefault() == w) {
03579 v->Set_switchdefault(new_bb);
03580 }
03581 }
03582
03583
03584 v->Replace_succ( w, new_bb );
03585 new_bb->Append_pred( v, Mem_pool() );
03586 w->Replace_pred( v, new_bb );
03587 new_bb->Append_succ( w, Mem_pool() );
03588
03589
03590 w->Insert_Before(new_bb);
03591
03592 if ( Feedback() )
03593 Feedback()->Split_edge( v->Id(), new_bb->Id(), w->Id() );
03594
03595
03596 BB_NODE *u = new_bb->Prev();
03597 if (w->Pred()->Contains(u)) {
03598 STMTREP *u_branch = u->Branch_stmtrep();
03599 if (u_branch == NULL && u->Kind() != BB_REGIONSTART &&
03600 u->Kind() != BB_ENTRY) {
03601
03602
03603 STMTREP *new_goto = CXX_NEW( STMTREP(OPC_GOTO), Mem_pool() );
03604 new_goto->Init_Goto( NULL, w->Labnam(), 0 );
03605 u->Append_stmtrep( new_goto );
03606 if (w->Label_stmtrep() == NULL)
03607 w->Add_label_stmtrep( Mem_pool() );
03608
03609 }
03610 else {
03611
03612 if (u->Kind() == BB_REGIONSTART || u->Kind() == BB_ENTRY ||
03613 OPCODE_operator(u_branch->Op()) == OPR_TRUEBR ||
03614 OPCODE_operator(u_branch->Op()) == OPR_FALSEBR) {
03615
03616
03617 BB_NODE *new_u = Create_and_allocate_bb(BB_GOTO);
03618 u->Insert_After(new_u);
03619
03620
03621 u->Replace_succ( w, new_u );
03622 new_u->Append_pred( u, Mem_pool() );
03623 w->Replace_pred( u, new_u );
03624 new_u->Append_succ( w, Mem_pool() );
03625
03626 if ( Feedback() )
03627 Feedback()->Split_edge( u->Id(), new_u->Id(), w->Id() );
03628
03629 STMTREP *new_goto = CXX_NEW( STMTREP(OPC_GOTO), Mem_pool() );
03630 new_goto->Init_Goto( NULL, w->Labnam(), 0 );
03631 new_u->Append_stmtrep( new_goto );
03632
03633 if (w->Label_stmtrep() == NULL)
03634 w->Add_label_stmtrep( Mem_pool() );
03635 }
03636
03637 }
03638 }
03639 }
03640 return new_bb;
03641 }
03642
03643
03644
03645
03646
03647 void
03648 CFG::Prop_entry(BB_NODE *bb) const
03649 {
03650 bb->Set_flag(BB_REACHED|BB_DFORDER);
03651 Is_Trace(Trace(), (TFile,"%d, ",bb->Id()));
03652
03653 BB_LIST_ITER bb_succ_iter;
03654 BB_NODE *succ;
03655 FOR_ALL_ELEM(succ, bb_succ_iter, Init(bb->Succ())) {
03656 if (!succ->Dforder())
03657 Prop_entry(succ);
03658 }
03659 }
03660
03661
03662
03663 void
03664 CFG::Find_not_reached(void)
03665 {
03666 CFG_ITER cfg_iter(this);
03667 BB_NODE *bb;
03668
03669 FOR_ALL_NODE( bb, cfg_iter, Init() ) {
03670 bb->Reset_dforder();
03671 bb->Reset_reached();
03672 }
03673
03674
03675 Is_Trace(Trace(),(TFile,"CFG::Find_not_reached, prop_entry blocks:\n"));
03676 for (INT i=0; i <= _entry_vec.Lastidx(); i++) {
03677 Prop_entry(_entry_vec[i]);
03678 }
03679 Is_Trace(Trace(),(TFile,"\n"));
03680 }
03681
03682 void
03683 CFG::Process_not_reached( BOOL )
03684 {
03685 CFG_ITER cfg_iter(this);
03686 BB_NODE *bb;
03687
03688
03689 _notreach_vec.Bzero_array();
03690 _notreach_vec.Resetidx();
03691
03692
03693
03694 if ( Fake_entry_bb() != NULL )
03695 Fake_entry_bb()->Set_succ( NULL );
03696
03697 Find_not_reached();
03698
03699 FOR_ALL_NODE( bb, cfg_iter, Init() ) {
03700 if ( ! bb->Reached() && Removable_bb(bb) )
03701 {
03702
03703 while ( bb->Pred() != NULL ) {
03704 BB_NODE *pred = bb->Pred()->Node();
03705 Remove_path( pred, bb );
03706 if ( Feedback() )
03707 Feedback()->Delete_edge( pred->Id(), bb->Id() );
03708 }
03709 while ( bb->Succ() != NULL ) {
03710 BB_NODE *succ = bb->Succ()->Node();
03711 Remove_path( bb, succ );
03712 if ( Feedback() )
03713 Feedback()->Delete_edge( bb->Id(), succ->Id() );
03714 }
03715
03716
03717
03718 Is_Trace(Trace(),
03719 (TFile,"CFG::Process_not_reached() 1, deleting BB%d %s\n",
03720 bb->Id(),bb->Kind_name()));
03721 Change_block_kind(bb, BB_GOTO);
03722 Add_notreach(bb);
03723 }
03724 }
03725 }
03726
03727
03728
03729
03730 void
03731 CFG::Change_block_kind( BB_NODE *bb, BB_KIND newkind ) const
03732 {
03733 switch ( bb->Kind() ) {
03734
03735 case BB_DOSTART:
03736
03737
03738 {
03739 BB_LOOP *loopinfo = bb->Loop();
03740
03741
03742 bb->Set_kind( newkind );
03743
03744 if ( loopinfo->End() != NULL &&
03745 loopinfo->End()->Kind() == BB_DOEND )
03746 Change_block_kind( loopinfo->End(), BB_LOGIF );
03747 if ( loopinfo->Step() != NULL &&
03748 loopinfo->Step()->Kind() == BB_DOSTEP )
03749 Change_block_kind( loopinfo->Step(), BB_GOTO );
03750
03751 bb->Set_loop( NULL );
03752 }
03753 break;
03754
03755 case BB_DOEND:
03756
03757
03758 {
03759 BB_LOOP *loopinfo = bb->Loop();
03760 if ( loopinfo->Start() != NULL &&
03761 (loopinfo->Start()->Kind() == BB_DOSTART ||
03762 loopinfo->Start()->Kind() == BB_DOHEAD) )
03763 Change_block_kind( loopinfo->Start(), BB_GOTO );
03764 if ( loopinfo->Step() != NULL &&
03765 loopinfo->Step()->Kind() == BB_DOSTEP )
03766 Change_block_kind( loopinfo->Step(), BB_GOTO );
03767
03768
03769 if ( loopinfo->Merge() != NULL &&
03770 loopinfo->Merge()->Kind() == BB_DOTAIL )
03771 Change_block_kind( loopinfo->Merge(), BB_GOTO );
03772
03773 bb->Set_loop( NULL );
03774 }
03775 break;
03776
03777 case BB_DOHEAD:
03778
03779
03780
03781 break;
03782
03783 case BB_DOSTEP:
03784 {
03785 BB_LOOP *loopinfo = bb->Loop();
03786
03787
03788 bb->Set_kind( newkind );
03789
03790 if ( loopinfo->End() != NULL &&
03791 loopinfo->End()->Kind() == BB_DOEND )
03792 Change_block_kind( loopinfo->End(), BB_LOGIF );
03793 if ( loopinfo->Start() != NULL &&
03794 loopinfo->Start()->Kind() == BB_DOSTART )
03795 Change_block_kind( loopinfo->Start(), BB_GOTO );
03796
03797 bb->Set_loop( NULL );
03798 }
03799 break;
03800
03801 case BB_DOTAIL:
03802 break;
03803
03804 case BB_ENTRY:
03805
03806
03807 if ( bb == Fake_entry_bb() )
03808 return;
03809 FmtAssert( FALSE,
03810 ("CFG::Change_block_kind: trying to change kind of entry bb:%d",
03811 bb->Id()) );
03812 break;
03813
03814 case BB_EXIT:
03815
03816
03817 return;
03818
03819
03820 case BB_REGIONEXIT:
03821 {
03822 BOOL everything_gone = Remove_region_exit(bb, TRUE);
03823 if (everything_gone)
03824 bb->Set_kind( newkind );
03825 }
03826 return;
03827
03828
03829 case BB_REGIONSTART:
03830
03831 Remove_region_entry(bb);
03832
03833 break;
03834
03835 case BB_IO:
03836
03837 bb->Set_ioinfo( NULL );
03838 break;
03839
03840 case BB_LOGIF:
03841
03842 if ( bb->Ifinfo() != NULL ) {
03843 BB_NODE *mergebb = bb->Ifinfo()->Merge();
03844 if ( mergebb != NULL )
03845 mergebb->Reset_ifmerge();
03846 bb->Set_ifinfo( NULL );
03847 }
03848 break;
03849
03850 case BB_REPEATBODY:
03851 {
03852 BB_LOOP *loopinfo = bb->Loop();
03853 if ( loopinfo != NULL && loopinfo->End() != NULL &&
03854 loopinfo->End()->Kind() == BB_REPEATEND )
03855 {
03856
03857 bb->Set_kind( newkind );
03858
03859
03860 Change_block_kind( loopinfo->End(), BB_LOGIF );
03861 }
03862 bb->Set_loop( NULL );
03863 }
03864
03865 bb->Set_loop( NULL );
03866 break;
03867
03868 case BB_REPEATEND:
03869 {
03870 BB_LOOP *loopinfo = bb->Loop();
03871 if ( loopinfo != NULL ) {
03872 if ( Lower_fully() && loopinfo->Start() != NULL &&
03873 loopinfo->Start()->Kind() == BB_DOHEAD )
03874 {
03875
03876 bb->Set_kind( newkind );
03877
03878 Change_block_kind( loopinfo->Start(), BB_GOTO );
03879 }
03880 else if ( ! Lower_fully() && loopinfo->Body() != NULL &&
03881 loopinfo->Body()->Kind() == BB_REPEATBODY )
03882 {
03883
03884 bb->Set_kind( newkind );
03885
03886 Change_block_kind( loopinfo->Body(), BB_GOTO );
03887 }
03888 }
03889 bb->Set_loop( NULL );
03890 }
03891 break;
03892
03893 case BB_WHILEEND:
03894 {
03895 BB_LOOP *loopinfo = bb->Loop();
03896 if ( loopinfo != NULL ) {
03897 if ( Lower_fully() ) {
03898 if ( loopinfo->Start() != NULL &&
03899 loopinfo->Start()->Kind() == BB_DOHEAD )
03900 {
03901
03902 bb->Set_kind( newkind );
03903
03904 Change_block_kind( loopinfo->Start(), BB_GOTO );
03905 }
03906 if ( loopinfo->Merge() != NULL &&
03907 loopinfo->Merge()->Kind() == BB_DOTAIL )
03908 {
03909
03910 bb->Set_kind( newkind );
03911
03912 Change_block_kind( loopinfo->Merge(), BB_GOTO );
03913 }
03914 }
03915
03916
03917
03918
03919 bb->Set_loop( NULL );
03920 }
03921 }
03922 break;
03923
03924 case BB_VARGOTO:
03925
03926 bb->Set_switchinfo( NULL );
03927 break;
03928
03929 case BB_GOTO:
03930 case BB_SUMMARY:
03931 break;
03932
03933 case BB_UNKNOWN:
03934 default:
03935 ErrMsg( EC_Unimplemented, "CFG::Change_block_kind: bad kind" );
03936 break;
03937 }
03938
03939 bb->Set_kind( newkind );
03940 }
03941
03942
03943
03944
03945
03946
03947
03948
03949 void
03950 CFG::Find_no_exit_blocks( BB_NODE *bb, BB_NODE_SET *instack )
03951 {
03952 BB_NODE *succ;
03953 BB_LIST_ITER bb_succ_iter;
03954
03955
03956
03957
03958
03959 if ( ! bb->Dforder() ) {
03960 INT succs_visited = 0;
03961 bb->Set_dforder();
03962 instack->Union1D( bb );
03963 FOR_ALL_ELEM( succ, bb_succ_iter, Init(bb->Succ()) ) {
03964 if ( ! instack->MemberP(succ) ) {
03965 Find_no_exit_blocks( succ, instack );
03966 succs_visited++;
03967 }
03968 }
03969 instack->Difference1D( bb );
03970
03971
03972
03973 if ( succs_visited == 0 && !bb->Willexit() &&
03974 bb != Fake_exit_bb() )
03975 {
03976 Add_earlyexit(bb);
03977 }
03978 }
03979 }
03980
03981 void
03982 CFG::Bkwd_prop_exit(BB_NODE *bb) const
03983 {
03984 bb->Set_flag(BB_WILLEXIT|BB_DFORDER);
03985
03986 BB_LIST_ITER bb_pred_iter;
03987 BB_NODE *pred;
03988
03989 FOR_ALL_ELEM( pred, bb_pred_iter, Init(bb->Pred()) )
03990 if (!pred->Dforder())
03991 Bkwd_prop_exit(pred);
03992 }
03993
03994 void
03995 CFG::Process_no_exit(void)
03996 {
03997 CFG_ITER cfg_iter(this);
03998 BB_NODE *bb;
03999
04000
04001 FOR_ALL_NODE( bb, cfg_iter, Init() ) {
04002 bb->Reset_visit();
04003 bb->Reset_willexit();
04004 }
04005
04006
04007 INT i;
04008 for (i = 0; i <= _exit_vec.Lastidx(); ++i)
04009 Bkwd_prop_exit(_exit_vec[i]);
04010
04011
04012 FOR_ALL_NODE( bb, cfg_iter, Init() )
04013 bb->Reset_dforder();
04014 for (i=0; i <= _entry_vec.Lastidx(); i++) {
04015 BB_NODE_SET instack(Total_bb_count(), this, Loc_pool(), BBNS_EMPTY);
04016 Find_no_exit_blocks( _entry_vec[i], &instack );
04017 }
04018
04019
04020
04021
04022
04023 if ( Fake_entry_bb() != NULL ) {
04024 BB_NODE_SET instack(Total_bb_count(), this, Loc_pool(), BBNS_EMPTY);
04025 Find_no_exit_blocks( Fake_entry_bb(), &instack );
04026 }
04027 }
04028
04029
04030
04031
04032
04033
04034 void
04035 CFG::Find_exit_blocks( void )
04036 {
04037 CFG_ITER cfg_iter;
04038 BB_NODE *bb;
04039
04040
04041 _exit_vec.Bzero_array();
04042 _exit_vec.Resetidx();
04043
04044
04045
04046 if ( Fake_exit_bb() != NULL )
04047 Fake_exit_bb()->Set_pred( NULL );
04048
04049
04050
04051
04052
04053 FOR_ALL_ELEM ( bb, cfg_iter, Init(this) ) {
04054
04055 if (bb == Fake_exit_bb() || bb == Fake_entry_bb())
04056 continue;
04057
04058 if (bb->Kind() == BB_REGIONEXIT) {
04059
04060 Is_True(bb->Regioninfo() != NULL && bb->Regioninfo()->Rid() != NULL,
04061 ("CFG::Find_exit_blocks, Region info missing from region exit"));
04062
04063 if (!RID_TYPE_mp(bb->Regioninfo()->Rid())) {
04064
04065
04066 if (_entry_bb->Kind() == BB_REGIONSTART) {
04067 Is_True(_entry_bb->Regioninfo(),
04068 ("CFG::Find_exit_block, entry is not region start"));
04069
04070
04071
04072
04073
04074 INT32 label_number;
04075 if (bb->Laststmt()) {
04076 Is_True(WN_opcode(bb->Laststmt()) == OPC_REGION_EXIT,
04077 ("CFG::Find_exit_block, region exit not found (1)"));
04078 label_number = WN_label_number(bb->Laststmt());
04079 } else if (bb->Last_stmtrep()) {
04080 Is_True(bb->Last_stmtrep()->Op() == OPC_REGION_EXIT,
04081 ("CFG::Find_exit_block, region exit not found (2)"));
04082 label_number = bb->Last_stmtrep()->Label_number();
04083 } else
04084 Is_True(FALSE,
04085 ("CFG::Find_exit_block, region exit not found (3)"));
04086
04087 if (REGION_scan_exits(_entry_bb->Regioninfo()->Region_exit_list(),
04088 label_number)) {
04089 Add_earlyexit( bb );
04090 }
04091 } else {
04092
04093
04094 }
04095 }
04096 } else if (bb->Kind() == BB_EXIT) {
04097 Add_earlyexit( bb );
04098 } else {
04099
04100
04101 if (bb->Succ() == NULL ||
04102 (bb->Succ() != NULL && bb->Succ()->Len() == 0)) {
04103 Add_earlyexit( bb );
04104 }
04105 }
04106
04107 }
04108 }
04109
04110
04111
04112
04113
04114
04115
04116
04117 void
04118 CFG::Remove_fake_entryexit_arcs( void )
04119 {
04120 if ( Fake_entry_bb() != NULL ) {
04121 BB_NODE *succ;
04122 BB_LIST_ITER bb_succ_iter;
04123 FOR_ALL_ELEM( succ, bb_succ_iter, Init(Fake_entry_bb()->Succ()) ) {
04124 succ->Remove_pred( Fake_entry_bb(), Mem_pool() );
04125 }
04126 }
04127 if ( Fake_exit_bb() != NULL ) {
04128 BB_NODE *pred;
04129 BB_LIST_ITER bb_pred_iter;
04130 FOR_ALL_ELEM( pred, bb_pred_iter, Init(Fake_exit_bb()->Pred()) ) {
04131 pred->Remove_succ( Fake_exit_bb(), Mem_pool() );
04132 }
04133 }
04134 }
04135
04136
04137
04138
04139
04140
04141
04142 BB_NODE*
04143 CFG::Func_entry_bb(void) const
04144 {
04145 CFG_ITER cfg_iter( this );
04146 BB_NODE *bb;
04147 FOR_ALL_NODE( bb, cfg_iter, Init() ) {
04148 if (bb->Kind() == BB_ENTRY && bb->Entrywn() &&
04149 WN_opcode(bb->Entrywn()) == OPC_FUNC_ENTRY )
04150 return bb;
04151 if (bb->Kind() == BB_REGIONSTART) {
04152 Is_True(bb->Regioninfo() != NULL,
04153 ("CFG::Func_entry_bb, NULL regioninfo"));
04154 return bb;
04155 }
04156 }
04157 return NULL;
04158 }
04159
04160
04161
04162
04163
04164
04165
04166
04167
04168
04169 BB_NODE*
04170 CFG::Split_bb_with_wns( BB_NODE *oldbb, WN *after_wn )
04171 {
04172 BB_NODE *newbb = CXX_NEW(BB_NODE(*oldbb),Mem_pool());
04173
04174 newbb->Set_id(Alloc_bb_id());
04175 _bb_vec[newbb->Id()] = newbb;
04176 newbb->Set_labnam(0);
04177
04178
04179
04180 oldbb->Insert_After(newbb);
04181 if ( oldbb == _last_bb )
04182 _last_bb = newbb;
04183
04184
04185
04186
04187
04188 newbb->Set_pred(NULL);
04189 newbb->Set_succ(NULL);
04190
04191
04192 BB_NODE *succ;
04193 BB_LIST_ITER bb_iter;
04194 FOR_ALL_ELEM( succ, bb_iter, Init(oldbb->Succ())) {
04195 Connect_predsucc(newbb, succ);
04196 }
04197
04198 FOR_ALL_ELEM( succ, bb_iter, Init(newbb->Succ())) {
04199 DisConnect_predsucc(oldbb, succ);
04200 }
04201
04202
04203 Connect_predsucc(oldbb, newbb);
04204
04205 Is_True(oldbb->Kind() != BB_REGIONEXIT,
04206 ("CFG::Split_bb_with_wns, Splitting a REGION exit requires more code"));
04207 oldbb->Set_kind( BB_GOTO );
04208
04209
04210 newbb->Set_firststmt( WN_next(after_wn) );
04211 if ( WN_next(after_wn) )
04212 WN_prev(WN_next(after_wn)) = NULL;
04213 oldbb->Set_laststmt( after_wn );
04214 WN_next(after_wn) = NULL;
04215
04216 return newbb;
04217 }
04218
04219
04220
04221
04222
04223
04224
04225
04226
04227 static void
04228 get_pred_first_vec( BB_NODE *bb, BB_NODE *bbvec[], INT32 *numbbs )
04229 {
04230 BB_NODE *pred;
04231 BB_LIST_ITER bb_pred_iter;
04232
04233 bb->Set_dforder();
04234
04235 FOR_ALL_ELEM( pred, bb_pred_iter, Init(bb->Pred()) ) {
04236 if ( ! pred->Dforder() ) {
04237 get_pred_first_vec( pred, bbvec, numbbs );
04238 }
04239 }
04240
04241 bbvec[*numbbs] = bb;
04242 (*numbbs)++;
04243 }
04244
04245 void
04246 CFG::Get_pred_first_vec( BB_NODE *bbvec[], INT32 *numbbs )
04247 {
04248 BB_NODE *bb;
04249 CFG_ITER cfg_iter(this);
04250
04251
04252 FOR_ALL_NODE( bb, cfg_iter, Init() )
04253 bb->Reset_dforder();
04254
04255 *numbbs = 0;
04256 get_pred_first_vec( Exit_bb(), bbvec, numbbs );
04257 }
04258
04259
04260
04261
04262
04263
04264
04265 void
04266 CFG::Fill_DFS_vec( BB_NODE *bb )
04267 {
04268 bb->Set_dforder();
04269
04270 if (bb != _fake_entry_bb && bb != _fake_exit_bb) {
04271 _dfs_vec[_dfs_vec_sz] = bb;
04272 (_dfs_vec_sz)++;
04273 }
04274
04275 BB_NODE *succ;
04276 BB_LIST_ITER bb_succ_iter;
04277 FOR_ALL_ELEM( succ, bb_succ_iter, Init(bb->Succ()) ) {
04278 if ( ! succ->Dforder() ) {
04279 Fill_DFS_vec( succ );
04280 }
04281 }
04282
04283 if (bb != _fake_entry_bb && bb != _fake_exit_bb) {
04284 _po_vec[_po_vec_sz] = bb;
04285 (_po_vec_sz)++;
04286 }
04287 }
04288
04289 BB_NODE **
04290 CFG::Dfs_vec(void)
04291 {
04292 if (_dfs_vec == NULL) {
04293
04294 if (_po_vec != NULL) {
04295 CXX_DELETE_ARRAY(_po_vec, Mem_pool());
04296 _po_vec = NULL;
04297 }
04298
04299 _dfs_vec = (BB_NODE **)
04300 CXX_NEW_ARRAY(BB_NODE*,Last_bb_id()+1,Mem_pool());
04301 _po_vec = (BB_NODE **)
04302 CXX_NEW_ARRAY(BB_NODE*,Last_bb_id()+1,Mem_pool());
04303
04304 BB_NODE *bb;
04305 CFG_ITER cfg_iter(this);
04306 FOR_ALL_NODE( bb, cfg_iter, Init() )
04307 bb->Reset_dforder();
04308
04309 _dfs_vec_sz = 0;
04310 _po_vec_sz = 0;
04311 Fill_DFS_vec( Entry_bb() );
04312
04313 RPOBB_ITER rpo_iter(this);
04314 INT32 rpo_id = 1;
04315 FOR_ALL_ELEM( bb, rpo_iter, Init() )
04316 bb->Set_rpo_id(rpo_id++);
04317 }
04318 return _dfs_vec;
04319 }
04320
04321 BB_NODE **
04322 CFG::Po_vec(void)
04323 {
04324 if (_po_vec == NULL)
04325 {
04326 if (_dfs_vec != NULL)
04327 {
04328 CXX_DELETE_ARRAY(_dfs_vec, Mem_pool());
04329 _dfs_vec = NULL;
04330 }
04331 (void)Dfs_vec();
04332 }
04333 return _po_vec;
04334 }
04335
04336
04337
04338
04339
04340
04341 void
04342 CFG::Init_dpo_vec(BB_NODE *bb, INT *id)
04343 {
04344 Is_True(bb->Dom_dfs_id() == *id,
04345 ("CFG::Init_dpo_vec: bb->Dom_dfs_id() = %u, *id = %u",
04346 bb->Dom_dfs_id(), *id));
04347
04348 _dpo_vec[*id] = bb;
04349 ++(*id);
04350
04351 BB_NODE *dom_bb;
04352 BB_LIST_ITER dom_bb_iter;
04353 FOR_ALL_ELEM ( dom_bb, dom_bb_iter, Init(bb->Dom_bbs()) )
04354 Init_dpo_vec( dom_bb, id );
04355 }
04356
04357 void
04358 CFG::Init_pdo_vec(BB_NODE *bb, INT *id)
04359 {
04360 Is_True(bb->Pdom_dfs_id() == *id,
04361 ("CFG::Init_pdo_vec: bb->Pdom_dfs_id() = %u, *id = %u",
04362 bb->Pdom_dfs_id(), *id));
04363
04364 _pdo_vec[*id] = bb;
04365 ++(*id);
04366
04367 BB_NODE *dom_bb;
04368 BB_LIST_ITER dom_bb_iter;
04369 FOR_ALL_ELEM ( dom_bb, dom_bb_iter, Init(bb->Pdom_bbs()) )
04370 Init_pdo_vec( dom_bb, id );
04371 }
04372
04373
04374
04375
04376
04377
04378 BB_NODE **
04379 CFG::Dpo_vec(void)
04380 {
04381 if (_dpo_vec == NULL) {
04382 _dpo_vec = (BB_NODE **) CXX_NEW_ARRAY(BB_NODE*, Last_bb_id(), Mem_pool());
04383 INT id = 0;
04384 Init_dpo_vec(Entry_bb(), &id);
04385 _dpo_vec_sz = id;
04386 }
04387 return _dpo_vec;
04388 }
04389
04390 BB_NODE **
04391 CFG::Pdo_vec(void)
04392 {
04393 if (_pdo_vec == NULL) {
04394 _pdo_vec = (BB_NODE **) CXX_NEW_ARRAY(BB_NODE*, Last_bb_id(), Mem_pool());
04395 INT id = 0;
04396 Init_pdo_vec(Exit_bb(), &id);
04397 _pdo_vec_sz = id;
04398 }
04399 return _pdo_vec;
04400 }
04401
04402
04403
04404
04405
04406
04407 static void
04408 invalidate_loops( BB_LOOP *loop )
04409 {
04410 BB_LOOP_CONTAINER loop_con(loop);
04411 BB_LOOP *head;
04412 while ( (head = loop_con.Remove_Headnode()) != NULL ) {
04413
04414 if ( head->Child() != NULL ) {
04415 invalidate_loops( head->Child() );
04416 head->Set_child(NULL);
04417 }
04418 head->Set_parent(NULL);
04419 if ( head->Body_set() != NULL )
04420 head->Body_set()->ClearD();
04421 if ( head->True_body_set() != NULL )
04422 head->True_body_set()->ClearD();
04423 head->Set_size_estimate(0);
04424 }
04425 }
04426
04427 void
04428 CFG::Invalidate_loops(void)
04429 {
04430 if ( Loops_valid() && Loops() ) {
04431 invalidate_loops(Loops());
04432 _loops = NULL;
04433 }
04434 Set_loops_valid(FALSE);
04435 }
04436
04437
04438
04439
04440
04441
04442
04443
04444 BB_LOOP *
04445 CFG::Ident_loop( BB_NODE *first_bb, BB_NODE *last_bb,
04446 INT32 loopnest, BB_LOOP *cur_loop)
04447 {
04448
04449 BB_NODE *bb = first_bb;
04450 BB_NODE_SET *body_set = (cur_loop) ? cur_loop->Body_set() : NULL;
04451 BB_LOOP *sibling = NULL;
04452 BB_LOOP *nest_loop;
04453
04454 while (bb != NULL) {
04455
04456 bb->Set_loopdepth(loopnest);
04457 if (body_set) body_set->Union1D(bb);
04458 bb->Set_innermost(cur_loop);
04459 switch (bb->Kind()) {
04460 case BB_DOEND:
04461 case BB_WHILEEND:
04462 case BB_REPEATBODY:
04463 {
04464 bb->Loop()->Set_header(bb);
04465 BB_NODE_SET *new_body_set =
04466 CXX_NEW(BB_NODE_SET(_last_bb_id, this, Mem_pool(), BBNS_EMPTY),
04467 Mem_pool());
04468
04469
04470 new_body_set->Union1D(bb);
04471 bb->Set_loopbodyset(new_body_set);
04472 nest_loop = bb->Loop();
04473 nest_loop->Set_parent(cur_loop);
04474
04475 if (sibling) sibling->Append(nest_loop);
04476 else {
04477 sibling = nest_loop;
04478 if (cur_loop)
04479 cur_loop->Set_child(sibling);
04480 }
04481
04482 Is_Trace(Trace(),(TFile, "new loop formed at BB%d (inside loop at %d)\n",
04483 bb->Id(), cur_loop ? cur_loop->End()->Id() : 0));
04484
04485
04486
04487
04488
04489 bb->Set_loopdepth(loopnest+1);
04490 bb->Set_innermost(nest_loop);
04491
04492 if (bb->Kind() == BB_DOEND) {
04493
04494 Ident_loop(bb->Next(), bb->Loopstep(), loopnest+1, nest_loop);
04495 if (body_set) body_set->UnionD(new_body_set);
04496 bb = bb->Loopmerge();
04497 }
04498 else if (bb->Kind() == BB_WHILEEND) {
04499 Ident_loop(bb->Next(), bb->Loopmerge()->Prev(), loopnest+1, nest_loop);
04500 if (body_set) body_set->UnionD(new_body_set);
04501 if (bb->Loopmerge()->Prev() == last_bb) return sibling;
04502 bb = bb->Loopmerge();
04503 }
04504 else {
04505 Ident_loop(bb->Next(), bb->Loopend(), loopnest+1, nest_loop);
04506 if (body_set) body_set->UnionD(new_body_set);
04507 if (bb->Loopend() == last_bb) return sibling;
04508 bb = bb->Loopmerge();
04509 }
04510 }
04511 break;
04512 case BB_REGIONEXIT:
04513 case BB_REGIONSTART:
04514 Is_True(bb->Regioninfo() != NULL,
04515 ("CFG:Ident_mp_regions, NULL regioninfo"));
04516
04517 case BB_GOTO:
04518 case BB_IO:
04519 case BB_LOGIF:
04520 case BB_VARGOTO:
04521 case BB_ENTRY:
04522 case BB_EXIT:
04523 case BB_DOSTART:
04524 case BB_DOSTEP:
04525 case BB_REPEATEND:
04526 if (bb == last_bb) return sibling;
04527 bb = bb->Next();
04528 break;
04529 default:
04530 FmtAssert(FALSE, ("CFG::Ident_loop: Illegal BB_KIND "));
04531 break;
04532 }
04533 }
04534 return sibling;
04535 }
04536
04537 void
04538 CFG::Set_loop_bb_set(BB_LOOP *loop)
04539 {
04540 if (_bb_set == NULL)
04541 _bb_set = CXX_NEW(BB_NODE_SET(_last_bb_id, this, Mem_pool(), BBNS_EMPTY),
04542 Mem_pool());
04543
04544 _bb_set->CopyD(loop->Body_set());
04545
04546 BB_LOOP_CONST_ITER loop_iter(loop->Child());
04547 const BB_LOOP *nest_loop;
04548 FOR_ALL_NODE(nest_loop, loop_iter, Init()) {
04549 _bb_set->DifferenceD(nest_loop->Body_set());
04550 }
04551 }
04552
04553 BOOL
04554 CFG::Loop_itself_is_empty(BB_LOOP *loop)
04555 {
04556 if (loop->Child() == NULL) return FALSE;
04557
04558 if (loop->End()->Kind() == BB_LOGIF) return TRUE;
04559 Set_loop_bb_set(loop);
04560 return _bb_set->EmptyP();
04561 }
04562
04563 BB_LOOP*
04564 CFG::Get_last_loop(BB_LOOP *loop)
04565 {
04566 BB_LOOP_ITER loop_iter(loop);
04567 BB_LOOP *nest_loop;
04568 BB_LOOP *last_loop = NULL;
04569 FOR_ALL_NODE(nest_loop, loop_iter, Init())
04570 last_loop = nest_loop;
04571 return last_loop;
04572 }
04573
04574
04575
04576
04577
04578
04579
04580
04581 BOOL
04582 CFG::Check_if_it_can_reach_body_first_bb(BB_NODE *bb, BB_LOOP *loop)
04583 {
04584 if (bb->TLBS_processing())
04585 return FALSE;
04586 bb->Set_TLBS_processing();
04587
04588 BB_LIST_ITER bb_succ_iter;
04589 BB_NODE *succ;
04590 BOOL can_reach_body_first_bb = FALSE;
04591 FOR_ALL_ELEM(succ, bb_succ_iter, Init(bb->Succ())) {
04592 if (loop->True_body_set()->MemberP(succ)) {
04593 can_reach_body_first_bb = TRUE;
04594 break;
04595 }
04596 if (! _non_true_body_set->MemberP(succ)) {
04597 if (Check_if_it_can_reach_body_first_bb(succ, loop)) {
04598 can_reach_body_first_bb = TRUE;
04599 break;
04600 }
04601 }
04602 }
04603 bb->Reset_TLBS_processing();
04604 if (can_reach_body_first_bb) {
04605 loop->True_body_set()->Union1D(bb);
04606 loop->Incr_size_estimate(bb->Code_size_est());
04607 if (Trace())
04608 fprintf(TFile, "adding bb%d\n", bb->Id());
04609 return TRUE;
04610 }
04611 else {
04612 _non_true_body_set->Union1D(bb);
04613 if (Trace())
04614 fprintf(TFile, "disqualifying bb%d\n", bb->Id());
04615 return FALSE;
04616 }
04617 }
04618
04619
04620
04621
04622
04623
04624
04625
04626
04627
04628
04629
04630 void
04631 CFG::Compute_true_loop_body_set(BB_LOOP *loops)
04632 {
04633 if (loops == NULL) return;
04634
04635 BB_NODE *bb;
04636 BB_NODE_SET_ITER bb_iter;
04637 BB_LOOP *loop;
04638 BB_LOOP_ITER loop_iter(loops);
04639 FOR_ALL_NODE(loop, loop_iter, Init()) {
04640
04641 Compute_true_loop_body_set(loop->Child());
04642
04643 if (loop->True_body_set() == NULL)
04644 loop->Set_true_body_set(
04645 CXX_NEW(BB_NODE_SET(_last_bb_id, this, Mem_pool(), BBNS_EMPTY),
04646 Mem_pool()));
04647 else loop->True_body_set()->ClearD();
04648 loop->True_body_set()->Union1D(loop->Body());
04649 loop->Set_size_estimate(loop->Body()->Code_size_est());
04650 {
04651 BB_LOOP *nested_loop;
04652 BB_LOOP_ITER nested_loop_iter(loop->Child());
04653 FOR_ALL_NODE(nested_loop, nested_loop_iter, Init()) {
04654 loop->True_body_set()->UnionD(nested_loop->True_body_set());
04655 loop->Incr_size_estimate(nested_loop->Size_estimate());
04656 }
04657 }
04658
04659 _non_true_body_set->UniverseD(_last_bb_id);
04660 _non_true_body_set->DifferenceD(loop->Body_set());
04661 if (Trace()) {
04662 fprintf(TFile, "Determining true loop body set from body set: ");
04663 loop->Body_set()->Print(TFile);
04664 fprintf(TFile, "\nInitial true loop body set: ");
04665 loop->True_body_set()->Print(TFile);
04666 fprintf(TFile, "\nInitial non-true loop body set: ");
04667 _non_true_body_set->Print(TFile);
04668 fprintf(TFile, "\n");
04669 }
04670
04671 FOR_ALL_ELEM(bb, bb_iter, Init(loop->Body_set())) {
04672 if (loop->True_body_set()->MemberP(bb))
04673 continue;
04674 if (_non_true_body_set->MemberP(bb))
04675 continue;
04676 Check_if_it_can_reach_body_first_bb(bb, loop);
04677 }
04678 }
04679 }
04680
04681
04682
04683
04684
04685
04686
04687
04688
04689
04690
04691
04692
04693
04694
04695
04696
04697
04698
04699
04700
04701
04702
04703
04704
04705
04706
04707
04708
04709
04710
04711
04712
04713
04714
04715
04716
04717
04718
04719
04720 void Update_loops_for_mainopt(BB_LOOP *loop)
04721 {
04722
04723
04724 loop->Set_loopback(NULL);
04725 loop->Set_preheader(NULL);
04726 loop->Set_tail(NULL);
04727 loop->Reset_well_formed();
04728
04729 loop->Set_test_at_entry(false);
04730 loop->Set_test_at_exit(false);
04731 loop->Set_exit_early(true);
04732
04733 BB_LIST_ITER bb_pred_iter;
04734 BB_NODE *pred;
04735 INT count = 0;
04736 FOR_ALL_ELEM( pred, bb_pred_iter, Init(loop->Header()->Pred()) ) {
04737 if (Is_backedge(pred, loop->Header())) {
04738 loop->Set_loopback(pred);
04739 loop->Set_loopback_pred_num(count);
04740 } else {
04741 loop->Set_preheader(pred);
04742 loop->Set_preheader_pred_num(count);
04743 }
04744 count++;
04745 }
04746 loop->Set_header_pred_count(count);
04747 if (count != 2 ||
04748 loop->Loopback() == NULL ||
04749 loop->Preheader() == NULL ||
04750 loop->Preheader()->Succ()->Len() != 1) {
04751 loop->Set_loopback(NULL);
04752 loop->Set_preheader(NULL);
04753 return;
04754 }
04755
04756
04757
04758
04759 loop->Set_well_formed();
04760
04761 if (loop->Loopback()->Succ()->Len() == 2) {
04762 loop->Set_test_at_entry(false);
04763 loop->Set_test_at_exit(true);
04764 BB_LIST_ITER bb_succ_iter;
04765 BB_NODE *succ;
04766 FOR_ALL_ELEM(succ, bb_succ_iter, Init(loop->Loopback()->Succ())) {
04767 if (succ != loop->Header()) {
04768 loop->Set_tail(succ);
04769 break;
04770 }
04771 }
04772 } else if (loop->Header()->Succ()->Len() == 2) {
04773 loop->Set_test_at_entry(true);
04774 loop->Set_test_at_exit(false);
04775 BB_LIST_ITER bb_succ_iter;
04776 BB_NODE *succ;
04777 FOR_ALL_ELEM(succ, bb_succ_iter, Init(loop->Header()->Succ())) {
04778 if (succ != loop->Header()) {
04779 loop->Set_tail(succ);
04780 break;
04781 }
04782 }
04783 }
04784
04785 loop->Set_exit_early(loop->Tail() == NULL ||
04786 loop->Tail()->Pred()->Len() != 1 ||
04787 ! loop->Tail()->Postdominates_strictly(loop->Header()));
04788 }
04789
04790
04791
04792
04793
04794 void Update_loops_for_preopt(BB_LOOP *loop)
04795 {
04796 Update_loops_for_mainopt(loop);
04797
04798
04799
04800 if (loop->Body() == loop->End()) {
04801 loop->Set_test_at_entry(false);
04802 loop->Set_test_at_exit(true);
04803 } else {
04804 loop->Set_test_at_entry(loop->Header() == loop->End());
04805 loop->Set_test_at_exit(loop->Header() != loop->End());
04806 }
04807 loop->Set_exit_early(loop->Dotail()->Pred()->Len() != 1 ||
04808 ! loop->Dotail()->Postdominates_strictly(loop->Body()));
04809 }
04810
04811
04812
04813 static bool
04814 BB_is_header(BB_NODE *bb)
04815 {
04816 BB_NODE *pred;
04817 BB_LIST_ITER bb_pred_iter;
04818 FOR_ALL_ELEM( pred, bb_pred_iter, Init(bb->Pred()) ) {
04819 if (Is_backedge(pred, bb)) {
04820 return true;
04821 }
04822 }
04823 return false;
04824 }
04825
04826
04827
04828
04829
04830
04831 static void
04832 Collect_loop_body(BB_LOOP *loop, BB_NODE *bb)
04833 {
04834 Is_True( loop->Header()->Dominates(bb),
04835 ("Loop header %d does not dominate body BB%d.",
04836 loop->Header()->Id(), bb->Id()) );
04837
04838 Is_True(!loop->True_body_set()->MemberP(bb),
04839 ("BB %d already visited.", bb->Id()));
04840
04841 loop->True_body_set()->Union1D(bb);
04842 loop->Incr_size_estimate(bb->Code_size_est());
04843
04844
04845 if (bb->Innermost() == NULL)
04846 bb->Set_innermost(loop);
04847
04848 if (bb == loop->Header()) return;
04849
04850 BB_LIST_ITER bb_pred_iter;
04851 BB_NODE *pred;
04852 FOR_ALL_ELEM( pred, bb_pred_iter, Init(bb->Pred()) ) {
04853 if (loop->True_body_set()->MemberP(pred))
04854 continue;
04855
04856 BB_LOOP *inner = pred->Innermost();
04857 Is_True(inner != loop, ("wrong pred->Innermost()."));
04858 if (inner) {
04859 Is_True(!inner->True_body_set()->EmptyP(),
04860 ("inner loop true body set not computed."));
04861 loop->True_body_set()->UnionD(inner->True_body_set());
04862 loop->Incr_size_estimate(inner->Size_estimate());
04863 if (inner->Well_formed()) {
04864 if (!loop->True_body_set()->MemberP(inner->Preheader()))
04865 Collect_loop_body(loop, inner->Preheader());
04866 } else {
04867 BB_LIST_ITER bb_pred_iter;
04868 BB_NODE *pred;
04869 FOR_ALL_ELEM( pred, bb_pred_iter, Init(inner->Header()->Pred()) ) {
04870 if ( ! Is_backedge(pred, inner->Header())
04871 && ! loop->True_body_set()->MemberP(pred) )
04872 Collect_loop_body(loop, pred);
04873 }
04874 }
04875 } else
04876 Collect_loop_body(loop, pred);
04877 }
04878 }
04879
04880
04881 static BB_LOOP *
04882 Allocate_loop(BB_NODE *bb, BB_LOOP *parent, CFG *cfg)
04883 {
04884 BB_LOOP *loop = bb->Loop();
04885 if (loop == NULL)
04886 loop = CXX_NEW( BB_LOOP(NULL, NULL, NULL, NULL, NULL, NULL),
04887 cfg->Mem_pool() );
04888 loop->Set_true_body_set(CXX_NEW(BB_NODE_SET(cfg->Last_bb_id(), cfg,
04889 cfg->Mem_pool(), BBNS_EMPTY),
04890 cfg->Mem_pool()));
04891 loop->Set_body_set(NULL);
04892 loop->Set_header(bb);
04893 loop->Set_child(NULL);
04894 loop->Set_parent(NULL);
04895 loop->Set_depth(0);
04896 loop->Set_max_depth(0);
04897 Update_loops_for_mainopt(loop);
04898 return loop;
04899 }
04900
04901
04902
04903
04904
04905
04906 void Find_real_loops(BB_NODE *bb, BB_LOOP *parent, CFG *cfg)
04907 {
04908 bb->Set_innermost(NULL);
04909
04910 BB_LOOP *cur = parent;
04911 bool is_header = BB_is_header(bb);
04912 if (is_header) {
04913 cur = Allocate_loop(bb, parent, cfg);
04914 bb->Set_loop(cur);
04915 } else
04916 bb->Set_loop(NULL);
04917
04918 BB_NODE *dom_bb;
04919 BB_LIST_ITER dom_bb_iter;
04920 if (is_header) {
04921 FOR_ALL_ELEM (dom_bb, dom_bb_iter, Init(bb->Dom_bbs())) {
04922 Find_real_loops(dom_bb, cur, cfg);
04923 }
04924 if (cur->Well_formed())
04925 Collect_loop_body(cur, cur->Loopback());
04926 else {
04927 BB_LIST_ITER bb_pred_iter;
04928 BB_NODE *pred;
04929 FOR_ALL_ELEM( pred, bb_pred_iter, Init(cur->Header()->Pred()) ) {
04930 if ( Is_backedge(pred, cur->Header())
04931 && ! cur->True_body_set()->MemberP(pred) )
04932 Collect_loop_body(cur, pred);
04933 }
04934 }
04935 } else {
04936 FOR_ALL_ELEM (dom_bb, dom_bb_iter, Init(bb->Dom_bbs())) {
04937 Find_real_loops(dom_bb, parent, cfg);
04938 }
04939 }
04940 }
04941
04942
04943 static void
04944 Fix_SCF_for_mainopt(CFG *cfg)
04945 {
04946
04947
04948 BB_NODE *bb;
04949 for (bb = cfg->First_bb(); bb != NULL; bb = bb->Next()) {
04950 BB_LOOP *loop = bb->Loop();
04951 if (loop != NULL && loop->Header() == bb) {
04952 if (loop->End() != NULL) {
04953 loop->Start()->Set_loop(loop);
04954 loop->End()->Set_loop(loop);
04955 loop->Body()->Set_loop(loop);
04956 if (loop->Step())
04957 loop->Step()->Set_loop(loop);
04958
04959
04960
04961
04962 }
04963 }
04964 }
04965
04966
04967 for (bb = cfg->First_bb(); bb != NULL; bb = bb->Next()) {
04968 BB_LOOP *loop = bb->Loop();
04969 if (loop == NULL || !loop->Well_formed()) {
04970 switch (bb->Kind()) {
04971 case BB_DOSTART:
04972 case BB_DOHEAD:
04973 case BB_DOSTEP:
04974 case BB_DOTAIL:
04975 case BB_REPEATBODY:
04976 bb->Set_kind(BB_GOTO);
04977 break;
04978 case BB_DOEND:
04979 case BB_REPEATEND:
04980 case BB_WHILEEND:
04981 bb->Set_kind(BB_LOGIF);
04982 }
04983 }
04984 }
04985 }
04986
04987 static INT
04988 Compute_loop_depth_rec(BB_LOOP *loop, INT depth)
04989 {
04990 INT max_depth = depth;
04991 if (loop->Child()) {
04992 BB_LOOP_ITER loop_iter(loop->Child());
04993 BB_LOOP *child;
04994 FOR_ALL_NODE(child, loop_iter, Init()) {
04995 INT child_depth = Compute_loop_depth_rec(child, depth+1);
04996 max_depth = MAX(max_depth, child_depth);
04997 }
04998 }
04999 loop->Set_depth(depth);
05000 loop->Set_max_depth(max_depth);
05001 return max_depth;
05002 }
05003
05004 static void
05005 Compute_loop_depth(CFG *cfg)
05006 {
05007
05008
05009 BB_NODE *bb;
05010 for (bb = cfg->First_bb(); bb != NULL; bb = bb->Next()) {
05011 BB_LOOP *loop = bb->Loop();
05012 if (loop != NULL && loop->Header() == bb) {
05013 BB_NODE *dom = bb->Idom();
05014 while (dom != NULL) {
05015 if (dom->Loop() &&
05016 dom->Loop()->Header() == dom &&
05017 dom->Loop()->True_body_set()->MemberP(bb))
05018 break;
05019 dom = dom->Idom();
05020 }
05021 BB_LOOP *parent = dom ? dom->Loop() : NULL;
05022 loop->Set_parent(parent);
05023 if (parent) {
05024 if (parent->Child())
05025 parent->Child()->Append(loop);
05026 else
05027 parent->Set_child(loop);
05028 } else {
05029 if (cfg->Loops())
05030 cfg->Loops()->Append(loop);
05031 else
05032 cfg->Set_loops(loop);
05033 }
05034 }
05035 }
05036
05037
05038 if (cfg->Loops()) {
05039 BB_LOOP_ITER loop_iter(cfg->Loops());
05040 BB_LOOP *child;
05041 FOR_ALL_NODE(child, loop_iter, Init()) {
05042 Compute_loop_depth_rec(child, 1);
05043 }
05044 }
05045
05046
05047 for (bb = cfg->First_bb(); bb != NULL; bb = bb->Next()) {
05048 bb->Set_loopdepth( bb->Innermost() ? bb->Innermost()->Depth() : 0);
05049 }
05050 }
05051
05052
05053 #ifdef Is_True_On
05054 static void
05055 verify_loops(CFG *cfg)
05056 {
05057 for (BB_NODE *bb = cfg->First_bb(); bb != NULL; bb = bb->Next()) {
05058 BB_LOOP *loop = bb->Loop();
05059 if (loop != NULL && loop->Header() == bb) {
05060 if (loop->End() == NULL) {
05061 Is_True(loop->Start() == NULL &&
05062 loop->End() == NULL &&
05063 loop->Body() == NULL &&
05064 loop->Step() == NULL &&
05065 loop->Merge() == NULL,
05066 ("found inconsistent BB_LOOP."));
05067 Is_True(loop->Header() == NULL ||
05068 loop->Header()->Kind() == BB_GOTO ||
05069 loop->Header()->Kind() == BB_LOGIF ||
05070 loop->Header()->Kind() == BB_VARGOTO,
05071 ("found inconsistent BB_LOOP -- header is not BB_GOTO"));
05072 Is_True(loop->Loopback() == NULL ||
05073 loop->Loopback()->Kind() == BB_GOTO ||
05074 loop->Loopback()->Kind() == BB_LOGIF ||
05075 loop->Loopback()->Kind() == BB_VARGOTO||
05076 loop->Loopback()->Kind() == BB_REGIONSTART,
05077 ("found inconsistent BB_LOOP -- loopback is not BB_GOTO"));
05078 } else {
05079 Is_True(loop->Start()->Loop() == loop &&
05080 loop->End()->Loop() == loop &&
05081 loop->Body()->Loop() == loop &&
05082 (loop->Step() == NULL || loop->Step()->Loop() == loop),
05083
05084 ("found inconsistent BB_LOOP and CFG."));
05085 }
05086 }
05087
05088 BB_NODE *dom = bb;
05089 while (dom != NULL) {
05090 if (dom->Loop() &&
05091 dom->Loop()->Header() == dom &&
05092 dom->Loop()->True_body_set()->MemberP(bb))
05093 break;
05094 dom = dom->Idom();
05095 }
05096 Is_True(bb->Innermost() == (dom ? dom->Loop() : NULL),
05097 ("BB%d innermost loop should be %d instead of %d\n",
05098 bb->Id(),
05099 dom ? dom->Id(): 0,
05100 bb->Innermost() ? bb->Innermost()->Header()->Id() : 0));
05101 }
05102 }
05103 #else
05104 #define verify_loops(cfg)
05105 #endif
05106
05107 static void
05108 print_nested_loops_rec(const BB_LOOP *loop, FILE *fp)
05109 {
05110 if (loop->Child()) {
05111 BB_LOOP_CONST_ITER loop_iter(loop->Child());
05112 const BB_LOOP *nest_loop;
05113 FOR_ALL_NODE(nest_loop, loop_iter, Init()) {
05114 nest_loop->Print(fp);
05115 print_nested_loops_rec(nest_loop, fp);
05116 }
05117 }
05118 }
05119
05120 static void
05121 print_nested_loops(CFG *cfg, FILE *fp)
05122 {
05123 if (cfg->Loops()) {
05124 BB_LOOP_CONST_ITER loop_iter(cfg->Loops());
05125 const BB_LOOP *nest_loop;
05126 FOR_ALL_NODE(nest_loop, loop_iter, Init()) {
05127 nest_loop->Print(fp);
05128 print_nested_loops_rec(nest_loop, fp);
05129 }
05130 }
05131 }
05132
05133 static void
05134 print_bb_loopinfo(CFG *cfg, FILE *fp)
05135 {
05136 for (BB_NODE *bb = cfg->First_bb(); bb != NULL; bb = bb->Next()) {
05137 BB_LOOP *loop = bb->Loop();
05138 BB_LOOP *inner = bb->Innermost();
05139 fprintf(fp, "BB%d depth=%d, loop=%d, innermost=%d\n",
05140 bb->Id(),
05141 bb->Loopdepth(),
05142 loop ?
05143 (loop->Header() ? loop->Header()->Id() : loop->Dohead()->Id()) : 0,
05144 inner ? inner->Header()->Id() : 0);
05145 }
05146 }
05147
05148
05149
05150 BB_LOOP*
05151 CFG::Analyze_loops(void)
05152 {
05153 if (Loops_valid()) return Loops();
05154 Is_True(Loops() == NULL,
05155 ("Loops are already updated."));
05156
05157 if (Lower_fully()) {
05158
05159 Find_real_loops(Entry_bb(), NULL, this);
05160 Fix_SCF_for_mainopt(this);
05161 Compute_loop_depth(this);
05162 if (Trace() && Loops()) {
05163 print_nested_loops(this, TFile);
05164 print_bb_loopinfo(this, TFile);
05165 }
05166
05167 verify_loops(this);
05168 } else {
05169
05170 _loops = Ident_loop(First_bb(), Last_bb(), 0, NULL);
05171
05172 if (_non_true_body_set == NULL ||
05173 (bs_PBPB(_non_true_body_set->Alloc_size() - sizeof(BS_WORD)) <
05174 _last_bb_id))
05175 _non_true_body_set = CXX_NEW(BB_NODE_SET(_last_bb_id, this, Mem_pool(),
05176 BBNS_EMPTY), Mem_pool());
05177
05178 Compute_true_loop_body_set(_loops);
05179
05180 for (BB_NODE *bb = First_bb(); bb != NULL; bb = bb->Next()) {
05181 if (bb->Loop() != NULL && bb->Loop()->Header() == bb)
05182 Update_loops_for_preopt(bb->Loop());
05183 }
05184 }
05185 Set_loops_valid(TRUE);
05186 return Loops();
05187 }
05188
05189 const BB_LOOP*
05190 CFG::Find_innermost_loop_contains(BB_NODE *bb)
05191 {
05192 Analyze_loops();
05193 return bb->Innermost();
05194 }
05195
05196
05197
05198
05199
05200
05201 BB_NODE*
05202 CFG::Find_enclosing_region_bb( BB_NODE *bb, WN_PRAGMA_ID region_pragma )
05203 {
05204 for ( BB_NODE *dom = bb->Idom(); dom != NULL; dom = dom->Idom() ) {
05205 if ( dom->Kind() == BB_REGIONSTART ) {
05206
05207 {
05208 WN *wn;
05209 STMT_ITER stmt_iter;
05210 FOR_ALL_ELEM (wn, stmt_iter, Init(dom->Firststmt(), dom->Laststmt())) {
05211 if ( WN_opcode(wn) == OPC_PRAGMA ) {
05212 if ( (WN_PRAGMA_ID)WN_pragma(wn) == region_pragma ) {
05213
05214
05215 BB_REGION *dom_region = dom->Regioninfo();
05216 for ( BB_NODE *region_bb = dom_region->Region_start();
05217 region_bb != NULL;
05218 region_bb = region_bb->Next() )
05219 {
05220 if ( region_bb == bb ) {
05221 return dom;
05222 }
05223 else if ( region_bb == dom_region->Region_end() ) {
05224
05225 break;
05226 }
05227 }
05228 }
05229 }
05230 }
05231 }
05232
05233
05234 {
05235 STMTREP *stmt;
05236 STMTREP_ITER stmt_iter(dom->Stmtlist());
05237 FOR_ALL_NODE(stmt, stmt_iter, Init()) {
05238 if ( stmt->Op() == OPC_PRAGMA ) {
05239 WN *pragma_wn = stmt->Orig_wn();
05240 if ( (WN_PRAGMA_ID)WN_pragma(pragma_wn) == region_pragma ) {
05241
05242
05243 BB_REGION *dom_region = dom->Regioninfo();
05244 for ( BB_NODE *region_bb = dom_region->Region_start();
05245 region_bb != NULL;
05246 region_bb = region_bb->Next() )
05247 {
05248 if ( region_bb == bb ) {
05249 return dom;
05250 }
05251 else if ( region_bb == dom_region->Region_end() ) {
05252
05253 break;
05254 }
05255 }
05256 }
05257 }
05258 }
05259 }
05260 }
05261 }
05262
05263
05264 return NULL;
05265 }
05266
05267
05268
05269
05270
05271 BB_NODE*
05272 CFG::Find_enclosing_parallel_region_bb( BB_NODE *bb)
05273 {
05274 for ( BB_NODE *dom = bb->Idom(); dom != NULL; dom = dom->Idom() ) {
05275
05276
05277
05278
05279 if ( dom->Kind() == BB_REGIONSTART && dom->MP_region() &&
05280 RID_TYPE_mp(dom->Regioninfo()->Rid()) ) {
05281
05282
05283 BB_REGION *dom_region = dom->Regioninfo();
05284 for ( BB_NODE *region_bb = dom_region->Region_start();
05285 region_bb != NULL;
05286 region_bb = region_bb->Next() )
05287 {
05288 if ( region_bb == bb ) {
05289 return dom;
05290 }
05291 else if ( region_bb == dom_region->Region_end() ) {
05292
05293 break;
05294 }
05295 }
05296 }
05297 }
05298
05299 return NULL;
05300 }
05301
05302
05303
05304
05305
05306
05307
05308
05309 BOOL
05310 CFG::Is_outermost_loop_in_parallel_region( BB_LOOP *loop,
05311 WN_PRAGMA_ID pragma_id )
05312 {
05313 Analyze_loops();
05314
05315 BB_NODE *par_region_bb =
05316 Find_enclosing_region_bb( loop->End(), pragma_id );
05317
05318 if ( par_region_bb != NULL ) {
05319
05320
05321 if ( loop->Parent() != NULL ) {
05322 BB_NODE *parent_loop_bb = loop->Parent()->End();
05323
05324 if ( ! par_region_bb->Dominates_strictly( parent_loop_bb ) ) {
05325
05326
05327 return TRUE;
05328 }
05329 }
05330 else {
05331
05332 return TRUE;
05333 }
05334 }
05335
05336 return FALSE;
05337 }
05338
05339
05340
05341
05342
05343
05344 void
05345 CFG::Invalidate_and_update_aux_info(void)
05346 {
05347
05348 Process_multi_entryexit( FALSE );
05349
05350 if (_dfs_vec != NULL) {
05351
05352
05353 CXX_DELETE_ARRAY(_dfs_vec, Mem_pool());
05354 _dfs_vec = NULL;
05355 }
05356
05357 Compute_dom_tree(TRUE);
05358 Compute_dom_tree(FALSE);
05359 Remove_fake_entryexit_arcs();
05360 Compute_dom_frontier();
05361 Compute_control_dependence();
05362
05363
05364 if ( Fake_entry_bb() != NULL )
05365 Fake_entry_bb()->Reset_reached();
05366 if ( Fake_exit_bb() != NULL )
05367 Fake_exit_bb()->Reset_reached();
05368
05369 if (_po_vec != NULL) {
05370 CXX_DELETE_ARRAY(_po_vec, Mem_pool());
05371 _po_vec = NULL;
05372 _po_vec_sz = 0;
05373 }
05374 if (_dfs_vec != NULL) {
05375 CXX_DELETE_ARRAY(_dfs_vec, Mem_pool());
05376 _dfs_vec = NULL;
05377 _dfs_vec_sz = 0;
05378 }
05379 if (_dpo_vec != NULL) {
05380 CXX_DELETE_ARRAY(_dpo_vec, Mem_pool());
05381 _dpo_vec = NULL;
05382 _dpo_vec_sz = 0;
05383 }
05384 if (_pdo_vec != NULL) {
05385 CXX_DELETE_ARRAY(_pdo_vec, Mem_pool());
05386 _pdo_vec = NULL;
05387 _pdo_vec_sz = 0;
05388 }
05389 }
05390
05391 INT
05392 CFG::Remove_critical_edge()
05393 {
05394 INT inserted = 0;
05395 OPT_POOL_Push( Loc_pool(), CFG_DUMP_FLAG );
05396 CFG_ITER cfg_iter(this);
05397 BB_NODE *bb;
05398 FOR_ALL_NODE( bb, cfg_iter, Init() ) {
05399
05400 if ( ! bb->Reached() )
05401 continue;
05402
05403
05404
05405 if (bb->Kind() == BB_GOTO &&
05406 ((bb->Last_stmtrep() && bb->Last_stmtrep()->Op() == OPC_REGION) ||
05407 (bb->Laststmt() && WN_opcode(bb->Laststmt()) == OPC_REGION)))
05408 continue;
05409
05410 if ( (bb->Succ()->Len() > 1 &&
05411 bb->Branch_stmtrep() != NULL &&
05412 bb->Branch_stmtrep()->Opr() != OPR_AGOTO) ||
05413 bb->Kind() == BB_REGIONSTART ) {
05414
05415 BB_LIST_ITER bb_succ_iter;
05416 BB_NODE *succ;
05417 FOR_ALL_ELEM( succ, bb_succ_iter, Init(bb->Succ()) ) {
05418 if ( succ->Pred()->Len() > 1) {
05419 if (!Is_backedge(bb, succ) ||
05420 WOPT_Enable_Backedge_Placement) {
05421
05422 BB_NODE *new_bb = Add_bb_to_edge(bb, succ);
05423 new_bb->Set_phi_list(CXX_NEW(PHI_LIST(new_bb), Mem_pool()));
05424 inserted++;
05425 }
05426 }
05427 }
05428 }
05429 }
05430
05431 if (inserted > 0) {
05432 Invalidate_and_update_aux_info();
05433 Invalidate_loops();
05434 Analyze_loops();
05435 }
05436 OPT_POOL_Pop( Loc_pool(), CFG_DUMP_FLAG );
05437 return inserted;
05438 }
05439
05440
05441
05442 BB_NODE *
05443 CFG::Find_entry_bb(void)
05444 {
05445 BB_NODE *entry_bb = Entry_bb();
05446 if (entry_bb == Fake_entry_bb()) {
05447
05448 BB_NODE *succ;
05449 BB_LIST_ITER bb_succ_iter;
05450 FOR_ALL_ELEM( succ, bb_succ_iter, Init(entry_bb->Succ()) ) {
05451 if ( succ->Kind() == BB_ENTRY && succ->Entrywn() &&
05452 #ifndef KEY
05453 !WN_Label_Is_Handler_Begin(succ->Entrywn())
05454 #else
05455 WN_operator(succ->Entrywn()) != OPR_LABEL
05456 #endif
05457 ) {
05458
05459 if ( WN_opcode(succ->Entrywn()) == OPC_FUNC_ENTRY)
05460 entry_bb = succ;
05461 break;
05462 }
05463 if ( succ->Kind() == BB_REGIONSTART ) {
05464 Is_True(succ->Regioninfo() != NULL,
05465 ("CFG::Find_entry_bb, NULL regioninfo"));
05466 entry_bb = succ;
05467 break;
05468 }
05469 }
05470 Is_True(entry_bb != Fake_entry_bb(),
05471 ("CFG::Find_entry_bb, did not find entry_bb"));
05472 }
05473 return entry_bb;
05474 }
05475
05476
05477 void
05478 MOD_PHI_BB_CONTAINER::Add_entry(BB_NODE *bb,
05479 PHI_LIST *old_lst,
05480 PHI_LIST *new_lst,
05481 MEM_POOL *pool)
05482 {
05483 if (this == NULL) return;
05484
05485 MOD_PHI_BB *tmp;
05486 MOD_PHI_BB_ITER mod_iter(this);
05487 FOR_ALL_NODE(tmp, mod_iter, Init()) {
05488 if (tmp->Bb() == bb) {
05489
05490 Is_True (old_lst == tmp->New_lst(),
05491 ("MOD_PHI_BB_CONTAINER::Add_entry: Not replacement?"));
05492 if (tmp->Old_lst() != old_lst){
05493 PHI_NODE *phi;
05494 PHI_LIST_ITER phi_iter;
05495 FOR_ALL_ELEM ( phi, phi_iter, Init(old_lst) ){
05496 CXX_DELETE_ARRAY(phi->Vec(), pool);
05497 CXX_DELETE(phi, pool);
05498 }
05499 CXX_DELETE(old_lst, pool);
05500 }
05501 tmp->Set_new_lst(new_lst);
05502 return;
05503 }
05504 }
05505
05506 Is_True(tmp == NULL, ("Logic error"));
05507 tmp = CXX_NEW(MOD_PHI_BB(bb, old_lst, new_lst), _mem_pool);
05508 Append(tmp);
05509 }
05510
05511
05512
05513
05514 BOOL
05515 CFG::Verify_tree(WN *wn)
05516 {
05517 if (!WOPT_Enable_Verify)
05518 return TRUE;
05519
05520 OPT_POOL_Push( Loc_pool(), CFG_DUMP_FLAG );
05521 WN_MAP wn_map = WN_MAP_Create( Loc_pool());
05522
05523 BOOL result = Verify_wn(wn, NULL, wn_map);
05524
05525 WN_MAP_Delete(wn_map);
05526 OPT_POOL_Pop( Loc_pool(), CFG_DUMP_FLAG);
05527 return result;
05528 }
05529
05530
05531
05532 BOOL
05533 CFG::Verify_wn(WN *wn, WN *parent, WN_MAP wn_map)
05534 {
05535 if (!WOPT_Enable_Verify)
05536 return TRUE;
05537
05538 INT32 i;
05539 WN *stmt;
05540
05541 if (wn == NULL) return TRUE;
05542
05543 WN *old_parent = (WN *) WN_MAP_Get(wn_map, wn);
05544 if (old_parent && old_parent != parent) {
05545 FmtAssert(FALSE,
05546 ("WHIRL tree 0x%08x is pointed to from 0x%08x and 0x%08x\n",
05547 wn, parent, old_parent));
05548 return FALSE;
05549 }
05550 WN_MAP_Set(wn_map, wn, (void *)parent);
05551
05552 if (WN_opcode(wn) == OPC_BLOCK)
05553 for (stmt = WN_first(wn); stmt != NULL; stmt = WN_next(stmt)) {
05554 if ( ! Verify_wn(stmt, wn, wn_map) )
05555 return FALSE;
05556 }
05557 else
05558 for (i = 0; i < WN_kid_count(wn); i++) {
05559 if ( ! Verify_wn(WN_kid(wn,i), wn, wn_map) )
05560 return FALSE;
05561 }
05562
05563 return TRUE;
05564 }
05565
05566
05567
05568
05569
05570 BOOL
05571 CFG::Verify_cfg(void)
05572 {
05573 if (! WOPT_Enable_Verify)
05574 return TRUE;
05575
05576 WN *wn;
05577 BB_NODE *bb;
05578 CFG_ITER cfg_iter;
05579 STMT_ITER stmt_iter;
05580
05581 OPT_POOL_Push( &MEM_local_pool, CFG_DUMP_FLAG );
05582 WN_MAP wn_map = WN_MAP32_Create(&MEM_local_pool);
05583
05584 FOR_ALL_ELEM (bb, cfg_iter, Init(this)) {
05585 FOR_ALL_ELEM (wn, stmt_iter, Init(bb->Firststmt(), bb->Laststmt())) {
05586 IDTYPE id = WN_MAP32_Get(wn_map, wn);
05587 FmtAssert( id == 0,
05588 ("Shared WN node at BB %d and BB %d\n", id, bb->Id()) );
05589 WN_MAP32_Set(wn_map, wn, bb->Id());
05590 }
05591 }
05592
05593 WN_MAP_Delete(wn_map);
05594 OPT_POOL_Pop(&MEM_local_pool, CFG_DUMP_FLAG);
05595 return TRUE;
05596 }
05597
05598 void
05599 CFG::Print(FILE *fp, BOOL rpo, IDTYPE bb_id)
05600 {
05601
05602
05603
05604 if (!WOPT_Enable_Source_Order && rpo && Entry_bb() != NULL)
05605 {
05606 RPOBB_ITER rpo_iter(this);
05607 BB_NODE *tmp;
05608 FOR_ALL_ELEM(tmp, rpo_iter, Init()) {
05609
05610 if (bb_id == -1 || bb_id == tmp->Id())
05611 tmp->Print(fp);
05612 }
05613 }
05614 else
05615 {
05616 CFG_ITER cfg_iter(this);
05617 BB_NODE *tmp;
05618 FOR_ALL_NODE(tmp, cfg_iter, Init()) {
05619
05620 if (bb_id == -1 || bb_id == tmp->Id())
05621 tmp->Print(fp);
05622 }
05623 }
05624 }
05625
05626 void
05627 dump_cfg (CFG *cfg)
05628 {
05629 cfg->Print(stdout);
05630 }
05631
05632 void CFG::PrintLoopVis(BB_LOOP * loop, int& id)
05633 {
05634 BB_NODE *tmp;
05635 BB_NODE_SET_ITER bb_iter;
05636
05637 fprintf(stdout, "subgraph cluster%d {\n", id);
05638 FOR_ALL_ELEM(tmp, bb_iter, Init(loop->Body_set())) {
05639 fprintf(stdout, "BB%d;\n", tmp->Id());
05640 }
05641
05642 BB_LOOP_ITER loop_iter(loop->Child());
05643 BB_LOOP *child;
05644
05645 id = id + 1;
05646
05647 FOR_ALL_NODE(child, loop_iter, Init()) {
05648 PrintLoopVis(child, id);
05649 }
05650 fprintf(stdout, "};\n");
05651
05652 }
05653
05654 void
05655 CFG::PrintVis(BOOL draw_loops)
05656 {
05657 CFG_ITER cfg_iter(this);
05658 BB_NODE *tmp;
05659
05660
05661 fprintf(stdout, "digraph Cfg {\n");
05662
05663 if (draw_loops) {
05664 BB_LOOP_ITER loop_iter(Loops());
05665 BB_LOOP * loop;
05666 BB_LOOP * tmp_loop;
05667
05668 int loop_num = 0;
05669 FOR_ALL_NODE(loop, loop_iter, Init()) {
05670 PrintLoopVis(loop, loop_num);
05671 }
05672 }
05673
05674 FOR_ALL_NODE(tmp, cfg_iter, Init()) {
05675 tmp->PrintVis();
05676 }
05677 fprintf(stdout, "}\n");
05678
05679 }
05680
05681 void CFG::PrintCDVis(void)
05682 {
05683 CFG_ITER cfg_iter(this);
05684 BB_NODE * bb;
05685 fprintf(stdout, "digraph CD { \n");
05686 FOR_ALL_NODE(bb, cfg_iter, Init()) {
05687 BB_NODE * dep_node;
05688 BB_NODE_SET_ITER rcfg_iter;
05689 fprintf(stdout, "BB%d;\n", bb->Id());
05690 FOR_ALL_ELEM(dep_node, rcfg_iter, Init(bb->Rcfg_dom_frontier())) {
05691 fprintf(stdout, "BB%d -> BB%d;\n", dep_node->Id(), bb->Id());
05692 }
05693 }
05694 fprintf(stdout, "}\n");
05695 }
05696
05697 void
05698 CFG::Validate(FILE *fp)
05699 {
05700 CFG_ITER cfg_iter(this);
05701 BB_NODE *tmp;
05702
05703 FOR_ALL_NODE(tmp, cfg_iter, Init())
05704 tmp->Validate(fp);
05705
05706
05707 for (IDTYPE id = _first_bb_id+1; id <= _last_bb_id; id++) {
05708 if (_bb_vec[id] == NULL)
05709 fprintf(fp, "BB_id:%d assigned but not used\n", id);
05710 else if (_bb_vec[id]->Id() != id)
05711 fprintf(fp, "_bb_vec[%d] points to BB%d", id, _bb_vec[id]->Id());
05712 }
05713 }
05714
05715
05716
05717 void Add_new_auxid_to_entry_chis(AUX_ID new_temp, CFG *cfg, CODEMAP *htable,
05718 OPT_STAB *opt_stab)
05719 {
05720 CODEREP *zcr = htable->Ssa()->Get_zero_version_CR(new_temp, opt_stab, 0);
05721 if (cfg->Fake_entry_bb() != NULL) {
05722 BB_NODE *bb;
05723 BB_LIST_ITER bb_iter;
05724 FOR_ALL_ELEM (bb, bb_iter, Init(cfg->Fake_entry_bb()->Succ())) {
05725 if (bb->Kind() == BB_ENTRY) {
05726 STMTREP *entry_chi = bb->First_stmtrep();
05727 Is_True( OPCODE_operator(entry_chi->Op()) == OPR_OPT_CHI,
05728 ("cannot find entry chi.") );
05729 CHI_LIST *chi_list = entry_chi->Chi_list();
05730 CHI_NODE *cnode = chi_list->New_chi_node(new_temp, htable->Mem_pool());
05731 cnode->Set_OPND(zcr);
05732 cnode->Set_RESULT(zcr);
05733 cnode->Set_live(TRUE);
05734 }
05735 }
05736 } else {
05737 BB_NODE *bb = cfg->Entry_bb();
05738 STMTREP *entry_chi = bb->First_stmtrep();
05739 Is_True( OPCODE_operator(entry_chi->Op()) == OPR_OPT_CHI,
05740 ("cannot find entry chi.") );
05741 CHI_LIST *chi_list = entry_chi->Chi_list();
05742 CHI_NODE *cnode = chi_list->New_chi_node(new_temp, htable->Mem_pool());
05743 cnode->Set_OPND(zcr);
05744 cnode->Set_RESULT(zcr);
05745 cnode->Set_live(TRUE);
05746 }
05747 }
05748
05749
05750 BOOL
05751 CFG::Fall_through(BB_NODE *bb1, BB_NODE *bb2)
05752 {
05753 if (bb1->Next() != bb2) return FALSE;
05754 Is_True(bb2->Prev() == bb1, ("Invalid bb->Pred()"));
05755 STMTREP *bb_branch = bb1->Branch_stmtrep();
05756 if (bb_branch == NULL) return TRUE;
05757 if (OPC_GOTO != bb_branch->Op()) return FALSE;
05758
05759 if (bb1->Succ() == NULL) return FALSE;
05760
05761 if (bb1->Succ()->Node() == bb2) return TRUE;
05762 return FALSE;
05763 }
05764
05765
05766 static BOOL is_delete_bb_candidates(BB_NODE *bb)
05767 {
05768 return (!bb->Regionend() &&
05769 (bb->Kind() == BB_GOTO ||
05770 bb->Kind() == BB_LOGIF ||
05771 bb->Kind() == BB_EXIT));
05772 }
05773
05774
05775
05776
05777 void CFG::Delete_empty_BB()
05778 {
05779
05780
05781
05782 BB_NODE *bb, *bb_next;
05783 for (bb = First_bb(); bb != NULL; bb = bb_next) {
05784 bb_next = bb->Next();
05785 if (bb_next != NULL &&
05786 is_delete_bb_candidates(bb) &&
05787 bb->Is_empty() &&
05788 Fall_through(bb, bb_next) &&
05789 bb_next->Labnam() != 0 &&
05790 bb->Pred()->Len() == 1 &&
05791 is_delete_bb_candidates(bb->Pred()->Node()) &&
05792 bb->Pred()->Node()->Branch_stmtrep() != NULL &&
05793 (bb->Pred()->Node()->Branch_stmtrep()->Op() == OPC_TRUEBR ||
05794 bb->Pred()->Node()->Branch_stmtrep()->Op() == OPC_FALSEBR) &&
05795 bb->Pred()->Node()->Branch_stmtrep()->Label_number() == bb->Labnam()) {
05796
05797 BB_NODE *pred = bb->Pred()->Node();
05798 if (Trace())
05799 fprintf(TFile, "CFG::Remove_empty_bb %d between %d and %d\n", bb->Id(),
05800 pred->Id(), bb_next->Id());
05801 pred->Remove_succ(bb, _mem_pool);
05802 bb->Remove_pred(pred, _mem_pool);
05803 bb->Remove_succ(bb_next, _mem_pool);
05804 bb_next->Remove_pred(bb, _mem_pool);
05805 if (bb_next->Labnam() == 0)
05806 bb_next->Add_label(this);
05807 if (bb_next->Label_stmtrep() == NULL)
05808 bb_next->Add_label_stmtrep(_mem_pool);
05809 pred->Branch_stmtrep()->Set_label_number(bb_next->Labnam());
05810 pred->Append_succ(bb_next, _mem_pool);
05811 bb_next->Append_pred(pred, _mem_pool);
05812
05813 BB_NODE *bb_prev = bb->Prev();
05814 bb->Set_next(NULL);
05815 bb->Set_prev(NULL);
05816 bb_prev->Set_next(bb_next);
05817 bb_next->Set_prev(bb_prev);
05818 }
05819 }
05820
05821
05822
05823
05824 for (bb = First_bb();
05825 bb != NULL ;
05826 bb = bb->Next()) {
05827 if (bb->Branch_stmtrep() != NULL &&
05828 bb->Branch_stmtrep()->Op() == OPC_GOTO &&
05829 bb->Succ()->Len() == 1 &&
05830 bb->Succ()->Node() == bb->Next()) {
05831 if (Trace())
05832 fprintf(TFile, "CFG::Remove branch stmtrep at BB %d\n", bb->Id());
05833 bb->Remove_stmtrep(bb->Branch_stmtrep());
05834 }
05835
05836 if (bb->Label_stmtrep() != NULL &&
05837 ! LABEL_addr_saved( bb->Labnam() ) &&
05838 bb->Pred()->Len() == 1 &&
05839 (bb->Pred()->Node()->Branch_stmtrep() == NULL ||
05840 bb->Pred()->Node()->Branch_stmtrep()->Op() == OPC_GOTO ||
05841 bb->Pred()->Node()->Branch_stmtrep()->Op() == OPC_TRUEBR ||
05842 bb->Pred()->Node()->Branch_stmtrep()->Op() == OPC_FALSEBR) &&
05843 bb->Pred()->Node() == bb->Prev()) {
05844 if (Trace())
05845 fprintf(TFile, "CFG::Remove label stmtrep at BB %d\n", bb->Id());
05846 bb->Remove_label_stmtrep();
05847 }
05848 }
05849 }
05850
05851
05852 void CFG::Clone_bb(IDTYPE src, IDTYPE dst)
05853 {
05854 BB_NODE *srcbb = Get_bb(src);
05855 BB_NODE *destbb = Get_bb(dst);
05856
05857 Is_True( srcbb->Clonable(TRUE),
05858 ("CFG::Clone_bb: BB%d is not clonable.", src) );
05859
05860 destbb->Clear();
05861 destbb->Set_id(dst);
05862 destbb->Set_kind(srcbb->Kind());
05863 destbb->Set_labnam(0);
05864 destbb->Set_phi_list(CXX_NEW(PHI_LIST(destbb), Mem_pool()));
05865 destbb->Set_linenum(srcbb->Linenum());
05866
05867
05868
05869
05870
05871
05872
05873
05874
05875
05876
05877
05878
05879 PHI_NODE *phi;
05880 PHI_LIST_ITER phi_iter;
05881 FOR_ALL_ELEM (phi, phi_iter, Init(srcbb->Phi_list())) {
05882 if (phi->Live()) {
05883 for ( INT pkid = 0; pkid < phi->Size(); pkid++ ) {
05884 if (phi->OPND(pkid)->Is_flag_set(CF_IS_ZERO_VERSION)) {
05885 Htable()->Fix_zero_version(phi, pkid, true );
05886 }
05887 phi->OPND(pkid)->Reset_flag(CF_DONT_PROP);
05888 }
05889 }
05890 }
05891
05892
05893 STMTREP_ITER stmt_iter(srcbb->Stmtlist());
05894 STMTREP *stmt;
05895 FOR_ALL_NODE(stmt, stmt_iter, Init()) {
05896 if (stmt->Op() == OPC_LABEL) continue;
05897
05898 STMTREP *tmp = CXX_NEW(STMTREP, Htable()->Mem_pool());
05899 tmp->Clone(stmt, Htable(), Htable()->Mem_pool());
05900 destbb->Append_stmtrep(tmp);
05901 }
05902 }