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
00065
00066
00067
00068
00069
00070
00071
00072
00073 #ifdef USE_PCH
00074 #include "opt_pch.h"
00075 #endif // USE_PCH
00076 #pragma hdrstop
00077
00078
00079 #ifdef _KEEP_RCS_ID
00080 #define opt_loop_CXX "opt_loop.cxx"
00081 static char *rcs_id = opt_loop_CXX"$Revision: 1.7 $";
00082 #endif
00083
00084 #define USE_STANDARD_TYPES
00085 #include <set>
00086 #include <algorithm>
00087
00088 #include "defs.h"
00089 #include "config.h"
00090 #include "errors.h"
00091 #include "erglob.h"
00092 #include "tracing.h"
00093 #include "cxx_memory.h"
00094 #include "wn.h"
00095 #include "wn_util.h"
00096 #include "region_util.h"
00097 #include "stab.h"
00098
00099 #include "opt_base.h"
00100 #include "opt_bb.h"
00101 #include "bb_node_set.h"
00102 #include "opt_ivr.h"
00103 #include "opt_main.h"
00104 #include "opt_util.h"
00105 #include "opt_wn.h"
00106 #include "opt_mu_chi.h"
00107 #include "opt_alias_rule.h"
00108
00109 using std::set;
00110
00111
00112
00113
00114
00115
00116
00117
00118 class NORMALIZE_LOOP {
00119 private:
00120 WN_MAP _wn_map;
00121 OPT_PHASE _phase;
00122
00123
00124 NORMALIZE_LOOP(void);
00125 NORMALIZE_LOOP(const NORMALIZE_LOOP&);
00126 NORMALIZE_LOOP& operator = (const NORMALIZE_LOOP&);
00127
00128 BOOL Check_if_index_is_passed(WN *wn, ST *st);
00129 BOOL Find_barrier_in_tree(WN *wn);
00130 BOOL Is_pdo_loop(WN *wn);
00131 WN *Find_enclosing_parallel_region(WN *wn);
00132 BOOL Is_outermost_loop_in_parallel_region(WN *,WN_PRAGMA_ID);
00133 WN *Normalize_do_loop( WN *wn, OPT_PHASE phase );
00134
00135 public:
00136 NORMALIZE_LOOP( WN_MAP wn_map, OPT_PHASE phase )
00137 : _wn_map(wn_map), _phase(phase) { }
00138 ~NORMALIZE_LOOP( void ) { }
00139
00140 WN *Normalize_loop_stmt(WN *wn, WN *parent);
00141 };
00142
00143
00144
00145
00146 static BOOL
00147 Find_addr_passed(WN *wn, ST *st)
00148 {
00149 OPERATOR opr = WN_operator(wn);
00150
00151 if (OPERATOR_is_load(opr))
00152 return FALSE;
00153
00154 if (opr == OPR_LDA) {
00155 if (WN_st(wn) == st)
00156 return TRUE;
00157 else
00158 return FALSE;
00159 }
00160 for (INT i = 0; i < WN_kid_count(wn); i++)
00161 if (Find_addr_passed(WN_kid(wn,i), st))
00162 return TRUE;
00163
00164 return FALSE;
00165 }
00166
00167
00168
00169
00170
00171 BOOL
00172 NORMALIZE_LOOP::Check_if_index_is_passed(WN *wn, ST *st)
00173 {
00174 if (wn == NULL)
00175 return FALSE;
00176
00177 OPCODE opc = WN_opcode(wn);
00178 OPERATOR opr = OPCODE_operator(opc);
00179
00180 if (OPCODE_is_call(opc)) {
00181 for (INT32 i = 0; i < WN_kid_count(wn); i++) {
00182 WN *kid = WN_kid(wn,i);
00183 if (WN_operator(kid) == OPR_PARM &&
00184 Find_addr_passed(kid, st))
00185 return TRUE;
00186 }
00187 }
00188 else if (opr == OPR_BLOCK) {
00189 for (WN *stmt = WN_first(wn); stmt != NULL; stmt = WN_next(stmt))
00190 if (Check_if_index_is_passed(stmt, st))
00191 return TRUE;
00192 } else if (! OPCODE_is_black_box(opc)) {
00193 for (INT32 i = 0; i < WN_kid_count(wn); i++)
00194 if (Check_if_index_is_passed(WN_kid(wn,i), st))
00195 return TRUE;
00196 }
00197 return FALSE;
00198 }
00199
00200
00201
00202
00203 BOOL
00204 NORMALIZE_LOOP::Find_barrier_in_tree(WN *wn)
00205 {
00206 if (wn == NULL)
00207 return FALSE;
00208
00209 OPCODE opc = WN_opcode(wn);
00210 OPERATOR opr = OPCODE_operator(opc);
00211
00212 if (opr == OPR_FORWARD_BARRIER ||
00213 opr == OPR_BACKWARD_BARRIER)
00214 return TRUE;
00215
00216 else if (opr == OPR_BLOCK) {
00217 for (WN *stmt = WN_first(wn); stmt != NULL; stmt = WN_next(stmt))
00218 if (Find_barrier_in_tree(stmt))
00219 return TRUE;
00220 } else if (! OPCODE_is_black_box(opc)) {
00221 for (INT32 i = 0; i < WN_kid_count(wn); i++)
00222 if (Find_barrier_in_tree(WN_kid(wn,i)))
00223 return TRUE;
00224 }
00225 return FALSE;
00226 }
00227
00228
00229
00230 WN *
00231 NORMALIZE_LOOP::Find_enclosing_parallel_region(WN *wn)
00232 {
00233 WN *parent = (WN *) WN_MAP_Get(_wn_map, wn);
00234 while (parent != NULL && WN_opcode(parent) != OPC_FUNC_ENTRY) {
00235 if (WN_opcode(parent) == OPC_REGION)
00236 return parent;
00237 parent = (WN *) WN_MAP_Get(_wn_map, parent);
00238 }
00239 return NULL;
00240 }
00241
00242
00243 BOOL
00244 NORMALIZE_LOOP::Is_pdo_loop(WN *wn)
00245 {
00246 WN *parent = (WN *) WN_MAP_Get(_wn_map, wn);
00247
00248 Is_True(WN_opcode(parent) == OPC_BLOCK,
00249 ("NORMALIZE_LOOP::Is_pdo_loop: do loop's parent node is not block"));
00250
00251 parent = (WN *) WN_MAP_Get(_wn_map, parent);
00252
00253
00254 if (WN_opcode(parent) != OPC_REGION)
00255 return FALSE;
00256
00257 return Is_region_with_pragma(parent,WN_PRAGMA_PDO_BEGIN);
00258 }
00259
00260
00261
00262
00263
00264
00265 BOOL
00266 NORMALIZE_LOOP::Is_outermost_loop_in_parallel_region(
00267 WN *wn,
00268 WN_PRAGMA_ID pragma_id )
00269 {
00270 WN *parent = (WN *) WN_MAP_Get(_wn_map, wn);
00271
00272 Is_True(WN_opcode(parent) == OPC_BLOCK,
00273 ("NORMALIZE_LOOP::Is_outermost_loop_in_parallel_region: do loop's parent node is not block"));
00274
00275 parent = (WN *) WN_MAP_Get(_wn_map, parent);
00276
00277
00278
00279 while ( parent != NULL && WN_operator(parent) != OPR_FUNC_ENTRY ) {
00280 OPERATOR oper = WN_operator(parent);
00281
00282 if ( oper == OPR_FUNC_ENTRY )
00283 return FALSE;
00284 else if ( oper == OPR_DO_LOOP )
00285 return FALSE;
00286 else if ( oper == OPR_REGION ) {
00287 if ( Is_region_with_pragma(parent,pragma_id) ) {
00288 return TRUE;
00289 }
00290 }
00291
00292
00293 parent = (WN *) WN_MAP_Get(_wn_map, parent);
00294 }
00295
00296 return FALSE;
00297 }
00298
00299
00300
00301
00302
00303
00304
00305
00306 WN *
00307 NORMALIZE_LOOP::Normalize_do_loop( WN *wn, OPT_PHASE phase )
00308 {
00309 const OPCODE opc = WN_opcode(wn);
00310 Is_True( opc == OPC_DO_LOOP,
00311 ("Normalize_do_loop: Not a loop: %s", OPCODE_name(opc)) );
00312
00313 WN *step = WN_step(wn);
00314 if (WN_operator(step) == OPR_STID &&
00315 ((WN_operator(WN_kid0(step)) == OPR_ADD &&
00316 WN_operator(WN_kid0(WN_kid0(step))) == OPR_INTCONST &&
00317 WN_const_val(WN_kid0(WN_kid0(step))) != 1) ||
00318 (WN_operator(WN_kid0(step)) == OPR_ADD &&
00319 WN_operator(WN_kid1(WN_kid0(step))) == OPR_INTCONST &&
00320 WN_const_val(WN_kid1(WN_kid0(step))) != 1) ||
00321 (WN_operator(WN_kid0(step)) == OPR_SUB &&
00322 WN_operator(WN_kid1(WN_kid0(step))) == OPR_INTCONST &&
00323 WN_const_val(WN_kid1(WN_kid0(step))) != -1)))
00324 {
00325 WN *oldstep = WN_step(wn);
00326 WN *oldstart = WN_start(wn);
00327
00328
00329
00330
00331
00332
00333
00334 if (phase != MAINOPT_PHASE && ST_class(WN_st(oldstart)) == CLASS_VAR) {
00335 ST *index_st = WN_st(oldstart);
00336 if (ST_sclass(index_st) != SCLASS_AUTO &&
00337 ST_sclass(index_st) != SCLASS_PSTATIC &&
00338 ST_sclass(index_st) != SCLASS_FORMAL_REF)
00339 return NULL;
00340 if (Check_if_index_is_passed(WN_do_body(wn), index_st))
00341 return NULL;
00342 }
00343
00344
00345
00346
00347 if (phase != MAINOPT_PHASE &&
00348 Find_barrier_in_tree(WN_do_body(wn)))
00349 return NULL;
00350
00351 if (phase != PREOPT_PHASE &&
00352 phase != PREOPT_LNO_PHASE &&
00353 phase != PREOPT_IPA0_PHASE &&
00354 phase != PREOPT_IPA1_PHASE)
00355 return NULL;
00356
00357
00358
00359
00360 if ( !WOPT_Enable_IVR_Outermost_Loop_Parallel_Region &&
00361 (Is_outermost_loop_in_parallel_region(wn,WN_PRAGMA_PDO_BEGIN)))
00362 {
00363 return NULL;
00364 }
00365
00366
00367 WN *newblock = WN_CreateBlock();
00368 WN_Set_Linenum(newblock, WN_Get_Linenum(wn));
00369 WN_INSERT_BlockBefore(newblock, NULL, oldstart);
00370
00371 MTYPE mtype = WN_desc (oldstep );
00372
00373
00374
00375 if (mtype != MTYPE_I4 && mtype != MTYPE_I8)
00376 return NULL;
00377
00378 ST *preg_st = (MTYPE_size_min(mtype) > 32) ? Int64_Preg : Int32_Preg;
00379
00380 TY_IDX ty = WN_ty(WN_kid0(WN_kid0(step)));
00381 IDTYPE newindex = Create_Preg(TY_mtype(ST_type(preg_st)),".do_ivar", NULL);
00382 WN *kid0, *kid1, *init, *incr;
00383 kid0 = WN_CreateIntconst( OPCODE_make_op(OPR_INTCONST, mtype, MTYPE_V),
00384 (INT64) 0 );
00385 init = WN_CreateStid(OPCODE_make_op(OPR_STID, MTYPE_V, mtype),
00386 newindex, preg_st, ty, kid0);
00387 WN_CopyMap(init, RID_map, wn);
00388 WN_Set_Linenum(init, WN_Get_Linenum(wn));
00389
00390 kid0 = WN_CreateLdid(OPCODE_make_op(OPR_LDID, mtype, mtype),
00391 newindex, preg_st, ty);
00392 kid1 = WN_CreateIntconst( OPCODE_make_op(OPR_INTCONST, mtype, MTYPE_V),
00393 (INT64) 1 );
00394 kid0 = WN_CreateExp2(OPCODE_make_op(OPR_ADD, mtype, MTYPE_V),
00395 kid0, kid1);
00396 incr = WN_CreateStid(OPCODE_make_op(OPR_STID, MTYPE_V, mtype),
00397 newindex, preg_st, ty, kid0);
00398 WN_CopyMap(incr, RID_map, wn);
00399 WN_Set_Linenum(incr, WN_Get_Linenum(wn));
00400
00401 Is_True(WN_opcode(WN_do_body(wn)) == OPC_BLOCK,
00402 ("DO_LOOP body is not OPC_BLOCK."));
00403
00404 WN_next(oldstep) = WN_prev(oldstep) = NULL;
00405 WN_INSERT_BlockBefore( WN_do_body(wn), NULL, oldstep );
00406 WN *newloop = WN_CreateDO(WN_CreateIdname(newindex, preg_st),
00407 init, WN_end(wn), incr, WN_do_body(wn), NULL);
00408 WN_COPY_All_Maps(newloop, wn);
00409
00410 WN_CopyMap(newloop, RID_map, wn);
00411 if ( Cur_PU_Feedback )
00412 Cur_PU_Feedback->FB_duplicate_node( wn, newloop );
00413 WN_Set_Linenum(newloop, WN_Get_Linenum(wn));
00414 Set_wn_flags( newloop, Wn_flags(newloop) | WN_FLAG_DO_LOOP);
00415
00416 WN_INSERT_BlockBefore( newblock, NULL, newloop);
00417
00418
00419 WN *region_wn = wn;
00420 while (region_wn = Find_enclosing_parallel_region(region_wn)) {
00421 WN *pragma_block = WN_region_pragmas(region_wn);
00422 STMT_ITER stmt_iter; WN *stmt;
00423 FOR_ALL_ELEM (stmt, stmt_iter,
00424 Init(WN_first(pragma_block), WN_last(pragma_block))) {
00425 if (WN_operator(stmt) == OPR_PRAGMA &&
00426 (WN_pragma(stmt) == WN_PRAGMA_LASTLOCAL ||
00427 WN_pragma(stmt) == WN_PRAGMA_LOCAL ||
00428 WN_pragma(stmt) == WN_PRAGMA_SHARED ||
00429 WN_pragma(stmt) == WN_PRAGMA_FIRSTPRIVATE ||
00430 WN_pragma(stmt) == WN_PRAGMA_REDUCTION) &&
00431 WN_st(stmt) == WN_st(oldstart) &&
00432 WN_pragma_arg1(stmt) == WN_offset(oldstart)) {
00433 WN_PRAGMA_ID pragma_id = (WN_PRAGMA_ID) WN_pragma(stmt);
00434 WN *new_pragma = WN_CreatePragma(pragma_id, preg_st, newindex, 0);
00435 WN_INSERT_BlockBefore( pragma_block, stmt, new_pragma);
00436 return newblock;
00437 }
00438 }
00439 }
00440 return newblock;
00441 }
00442
00443 return NULL;
00444 }
00445
00446
00447
00448
00449 WN *
00450 NORMALIZE_LOOP::Normalize_loop_stmt(WN *wn, WN *parent)
00451 {
00452 if (wn == NULL)
00453 return NULL;
00454
00455 const OPCODE opc = WN_opcode(wn);
00456
00457 WN_MAP_Set(_wn_map, wn, (void *)parent);
00458
00459 if ( opc == OPC_BLOCK ) {
00460 WN *stmt, *replace, *nextstmt = NULL;
00461 for ( stmt = WN_first(wn); stmt != NULL; stmt = nextstmt ) {
00462
00463
00464 nextstmt = WN_next(stmt);
00465 if ( (replace = Normalize_loop_stmt(stmt, wn)) != NULL ) {
00466
00467
00468 WN_INSERT_BlockAfter( wn, stmt, replace );
00469 WN_EXTRACT_FromBlock( wn, stmt );
00470
00471
00472
00473
00474 WN_Delete(stmt);
00475 }
00476 }
00477 } else {
00478 for (INT i = 0; i < WN_kid_count(wn); i++) {
00479 if (OPCODE_is_scf(WN_opcode(WN_kid(wn,i)))) {
00480 WN *insert = Normalize_loop_stmt(WN_kid(wn,i), wn);
00481 Is_True(insert == NULL, ("not a BLOCK"));
00482 }
00483 }
00484 }
00485
00486 if (opc == OPC_DO_LOOP)
00487 return Normalize_do_loop( wn, _phase );
00488
00489 return NULL;
00490 }
00491
00492
00493 WN *
00494 COMP_UNIT::Normalize_loop(WN *wn)
00495 {
00496 if (wn == NULL)
00497 return NULL;
00498
00499 OPT_POOL_Push( Loc_pool(), -1 );
00500 WN_MAP wn_map = WN_MAP_Create( Loc_pool());
00501
00502 WN *result;
00503 {
00504 NORMALIZE_LOOP norm_loop(wn_map, _phase);
00505 result = norm_loop.Normalize_loop_stmt(wn, NULL);
00506 }
00507
00508 WN_MAP_Delete(wn_map);
00509 OPT_POOL_Pop( Loc_pool(), -1);
00510 return result;
00511 }
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531 BOOL
00532 BB_LOOP::Invariant_cr_rec( CODEREP *cr ) const
00533 {
00534
00535 if ( inCODEKIND( cr->Kind(), CK_LDA | CK_CONST | CK_RCONST ) ) {
00536 return TRUE;
00537 }
00538
00539
00540
00541 if ( cr->Is_flag_set( CF_DEF_BY_PHI ) ) {
00542 return ( ! True_body_set()->MemberP( cr->Defphi()->Bb() ) );
00543 }
00544
00545
00546
00547 if ( cr->Is_flag_set( CF_DEF_BY_CHI ) ) {
00548 return ( ! True_body_set()->MemberP( cr->Defstmt()->Bb() ) );
00549 }
00550
00551 switch ( cr->Kind() ) {
00552 case CK_VAR:
00553
00554 if ( cr->Is_var_volatile() ) {
00555 return FALSE;
00556 }
00557
00558
00559 if ( cr->Defstmt() == NULL ) {
00560 return FALSE;
00561 }
00562
00563 return ( ! True_body_set()->MemberP( cr->Defstmt()->Bb() ) );
00564
00565 case CK_IVAR:
00566 {
00567 CODEREP *base =
00568 cr->Istr_base() ? cr->Istr_base() : cr->Ilod_base();
00569 if ( ! Invariant_cr_rec(base) )
00570 return FALSE;
00571 if ( cr->Opr() == OPR_MLOAD && ! Invariant_cr_rec( cr->Mload_size() ) )
00572 return FALSE;
00573 if ( cr->Opr() == OPR_ILOADX && ! Invariant_cr_rec( cr->Index() ) )
00574 return FALSE;
00575 MU_NODE *mnode = cr->Ivar_mu_node();
00576 if ( mnode ) {
00577 CODEREP *opnd = mnode->OPND();
00578 if ( opnd && ! Invariant_cr_rec( opnd ) )
00579 return FALSE;
00580 }
00581 }
00582
00583
00584 if ( cr->Is_ivar_volatile() )
00585 return FALSE;
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595 return TRUE;
00596
00597 case CK_OP:
00598 {
00599 if ( cr->Is_isop_flag_set( ISOP_INVARIANT_VISITED )
00600 && WOPT_Enable_Prune )
00601 return TRUE;
00602
00603
00604 for ( INT32 ikid = 0; ikid < cr->Kid_count(); ikid++ ) {
00605 if ( ! Invariant_cr_rec( cr->Opnd( ikid ) ) ) {
00606 if ( WOPT_Enable_Prune ) {
00607 for ( INT32 j = 0; j < ikid; j++ )
00608 cr->Opnd(j)->Reset_isop_visited( ISOP_INVARIANT_VISITED );
00609 }
00610 return FALSE;
00611 }
00612 }
00613
00614 if ( WOPT_Enable_Prune )
00615 cr->Set_isop_flag( ISOP_INVARIANT_VISITED );
00616 return TRUE;
00617 }
00618
00619 default:
00620 FmtAssert( FALSE, ("BB_LOOP::Invariant_cr_rec: Bad coderep") );
00621 return FALSE;
00622 }
00623 }
00624
00625
00626 BOOL
00627 BB_LOOP::Invariant_cr( CODEREP *cr ) const
00628 {
00629 if ( this == NULL )
00630 return FALSE;
00631
00632 BOOL ret = Invariant_cr_rec( cr );
00633 if ( ret && WOPT_Enable_Prune )
00634 cr->Reset_isop_visited( ISOP_INVARIANT_VISITED );
00635 return ret;
00636 }
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650 BOOL
00651 BB_LOOP::Index_relative_expr( CODEREP *expr, const CODEREP *index ) const
00652 {
00653 Is_True( index->Kind() == CK_VAR,
00654 ( "BB_LOOP::Index_relative_expr: index is not var" ) );
00655
00656 switch ( expr->Kind() ) {
00657 case CK_OP:
00658 {
00659 for ( INT32 ekid = 0; ekid < expr->Kid_count(); ekid++ ) {
00660 if ( ! Index_relative_expr( expr->Opnd( ekid ), index ) )
00661 return FALSE;
00662 }
00663 }
00664 return TRUE;
00665
00666 case CK_VAR:
00667
00668 return ( expr == index || Invariant_cr( expr ) );
00669
00670 case CK_IVAR:
00671 return ( Invariant_cr( expr ) );
00672
00673 case CK_LDA:
00674 case CK_CONST:
00675 case CK_RCONST:
00676 return TRUE;
00677
00678 default:
00679 FmtAssert( FALSE, ( "BB_LOOP::Index_relative_expr: invalid kind" ) );
00680 break;
00681 }
00682
00683
00684 return FALSE;
00685 }
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701 CODEREP *Find_variant(BB_LOOP *loop, CODEREP *expr)
00702 {
00703 switch (expr->Kind()) {
00704 case CK_LDA:
00705 case CK_CONST:
00706 case CK_RCONST:
00707 return NULL;
00708
00709 case CK_IVAR:
00710 case CK_VAR:
00711 if (loop->Invariant_cr(expr))
00712 return NULL;
00713 else
00714 return expr;
00715
00716 case CK_OP:
00717 {
00718 for (INT i = 0; i < expr->Kid_count(); i++) {
00719 CODEREP *variant = Find_variant( loop, expr->Opnd(i) );
00720 if ( variant )
00721 return variant;
00722 }
00723 return NULL;
00724 }
00725
00726 default:
00727 Is_True( FALSE, ( "BB_LOOP::Find_variant: unsupported CK_KIND" ) );
00728 }
00729 return NULL;
00730 }
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750 enum EXPR_TYPE { INVAR_EXPR, LINEAR_EXPR, NON_LINEAR_EXPR };
00751
00752 struct LINEAR_FUNCTION {
00753 EXPR_TYPE type;
00754 CODEREP *variant;
00755 LINEAR_FUNCTION(EXPR_TYPE e, CODEREP *v) : type(e), variant(v) {}
00756 LINEAR_FUNCTION(EXPR_TYPE e) : type(e) {}
00757 };
00758
00759
00760 static LINEAR_FUNCTION
00761 Linear_function(BB_LOOP *loop, CODEREP *expr)
00762 {
00763 switch (expr->Kind()) {
00764 case CK_LDA:
00765 case CK_CONST:
00766 case CK_RCONST:
00767 return LINEAR_FUNCTION(INVAR_EXPR);
00768
00769 case CK_IVAR:
00770 case CK_VAR:
00771 if (loop->Invariant_cr(expr))
00772 return LINEAR_FUNCTION(INVAR_EXPR);
00773 else
00774 return LINEAR_FUNCTION(LINEAR_EXPR, expr);
00775
00776 case CK_OP:
00777 OPERATOR opr = expr->Opr();
00778 switch (opr) {
00779 case OPR_PAREN:
00780 case OPR_NEG:
00781 return Linear_function(loop, expr->Opnd(0));
00782
00783 case OPR_MPY:
00784 {
00785 LINEAR_FUNCTION l0 = Linear_function(loop, expr->Opnd(0));
00786 LINEAR_FUNCTION l1 = Linear_function(loop, expr->Opnd(1));
00787
00788 if (l0.type == INVAR_EXPR)
00789 return l1;
00790 if (l1.type == INVAR_EXPR)
00791 return l0;
00792
00793 return LINEAR_FUNCTION(NON_LINEAR_EXPR);
00794 }
00795
00796 case OPR_ADD:
00797 case OPR_SUB:
00798 {
00799 LINEAR_FUNCTION l0 = Linear_function(loop, expr->Opnd(0));
00800 LINEAR_FUNCTION l1 = Linear_function(loop, expr->Opnd(1));
00801
00802 if (l0.type == INVAR_EXPR)
00803 return l1;
00804 if (l1.type == INVAR_EXPR)
00805 return l0;
00806 if (l0.type == LINEAR_EXPR && l1.type == LINEAR_EXPR &&
00807 l0.variant == l1.variant)
00808 return l0;
00809 return LINEAR_FUNCTION(NON_LINEAR_EXPR);
00810 }
00811
00812 default:
00813 if (loop->Invariant_cr(expr))
00814 return LINEAR_FUNCTION(INVAR_EXPR);
00815 else
00816 return LINEAR_FUNCTION(NON_LINEAR_EXPR);
00817 }
00818 }
00819 if (loop->Invariant_cr(expr))
00820 return LINEAR_FUNCTION(INVAR_EXPR);
00821 else
00822 return LINEAR_FUNCTION(NON_LINEAR_EXPR);
00823 }
00824
00825
00826 inline BOOL
00827 Is_linear_function_of(CODEREP *expr, CODEREP *variant, BB_LOOP *loop)
00828 {
00829 LINEAR_FUNCTION l = Linear_function(loop, expr);
00830 return (l.type == INVAR_EXPR ||
00831 (l.type == LINEAR_EXPR && l.variant == variant));
00832 }
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849 static BOOL
00850 Found_aliasing_store_in_loop(POINTS_TO *pt, TY_IDX ty, BB_LOOP *loop,
00851 BB_NODE *bb, OPT_STAB *opt_stab)
00852 {
00853 STMTREP_ITER stmt_iter(bb->Stmtlist());
00854 STMTREP *stmt;
00855 FOR_ALL_NODE(stmt, stmt_iter, Init()) {
00856
00857 POINTS_TO *pt2;
00858 TY_IDX ty2;
00859
00860 switch (stmt->Opr()) {
00861 case OPR_STBITS:
00862 case OPR_STID:
00863 ty2 = stmt->Lhs()->Lod_ty();
00864 pt2 = stmt->Lhs()->Points_to(opt_stab);
00865 if (opt_stab->Rule()->Aliased_Memop(pt, pt2, ty, ty2))
00866 return TRUE;
00867 break;
00868
00869 case OPR_ISTORE:
00870 case OPR_ISTBITS:
00871 case OPR_ISTOREX:
00872 ty2 = stmt->Lhs()->Ilod_ty();
00873 pt2 = stmt->Lhs()->Points_to(opt_stab);
00874 if (opt_stab->Rule()->Aliased_Memop(pt, pt2, ty, ty2))
00875 return TRUE;
00876 break;
00877
00878 case OPR_MSTORE:
00879 ty2 = TY_IDX_ZERO;
00880 pt2 = stmt->Lhs()->Points_to(opt_stab);
00881 if (opt_stab->Rule()->Aliased_Memop(pt, pt2, ty, ty2))
00882 return TRUE;
00883 break;
00884
00885 case OPR_RETURN:
00886 case OPR_RETURN_VAL:
00887 case OPR_GOTO:
00888 case OPR_LABEL:
00889 case OPR_TRUEBR:
00890 case OPR_FALSEBR:
00891 case OPR_EVAL:
00892 case OPR_PRAGMA:
00893 case OPR_XPRAGMA:
00894 #ifdef KEY
00895 case OPR_GOTO_OUTER_BLOCK:
00896 #endif
00897 break;
00898
00899 default:
00900 return TRUE;
00901 }
00902 }
00903
00904 BB_NODE *dom_bb;
00905 BB_LIST_ITER dom_bb_iter;
00906 FOR_ALL_ELEM(dom_bb, dom_bb_iter, Init(bb->Dom_bbs())) {
00907 if (loop->True_body_set()->MemberP(dom_bb))
00908 if (Found_aliasing_store_in_loop(pt, ty, loop, dom_bb, opt_stab))
00909 return TRUE;
00910 }
00911 return FALSE;
00912 }
00913
00914
00915 void
00916 CODEMAP::Convert_iload_to_loop_invariant(BB_LOOP *loop, CODEREP *cr)
00917 {
00918 switch (cr->Kind()) {
00919 case CK_OP:
00920 {
00921 for (INT i = 0; i < cr->Kid_count(); i++) {
00922 Convert_iload_to_loop_invariant(loop, cr->Opnd(i));
00923 }
00924 }
00925 break;
00926 case CK_IVAR:
00927 {
00928 if (cr->Is_ivar_volatile())
00929 return;
00930
00931 MU_NODE *mnode = cr->Ivar_mu_node();
00932 if (mnode == NULL)
00933 return;
00934
00935 CODEREP *vsym = mnode->OPND();
00936 BB_NODE *defbb = vsym->Defbb();
00937 if ( defbb == NULL || ! loop->True_body_set()->MemberP( defbb ) )
00938 return;
00939
00940 BB_NODE *startbb = loop->Header();
00941
00942 #ifdef KEY
00943 if (! WOPT_Enable_Invariant_Loop_Bounds)
00944 #endif
00945
00946
00947
00948 if (Found_aliasing_store_in_loop(cr->Points_to(Opt_stab()),
00949 cr->Ilod_ty(),
00950 loop,
00951 startbb,
00952 Opt_stab()))
00953 return;
00954
00955
00956 if (Get_Trace(TP_GLOBOPT, IVR_DUMP_FLAG)) {
00957 fprintf(TFile,
00958 "IVR: convert iload to invar in loop with body BB %d.\n",
00959 startbb->Id());
00960 }
00961
00962
00963
00964
00965 PHI_NODE *phi;
00966 PHI_LIST_ITER phi_iter;
00967
00968 FOR_ALL_ELEM (phi, phi_iter, Init(startbb->Phi_list())) {
00969 if (phi->Live() && phi->Aux_id() == vsym->Aux_id()) {
00970 BB_NODE *pred;
00971 BB_LIST_ITER bb_iter;
00972 FOR_ALL_ELEM (pred, bb_iter, Init(startbb->Pred())) {
00973 if (pred == loop->Preheader()) {
00974 CODEREP *tmp = phi->OPND(bb_iter.Idx());
00975 mnode->Set_OPND(tmp);
00976 return;
00977 }
00978 }
00979 }
00980 }
00981 }
00982 break;
00983
00984 default:
00985 break;
00986 }
00987 }
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999 template <class BOOL_FUNC>
01000 BOOL expr_iter(CODEREP *cr, BOOL_FUNC f)
01001 {
01002 if (f(cr)) return TRUE;
01003
01004 switch ( cr->Kind() ) {
01005 case CK_IVAR:
01006 {
01007 CODEREP *base =
01008 (cr->Istr_base()) ? cr->Istr_base() : cr->Ilod_base();
01009 if (expr_iter(base, f))
01010 return TRUE;
01011 if (cr->Opr() == OPR_MLOAD && expr_iter(cr->Mload_size(), f))
01012 return TRUE;
01013 if (cr->Opr() == OPR_ILOADX && expr_iter(cr->Index(), f))
01014 return TRUE;
01015 MU_NODE *mnode = cr->Ivar_mu_node();
01016 if (mnode) {
01017 CODEREP *opnd = mnode->OPND();
01018 if (opnd && expr_iter(opnd, f))
01019 return TRUE;
01020 }
01021 }
01022 break;
01023
01024 case CK_OP:
01025 for (INT32 ikid = 0; ikid < cr->Kid_count(); ikid++ ) {
01026 if (expr_iter(cr->Opnd(ikid), f))
01027 return TRUE;
01028 }
01029 break;
01030 }
01031 return FALSE;
01032 }
01033
01034
01035 template <class BOOL_FUNC>
01036 BOOL ref_iter(CODEREP *cr, BOOL_FUNC f)
01037 {
01038 expr_iter(cr, f);
01039 }
01040
01041
01042 template <class BOOL_FUNC>
01043 BOOL ref_iter(STMTREP *stmt, BOOL_FUNC f)
01044 {
01045 if (stmt->Rhs())
01046 if (expr_iter(stmt->Rhs(), f))
01047 return TRUE;
01048 if (OPERATOR_is_scalar_istore (stmt->Opr())
01049 #ifdef KEY
01050 || stmt->Opr() == OPR_MSTORE
01051 #endif
01052 ) {
01053 if (expr_iter(stmt->Lhs(), f)) return TRUE;
01054 }
01055 return FALSE;
01056 }
01057
01058
01059
01060 template <class BOOL_FUNC>
01061 BOOL mod_iter(STMTREP *stmt, BOOL_FUNC f)
01062 {
01063 if (stmt->Has_chi()) {
01064 CHI_LIST_ITER chi_iter;
01065 CHI_NODE *cnode;
01066 CHI_LIST *chi_list = stmt->Chi_list();
01067 FOR_ALL_NODE( cnode, chi_iter, Init(chi_list)) {
01068 if (!cnode->Dse_dead()) {
01069 if (f(cnode->RESULT()))
01070 return TRUE;
01071 } else {
01072 if (f(cnode->Aux_id()))
01073 return TRUE;
01074 }
01075 }
01076 }
01077 if (OPERATOR_is_scalar_store (stmt->Opr()))
01078 if (f(stmt->Lhs())) return TRUE;
01079 return FALSE;
01080 }
01081
01082
01083 struct collect_use {
01084 set<AUX_ID> *use;
01085 BOOL operator()(CODEREP *cr) {
01086 if (cr->Kind() == CK_VAR)
01087 use->insert(cr->Aux_id());
01088 return FALSE;
01089 }
01090 collect_use(set<AUX_ID> *u) : use(u) {}
01091 };
01092
01093
01094 struct collect_def {
01095 set<AUX_ID> *def;
01096 BOOL operator()(CODEREP *cr) {
01097 if (cr->Kind() == CK_VAR)
01098 def->insert(cr->Aux_id());
01099 return FALSE;
01100 }
01101 BOOL operator()(AUX_ID id) {
01102 def->insert(id);
01103 return FALSE;
01104 }
01105 collect_def(set<AUX_ID> *d) : def(d) {}
01106 };
01107
01108
01109 enum DEPENDENCE_KIND {
01110 NO_DEPENDENCE = 0,
01111 ANTI_DEPENDENCE = 1,
01112 FLOW_DEPENDENCE = 2,
01113 OUTPUT_DEPENDENCE = 4,
01114 UNKNOWN_DEPENDENCE = 8,
01115 };
01116
01117
01118
01119
01120
01121
01122
01123 static DEPENDENCE_KIND
01124 Compute_dependence(STMTREP *stmt, BB_NODE *end_bb, STMTREP *after_this_stmt)
01125 {
01126 Is_True(after_this_stmt == NULL || after_this_stmt->Bb() == end_bb,
01127 ("Compute_dependence: inconsistency input"));
01128 Is_True(stmt->Bb()->Dominates(end_bb),
01129 ("Compute_dependence: inconsistency input"));
01130
01131 set<AUX_ID> use;
01132 set<AUX_ID> def;
01133 {
01134 collect_use collect_use(&use);
01135 collect_def collect_def(&def);
01136 ref_iter(stmt, collect_use);
01137 mod_iter(stmt, collect_def);
01138 }
01139
01140 BB_NODE *begin_bb = stmt->Bb();
01141 BB_NODE *bb = begin_bb;
01142 STMTREP *begin_stmt;
01143 STMTREP *end_stmt;
01144
01145 set<AUX_ID> path_use;
01146 set<AUX_ID> path_def;
01147 collect_use collect_use(&path_use);
01148 collect_def collect_def(&path_def);
01149
01150 while (bb) {
01151 if (bb == begin_bb)
01152 begin_stmt = stmt->Next();
01153 else
01154 begin_stmt = bb->First_stmtrep();
01155
01156 if (bb == end_bb)
01157 end_stmt = after_this_stmt;
01158 else
01159 end_stmt = bb->Last_stmtrep();
01160
01161 stmt = begin_stmt;
01162 while (stmt) {
01163 ref_iter(stmt, collect_use);
01164 mod_iter(stmt, collect_def);
01165
01166 if (stmt == end_stmt) break;
01167 stmt = stmt->Next();
01168 }
01169
01170 if (bb == end_bb) break;
01171 if (bb->Succ()->Len() > 1) return UNKNOWN_DEPENDENCE;
01172 bb = bb->Nth_succ(0);
01173 }
01174
01175 DEPENDENCE_KIND ret = NO_DEPENDENCE;
01176
01177 vector<AUX_ID> dummy_vec;
01178
01179
01180 set_intersection(use.begin(), use.end(), path_def.begin(), path_def.end(),
01181 inserter(dummy_vec, dummy_vec.begin()));
01182 if (dummy_vec.begin() != dummy_vec.end())
01183 ret = (DEPENDENCE_KIND)(ret | ANTI_DEPENDENCE);
01184
01185
01186 dummy_vec.erase(dummy_vec.begin(), dummy_vec.end());
01187 set_intersection(def.begin(), def.end(), path_def.begin(), path_def.end(),
01188 inserter(dummy_vec, dummy_vec.begin()));
01189 if (dummy_vec.begin() != dummy_vec.end())
01190 ret = (DEPENDENCE_KIND)(ret | OUTPUT_DEPENDENCE);
01191
01192
01193 dummy_vec.erase(dummy_vec.begin(), dummy_vec.end());
01194 set_intersection(def.begin(), def.end(), path_use.begin(), path_use.end(),
01195 inserter(dummy_vec, dummy_vec.begin()));
01196 if (dummy_vec.begin() != dummy_vec.end())
01197 ret = (DEPENDENCE_KIND)(ret | FLOW_DEPENDENCE);
01198
01199 return ret;
01200 }
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219 #ifdef Is_True_On
01220 inline BOOL RAISE(BOOL r, const char *msg)
01221 {
01222 if (Get_Trace(TP_GLOBOPT, EMIT_DUMP_FLAG))
01223 if (!r)
01224 fprintf(TFile,
01225 "Can_raise_to_doloop: doloop not raised because %s\n", msg);
01226 return r;
01227 }
01228 #else
01229
01230 inline BOOL RAISE(BOOL r, const char *msg) { return r; }
01231 #endif
01232
01233
01234 BOOL
01235 Can_raise_to_doloop(BB_LOOP *loop, BOOL repair, CODEMAP *htable)
01236 {
01237 if (!loop->Well_formed()) return RAISE(FALSE, "loop not well formed");
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248 #if !defined(OSP_OPT) || !defined(TARG_IA64)
01249 if (loop->Exit_early()) return RAISE(FALSE, "loop exits early");
01250 #endif
01251 BB_NODE *header = loop->Header();
01252 BB_NODE *preheader = loop->Preheader();
01253 BB_NODE *loopback = loop->Loopback();
01254 INT preheader_opnd_num = loop->Preheader_pred_num();
01255 INT loopback_opnd_num = loop->Loopback_pred_num();
01256
01257 STMTREP_ITER stmt_iter(header->Stmtlist());
01258 STMTREP *sr;
01259 FOR_ALL_NODE( sr, stmt_iter, Init() ) {
01260 if (sr->Op() != OPC_LABEL && sr != header->Last_stmtrep())
01261 return RAISE(FALSE, "too many stmt in header BB");
01262 }
01263
01264 STMTREP *cond_br = header->Branch_stmtrep();
01265
01266
01267 if ( cond_br->Op() != OPC_TRUEBR && cond_br->Op() != OPC_FALSEBR )
01268 return RAISE(FALSE, "not a conditional branch");
01269
01270
01271 CODEREP *cmp = cond_br->Rhs();
01272 if ( cmp->Kind() != CK_OP || !OPCODE_is_compare(cmp->Op()) )
01273 return RAISE(FALSE, "not a compare opcode");
01274
01275 if ( cmp->Get_opnd(1)->Kind() != CK_CONST && loop->Exit_early())
01276 return RAISE(FALSE, "early exit without const comparison");
01277
01278 const OPERATOR cond_opr = cmp->Opr();
01279 if (!(cond_opr == OPR_LE || cond_opr == OPR_GE ||
01280 cond_opr == OPR_LT || cond_opr == OPR_GT))
01281 return RAISE(FALSE, "== or != is not allowed.");
01282
01283
01284 if (WOPT_Enable_Aggr_Invariant) {
01285 if (!loop->Invariant_cr(cmp->Opnd(0)) &&
01286 !loop->Invariant_cr(cmp->Opnd(1))) {
01287 htable->Convert_iload_to_loop_invariant(loop, cmp);
01288 }
01289 }
01290
01291 CODEREP *variant0 = Find_variant(loop, cmp->Opnd(0));
01292 CODEREP *variant1 = Find_variant(loop, cmp->Opnd(1));
01293
01294
01295 if ((variant0 == NULL && variant1 == NULL) ||
01296 (variant0 != NULL && variant1 != NULL))
01297 return RAISE(FALSE, "expecting variant cmp_op invariant | invariant cmp_op variant");
01298
01299
01300 CODEREP *iv;
01301 CODEREP *expr;
01302 if (variant0) {
01303 iv = variant0;
01304 expr = cmp->Opnd(0);
01305 } else {
01306 iv = variant1;
01307 expr = cmp->Opnd(1);
01308 }
01309
01310 if (iv->Kind() != CK_VAR)
01311 return RAISE(FALSE, "induction variable is not CK_VAR");
01312
01313 if (iv->Is_var_volatile())
01314 return RAISE(FALSE, "induction variable is volatile");
01315
01316 if (!Is_linear_function_of(expr,iv,loop))
01317 return RAISE(FALSE, "exit test is not a linear function of induction var");
01318
01319 loop->Set_iv(iv);
01320
01321
01322 Is_True(iv->Is_flag_set(CF_DEF_BY_PHI), ("BB_LOOP::Can_raise_to_doloop"));
01323 PHI_NODE *phi = iv->Defphi();
01324
01325
01326 STMTREP *init_stmt = phi->OPND(preheader_opnd_num)->Defstmt();
01327 STMTREP *incr_stmt = phi->OPND(loopback_opnd_num)->Defstmt();
01328
01329 if (init_stmt == NULL)
01330 return RAISE(FALSE, "cannot find init stmt");
01331
01332 if (init_stmt->Opr() != OPR_STID)
01333 return RAISE(FALSE, "init stmt is not STID");
01334
01335 if (incr_stmt == NULL)
01336 return RAISE(FALSE, "cannot find incr stmt");
01337
01338 if (incr_stmt->Opr() != OPR_STID)
01339 return RAISE(FALSE, "incr stmt is not STID");
01340
01341 if (init_stmt != preheader->Last_stmtrep() &&
01342 !(repair && Compute_dependence(init_stmt, preheader, NULL) == NO_DEPENDENCE))
01343 return RAISE(FALSE, "init stmt is not the last statement in preheader.");
01344
01345 BOOL sink_init_stmt = (repair && init_stmt != preheader->Last_stmtrep());
01346
01347 STMTREP *last_stmt_in_loopback = loopback->Last_stmtrep();
01348 if (last_stmt_in_loopback != NULL &&
01349 last_stmt_in_loopback == loopback->Branch_stmtrep())
01350 last_stmt_in_loopback = last_stmt_in_loopback->Prev();
01351
01352 if (incr_stmt != last_stmt_in_loopback &&
01353 !(repair && Compute_dependence(incr_stmt, loopback, NULL) == NO_DEPENDENCE))
01354 return RAISE(FALSE, "incr stmt is not the last statement in loopback.");
01355
01356 BOOL sink_incr_stmt = (repair && incr_stmt != last_stmt_in_loopback);
01357
01358
01359
01360 if (incr_stmt->Opr() != OPR_STID)
01361 return RAISE(FALSE, "incr stmt is not an assignment stmt");
01362
01363 CODEREP *iv2 = incr_stmt->Rhs();
01364 CODEREP *iv1 = phi->RESULT();
01365 if (iv2->Kind() == CK_OP && iv2->Opr() == OPR_ADD) {
01366 if (iv1 == iv2->Opnd(0)) {
01367 if (!loop->Invariant_cr(iv2->Opnd(1)))
01368 return RAISE(FALSE, "incr amount is not invariant");
01369
01370 } else if (iv1 == iv2->Opnd(1)) {
01371 if (!loop->Invariant_cr(iv2->Opnd(0)))
01372 return RAISE(FALSE, "incr amount is not invariant");
01373
01374 } else
01375 return RAISE(FALSE, "cannot find induction variable in incr stmt");
01376
01377 } else if (iv2->Kind() == CK_OP && iv2->Opr() == OPR_SUB) {
01378 if (iv1 != iv2->Opnd(0) ||
01379 !loop->Invariant_cr(iv2->Opnd(1)))
01380 return RAISE(FALSE, "incr amount is not invariant");
01381
01382 } else
01383 return RAISE(FALSE, "incr stmt is neither + or -");
01384
01385 BOOL trace = Get_Trace(TP_GLOBOPT, EMIT_DUMP_FLAG);
01386
01387
01388
01389 if (sink_init_stmt) {
01390 if (trace)
01391 fprintf(TFile, "Can_raise_do_loop: sinking the init stmt\n");
01392 init_stmt->Bb()->Remove_stmtrep(init_stmt);
01393 preheader->Append_stmt_before_branch(init_stmt);
01394 }
01395
01396 if (sink_incr_stmt) {
01397 if (trace)
01398 fprintf(TFile, "Can_raise_to_doloop: sinking the incr stmt\n");
01399 incr_stmt->Bb()->Remove_stmtrep(incr_stmt);
01400 loopback->Append_stmt_before_branch(incr_stmt);
01401 }
01402
01403 #ifdef Is_True_On
01404 {
01405 STMTREP *last_stmt_in_loopback = loopback->Last_stmtrep();
01406 if (last_stmt_in_loopback != NULL &&
01407 last_stmt_in_loopback == loopback->Branch_stmtrep())
01408 last_stmt_in_loopback = last_stmt_in_loopback->Prev();
01409 Is_True(incr_stmt == last_stmt_in_loopback,
01410 ("incr stmt not last stmt in loopback"));
01411 }
01412 #endif
01413
01414 return RAISE(TRUE, "OK");
01415 }
01416
01417
01418
01419
01420
01421
01422
01423
01424
01425
01426
01427
01428
01429
01430
01431
01432
01433
01434 void Fix_do_loop(BB_LOOP *loop, CODEMAP *htable)
01435 {
01436 AUX_ID aux;
01437 PHI_NODE *phi;
01438
01439 if (!loop->Well_formed()) return;
01440 if (loop->End() == NULL) return;
01441
01442 if (loop->Iv() != NULL) {
01443 aux = loop->Iv()->Aux_id();
01444 phi = htable->Lookup_var_phi(loop->Header(), aux);
01445 } else {
01446 BOOL found = FALSE;
01447 WN *index_wn = loop->Index();
01448 ST *index_st = index_wn ? WN_st(index_wn) : NULL;
01449 WN_OFFSET index_ofs = index_wn ? WN_idname_offset(index_wn) : 0;
01450
01451 PHI_LIST_ITER phi_iter;
01452 FOR_ALL_ELEM (phi, phi_iter, Init(loop->Header()->Phi_list())) {
01453 if (!phi->Live()) continue;
01454 CODEREP *cr = phi->RESULT();
01455 if ( htable->Opt_stab()->St(cr->Aux_id()) == index_st &&
01456 cr->Offset() == index_ofs ) {
01457 aux = cr->Aux_id();
01458 found = TRUE;
01459 break;
01460 }
01461 }
01462 if (!found) return;
01463 }
01464
01465 FmtAssert(phi, ("Fix_do_loop: cannot locate phi."));
01466
01467 CODEREP *init_value = phi->OPND(loop->Preheader_pred_num());
01468 if (init_value->Is_flag_set(CF_IS_ZERO_VERSION)) {
01469 htable->Fix_zero_version(phi, loop->Preheader_pred_num());
01470 init_value = phi->OPND(loop->Preheader_pred_num());
01471 }
01472 BOOL create_identity_asgn = FALSE;
01473 BOOL sink_init_stmt = FALSE;
01474 BB_NODE *preheader = loop->Preheader();
01475 STMTREP *init_stmt = init_value->Defstmt();
01476
01477 if (init_stmt != NULL) {
01478 if (init_stmt->Bb() != preheader)
01479 create_identity_asgn = TRUE;
01480 else {
01481 if (init_stmt != preheader->Last_stmtrep()) {
01482 if (Compute_dependence(init_stmt, preheader, NULL) == NO_DEPENDENCE)
01483 sink_init_stmt = TRUE;
01484 else
01485 create_identity_asgn = TRUE;
01486 }
01487 }
01488 } else
01489 create_identity_asgn = TRUE;
01490
01491 Is_True( create_identity_asgn ||
01492 (sink_init_stmt && init_stmt->Bb() == preheader) ||
01493 (init_stmt->Bb() == preheader && init_stmt == preheader->Last_stmtrep()),
01494 ("Fix_do_loop: unable to fix init stmt."));
01495
01496 BOOL trace = Get_Trace(TP_GLOBOPT, EMIT_DUMP_FLAG);
01497
01498 if (sink_init_stmt) {
01499 if (trace)
01500 fprintf(TFile, "Fix_do_loop: sinking the init stmt\n");
01501 init_stmt->Bb()->Remove_stmtrep(init_stmt);
01502 preheader->Append_stmt_before_branch(init_stmt);
01503 }
01504
01505 if (create_identity_asgn) {
01506 if (trace)
01507 fprintf(TFile, "Fix_do_loop: creating identity asgn\n");
01508 MTYPE dtype = init_value->Dtyp();
01509 MTYPE dsctype = init_value->Dsctyp();
01510 CODEREP *init_cr = htable->Add_def(aux, -1, NULL, dtype, dsctype,
01511 htable->Opt_stab()->Aux_stab_entry(aux)->St_ofst(),
01512 MTYPE_To_TY(dtype),
01513 init_value->Field_id(), TRUE);
01514 STMTREP *init_stmt = init_value->Create_cpstmt(init_cr, htable->Mem_pool());
01515 loop->Preheader()->Append_stmtrep(init_stmt);
01516 init_stmt->Set_bb(loop->Preheader());
01517 phi->Set_opnd(loop->Preheader_pred_num(), init_cr);
01518 }
01519 }
01520
01521
01522