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 #ifdef USE_PCH
00061 #include "opt_pch.h"
00062 #endif // USE_PCH
00063 #pragma hdrstop
00064
00065
00066 #ifdef _KEEP_RCS_ID
00067 #define opt_emit_CXX "opt_emit.cxx"
00068 static char *rcs_id = opt_emit_CXX"$Revision: 1.13 $";
00069 #endif
00070
00071
00072
00073 #define USE_STANDARD_TYPES
00074
00075 #define __STDC_LIMIT_MACROS
00076 #include <stdint.h>
00077 #include "defs.h"
00078 #include "tracing.h"
00079 #include "erglob.h"
00080 #include "config_targ.h"
00081 #include "wn.h"
00082 #include "ir_reader.h"
00083 #include "wn_simp.h"
00084 #include "wn_util.h"
00085 #include "region_util.h"
00086 #include "pu_info.h"
00087
00088 #include "config.h"
00089 #include "opt_config.h"
00090 #include "opt_base.h"
00091 #include "opt_config.h"
00092 #include "opt_util.h"
00093 #include "opt_htable.h"
00094 #include "opt_mu_chi.h"
00095 #include "opt_emit.h"
00096 #include "opt_cfg.h"
00097 #include "opt_region_emit.h"
00098 #include "opt_rvi.h"
00099 #include "opt_sym.h"
00100 #include "opt_ssa.h"
00101 #include "opt_du.h"
00102 #include "opt_alias_mgr.h"
00103 #include "opt_loop.h"
00104 #include "opt_main.h"
00105
00106 #include "opt_emit_template.h"
00107
00108 extern WN_MAP Prompf_Id_Map;
00109 #if defined(TARG_NVISA)
00110
00111
00112
00113 static INT cur_loop_depth = 0;
00114 #endif
00115
00116
00117 inline WN *
00118 STMTREP::Gen_wn(STMT_CONTAINER *stmt_container, EMITTER *emitter)
00119 {
00120 return Gen_stmt_wn(this, stmt_container, emitter);
00121 }
00122
00123
00124 inline void
00125 STMT_LIST::Gen_wn(STMT_CONTAINER *stmt_container, EMITTER *emitter)
00126 {
00127 Gen_stmt_list_wn(this, stmt_container, emitter);
00128 }
00129
00130 inline WN*
00131 CODEREP::Gen_wn(EMITTER *emitter)
00132 {
00133 WN *wn = Gen_exp_wn(this, emitter);
00134 if (Kind() == CK_VAR ||
00135 (Kind() == CK_IVAR && Opr() == OPR_PARM))
00136 emitter->Connect_cr_wn(this, wn);
00137 return wn;
00138 }
00139
00140
00141 inline void
00142 BB_NODE::Gen_wn(EMITTER *emitter)
00143 {
00144 Gen_bb_wn(this, emitter);
00145 }
00146
00147
00148
00149
00150
00151 #define SWAP(a, b, tmp) ( tmp = a, a = b, b = tmp )
00152
00153 inline BOOL
00154 Verify_Block_Stmt_Sequence(WN *block)
00155 {
00156
00157
00158 WN *tmp = WN_first(block);
00159 while (tmp && WN_next(tmp) != NULL)
00160 tmp = WN_next(tmp);
00161 if (tmp != WN_last(block))
00162 return FALSE;
00163 else
00164 return TRUE;
00165 }
00166
00167 static WN*
00168 Create_block_stmt(BB_NODE *ff, BB_NODE *ll)
00169 {
00170 WN *wn = WN_CreateBlock();
00171
00172
00173 WN_first(wn) = NULL;
00174 WN_last(wn) = NULL;
00175
00176
00177
00178
00179
00180
00181
00182 while (ff->First_stmtrep() == NULL &&
00183 #ifdef KEY
00184 ff->Firststmt() == NULL &&
00185 #endif
00186 ff->Kind() == BB_GOTO &&
00187 ff != ll)
00188 ff = ff->Next();
00189 if (ff == ll && ll->First_stmtrep() == NULL)
00190 return wn;
00191
00192 for ( BB_NODE *tmpf = ff; tmpf != NULL; tmpf = tmpf->Next() ) {
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214 if ( WN_first(wn) == NULL && tmpf->Firststmt() != NULL ) {
00215 WN_first(wn) = tmpf->Firststmt();
00216 }
00217 if ( tmpf->Laststmt() != NULL) {
00218 WN_last(wn) = tmpf->Laststmt();
00219 }
00220
00221 if (tmpf == ll)
00222 break;
00223 }
00224
00225 Is_True( WN_first(wn) == NULL || WN_prev(WN_first(wn)) == NULL,
00226 ("First stmt has prev stmt."));
00227 Is_True(Verify_Block_Stmt_Sequence(wn),
00228 ("Illegal stmt sequence in block created in Create_block_stmt"));
00229 return wn;
00230 }
00231
00232 static WN*
00233 Create_block(EMITTER *emitter, BB_NODE *ff, BB_NODE *ll)
00234 {
00235 emitter->Gen_wn(ff, ll);
00236 return Create_block_stmt( ff, ll);
00237 }
00238
00239 BOOL
00240 EMITTER::Raise_altentry( BB_NODE *bb )
00241 {
00242 bb->Init_stmt( bb->Entrywn() );
00243 if (bb->First_stmtrep()) {
00244 if (bb->First_stmtrep()->Op() == OPC_OPT_CHI) {
00245 Connect_sr_wn( bb->First_stmtrep(), bb->Entrywn() );
00246 if (bb->First_stmtrep() == bb->Last_stmtrep())
00247 return TRUE;
00248 }
00249 }
00250 return FALSE;
00251 }
00252
00253
00254 void
00255 EMITTER::Raise_func_entry(BB_NODE *bb, BB_NODE *last_bb)
00256 {
00257 FmtAssert(bb != NULL,
00258 ("EMITTER::Raise_func_entry: no OPR_FUNC_ENTRY statement"));
00259 WN *stmt;
00260 BB_REGION *bb_region = NULL;
00261
00262 if (bb->Kind() == BB_ENTRY) {
00263 _opt_func = bb->Entrywn();
00264 stmt = Create_block(this, bb, last_bb);
00265 } else {
00266 Is_True(bb->Kind() == BB_REGIONSTART,
00267 ("EMITTER::Raise_func_entry, inappropriate entry"));
00268 bb_region = bb->Regioninfo();
00269 RID *rid = bb_region->Rid();
00270
00271 stmt = Create_block(this, bb, last_bb);
00272 _opt_func = WN_CreateRegion(REGION_type_to_kind(bb_region->Rid()),
00273 stmt,
00274 bb_region->Region_pragma_list(),
00275 bb_region->Region_exit_list(),
00276 RID_id(bb_region->Rid()),
00277 bb_region->Ereg_supp());
00278 WN_COPY_All_Maps(_opt_func, bb_region->Orig_wn());
00279
00280
00281 if (REGION_is_EH(_opt_func))
00282 Opt_stab()->Convert_EH_pragmas(_opt_func);
00283
00284 Connect_sr_wn(Region_entry_stmt(),_opt_func);
00285
00286 WN_Set_Linenum(_opt_func, bb->Linenum());
00287
00288 if (bb->First_stmtrep() && bb->First_stmtrep()->Op() == OPC_OPT_CHI)
00289
00290
00291
00292
00293
00294 ;
00295 else
00296 FmtAssert(0,("EMITTER::Raise_func_entry, could not find entry CHI"));
00297 }
00298
00299 bb->Init_stmt(_opt_func);
00300 WN_Set_Linenum(stmt, WN_Get_Linenum(_opt_func));
00301 if (Cfg()->Feedback()) {
00302 Cfg()->Feedback()->Emit_feedback(_opt_func, bb);
00303 }
00304
00305 WN *pragmas;
00306 if (WN_opcode(_opt_func) == OPC_FUNC_ENTRY) {
00307 WN_func_body(_opt_func) = stmt;
00308 pragmas = WN_func_pragmas(_opt_func);
00309 } else {
00310 Is_True(WN_opcode(_opt_func) == OPC_REGION,
00311 ("EMITTER::Raise_func_entry, unknown entry WN"));
00312 pragmas = WN_region_pragmas(_opt_func);
00313 }
00314
00315 WN *wopt_pragma;
00316 for (wopt_pragma = WN_first(pragmas);
00317 wopt_pragma != NULL;
00318 wopt_pragma = WN_next(wopt_pragma)) {
00319 if ( WN_pragma(wopt_pragma) == WN_PRAGMA_WOPT_FINISHED_OPT )
00320 break;
00321 }
00322
00323 if (wopt_pragma == NULL) {
00324 wopt_pragma = WN_CreatePragma(WN_PRAGMA_WOPT_FINISHED_OPT,
00325 (ST *) NULL, 0, 0);
00326 WN_INSERT_BlockBefore(pragmas, NULL, wopt_pragma);
00327 }
00328
00329 INT32 pragma_flag = WN_pragma_arg2(wopt_pragma);
00330 if (WOPT_Enable_Tail_Recur)
00331 pragma_flag |= WOPT_TAIL_RECUR_FINISHED;
00332 WN_pragma_arg2(wopt_pragma) = pragma_flag;
00333
00334 if (WN_opcode(_opt_func) == OPC_FUNC_ENTRY) {
00335 WN_func_pragmas(_opt_func) = pragmas;
00336
00337 REGION_emit(Cfg()->Rid(), _opt_func, Cfg()->Rgn_level(), 1, 0);
00338 } else {
00339 WN_region_pragmas(_opt_func) = pragmas;
00340
00341 REGION_emit(Cfg()->Rid(), _opt_func, Cfg()->Rgn_level(),
00342 bb_region->Region_num_exits(), bb_region->Region_line_num());
00343 }
00344 }
00345
00346
00347 static WN*
00348 Raise_if_stmt(EMITTER *emitter, BB_NODE **bb)
00349 {
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361 BB_LIST_ITER bb_iter;
00362 BB_NODE *bb_cond, *bb_then, *bb_else, *bb_merge;
00363
00364 bb_cond = *bb;
00365
00366 bb_then = bb_cond->If_then();
00367 bb_else = bb_cond->If_else();
00368 bb_merge = bb_cond->If_merge();
00369
00370 bb_cond->Gen_wn(emitter);
00371
00372
00373 Is_True(bb_cond->Next() == bb_then,
00374 ("EMITTER::Raise_if_stmt: then statement (BB%d) does not follow if-statement (BB%d).",
00375 bb_then->Id(), bb_cond->Id()));
00376
00377
00378 WN *block_then = Create_block(emitter, bb_then, bb_else->Prev());
00379 WN_Set_Linenum(block_then, bb_cond->Then_loc());
00380 WN *block_else = Create_block(emitter, bb_else, bb_merge->Prev());
00381 WN_Set_Linenum(block_else, bb_cond->Else_loc());
00382
00383
00384 *bb = bb_merge;
00385
00386
00387
00388 WN *rwn = WN_CreateIf(WN_kid0(bb_cond->Laststmt()), block_then, block_else);
00389 WN_Set_Linenum(rwn, bb_cond->Linenum());
00390 if (emitter->Cfg()->Feedback()) {
00391 emitter->Cfg()->Feedback()->Emit_feedback( rwn, bb_cond );
00392 }
00393 emitter->Connect_sr_wn( bb_cond->Branch_stmtrep(), rwn );
00394
00395
00396 if (bb_cond->Firststmt() != bb_cond->Laststmt()) {
00397 WN *block = WN_CreateBlock();
00398 STMT_CONTAINER stmtcon(bb_cond->Firststmt(), bb_cond->Laststmt());
00399 stmtcon.Remove(bb_cond->Laststmt());
00400 stmtcon.Append(rwn);
00401 WN_first(block) = stmtcon.Head();
00402 WN_last(block) = stmtcon.Tail();
00403 return block;
00404 } else
00405 return rwn;
00406 }
00407
00408
00409
00410
00411
00412 static BOOL
00413 Valid_doloop_condition( BB_NODE *bb_end, const OPT_STAB *opt_stab )
00414 {
00415 STMTREP *cond_br = bb_end->Branch_stmtrep();
00416 BB_LOOP *loop_info = bb_end->Loop();
00417 WN *index = loop_info->Index();
00418
00419
00420 if ( cond_br->Op() != OPC_TRUEBR && cond_br->Op() != OPC_FALSEBR ) {
00421 DevWarn( "Valid_doloop_condition(BB:%d) not true/falsebr",
00422 bb_end->Id() );
00423 return FALSE;
00424 }
00425
00426
00427 CODEREP *rhs = cond_br->Rhs();
00428 if ( rhs->Kind() != CK_OP || ! OPERATOR_is_compare(rhs->Opr()) ) {
00429 DevWarn( "Valid_doloop_condition(BB:%d) cond_br not compare",
00430 bb_end->Id() );
00431 return FALSE;
00432 }
00433
00434
00435 const OPERATOR cond_opr = rhs->Opr();
00436 if (!(cond_opr == OPR_LE || cond_opr == OPR_GE ||
00437 cond_opr == OPR_LT || cond_opr == OPR_GT))
00438 return FALSE;
00439
00440
00441
00442 CODEREP *index_cr = NULL;
00443 PHI_LIST_ITER phi_iter;
00444 PHI_NODE *phi;
00445 FOR_ALL_ELEM ( phi, phi_iter, Init(bb_end->Phi_list()) ) {
00446 if (!phi->Res_is_cr()) continue;
00447 CODEREP *res = phi->RESULT();
00448
00449 if (res == NULL) continue;
00450 if (WN_st(index) == opt_stab->St(res->Aux_id()) &&
00451 WN_idname_offset(index) == opt_stab->St_ofst(res->Aux_id()) &&
00452 opt_stab->Is_real_var(res->Aux_id())) {
00453 index_cr = res;
00454 break;
00455 }
00456 }
00457 if ( index_cr == NULL ) {
00458 DevWarn( "Valid_doloop_condition(BB:%d) no index in phis",
00459 bb_end->Id() );
00460 return FALSE;
00461 }
00462
00463
00464
00465 BOOL found_one_side_use_index = FALSE;
00466 for (INT i = 0; i < rhs->Kid_count(); i++)
00467 if (rhs->Opnd(i)->Contains(index_cr) &&
00468 loop_info->Index_relative_expr(rhs->Opnd(i), index_cr))
00469 found_one_side_use_index = TRUE;
00470 if (found_one_side_use_index == FALSE) {
00471 DevWarn( "Valid_doloop_condition(BB:%d) can't find index var on comparison",
00472 bb_end->Id() );
00473 return FALSE;
00474 }
00475
00476 STMTREP_ITER stmt_iter(bb_end->Stmtlist());
00477 STMTREP *sr;
00478 FOR_ALL_NODE( sr, stmt_iter, Init() ) {
00479 if (sr->Op() != OPC_LABEL && sr != bb_end->Last_stmtrep()) {
00480 DevWarn( "Valid_doloop_condition(BB:%d) more than one stmt",
00481 bb_end->Id() );
00482 return FALSE;
00483 }
00484 }
00485
00486 return TRUE;
00487 }
00488
00489 void
00490 Detect_invalid_doloops(COMP_UNIT *cu)
00491 {
00492 if (cu->Phase() != MAINOPT_PHASE) {
00493 CFG_ITER cfg_iter(cu->Cfg());
00494 BB_NODE *bb;
00495 FOR_ALL_NODE( bb, cfg_iter, Init() ) {
00496 if (bb->Kind() == BB_DOEND) {
00497 if (!Valid_doloop_condition(bb, cu->Opt_stab())) {
00498 bb->Loop()->Reset_valid_doloop();
00499 DevWarn("Invalid doloop detected in WHIRL input to PREOPT.");
00500 }
00501 }
00502 }
00503 }
00504 }
00505
00506
00507
00508
00509
00510
00511 static WN *
00512 Build_new_loop_info( WN *do_loop, WN *old_info )
00513 {
00514 WN *induction = NULL;
00515 WN *trip_count= NULL;
00516 UINT16 est_trips;
00517 UINT16 depth;
00518 INT32 lflags;
00519 INT new_kid_count = 0;
00520
00521
00522 if ( old_info != NULL ) {
00523 est_trips = WN_loop_trip_est(old_info);
00524 depth = WN_loop_depth(old_info);
00525 lflags = WN_loop_flag(old_info);
00526 }
00527 else {
00528 est_trips = 0;
00529 #if defined(TARG_NVISA)
00530 depth = cur_loop_depth;
00531 #else
00532 depth = 0;
00533 #endif
00534 lflags = 0;
00535 }
00536
00537
00538 induction = WN_LOOP_InductionVariable( do_loop );
00539 if ( induction ) {
00540 Is_True( WN_opcode(induction) == OPC_IDNAME,
00541 ("Build_new_loop_info: bad induction var: %s",
00542 OPCODE_name(WN_opcode(induction))) );
00543 induction = WN_COPY_Tree_With_Map(induction);
00544 }
00545 trip_count= WN_LOOP_TripCount( do_loop );
00546
00547
00548 if ( trip_count != NULL ) {
00549 if ( WN_operator(trip_count) == OPR_INTCONST ) {
00550 INT64 trip_count_val = WN_const_val(trip_count);
00551 if ( trip_count_val <= 0 )
00552 est_trips = 0;
00553 else
00554 est_trips = MIN( trip_count_val, UINT16_MAX );
00555 }
00556 else {
00557
00558
00559 trip_count = NULL;
00560 }
00561 }
00562
00563 if ( induction != NULL ) new_kid_count++;
00564 if ( trip_count != NULL ) new_kid_count++;
00565
00566 WN *new_info;
00567 if ( old_info == NULL || new_kid_count != WN_kid_count(old_info) ) {
00568 new_info = WN_CreateLoopInfo( induction, trip_count,
00569 est_trips, depth, lflags );
00570 }
00571 else {
00572
00573 if ( induction )
00574 WN_set_loop_induction(old_info, induction);
00575 if ( trip_count )
00576 WN_set_loop_trip(old_info, trip_count);
00577 WN_loop_trip_est(old_info) = est_trips;
00578 WN_loop_depth(old_info) = depth;
00579 WN_loop_flag(old_info) = lflags;
00580
00581 new_info = old_info;
00582 }
00583
00584 return new_info;
00585 }
00586
00587
00588
00589
00590
00591
00592
00593 static BOOL
00594 Find_doloop_init_stmt(EMITTER *emitter, BB_NODE *bb_start,
00595 BB_LOOP *loop_info, WN **init_stmtwn)
00596 {
00597 BOOL found_init = FALSE;
00598
00599 OPT_STAB *opt_stab = emitter->Opt_stab();
00600 WN *index_wn = loop_info ? loop_info->Index() : NULL;
00601 ST *index_st = index_wn ? WN_st(index_wn) : NULL;
00602 WN_OFFSET index_ofs = index_wn ? WN_idname_offset(index_wn) : 0;
00603
00604
00605 STMTREP_ITER stmt_iter(bb_start->Stmtlist());
00606 STMTREP *init_sr;
00607 WN *init_wn = bb_start->Firststmt();
00608 STMTREP *found_init_sr;
00609 WN *found_init_wn;
00610 FOR_ALL_NODE( init_sr, stmt_iter, Init() ) {
00611 if ( init_sr->Opr() == OPR_STID ) {
00612 CODEREP *init_lhs = init_sr->Lhs();
00613 if ( opt_stab->St(init_lhs->Aux_id()) == index_st &&
00614 init_lhs->Offset() == index_ofs )
00615 {
00616
00617 if ( init_wn &&
00618 WN_operator(init_wn) == OPR_STID &&
00619 WN_st(init_wn) == index_st &&
00620 WN_store_offset(init_wn) == index_ofs )
00621 {
00622 found_init = TRUE;
00623 found_init_sr = init_sr;
00624 found_init_wn = init_wn;
00625 }
00626 else {
00627
00628 found_init = FALSE;
00629 }
00630 }
00631 }
00632
00633 init_wn = init_wn ? WN_next(init_wn) : NULL;
00634 }
00635
00636 if ( found_init ) {
00637
00638
00639
00640 if ( found_init_sr != bb_start->Last_stmtrep() ) {
00641 CODEREP *index_cr = found_init_sr->Lhs();
00642
00643
00644 STMTREP_ITER rev_stmt_iter(bb_start->Stmtlist());
00645 STMTREP *tmp_sr;
00646 FOR_ALL_NODE_REVERSE( tmp_sr, rev_stmt_iter, Init() ) {
00647
00648 if ( tmp_sr == found_init_sr )
00649 break;
00650
00651
00652 if ( tmp_sr->Redefines_var( index_cr->Aux_id() ) ) {
00653 found_init = FALSE;
00654 break;
00655 }
00656
00657
00658 if ( tmp_sr->References_var( index_cr->Aux_id() ) ) {
00659 found_init = FALSE;
00660 break;
00661 }
00662
00663
00664
00665 if ( tmp_sr->Opr() == OPR_STID ) {
00666 if ( found_init_sr->Rhs()->References_var( tmp_sr->Lhs()->Aux_id() ) ) {
00667 found_init = FALSE;
00668 break;
00669 }
00670 }
00671
00672
00673
00674 if ( tmp_sr->Has_chi() ) {
00675 CHI_LIST_ITER chi_iter;
00676 CHI_NODE *cnode;
00677 CHI_LIST *chi_list = tmp_sr->Chi_list();
00678 FOR_ALL_NODE( cnode, chi_iter, Init(chi_list)) {
00679 if ( found_init_sr->Rhs()->References_var( cnode->Aux_id() ) ) {
00680 found_init = FALSE;
00681 break;
00682 }
00683 }
00684 if ( !found_init )
00685 break;
00686 }
00687
00688 }
00689 }
00690
00691
00692 if ( found_init ) {
00693 *init_stmtwn = found_init_wn;
00694 }
00695 }
00696
00697 return found_init;
00698 }
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708 static WN*
00709 Raise_doloop_stmt(EMITTER *emitter, BB_NODE **bb)
00710 {
00711
00712
00713
00714
00715
00716
00717
00718
00719 BB_LIST_ITER bb_iter;
00720 BB_NODE *bb_start, *bb_end, *bb_body, *bb_step, *bb_merge;
00721
00722 bb_start = *bb;
00723 bb_end = bb_start->Next();
00724 bb_body = bb_end->Next();
00725
00726 bb_iter.Init(bb_end->Succ());
00727 BB_NODE *s1 = bb_iter.First_elem(); BB_NODE *s2 = bb_iter.Next_elem();
00728 bb_merge = (s1 == bb_body)? s2 : s1;
00729
00730 bb_iter.Init(bb_end->Pred());
00731 s1 = bb_iter.First_elem(); s2 = bb_iter.Next_elem();
00732 bb_step = (s1 == bb_start)? s2 : s1;
00733
00734 FmtAssert(bb_start == bb_start->Loopstart(), ("Wrong start"));
00735 FmtAssert(bb_end == bb_start->Loopend(), ("Wrong end"));
00736 FmtAssert(bb_body == bb_start->Loopbody(), ("Wrong body"));
00737 FmtAssert(bb_step == bb_start->Loopstep(), ("Wrong step"));
00738 FmtAssert(bb_merge == bb_start->Loopmerge(), ("Wrong merge"));
00739
00740 #if defined(TARG_NVISA)
00741 ++cur_loop_depth;
00742 #endif
00743
00744
00745 bb_start->Gen_wn(emitter);
00746
00747
00748 WN *init_stmtwn = NULL;
00749 if ( ! Find_doloop_init_stmt( emitter, bb_start, bb_end->Loop(),
00750 &init_stmtwn ) )
00751 {
00752 FmtAssert(FALSE, ( "Find_doloop_init_stmt(BB:%d) returns FALSE",
00753 bb_end->Id() ));
00754 }
00755
00756
00757 STMTREP *goto_end = bb_step->Branch_stmtrep();
00758 if ( goto_end != NULL && goto_end->Op() == OPC_GOTO ) {
00759 if ( goto_end->Label_number() == bb_end->Labnam() ) {
00760 bb_step->Remove_stmtrep( goto_end );
00761 }
00762 }
00763
00764 bb_step->Gen_wn(emitter);
00765
00766
00767 bb_end->Gen_wn(emitter);
00768 FmtAssert(WN_opcode(bb_end->Laststmt()) == OPC_TRUEBR ||
00769 WN_opcode(bb_end->Laststmt()) == OPC_FALSEBR,
00770 ("DO condition is not TRUEBR/FALSEBR. (BB:%d)", bb_end->Id()));
00771
00772 if ( ! Valid_doloop_condition( bb_end, emitter->Opt_stab()) ) {
00773
00774
00775 if (bb_end->Loop()->Valid_doloop())
00776 FmtAssert(FALSE, ( "Valid_doloop_condition(BB:%d) returns FALSE",
00777 bb_end->Id() ));
00778 }
00779
00780
00781 WN *block_body = Create_block(emitter, bb_body, bb_step->Prev());
00782 WN_Set_Linenum(block_body, bb_start->Linenum());
00783
00784
00785 WN *index = bb_start->Loopindex();
00786
00787
00788 WN *rwn = NULL;
00789
00790
00791 WN *step = bb_step->Laststmt();
00792
00793
00794 if (bb_step->Firststmt() != bb_step->Laststmt()) {
00795 STMT_CONTAINER stmtcon(WN_first(block_body), WN_last(block_body));
00796 stmtcon.Append_list(bb_step->Firststmt(), bb_step->Laststmt());
00797 STMT_ITER stmt_iter;
00798 FOR_ALL_ELEM(step,stmt_iter,Init(bb_step->Firststmt(),
00799 bb_step->Laststmt())) {
00800 if (WN_operator(step) == OPR_STID && WN_st(step) == WN_st(index)) {
00801 stmtcon.Remove(step);
00802 break;
00803 }
00804 }
00805 Is_True(step, ("Raise_doloop_stmt: cannot find step statement"));
00806 WN_first(block_body) = stmtcon.Head();
00807 WN_last(block_body) = stmtcon.Tail();
00808 }
00809
00810 Is_True(WN_opcode(bb_end->Laststmt()) == OPC_FALSEBR,
00811 ("Raise_doloop_stmt, unknown opcode"));
00812 WN *loop_cond = WN_kid0(bb_end->Laststmt());
00813
00814
00815 WN *loop_info_wn = bb_body->Label_loop_info();
00816 char fake_info_wn_area [sizeof (WN)];
00817 WN* fake_info_wn = (WN *) &fake_info_wn_area;
00818 if ( loop_info_wn == NULL && WOPT_Enable_Add_Do_Loop_Info ) {
00819
00820 loop_info_wn = fake_info_wn;
00821 WN_set_opcode(loop_info_wn, OPC_LOOP_INFO);
00822 }
00823
00824 rwn = WN_CreateDO(index,
00825 init_stmtwn,
00826 loop_cond,
00827 step,
00828 block_body,
00829 loop_info_wn);
00830 WN_COPY_All_Maps(rwn, bb_end->Loop()->Orig_wn());
00831
00832 WN_Set_Linenum(rwn, bb_start->Linenum());
00833 if (emitter->Cfg()->Feedback()) {
00834 emitter->Cfg()->Feedback()->Emit_feedback( rwn, bb_end );
00835 }
00836 bb_end->Set_loopstmt(rwn);
00837 emitter->Connect_sr_wn( bb_end->Branch_stmtrep(), rwn );
00838 emitter->Set_has_do_loop();
00839
00840
00841
00842 if ( loop_info_wn != NULL ) {
00843
00844 if ( loop_info_wn == fake_info_wn )
00845 loop_info_wn = NULL;
00846 WN_set_do_loop_info(rwn, Build_new_loop_info(rwn, loop_info_wn));
00847 }
00848
00849
00850 if (bb_start->Firststmt() != bb_start->Laststmt()) {
00851 WN *newblock = WN_CreateBlock();
00852 STMT_CONTAINER stmtcon(bb_start->Firststmt(), bb_start->Laststmt());
00853 stmtcon.Remove(init_stmtwn);
00854 stmtcon.Append(rwn);
00855 WN_first(newblock) = stmtcon.Head();
00856 WN_last(newblock) = stmtcon.Tail();
00857 rwn = newblock;
00858 }
00859
00860
00861
00862
00863 if (bb_merge->Label_stmtrep() != NULL && bb_merge->Pred()->Len() == 1)
00864 bb_merge->Remove_stmtrep( bb_merge->Label_stmtrep() );
00865
00866
00867 *bb = bb_merge;
00868
00869 #if defined(TARG_NVISA)
00870 --cur_loop_depth;
00871 #endif
00872 return rwn;
00873 }
00874
00875
00876
00877 static WN*
00878 Raise_whiledo_stmt_to_whileloop(EMITTER *emitter, BB_NODE *bb, BB_NODE **next_bb)
00879 {
00880
00881
00882
00883
00884
00885
00886
00887
00888 BB_LIST_ITER bb_iter;
00889
00890 BB_NODE *bb_end = bb;
00891 FmtAssert(bb_end == bb_end->Loopend(), ("Wrong end"));
00892
00893 BB_NODE *bb_body = bb_end->Loopbody();
00894 BB_NODE *loop_back = bb_end->Loopstep();
00895 BB_NODE *merge_bb = bb_end->Loopmerge();
00896
00897
00898 STMTREP *goto_end = loop_back->Branch_stmtrep();
00899 if ( goto_end != NULL ) {
00900 FmtAssert( goto_end->Op() == OPC_GOTO,
00901 ("Raise_whiledo_stmt: loop-back with non-goto branch") );
00902 FmtAssert( goto_end->Label_number() == bb_end->Labnam(),
00903 ("Raise_whiledo_stmt: loop-back to wrong location") );
00904
00905 loop_back->Remove_stmtrep( goto_end );
00906 }
00907
00908
00909 bb_end->Gen_wn(emitter);
00910
00911
00912 WN *block_body = Create_block(emitter, bb_body, loop_back);
00913 WN_Set_Linenum(block_body, bb_end->Linenum());
00914
00915 Is_True(WN_opcode(bb_end->Laststmt()) == OPC_FALSEBR,
00916 ("Raise_whiledo_stmt: condition not a falsebr") );
00917 WN *cond = WN_kid0(bb_end->Laststmt());
00918
00919 WN *rwn = WN_CreateWhileDo(cond, block_body);
00920 WN_Set_Linenum(rwn, bb_end->Linenum());
00921 if (emitter->Cfg()->Feedback()) {
00922 emitter->Cfg()->Feedback()->Emit_feedback( rwn, bb_end );
00923 }
00924
00925
00926
00927
00928
00929 emitter->Connect_sr_wn( bb_end->Branch_stmtrep(), rwn );
00930
00931
00932
00933
00934 if (bb_end->Firststmt() != bb_end->Laststmt()) {
00935 WN *newblock = WN_CreateBlock();
00936 STMT_CONTAINER stmtcon(bb_end->Firststmt(), bb_end->Laststmt());
00937 stmtcon.Remove(bb_end->Laststmt());
00938
00939
00940
00941
00942 STMT_ITER stmt_iter( stmtcon.Head(), stmtcon.Tail() );
00943 WN *wnstmt;
00944 FOR_ALL_ELEM(wnstmt,stmt_iter,Init(stmtcon.Head(),stmtcon.Tail())) {
00945 if ( WN_opcode(wnstmt) == OPC_LABEL )
00946 continue;
00947
00948 WN *newwn = WN_COPY_Tree(wnstmt);
00949 emitter->Duplicate_sr_cr_connections( wnstmt, newwn );
00950 emitter->Alias_Mgr()->Dup_tree_alias_id( wnstmt, newwn );
00951 WN_INSERT_BlockLast( block_body, newwn );
00952 }
00953
00954
00955 stmtcon.Append(rwn);
00956 WN_first(newblock) = stmtcon.Head();
00957 WN_last(newblock) = stmtcon.Tail();
00958 rwn = newblock;
00959 }
00960
00961
00962
00963
00964 if (merge_bb->Label_stmtrep() != NULL && merge_bb->Pred()->Len() == 1)
00965 merge_bb->Remove_stmtrep( merge_bb->Label_stmtrep() );
00966
00967
00968 *next_bb = merge_bb;
00969
00970 return rwn;
00971 }
00972
00973
00974 static WN*
00975 Raise_whiledo_stmt_to_doloop(EMITTER *emitter, BB_NODE *bb, BB_NODE *prev_bb, BB_NODE **next_bb)
00976 {
00977 BB_NODE *header = bb;
00978 BB_NODE *preheader;
00979 BB_NODE *loopback;
00980 BB_NODE *loopbody;
00981 BB_NODE *loopmerge;
00982
00983 BB_LOOP *loop = header->Loop();
00984
00985 BB_LIST_ITER bb_pred_iter;
00986 BB_NODE *pred;
00987 INT count = 0;
00988 FOR_ALL_ELEM( pred, bb_pred_iter, Init(header->Pred()) ) {
00989 if (Is_backedge(pred, header)) {
00990 loopback = pred;
00991 } else {
00992 preheader = pred;
00993 }
00994 count++;
00995 }
00996 Is_True(count == 2, ("Raise_whiledo_stmt_to_doloop:"
00997 " too many or too litter predecessor"));
00998
00999 loopbody = header->Next();
01000 loopmerge = (header->Nth_succ(0) != header->Next())
01001 ? header->Nth_succ(0) : header->Nth_succ(1);
01002 Is_True(loopmerge, ("Loop merge is NULL"));
01003
01004 header->Gen_wn(emitter);
01005
01006
01007 WN *init_stmt = preheader->Laststmt();
01008 if (WN_prev(init_stmt) != NULL)
01009 WN_next(WN_prev(init_stmt)) = NULL;
01010
01011 Is_True(prev_bb->Laststmt() == init_stmt,
01012 ("Raise_whiledo_stmt_doloop: prev_bb and preheader didn't agree."));
01013
01014 if (prev_bb->Firststmt() == prev_bb->Laststmt()) {
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024 prev_bb->Set_firststmt(WN_prev(init_stmt));
01025 prev_bb->Set_laststmt(WN_prev(init_stmt));
01026
01027 } else
01028 prev_bb->Set_laststmt(WN_prev(init_stmt));
01029 WN_prev(init_stmt) = WN_next(init_stmt) = NULL;
01030
01031 #ifdef KEY
01032 if (preheader->Last_stmtrep())
01033 #endif
01034 preheader->Remove_stmtrep( preheader->Last_stmtrep());
01035
01036 STMTREP *goto_end = loopback->Branch_stmtrep();
01037 if ( goto_end != NULL)
01038 loopback->Remove_stmtrep( goto_end );
01039
01040 #if defined(TARG_NVISA)
01041 ++cur_loop_depth;
01042 #endif
01043
01044
01045 WN *block_body = Create_block(emitter, loopbody, loopback);
01046 WN_Set_Linenum(block_body, header->Linenum());
01047
01048
01049 WN *incr_stmt = loopback->Laststmt();
01050 if (WN_first(block_body) != WN_last(block_body)) {
01051 WN_next(WN_prev(incr_stmt)) = NULL;
01052 WN_last(block_body) = WN_prev(incr_stmt);
01053 } else {
01054 DevWarn("EMITTER: an empty loop is emitted.");
01055 WN_first(block_body) = WN_last(block_body) = NULL;
01056 }
01057
01058 if (loopback->Firststmt() == loopback->Laststmt()) {
01059 loopback->Set_firststmt(NULL);
01060 loopback->Set_laststmt(NULL);
01061 } else
01062 loopback->Set_laststmt(WN_prev(incr_stmt));
01063
01064 loopback->Remove_stmtrep( loopback->Last_stmtrep());
01065 WN_next(incr_stmt) = WN_prev(incr_stmt) = NULL;
01066
01067 ST *index_st = emitter->Opt_stab()->St(loop->Iv()->Aux_id());
01068 INT64 ofst = emitter->Opt_stab()->St_ofst(loop->Iv()->Aux_id());
01069 WN *index = WN_CreateIdname(ofst, index_st);
01070
01071 WN *loop_info_wn = NULL;
01072 char fake_info_wn_area [sizeof (WN)];
01073 WN* fake_info_wn = (WN *) &fake_info_wn_area;
01074 if ( WOPT_Enable_Add_Do_Loop_Info ) {
01075
01076 loop_info_wn = fake_info_wn;
01077 WN_set_opcode(loop_info_wn, OPC_LOOP_INFO);
01078 }
01079
01080 WN *loop_cond = WN_kid0(header->Laststmt());
01081
01082 WN *rwn = WN_CreateDO(index,
01083 init_stmt,
01084 loop_cond,
01085 incr_stmt,
01086 block_body,
01087 loop_info_wn);
01088
01089 header->Set_loopstmt(rwn);
01090 header->Loop()->Set_loopstmt(rwn);
01091
01092 emitter->Connect_sr_wn( header->Branch_stmtrep(), rwn );
01093
01094
01095
01096
01097 if (loopmerge->Label_stmtrep() != NULL && loopmerge->Pred()->Len() == 1)
01098 loopmerge->Remove_stmtrep( loopmerge->Label_stmtrep() );
01099
01100 *next_bb = loopmerge;
01101
01102
01103
01104 WN_Set_Linenum(rwn, header->Linenum());
01105 if (emitter->Cfg()->Feedback()) {
01106 emitter->Cfg()->Feedback()->Emit_feedback( rwn, header );
01107 }
01108 header->Set_loopstmt(rwn);
01109 emitter->Set_has_do_loop();
01110
01111 if (WOPT_Enable_Add_Do_Loop_Info)
01112 WN_set_do_loop_info(rwn, Build_new_loop_info(rwn, NULL));
01113
01114 #if defined(TARG_NVISA)
01115 --cur_loop_depth;
01116 #endif
01117
01118 return rwn;
01119 }
01120
01121
01122 static WN*
01123 Raise_whiledo_stmt(EMITTER *emitter, BB_NODE *bb, BB_NODE *prev_bb, BB_NODE **next_bb)
01124 {
01125 WN *rwn;
01126
01127 if (WOPT_Enable_While_Loop &&
01128 Can_raise_to_doloop(bb->Loop(), FALSE, emitter->Htable()))
01129 rwn = Raise_whiledo_stmt_to_doloop(emitter, bb, prev_bb, next_bb);
01130 else
01131 rwn = Raise_whiledo_stmt_to_whileloop(emitter, bb, next_bb);
01132
01133 if (Run_prompf &&
01134 bb->Loop()->Orig_wn() != NULL &&
01135 WN_MAP32_Get(Prompf_Id_Map, bb->Loop()->Orig_wn()) != 0)
01136 {
01137 WN_CopyMap(rwn, Prompf_Id_Map, bb->Loop()->Orig_wn());
01138 }
01139 #ifdef KEY
01140 if (bb->Loop()->Orig_wn() != NULL &&
01141 WN_MAP32_Get(WN_MAP_FEEDBACK, bb->Loop()->Orig_wn()) != 0)
01142 {
01143 WN_CopyMap(rwn, WN_MAP_FEEDBACK, bb->Loop()->Orig_wn());
01144 }
01145 #endif
01146 return rwn;
01147 }
01148
01149
01150 static WN*
01151 Raise_dowhile_stmt(EMITTER *emitter, BB_NODE **bb)
01152 {
01153
01154
01155
01156
01157
01158
01159 BB_NODE *bb_body = *bb;
01160 BB_NODE *bb_end = bb_body->Loopend();
01161 BB_NODE *bb_merge = bb_body->Loopmerge();
01162
01163 FmtAssert( bb_end->Kind() == BB_REPEATEND,
01164 ("Raise_dowhile_stmt: repeatbody BB:%d has invalid end BB:%d",
01165 bb_body->Id(), bb_end->Id()) );
01166
01167 bb_end->Gen_wn(emitter);
01168
01169
01170 BB_KIND old_kind = bb_body->Kind();
01171 bb_body->Set_kind(BB_GOTO);
01172 BB_NODE *bb_tmp = bb_body;
01173
01174
01175 while (bb_tmp->First_stmtrep() == NULL && bb_tmp->Kind() == BB_GOTO &&
01176 bb_tmp != bb_end)
01177 bb_tmp = bb_tmp->Next();
01178 WN *block_body = (bb_tmp != bb_end) ?
01179 Create_block(emitter, bb_tmp, bb_end->Prev()) :
01180 Create_block(emitter, bb_end->Prev(), bb_end->Prev());
01181
01182 WN_Set_Linenum(block_body, bb_end->Linenum());
01183 bb_body->Set_kind(old_kind);
01184
01185
01186 *bb = bb_merge;
01187
01188
01189
01190 WN *rwn = WN_CreateDoWhile(WN_kid0(bb_end->Laststmt()),
01191 block_body);
01192 WN_Set_Linenum(rwn, bb_end->Linenum());
01193 if (emitter->Cfg()->Feedback()) {
01194 emitter->Cfg()->Feedback()->Emit_feedback( rwn, bb_end );
01195 }
01196 emitter->Connect_sr_wn( bb_end->Branch_stmtrep(), rwn );
01197
01198
01199 if (bb_end->Firststmt() != bb_end->Laststmt()) {
01200 STMT_CONTAINER stmtcon(WN_first(block_body), WN_last(block_body));
01201 stmtcon.Append_list(bb_end->Firststmt(), bb_end->Laststmt());
01202 stmtcon.Remove(bb_end->Laststmt());
01203 WN_first(block_body) = stmtcon.Head();
01204 WN_last(block_body) = stmtcon.Tail();
01205 }
01206
01207 if (Run_prompf &&
01208 bb_end->Loop()->Orig_wn() != NULL &&
01209 WN_MAP32_Get(Prompf_Id_Map, bb_end->Loop()->Orig_wn()) != 0)
01210 {
01211 WN_CopyMap(rwn, Prompf_Id_Map, bb_end->Loop()->Orig_wn());
01212 }
01213
01214 return rwn;
01215 }
01216
01217 static WN*
01218 Raise_region_stmt(EMITTER *emitter, BB_NODE **bb)
01219 {
01220 BB_NODE *region_start = *bb;
01221 BB_REGION *bb_region = region_start->Regioninfo();
01222 BB_NODE *region_end = bb_region->Region_end();
01223
01224
01225 WN *region_body;
01226 region_body = Create_block( emitter, region_start, region_end );
01227
01228 WN *region_wn = WN_CreateRegion(REGION_type_to_kind(bb_region->Rid()),
01229 region_body,
01230 bb_region->Region_pragma_list(),
01231 bb_region->Region_exit_list(),
01232 RID_id(bb_region->Rid()),
01233 bb_region->Ereg_supp());
01234 WN_COPY_All_Maps(region_wn, bb_region->Orig_wn());
01235
01236
01237 if (REGION_is_EH(region_wn))
01238 emitter->Opt_stab()->Convert_EH_pragmas(region_wn);
01239
01240 WN_Set_Linenum(region_wn, region_start->Linenum());
01241
01242
01243
01244 REGION_emit(bb_region->Rid(), region_wn, emitter->Cfg()->Rgn_level(),
01245 bb_region->Region_num_exits(), bb_region->Region_line_num());
01246
01247
01248
01249 emitter->Connect_sr_wn( region_start->Succ()->Node()->First_stmtrep(),
01250 region_wn );
01251
01252
01253 *bb = region_end->Next();
01254
01255 return region_wn;
01256 }
01257
01258
01259 static WN*
01260 Raise_unknown_stmt(EMITTER *emitter, BB_NODE **bb)
01261 {
01262 FmtAssert(FALSE, ("opt_emit: Raise unknown statement"));
01263 return NULL;
01264 }
01265
01266 typedef WN* (*RAISE_FUNC)(EMITTER *, BB_NODE **);
01267 static RAISE_FUNC raise_func[] = {
01268 Raise_unknown_stmt ,
01269 Raise_unknown_stmt ,
01270 Raise_if_stmt ,
01271 Raise_unknown_stmt ,
01272 Raise_unknown_stmt ,
01273 Raise_unknown_stmt ,
01274 Raise_doloop_stmt ,
01275 Raise_unknown_stmt ,
01276 Raise_unknown_stmt ,
01277 Raise_unknown_stmt ,
01278 Raise_unknown_stmt ,
01279 Raise_unknown_stmt ,
01280 Raise_unknown_stmt ,
01281 Raise_region_stmt ,
01282 Raise_unknown_stmt ,
01283 Raise_dowhile_stmt ,
01284 Raise_unknown_stmt ,
01285 Raise_unknown_stmt
01286 };
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303 void
01304 EMITTER::Gen_wn(BB_NODE *first_bb, BB_NODE *last_bb)
01305 {
01306 BB_NODE *prev_bb = NULL;
01307 BB_NODE *bb = first_bb;
01308 BB_NODE *next_bb;
01309 WN *stmt;
01310
01311 while (bb != NULL) {
01312 switch (bb->Kind()) {
01313 case BB_LOGIF:
01314 case BB_DOSTART:
01315 case BB_REPEATBODY:
01316 case BB_WHILEEND:
01317 if (!Can_raise_to_scf(bb))
01318 goto ordinary;
01319
01320 next_bb = bb;
01321 if (bb->Kind() == BB_WHILEEND)
01322 stmt = Raise_whiledo_stmt(this, bb, prev_bb, &next_bb);
01323 else
01324 stmt = (*raise_func[bb->Kind()])(this, & next_bb);
01325
01326 if ( WN_opcode(stmt) != OPC_BLOCK ) {
01327 bb->Init_stmt( stmt );
01328 } else {
01329 bb->Set_firststmt(WN_first(stmt));
01330 bb->Set_laststmt(WN_last(stmt));
01331 WN_Delete(stmt);
01332 }
01333 stmt = NULL;
01334
01335
01336 if (prev_bb) {
01337 if (prev_bb->Laststmt() != NULL)
01338 prev_bb->Connect_wn_list(bb->Firststmt(), bb->Laststmt());
01339 else {
01340 prev_bb->Set_firststmt(bb->Firststmt());
01341 prev_bb->Set_laststmt(bb->Laststmt());
01342 }
01343 }
01344
01345
01346 if ( next_bb != NULL && next_bb->Prev() == last_bb ) {
01347 return;
01348 }
01349
01350
01351 prev_bb = bb;
01352
01353
01354 bb = next_bb;
01355
01356 break;
01357
01358 case BB_ENTRY:
01359
01360 if (bb->Entrywn()) {
01361 const OPCODE entry_opc = WN_opcode(bb->Entrywn());
01362 if ( entry_opc == OPC_FUNC_ENTRY ) {
01363 goto ordinary;
01364 }
01365 else if ( entry_opc == OPC_ALTENTRY ||
01366 (entry_opc == OPC_LABEL &&
01367 (WN_Label_Is_Handler_Begin(bb->Entrywn())
01368 #ifdef KEY
01369 || LABEL_target_of_goto_outer_block(WN_label_number(bb->Entrywn()))
01370 #endif
01371 )) )
01372 {
01373 BOOL skip_curbb = Raise_altentry( bb );
01374
01375 if (!skip_curbb) {
01376 bb->Gen_wn(this);
01377 }
01378 if (prev_bb) {
01379 if (prev_bb->Laststmt() != NULL) {
01380 Is_True( WN_next(prev_bb->Laststmt()) == NULL,
01381 ("Next stmt of prev_bb last stmt is not NULL.") );
01382 prev_bb->Connect_wn_list(bb->Firststmt(), bb->Laststmt());
01383 } else {
01384 prev_bb->Set_firststmt(bb->Firststmt());
01385 prev_bb->Set_laststmt(bb->Laststmt());
01386 }
01387 }
01388 }
01389 else {
01390 FmtAssert( FALSE,
01391 ("EMITTER::Gen_wn: unknown entry opcode: %s",
01392 OPCODE_name(entry_opc)) );
01393 }
01394 }
01395
01396 prev_bb = bb;
01397 bb = bb->Next();
01398 break;
01399
01400 case BB_REGIONSTART:
01401 {
01402 BB_REGION *bb_region = bb->Regioninfo();
01403
01404
01405 if (RID_TYPE_mp(bb_region->Rid()) || RID_TYPE_eh(bb_region->Rid()) ||
01406
01407 RID_TYPE_olimit(bb_region->Rid()) ||
01408 #if defined(TARG_SL)
01409 RID_TYPE_sl2_para(bb_region->Rid()) ||
01410 #endif
01411 RID_TYPE_pragma(bb_region->Rid())) {
01412
01413 Is_True(bb_region->Region_start() == bb,
01414 ("EMITTER::Gen_wn, regioninfo is incorrect"));
01415
01416 Push_region(Region_stack(), bb, Loc_pool());
01417 BB_NODE *rstart = bb_region->Region_start();
01418 if (RID_TYPE_mp(bb_region->Rid())) {
01419 rstart->Gen_wn(this);
01420
01421 bb_region->Set_region_pragmas(Create_block_stmt(rstart,rstart));
01422 }
01423 Gen_wn(bb_region->Region_start()->Next(),
01424 bb_region->Region_end());
01425 WN *first, *last;
01426 bb_region->Find_first_last_stmt(bb_region->Region_start()->Next(),
01427 bb_region->Region_end(), &first, &last);
01428 stmt = Pop_region(Region_stack(), first, last,
01429 Cfg()->Rgn_level(), Opt_stab());
01430
01431
01432 if (stmt) {
01433 Is_True(WN_opcode(stmt) == OPC_REGION,
01434 ("EMITTER::Gen_wn, pop_region did not return a region"));
01435 bb->Init_stmt(stmt);
01436 stmt = NULL;
01437
01438
01439
01440 bb_region->Region_end()->Set_laststmt(bb->Laststmt());
01441
01442 if (prev_bb) {
01443 if (prev_bb->Laststmt() != NULL) {
01444 Is_True( WN_next(prev_bb->Laststmt()) == NULL,
01445 ("Next stmt of prev_bb last stmt is not NULL.") );
01446 prev_bb->Connect_wn_list(bb->Firststmt(), bb->Laststmt());
01447 } else {
01448 prev_bb->Set_firststmt(bb->Firststmt());
01449 prev_bb->Set_laststmt(bb->Laststmt());
01450 }
01451 }
01452 } else {
01453
01454 rstart->Set_firststmt(NULL);
01455 rstart->Set_laststmt(NULL);
01456
01457 RID_Delete2(bb_region->Rid());
01458 bb = prev_bb;
01459 }
01460
01461 if (bb_region->Region_end() == last_bb)
01462 return;
01463 prev_bb = bb;
01464 bb = bb_region->Region_end()->Next();
01465 } else
01466 goto ordinary;
01467 }
01468 break;
01469
01470 case BB_DOSTEP:
01471 case BB_EXIT:
01472 case BB_REGIONEXIT:
01473 case BB_GOTO:
01474 case BB_IO:
01475 case BB_VARGOTO:
01476 case BB_REPEATEND:
01477 case BB_DOEND:
01478 case BB_DOHEAD:
01479 case BB_DOTAIL:
01480 ordinary:
01481 if (bb->First_stmtrep()) {
01482 bb->Gen_wn(this);
01483
01484
01485 if (prev_bb) {
01486 if (prev_bb->Laststmt() != NULL) {
01487 Is_True( WN_next(prev_bb->Laststmt()) == NULL,
01488 ("Next stmt of prev_bb last stmt is not NULL.") );
01489 prev_bb->Connect_wn_list(bb->Firststmt(), bb->Laststmt());
01490 } else {
01491 prev_bb->Set_firststmt(bb->Firststmt());
01492 prev_bb->Set_laststmt(bb->Laststmt());
01493 #ifdef KEY // bug 1294
01494 if (bb != last_bb && bb->Succ() && !bb->Succ()->Multiple_bbs() &&
01495 bb->Succ()->Node() == bb->Next()) {
01496
01497
01498 BB_LIST *pred = bb->Next()->Pred();
01499 while (pred->Node() != bb)
01500 pred = pred->Next();
01501 pred->Set_node(prev_bb);
01502
01503
01504 prev_bb->Succ()->Set_node(bb->Next());
01505
01506 bb = bb->Next();
01507 break;
01508 }
01509 #endif
01510 }
01511 }
01512 }
01513 else {
01514 bb->Set_wngend();
01515 if (prev_bb) {
01516 bb->Set_laststmt(prev_bb->Laststmt());
01517 bb->Set_firststmt(prev_bb->Firststmt());
01518 }
01519 }
01520 if (bb == last_bb)
01521 return;
01522 prev_bb = bb;
01523 bb = bb->Next();
01524 break;
01525
01526 default:
01527 FmtAssert(FALSE, ("EMITTER::Gen_wn: Illegal BB_KIND "));
01528 break;
01529 }
01530 }
01531 }
01532
01533 WN *
01534 EMITTER::Emit(COMP_UNIT *cu, DU_MANAGER *du_mgr,
01535 ALIAS_MANAGER *alias_mgr )
01536 {
01537 _htable = cu->Htable();
01538 _cfg = cu->Cfg();
01539 _opt_stab = cu->Opt_stab();
01540 _trace = Get_Trace(TP_GLOBOPT, EMIT_DUMP_FLAG);
01541 _alias_mgr = alias_mgr;
01542 _du_mgr = du_mgr;
01543
01544
01545
01546 Cfg()->Analyze_loops();
01547
01548 {
01549 CFG_ITER cfg_iter;
01550 BB_NODE *bb;
01551 FOR_ALL_ELEM (bb, cfg_iter, Init(Cfg())) {
01552 if (bb->Kind() == BB_WHILEEND && WOPT_Enable_While_Loop) {
01553 if (Can_raise_to_doloop(bb->Innermost(), TRUE, Htable())) {
01554 if (_trace)
01555 fprintf(TFile, "EMIT: BB%d can raise to do-loop\n", bb->Id());
01556 } else {
01557 if (_trace)
01558 fprintf(TFile, "EMIT: BB%d cannot raise to do-loop\n", bb->Id());
01559 }
01560 } else if (bb->Kind() == BB_DOEND) {
01561 Fix_do_loop(bb->Loop(), Htable());
01562 }
01563 }
01564 }
01565
01566
01567 du_mgr->Set_alias_mgr(alias_mgr);
01568
01569
01570 Raise_func_entry(Cfg()->Func_entry_bb(), Cfg()->Last_bb());
01571
01572
01573 Compute_use_def(du_mgr);
01574
01575
01576 #ifdef Is_True_On
01577 {
01578 CFG_ITER cfg_iter;
01579 BB_NODE *bb;
01580 FOR_ALL_ELEM (bb, cfg_iter, Init(Cfg())) {
01581 PHI_NODE *phi;
01582 PHI_LIST_ITER phi_iter;
01583 FOR_ALL_ELEM (phi, phi_iter, Init(bb->Phi_list())) {
01584 Is_True(!phi->Visited(), ("EMITTER::PHI visted bit is not reset."));
01585 }
01586 }
01587 }
01588 #endif
01589
01590
01591
01592 if (Cur_PU_Feedback) {
01593 Set_PU_Info_state(Current_PU_Info, WT_FEEDBACK, Subsect_InMem);
01594 }
01595
01596 Is_True(Get_Preg_Num(PREG_Table_Size(CURRENT_SYMTAB)) ==
01597 Opt_stab()->Last_preg(),
01598 ("EMITTER:Emit, incorrect last preg number"));
01599
01600 #if !defined(TARG_NVISA)
01601 {
01602 BOOL tr = _trace || Get_Trace (TP_GLOBOPT, ALIAS_DUMP_FLAG);
01603 if (Opt_stab()->Phase() == PREOPT_LNO_PHASE) {
01604 Opt_stab()->Cr_sr_annot_mgr()->Export_annot
01605 (_opt_func, alias_mgr, FALSE, tr);
01606 } else {
01607 Opt_stab()->Cr_sr_annot_mgr()->Discard_offline_annot
01608 (_opt_func, alias_mgr, tr);
01609 }
01610 WN_MEMOP_ANNOT_MGR::WN_mem_annot_mgr()->Set_active_mgr();
01611 }
01612 #endif
01613
01614 Verify(_opt_func);
01615
01616 if (_trace) {
01617 fprintf( TFile, "%sAfter EMITTER\n%s", DBar, DBar );
01618 if (! Cur_PU_Feedback) {
01619 IR_dump_map_info = TRUE;
01620 fdump_tree( TFile, _opt_func);
01621 }
01622 else fdump_tree_with_freq( TFile, _opt_func, WN_MAP_FEEDBACK);
01623 }
01624
01625 return _opt_func;
01626 }
01627
01628
01629
01630
01631
01632
01633
01634
01635 BOOL
01636 EMITTER::Can_raise_to_scf(BB_NODE *bb)
01637 {
01638 Warn_todo("Cleanup gotos and labels in CFG.");
01639 BB_LIST_ITER bb_pred_iter;
01640 switch (bb->Kind()) {
01641 BB_NODE *bb_start;
01642 BB_NODE *bb_body;
01643 BB_NODE *bb_end;
01644 BB_NODE *bb_step;
01645 BB_NODE *bb_merge;
01646 STMTREP *new_goto;
01647 BB_NODE *pred;
01648 case BB_LOGIF:
01649 if (bb->Ifinfo() != NULL &&
01650 bb->Succ()->Contains(bb->If_then()) &&
01651 bb->Succ()->Contains(bb->If_else()))
01652 return TRUE;
01653 if (bb->Ifinfo() != NULL && bb->If_merge() != NULL) {
01654 if (bb->If_merge()->Label_stmtrep() == NULL) {
01655 if (bb->If_merge()->Labnam() == 0)
01656 bb->If_merge()->Set_labnam( _cfg->Alloc_label());
01657 bb->If_merge()->Add_label_stmtrep(Mem_pool());
01658 }
01659 FOR_ALL_ELEM( pred, bb_pred_iter, Init(bb->If_merge()->Pred())) {
01660 if (pred->Branch_stmtrep() == NULL) {
01661 new_goto = CXX_NEW( STMTREP(OPC_GOTO), Mem_pool() );
01662 new_goto->Init_Goto( NULL, bb->If_merge()->Labnam(), 0 );
01663 pred->Append_stmtrep( new_goto );
01664 }
01665 }
01666 }
01667 break;
01668 case BB_REGIONSTART:
01669 return TRUE;
01670 case BB_DOSTART:
01671 bb_start = bb;
01672 bb_end = bb_start->Loopend();
01673 bb_step = bb_start->Loopstep();
01674 bb_merge = bb_start->Loopmerge();
01675 #ifdef KEY // bug 8327: the incr stmt has been optimized to something else
01676
01677
01678
01679
01680
01681
01682 if (bb_step->Stmtlist()->Tail() == NULL ||
01683 ((bb_step->Stmtlist()->Tail()->Opr() != OPR_STID ||
01684 bb_step->Stmtlist()->Tail()->Rhs()->Kind() != CK_OP) &&
01685
01686 (bb_step->Stmtlist()->Tail()->Prev() == NULL ||
01687 bb_step->Stmtlist()->Tail()->Prev()->Opr() != OPR_STID ||
01688 bb_step->Stmtlist()->Tail()->Prev()->Rhs()->Kind() != CK_OP)))
01689 ;
01690 else
01691 #endif
01692 if (bb_step->Succ()->Contains(bb_end) &&
01693 bb_end->Succ()->Contains(bb_merge))
01694 return TRUE;
01695
01696 new_goto = CXX_NEW( STMTREP(OPC_GOTO), Mem_pool() );
01697 new_goto->Init_Goto( NULL, bb_end->Labnam(), 0 );
01698 bb_step->Append_stmtrep( new_goto );
01699 if (bb_end->Label_stmtrep() == NULL) {
01700 if (bb_end->Labnam() == 0)
01701 bb_end->Set_labnam( _cfg->Alloc_label());
01702 bb_end->Add_label_stmtrep(Mem_pool());
01703 }
01704 if (bb_merge->Label_stmtrep() == NULL) {
01705 if (bb_merge->Labnam() == 0)
01706 bb_merge->Set_labnam( _cfg->Alloc_label());
01707 bb_merge->Add_label_stmtrep(Mem_pool());
01708 }
01709 break;
01710 case BB_WHILEEND:
01711 bb_end = bb;
01712 bb_body = bb_end->Loopbody();
01713 bb_merge = bb_end->Loopmerge();
01714 if (bb_end->Succ()->Contains(bb_body) &&
01715 bb_end->Succ()->Contains(bb_merge) &&
01716 bb_end->Next() == bb_body)
01717 return TRUE;
01718 if (bb_end->Label_stmtrep() == NULL) {
01719 if (bb_end->Labnam() == 0)
01720 bb_end->Set_labnam( _cfg->Alloc_label());
01721 bb_end->Add_label_stmtrep(Mem_pool());
01722 }
01723 if (bb_merge->Label_stmtrep() == NULL) {
01724 if (bb_merge->Labnam() == 0)
01725 bb_merge->Set_labnam( _cfg->Alloc_label());
01726 bb_merge->Add_label_stmtrep(Mem_pool());
01727 }
01728 FOR_ALL_ELEM( pred, bb_pred_iter, Init(bb_merge->Pred())) {
01729 if (pred->Branch_stmtrep() == NULL) {
01730 new_goto = CXX_NEW( STMTREP(OPC_GOTO), Mem_pool() );
01731 new_goto->Init_Goto( NULL, bb_merge->Labnam(), 0 );
01732 pred->Append_stmtrep( new_goto );
01733 }
01734 }
01735 break;
01736 case BB_REPEATBODY:
01737 bb_body = bb;
01738 bb_end = bb_body->Loopend();
01739 bb_merge = bb_body->Loopmerge();
01740 if (bb_end->Succ()->Contains(bb_body) &&
01741 bb_end->Succ()->Contains(bb_merge) &&
01742 bb_end->Next() == bb_merge)
01743 return TRUE;
01744 if (bb_end->Label_stmtrep() == NULL) {
01745 if (bb_end->Labnam() == 0)
01746 bb_end->Set_labnam( _cfg->Alloc_label());
01747 bb_end->Add_label_stmtrep(Mem_pool());
01748 }
01749 break;
01750 }
01751 return FALSE;
01752 }
01753
01754
01755
01756
01757 void
01758 BB_REGION::Find_first_last_stmt(BB_NODE *first_bb, BB_NODE *last_bb,
01759 WN **first_stmt, WN **last_stmt)
01760 {
01761 BB_NODE *bbtmp;
01762
01763
01764
01765
01766 if (last_bb == NULL) {
01767 BB_NODE *bb = first_bb;
01768 while (bb && bb->Rid_id() == first_bb->Rid_id()) {
01769 last_bb = bb;
01770 bb = bb->Next();
01771 }
01772 DevWarn("fixing region %d with first_bb BB%d to have region_end BB%d\n",
01773 first_bb->Rid_id(),first_bb->Id(), last_bb->Id());
01774 Set_region_end(last_bb);
01775 }
01776
01777 Is_True(first_bb != NULL && last_bb != NULL,
01778 ("BB_REGION::Find_first_last_stmt, NULL BBs"));
01779
01780 if (first_bb->Firststmt())
01781 *first_stmt = first_bb->Firststmt();
01782 else {
01783 *first_stmt = NULL;
01784 bbtmp = first_bb;
01785 do {
01786 if (bbtmp->Firststmt()) {
01787 *first_stmt = bbtmp->Firststmt();
01788 break;
01789 }
01790
01791
01792 Is_True(bbtmp->Succ()->Next() == NULL,
01793 ("BB_REGION::Find_first_last_stmt, unexpected control flow split"));
01794 if (bbtmp == last_bb)
01795 break;
01796 bbtmp = bbtmp->Next();
01797 } while (1);
01798 }
01799
01800 if (last_bb->Last_stmtrep())
01801 *last_stmt = last_bb->Laststmt();
01802 else {
01803 *last_stmt = NULL;
01804 bbtmp = last_bb;
01805 do {
01806 if (bbtmp->Laststmt()) {
01807 *last_stmt = bbtmp->Laststmt();
01808 break;
01809 }
01810
01811
01812 if (bbtmp == first_bb)
01813 break;
01814 bbtmp = bbtmp->Prev();
01815 } while (1);
01816 }
01817 }
01818
01819
01820
01821
01822 BOOL
01823 EMITTER::Verify(WN *wn)
01824 {
01825 INT32 i;
01826 WN *stmt;
01827
01828 if (wn == NULL)
01829 return TRUE;
01830
01831 if (WN_opcode(wn) == OPC_BLOCK) {
01832 if (WN_first(wn) && WN_prev(WN_first(wn))) {
01833 fprintf(stderr, "### EMIT::Verify, WN_first has prev stmt.\n");
01834 fprintf(TFile, "### EMIT::Verify, WN_first has prev stmt.\n");
01835 fdump_tree(TFile,wn);
01836 fprintf(TFile, "### prev stmt is\n");
01837 fdump_tree(TFile,WN_prev(WN_first(wn)));
01838 }
01839 if (WN_last(wn) && WN_next(WN_last(wn))) {
01840 fprintf(stderr, "### EMIT::Verify, WN_last has next stmt.\n");
01841 fprintf(TFile, "### EMIT::Verify, WN_last has next stmt.\n");
01842 fdump_tree(TFile,wn);
01843 fprintf(TFile, "### next stmt is\n");
01844 fdump_tree(TFile,WN_next(WN_last(wn)));
01845 }
01846 for (stmt = WN_first(wn); stmt != NULL; stmt = WN_next(stmt))
01847 Verify(stmt);
01848 } else if (WN_opcode(wn) == OPC_FUNC_ENTRY) {
01849
01850 Verify(WN_func_body(wn));
01851 } else
01852 for (i = 0; i < WN_kid_count(wn); i++)
01853 Verify(WN_kid(wn,i));
01854 return TRUE;
01855 }
01856
01857 EMITTER::EMITTER(MEM_POOL *lpool, MEM_POOL *gpool, OPT_PHASE opt_phase):
01858 _loc_pool(lpool),
01859 _mem_pool(gpool),
01860 _opt_phase(opt_phase),
01861 _region_stack(lpool),
01862 _preg_renumbering_map(128, 0, lpool, FALSE)
01863 {
01864 _cfg = NULL;
01865 _htable = NULL;
01866 _opt_stab = NULL;
01867 _opt_func = NULL;
01868 _rgn_entry_stmt = NULL;
01869 _has_do_loop = FALSE;
01870
01871
01872 _wn_to_cr_map = WN_MAP_Create(Mem_pool());
01873 }
01874
01875 EMITTER::~EMITTER(void)
01876 {
01877
01878 WN_MAP_Delete( _wn_to_cr_map );
01879 }