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
00060 #define __STDC_LIMIT_MACROS
00061 #include <stdint.h>
00062 #ifdef USE_PCH
00063 #include "lno_pch.h"
00064 #endif // USE_PCH
00065 #pragma hdrstop
00066
00067 #define cond_CXX "cond.cxx"
00068
00069 #include <sys/types.h>
00070 #include "soe.h"
00071 #include "cond.h"
00072 #include "lwn_util.h"
00073 #include "lnopt_main.h"
00074 #include "opt_du.h"
00075 #include "lnoutils.h"
00076 #include "region_util.h"
00077 #include "lego_util.h"
00078 #include "snl_utils.h"
00079 #include "small_trips.h"
00080 #include "eliminate.h"
00081 #include "fb_whirl.h"
00082 #include "wn_simp.h"
00083
00084 extern WN* Find_SCF_Inside(WN* parent_wn, OPCODE opc);
00085
00086 void COND_SYMBOL_INFO::Print(FILE* f) const
00087 {
00088 if (Outer_Nondef)
00089 fprintf(f, "`%s' at line %d",
00090 Symbol.Name(),
00091 Srcpos_To_Line(WN_Get_Linenum(Outer_Nondef)));
00092 else
00093 fprintf(f, "%s no wn", Symbol.Name());
00094 }
00095
00096
00097
00098
00099
00100 COND_BOUNDS_INFO::COND_BOUNDS_INFO(MEM_POOL* mp)
00101 : _pool(mp),
00102 _bounds(0,0,0,mp),
00103 _symbol_info(mp)
00104 {
00105 }
00106
00107 COND_BOUNDS_INFO::~COND_BOUNDS_INFO()
00108 {
00109 }
00110
00111
00112
00113
00114
00115 INT COND_BOUNDS_INFO::Lookup_Entry(SYMBOL s, WN* control)
00116 {
00117 INT entry;
00118 for (entry = 0; entry < _symbol_info.Elements(); entry++) {
00119 if (_symbol_info.Bottom_nth(entry).Symbol == s)
00120 return entry;
00121 }
00122
00123
00124 _symbol_info.Push(COND_SYMBOL_INFO(s, control));
00125 _bounds.Add_Vars(1);
00126 return entry;
00127 }
00128
00129
00130
00131
00132
00133
00134 void COND_BOUNDS_INFO::Kill_Written_Symbols(ACCESS_VECTOR* av,
00135 WN* code,
00136 WN* control)
00137 {
00138 if (av->Contains_Lin_Symb() == FALSE)
00139 return;
00140
00141 for (LWN_ITER* i = LWN_WALK_TreeIter(code); i; i = LWN_WALK_TreeNext(i)) {
00142 WN* wn = i->wn;
00143
00144 if (WN_operator(wn) != OPR_LDID)
00145 continue;
00146
00147
00148
00149
00150 SYMBOL symbol(wn);
00151
00152 BOOL found = FALSE;
00153 INTSYMB_ITER ii(av->Lin_Symb);
00154 for (INTSYMB_NODE* nn = ii.First(); !ii.Is_Empty(); nn = ii.Next()) {
00155 if (symbol == nn->Symbol) {
00156 found = TRUE;
00157 break;
00158 }
00159 }
00160 if (!found) {
00161 continue;
00162 }
00163
00164 INT entry = Lookup_Entry(symbol, control);
00165 WN* wnouter = Symbol_Info().Bottom_nth(entry).Outer_Nondef;
00166
00167 if (wnouter == control)
00168 continue;
00169
00170 DEF_LIST *defs = Du_Mgr->Ud_Get_Def(wn);
00171 BOOL bad_write = FALSE;
00172 if (defs == NULL) {
00173 bad_write = TRUE;
00174 #ifdef Is_True_On
00175 if (TY_kind(ST_type(WN_st(wn))) == KIND_SCALAR) {
00176 WN *tmp = wn;
00177 while (tmp && WN_opcode(tmp) != OPC_IO) tmp = LWN_Get_Parent(tmp);
00178 Is_True(tmp, ("Missing defs for %s (wn=%ld=0x%lx)",
00179 SYMBOL(wn).Name(), wn, wn));
00180 }
00181 #endif
00182 } else {
00183 DEF_LIST_ITER iter(defs);
00184 for(const DU_NODE *n = iter.First();
00185 !bad_write && !iter.Is_Empty(); n = iter.Next()) {
00186 WN *def = n->Wn();
00187 while (!bad_write && def) {
00188 def = LWN_Get_Parent(def);
00189 if (def == wnouter) {
00190 bad_write = TRUE;
00191 if (LNO_Verbose) fprintf(stderr, "def at %d, wnouter at %d\n",
00192 Srcpos_To_Line(WN_Get_Linenum(def)),
00193 Srcpos_To_Line(WN_Get_Linenum(wnouter)));
00194 }
00195 }
00196 }
00197 }
00198
00199 if (bad_write) {
00200 if (LNO_Verbose) fprintf(stderr, "Bad write for %s\n", symbol.Name());
00201
00202
00203 Symbol_Info().Bottom_nth(entry).Outer_Nondef = control;
00204
00205 for (INT i = Bounds().Num_Le_Constraints() - 1; i >= 0; i--) {
00206 if (Bounds().Ale()(i,entry) != 0) {
00207
00208
00209
00210 for (INT j=0; j<Bounds().Num_Vars(); j++) {
00211 Bounds().Ale()(i,j) = 0;
00212 }
00213 Bounds().Ble()[i] = 0;
00214 }
00215 }
00216 }
00217 }
00218 }
00219
00220
00221
00222
00223
00224
00225
00226 INT COND_BOUNDS_INFO::Add_Access(ACCESS_VECTOR* av, WN* code, WN* control)
00227 {
00228 if (av->Too_Messy || av->Contains_Non_Lin_Symb())
00229 return 0;
00230
00231 Kill_Written_Symbols(av, code, control);
00232
00233 INT vsz = (av->Lin_Symb ? av->Lin_Symb->Len() : 0) +
00234 Symbol_Info().Elements() + av->Nest_Depth() + 1;
00235 mINT32* v = CXX_NEW_ARRAY(mINT32, vsz, &LNO_local_pool);
00236
00237 for (INT vszx = 0; vszx < vsz; vszx++)
00238 v[vszx] = 0;
00239
00240
00241
00242 for (INT i = 0; i <= av->Nest_Depth(); i++) {
00243 INT coeff = av->Loop_Coeff(i);
00244 if (coeff) {
00245 INT entry = Lookup_Entry(SYMBOL((ST*)NULL, i, MTYPE_V), control);
00246 Is_True(entry < vsz,("Overflow1 in Add_Access\n"));
00247 v[entry] = coeff;
00248 }
00249 }
00250
00251
00252
00253 if (av->Contains_Lin_Symb()) {
00254 INTSYMB_ITER ii(av->Lin_Symb);
00255 for (INTSYMB_NODE* n = ii.First(); !ii.Is_Empty(); n = ii.Next()) {
00256 INT entry = Lookup_Entry(n->Symbol, control);
00257 Is_True(entry < vsz,("Overflow2 in Add_Access\n"));
00258 v[entry] = n->Coeff;
00259 }
00260 }
00261
00262 _bounds.Add_Le(v, av->Const_Offset);
00263
00264 CXX_DELETE_ARRAY(v, &LNO_local_pool);
00265 return 1;
00266 }
00267
00268 INT COND_BOUNDS_INFO::Add_Access(ACCESS_ARRAY* aa, WN* code, WN* control)
00269 {
00270 INT added_cnt = 0;
00271
00272 for (INT i = 0; i < aa->Num_Vec(); i++)
00273 added_cnt += Add_Access(aa->Dim(i), code, control);
00274
00275 return added_cnt;
00276 }
00277
00278
00279
00280
00281
00282 void COND_BOUNDS_INFO::Collect_If_Info(WN* wn, BOOL in_then_part)
00283 {
00284 Is_True(WN_opcode(wn) == OPC_IF,
00285 ("bad opcode %d for Collect_If_Info()", WN_opcode(wn)));
00286
00287 IF_INFO* ii = Get_If_Info(wn, TRUE);
00288
00289 if (Pool() != &LNO_local_pool)
00290 MEM_POOL_Push(&LNO_local_pool);
00291
00292 if (ii == NULL) {
00293 fprintf(stderr, "Missing IF annotation!");
00294 }
00295 else if (!in_then_part == !ii->Condition_On_Then) {
00296
00297 Add_Access(ii->Condition, WN_if_test(wn), wn);
00298 }
00299 else {
00300
00301
00302 if (ii->Condition->Num_Vec() == 1) {
00303 ACCESS_VECTOR av(ii->Condition->Dim(0), Pool());
00304 av.Negate_Me();
00305 av.Const_Offset--;
00306 Add_Access(&av, WN_if_test(wn), wn);
00307 }
00308 }
00309 if (Pool() != &LNO_local_pool)
00310 MEM_POOL_Pop(&LNO_local_pool);
00311 }
00312
00313 void COND_BOUNDS_INFO::Collect_Do_Info(WN* wn)
00314 {
00315 Is_True(WN_opcode(wn) == OPC_DO_LOOP,
00316 ("bad opcode %d for Collect_Do_Info()", WN_opcode(wn)));
00317
00318
00319
00320 if (Pool() != &LNO_local_pool)
00321 MEM_POOL_Push(&LNO_local_pool);
00322
00323 DO_LOOP_INFO* dli = Get_Do_Loop_Info(wn);
00324 Add_Access(dli->LB, WN_kid0(WN_start(wn)), wn);
00325 Add_Access(dli->UB, WN_end(wn), wn);
00326
00327 if (Pool() != &LNO_local_pool)
00328 MEM_POOL_Pop(&LNO_local_pool);
00329 }
00330
00331
00332
00333
00334 void COND_BOUNDS_INFO::Collect_Outer_Info(WN* wn, WN* child)
00335 {
00336 if (wn == NULL)
00337 return;
00338
00339 Collect_Outer_Info(LWN_Get_Parent(wn), wn);
00340
00341 if (child == NULL)
00342 return;
00343
00344 switch (WN_opcode(wn)) {
00345 case OPC_IF:
00346 BOOL in_then_part;
00347 if (child == WN_then(wn))
00348 in_then_part = TRUE;
00349 else if (child == WN_else(wn))
00350 in_then_part = FALSE;
00351 else
00352 FmtAssert(0, ("Bad if/then/else prev condition"));
00353 Collect_If_Info(wn, in_then_part);
00354 break;
00355 case OPC_DO_LOOP:
00356 Collect_Do_Info(wn);
00357 break;
00358 }
00359 }
00360
00361 void COND_BOUNDS_INFO::Print(FILE* f) const
00362 {
00363 fprintf(f, "Variables: ");
00364 for (INT i = 0; i < _symbol_info.Elements(); i++) {
00365 if (i > 0)
00366 fprintf(f, ", ");
00367 _symbol_info.Bottom_nth(i).Print(f);
00368 }
00369
00370 fprintf(f, "\nBounds:\n");
00371 _bounds.Print(f);
00372 }
00373
00374 void COND_BOUNDS_INFO::Reset_Varcount_To(INT cols)
00375 {
00376 Is_True(cols <= _symbol_info.Elements(),
00377 ("Reset_Varcount_To() len=%d, cols=%d",
00378 _symbol_info.Elements(), cols));
00379
00380 for (INT i = _symbol_info.Elements(); i > cols; i--)
00381 _symbol_info.Pop();
00382 }
00383
00384 void COND_BOUNDS_INFO::Reset_Bounds_To(INT rows_le,
00385 INT rows_eq,
00386 INT cols,
00387 DYN_ARRAY<WN*>* kill_array)
00388 {
00389 Reset_Varcount_To(cols);
00390 Bounds().Reset_To(rows_le, rows_eq, cols);
00391 for (INT i = 0; i < cols; i++)
00392 _symbol_info.Bottom_nth(i).Outer_Nondef = (*kill_array)[i];
00393 }
00394
00396
00398
00399 COND_IF_INFO COND_If_Info(WN* wn_if, MEM_POOL* pool)
00400 {
00401 if (pool == NULL)
00402 pool = &LNO_local_pool;
00403
00404 COND_IF_INFO rval;
00405
00406 MEM_POOL_Push(pool);
00407
00408 {
00409
00410
00411
00412 COND_BOUNDS_INFO info(pool);
00413
00414
00415
00416
00417
00418
00419 info.Collect_Outer_Info(wn_if);
00420
00421 IF_INFO* ii = Get_If_Info(wn_if, TRUE);
00422 if (ii == NULL) {
00423 Is_True(1, ("Missing IF annotation!"));
00424 rval = COND_IF_NOT_SURE;
00425 }
00426 else {
00427 INT le = info.Bounds().Num_Le_Constraints();
00428 INT eq = info.Bounds().Num_Eq_Constraints();
00429 INT c = info.Symbol_Info().Elements();
00430 DYN_ARRAY<WN*> kill_array(&LNO_local_pool);
00431 for (INT i = 0; i < c; i++) {
00432 WN* wn = info.Symbol_Info().Bottom_nth(i).Outer_Nondef;
00433 kill_array.AddElement(wn);
00434 }
00435
00436 info.Collect_If_Info(wn_if, TRUE);
00437
00438 if (!info.Bounds().Is_Consistent())
00439 rval = COND_IF_ELSE_ONLY;
00440 else {
00441 info.Reset_Bounds_To(le, eq, c, &kill_array);
00442 info.Collect_If_Info(wn_if, FALSE);
00443 if (!info.Bounds().Is_Consistent())
00444 rval = COND_IF_THEN_ONLY;
00445 else
00446 rval = COND_IF_NOT_SURE;
00447 }
00448 }
00449 }
00450
00451 MEM_POOL_Pop(pool);
00452
00453 return rval;
00454 }
00455
00456 #ifdef KEY //bug 13026
00457 static void Replace_With_Init(WN *copy, SYMBOL sym,
00458 WN *cons, TYPE_ID index_type)
00459 {
00460 if (WN_operator(copy) == OPR_LDID){
00461 if (SYMBOL(copy) == sym) {
00462 WN *parent = LWN_Get_Parent(copy);
00463 INT kid;
00464 for (kid = 0; kid < WN_kid_count(parent); kid ++)
00465 if (WN_kid(parent, kid) == copy)
00466 break;
00467 OPCODE intconst_opc=
00468 OPCODE_make_op(OPR_INTCONST,index_type, MTYPE_V);
00469 WN_kid(parent, kid) =
00470 WN_CreateIntconst(intconst_opc, WN_const_val(cons));
00471 LWN_Set_Parent(WN_kid(parent, kid), parent);
00472 }
00473 }
00474
00475 for (INT i = 0; i < WN_kid_count(copy); i ++) {
00476 Replace_With_Init(WN_kid(copy, i), sym, cons, index_type);
00477 }
00478 return;
00479 }
00480
00481 static BOOL Loop_Not_Entered(WN *wn_do)
00482 {
00483 BOOL not_entered = FALSE;
00484 WN *start = WN_start(wn_do);
00485 WN *end = WN_end(wn_do);
00486 SYMBOL index_sym = SYMBOL(WN_index(wn_do));
00487
00488 WN *copy = LWN_Copy_Tree(end, TRUE, LNO_Info_Map);
00489 if(WN_operator(start)==OPR_STID &&
00490 WN_operator(WN_kid0(start))== OPR_INTCONST &&
00491 SYMBOL(start)==index_sym){
00492 Replace_With_Init(copy, index_sym, WN_kid0(start), WN_rtype(end));
00493 copy = WN_Simplify_Tree(copy);
00494 if(WN_operator(copy)==OPR_INTCONST &&
00495 WN_const_val(copy)==0)
00496 return TRUE;
00497 }
00498 return FALSE;
00499 }
00500 #endif
00501
00502 COND_DO_INFO COND_Do_Info(WN* wn_do, MEM_POOL* pool)
00503 {
00504 if (pool == NULL)
00505 pool = &LNO_local_pool;
00506
00507 COND_DO_INFO rval;
00508
00509 MEM_POOL_Push(pool);
00510
00511
00512
00513 {
00514
00515
00516
00517 COND_BOUNDS_INFO info(pool);
00518
00519
00520
00521
00522
00523
00524
00525 info.Collect_Outer_Info(wn_do);
00526
00527 INT le = info.Bounds().Num_Le_Constraints();
00528 INT eq = info.Bounds().Num_Eq_Constraints();
00529 INT c = info.Symbol_Info().Elements();
00530 DYN_ARRAY<WN*> kill_array(&LNO_local_pool);
00531 for (INT i = 0; i < c; i++) {
00532 WN* wn = info.Symbol_Info().Bottom_nth(i).Outer_Nondef;
00533 kill_array.AddElement(wn);
00534 }
00535
00536 info.Collect_Do_Info(wn_do);
00537
00538 if (info.Bounds().Is_Consistent() == FALSE) {
00539 rval = COND_DO_NEVER;
00540 goto return_point;
00541 }
00542
00543 {
00544
00545 info.Reset_Bounds_To(le, eq, c, &kill_array);
00546
00547 DO_LOOP_INFO* dli = Get_Do_Loop_Info(wn_do);
00548 if (dli->LB->Too_Messy || dli->UB->Too_Messy)
00549 rval = COND_DO_MAYBE;
00550 else {
00551 rval = COND_DO_AT_LEAST_ONCE;
00552
00553
00554
00555
00556
00557
00558 for (INT dimlb = 0; dimlb < dli->LB->Num_Vec(); dimlb++) {
00559 ACCESS_VECTOR* avlb = dli->LB->Dim(dimlb);
00560 if (avlb->Too_Messy) {
00561 rval = COND_DO_MAYBE;
00562 goto return_point;
00563 }
00564 #ifdef KEY
00565
00566
00567 if (!avlb->Has_Loop_Coeff()) {
00568 rval = COND_DO_MAYBE;
00569 goto return_point;
00570 }
00571 #endif
00572 for(INT dimub = 0; dimub < dli->UB->Num_Vec(); dimub++) {
00573 ACCESS_VECTOR* avub = dli->UB->Dim(dimub);
00574 if (avub->Too_Messy) {
00575 rval = COND_DO_MAYBE;
00576 goto return_point;
00577 }
00578 #ifdef KEY
00579
00580
00581 if (!avub->Has_Loop_Coeff()) {
00582 rval = COND_DO_MAYBE;
00583 goto return_point;
00584 }
00585 #endif
00586
00587 ACCESS_VECTOR* nox = Difference_Inequality(avlb, avub,
00588 avlb->Nest_Depth()-1,
00589 DIFFERENCE_EXEC_NEVER,
00590 pool);
00591
00592 info.Add_Access(nox, WN_kid0(WN_start(wn_do)), wn_do);
00593 info.Add_Access(nox, WN_kid1(WN_end(wn_do)), wn_do);
00594 BOOL is_consistent = info.Bounds().Is_Consistent();
00595 info.Bounds().Remove_Last_Le(2);
00596 if (is_consistent) {
00597 rval = COND_DO_MAYBE;
00598 goto return_point;
00599 }
00600 }
00601 }
00602 }
00603 }
00604
00605 return_point:
00606
00607 ;
00608 }
00609 MEM_POOL_Pop(pool);
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619 #ifdef KEY
00620 if(rval==COND_DO_AT_LEAST_ONCE){
00621 if(Loop_Not_Entered(wn_do))
00622 rval = COND_DO_NEVER;
00623 }
00624 #endif
00625
00626 return rval;
00627 }
00628
00629
00630
00631
00632 void COND_Test(WN* wn)
00633 {
00634 OPCODE opcode = WN_opcode(wn);
00635
00636 switch (opcode) {
00637 case OPC_BLOCK:
00638 {
00639 for (WN* kid = WN_first(wn); kid; kid = WN_next(kid)) {
00640 COND_Test(kid);
00641 }
00642 }
00643 break;
00644 case OPC_DO_LOOP:
00645 fprintf(stderr, "DO line %d (%s) ... ",
00646 Srcpos_To_Line(WN_Get_Linenum(wn)),
00647 SYMBOL(WN_index(wn)).Name());
00648 fflush(stderr);
00649 switch (COND_Do_Info(wn)) {
00650 case COND_DO_MAYBE:
00651 fprintf(stderr, "maybe\n");
00652 break;
00653 case COND_DO_NEVER:
00654 fprintf(stderr, "never\n");
00655 break;
00656 case COND_DO_AT_LEAST_ONCE:
00657 fprintf(stderr, "at least once\n");
00658 break;
00659 default:
00660 Is_True(0, ("Bug in COND_Do_Info result"));
00661 }
00662 COND_Test(WN_do_body(wn));
00663 break;
00664 case OPC_IF:
00665 fprintf(stderr, "IF line %d ... ",
00666 Srcpos_To_Line(WN_Get_Linenum(wn)));
00667 fflush(stderr);
00668 switch (COND_If_Info(wn)) {
00669 case COND_IF_NOT_SURE:
00670 fprintf(stderr, "not sure\n");
00671 break;
00672 case COND_IF_THEN_ONLY:
00673 fprintf(stderr, "then only\n");
00674 break;
00675 case COND_IF_ELSE_ONLY:
00676 fprintf(stderr, "else only\n");
00677 break;
00678 default:
00679 Is_True(0, ("Bug in COND_If_Info result"));
00680 }
00681 COND_Test(WN_then(wn));
00682 COND_Test(WN_else(wn));
00683 break;
00684 default:
00685 if (!OPCODE_is_expression(opcode)) {
00686 for (INT kidno = 0; kidno < WN_kid_count(wn); kidno++) {
00687 COND_Test(WN_kid(wn,kidno));
00688 }
00689 }
00690 break;
00691 }
00692 }
00693
00694 static BOOL Eliminate_Dead_SCF_rec(WN*, void Remove_Region(WN *),
00695 COND_BOUNDS_INFO *, LABEL_LIST* label_list);
00696 static BOOL Eliminate_Dead_If(WN*, void Remove_Region(WN *),
00697 COND_BOUNDS_INFO *, LABEL_LIST* label_list);
00698 static BOOL Eliminate_Dead_Do(WN*, void Remove_Region(WN *),
00699 COND_BOUNDS_INFO *, LABEL_LIST* label_list);
00700
00701
00702
00703 BOOL Eliminate_Dead_SCF(WN *wn, void Remove_Region(WN *))
00704 {
00705 if (Get_Trace(TP_LNOPT,TT_LNO_DEAD)) {
00706 fprintf(TFile,"Eliminating_Dead_SCF\n");
00707 }
00708 MEM_POOL_Push(&LNO_local_pool);
00709 LABEL_LIST* label_list =
00710 CXX_NEW(LABEL_LIST(&LNO_local_pool, Current_Func_Node), &LNO_local_pool);
00711 COND_BOUNDS_INFO *info =
00712 CXX_NEW(COND_BOUNDS_INFO(&LNO_local_pool),&LNO_local_pool);
00713 BOOL result = Eliminate_Dead_SCF_rec(wn, Remove_Region, info, label_list);
00714 MEM_POOL_Pop(&LNO_local_pool);
00715 return result;
00716 }
00717
00718
00719
00720
00721
00722 static INT64 Iters(WN *loop)
00723 {
00724 INT64 rval=-1;
00725 INT64 stepsz = Step_Size(loop);
00726 if (stepsz < 1) return -1;
00727
00728 DO_LOOP_INFO *dli = Get_Do_Loop_Info(loop);
00729 if (dli->LB->Num_Vec() > 1 ||
00730 dli->UB->Num_Vec() > 1) {
00731 return -1;
00732 }
00733 ACCESS_VECTOR *ub = dli->UB->Dim(0);
00734 ACCESS_VECTOR *lb = dli->LB->Dim(0);
00735
00736 MEM_POOL_Push(&LNO_local_pool);
00737 ACCESS_VECTOR *sum = Add(lb,ub,&LNO_local_pool);
00738 if (sum->Is_Const()) {
00739 rval = sum->Const_Offset >= 0 ? (sum->Const_Offset + stepsz)/stepsz : 0;
00740 }
00741 MEM_POOL_Pop(&LNO_local_pool);
00742 return rval;
00743 }
00744
00745
00746
00747
00748
00749 static BOOL Eliminate_Dead_SCF_rec(WN *wn,
00750 void Remove_Region(WN *),
00751 COND_BOUNDS_INFO *info,
00752 LABEL_LIST* label_list)
00753 {
00754 BOOL result = FALSE;
00755 OPCODE opcode = WN_opcode(wn);
00756 if (opcode == OPC_BLOCK) {
00757 WN *kid = WN_first(wn);
00758 while (kid) {
00759 WN *next = WN_next(kid);
00760 if (WN_operator(kid) == OPR_LABEL
00761 && label_list->Label_Is_Targeted_Outside_Scope(kid))
00762 return result;
00763 if (kid && WN_opcode(kid)==OPC_DO_LOOP
00764 && Iters(kid)==1
00765 && !Do_Loop_Is_Mp(kid)
00766 && !Is_Nested_Doacross(kid)) {
00767 WN *first, *last;
00768 Remove_Unity_Trip_Loop(kid,TRUE,&first,&last,Array_Dependence_Graph,
00769 Du_Mgr);
00770 WN *tmp=first;
00771 while (tmp && tmp!= next) {
00772 WN *next_tmp = WN_next(tmp);
00773 result |= Eliminate_Dead_SCF_rec(tmp, Remove_Region, info,
00774 label_list);
00775 tmp = next_tmp;
00776 }
00777 result = TRUE;
00778 } else {
00779 result |= Eliminate_Dead_SCF_rec(kid, Remove_Region, info,
00780 label_list);
00781 }
00782 kid = next;
00783 }
00784 } else if (opcode == OPC_REGION && Is_Mp_Region(wn)) {
00785 WN* wn_start = WN_first(WN_region_body(wn));
00786 WN* wnn = 0;
00787 for (wnn = wn_start; wnn != NULL; wnn = WN_next(wnn))
00788 if (WN_operator(wnn) == OPR_DO_LOOP)
00789 break;
00790 if (wnn != NULL)
00791 result |= Eliminate_Dead_Do(wnn, Remove_Region, info, label_list);
00792 } else if (opcode == OPC_DO_LOOP) {
00793 result |= Eliminate_Dead_Do(wn, Remove_Region, info, label_list);
00794 } else if (opcode == OPC_IF) {
00795 result |= Eliminate_Dead_If(wn, Remove_Region, info, label_list);
00796 } else if (OPCODE_operator(opcode) == OPR_STID) {
00797
00798
00799
00800 WN *intr_prev = WN_prev(wn);
00801 if(!intr_prev || WN_operator(intr_prev) != OPR_INTRINSIC_CALL ||
00802 ((WN_intrinsic(intr_prev) != INTRN_U8READSTACKPOINTER)&&
00803 (WN_intrinsic(intr_prev) != INTRN_U4READSTACKPOINTER) &&
00804 (WN_intrinsic(intr_prev) != INTRN_U8I8ALLOCA) &&
00805 (WN_intrinsic(intr_prev) != INTRN_U4I4ALLOCA))){
00806 USE_LIST *uses = Du_Mgr->Du_Get_Use(wn);
00807 if (uses && !uses->Incomplete() && uses->Is_Empty()) {
00808 label_list->Remove_Tree(wn);
00809 Remove_Region(wn);
00810 }
00811 }
00812 } else if (opcode == OPC_GOTO) {
00813
00814 WN *nxt = WN_next(wn);
00815 if (nxt && WN_opcode(nxt) == OPC_LABEL) {
00816 if (WN_label_number(wn) == WN_label_number(nxt)) {
00817 result = TRUE;
00818 label_list->Remove_Tree(wn);
00819 Remove_Region(wn);
00820 }
00821 }
00822 } else if (opcode == OPC_TRUEBR) {
00823 WN *kid = WN_kid0(wn);
00824 if (WN_operator(kid) == OPR_INTCONST &&
00825 WN_const_val(kid) == 0) {
00826 result = TRUE;
00827 label_list->Remove_Tree(wn);
00828 Remove_Region(wn);
00829 }
00830 } else if (opcode == OPC_FALSEBR) {
00831 WN *kid = WN_kid0(wn);
00832 if (WN_operator(kid) == OPR_INTCONST &&
00833 WN_const_val(kid) == 1) {
00834 result = TRUE;
00835 label_list->Remove_Tree(wn);
00836 Remove_Region(wn);
00837 }
00838 } else if (OPCODE_is_scf(opcode)) {
00839 for (INT kidno=0; kidno<WN_kid_count(wn); kidno++) {
00840 WN *kid = WN_kid(wn,kidno);
00841 result |= Eliminate_Dead_SCF_rec(kid,Remove_Region, info,
00842 label_list);
00843 }
00844 }
00845 return result;
00846 }
00847
00848
00849 static void Delete_MP_Region (WN* do_wn,
00850 void Remove_Region(WN *),
00851 LABEL_LIST* label_list) {
00852 Is_True (do_wn && WN_operator(do_wn) == OPR_DO_LOOP &&
00853 Do_Loop_Is_Mp(do_wn),
00854 ("Delete_MP_Region: must be called with an MP do-loop"));
00855
00856 WN *region=LWN_Get_Parent(LWN_Get_Parent(do_wn));
00857 #ifdef KEY
00858 if (PU_cxx_lang(Get_Current_PU()) && Is_Eh_Or_Try_Region(region))
00859 region=LWN_Get_Parent(LWN_Get_Parent(region));
00860 #endif
00861 WN *region_parent = LWN_Get_Parent(region);
00862 WN *body = WN_region_body(region);
00863 WN *tmp = WN_first(body);
00864 WN *next_tmp;
00865 while (tmp) {
00866 next_tmp = WN_next(tmp);
00867 if ((WN_opcode(tmp) != OPC_PRAGMA) ||
00868 !(WN_pragmas[WN_pragma(tmp)].users & PUSER_MP)) {
00869 LWN_Insert_Block_Before(region_parent,region,
00870 LWN_Extract_From_Block(tmp));
00871 }
00872 tmp = next_tmp;
00873 }
00874 label_list->Remove_Tree(region);
00875 Remove_Region(region);
00876 }
00877
00878
00879
00880 static BOOL Eliminate_Dead_Do(WN *do_wn,
00881 void Remove_Region(WN *),
00882 COND_BOUNDS_INFO *info,
00883 LABEL_LIST* label_list)
00884 {
00885 BOOL result = FALSE;
00886 INT le = info->Bounds().Num_Le_Constraints();
00887 INT eq = info->Bounds().Num_Eq_Constraints();
00888 INT c = info->Symbol_Info().Elements();
00889 DYN_ARRAY<WN*> kill_array(&LNO_local_pool);
00890 for (INT i = 0; i < c; i++) {
00891 WN* wn = info->Symbol_Info().Bottom_nth(i).Outer_Nondef;
00892 kill_array.AddElement(wn);
00893 }
00894 info->Collect_Do_Info(do_wn);
00895
00896
00897 if (!info->Bounds().Is_Consistent()) {
00898 if (Get_Trace(TP_LNOPT,TT_LNO_DEAD)) {
00899 fprintf(TFile,"Do will not execute \n");
00900 Dump_WN(do_wn, TFile, 3);
00901 info->Print(TFile);
00902 }
00903
00904 DO_LOOP_INFO* dli = Get_Do_Loop_Info(do_wn);
00905 if (!Is_Nested_Doacross(do_wn)) {
00906
00907
00908 if (Do_Loop_Is_Mp(do_wn)) {
00909 Delete_MP_Region (do_wn, Remove_Region, label_list);
00910 }
00911
00912 WN *lb;
00913 if ( Index_Variable_Live_At_Exit(do_wn)) {
00914 lb = LWN_Copy_Tree(WN_start(do_wn),TRUE,LNO_Info_Map);
00915
00916
00917 LWN_Copy_Def_Use(WN_kid0(WN_start(do_wn)),WN_kid0(lb),Du_Mgr);
00918
00919 USE_LIST *uses = Du_Mgr->Du_Get_Use(WN_start(do_wn));
00920 Is_True(uses,("Live variable but no uses "));
00921 USE_LIST_ITER iter(uses);
00922 for (const DU_NODE *node=iter.First();
00923 !iter.Is_Empty(); node=iter.Next()){
00924 WN *use = (WN *) node->Wn();
00925 Du_Mgr->Add_Def_Use(lb,use);
00926 }
00927 if (uses->Incomplete()) {
00928 USE_LIST *lb_uses = Du_Mgr->Du_Get_Use(lb);
00929 lb_uses->Set_Incomplete();
00930 }
00931
00932 LWN_Insert_Block_After(LWN_Get_Parent(do_wn),do_wn,lb);
00933 }
00934 result = TRUE;
00935
00936 label_list->Remove_Tree(do_wn);
00937 Remove_Region(do_wn);
00938
00939 }
00940 } else {
00941 if (Get_Trace(TP_LNOPT,TT_LNO_DEAD)) {
00942 fprintf(TFile,"Do will execute \n");
00943 }
00944 result |= Eliminate_Dead_SCF_rec(WN_do_body(do_wn),Remove_Region,info,
00945 label_list);
00946
00947
00948 if ((WN_first(WN_do_body(do_wn)) == NULL)) {
00949 BOOL cant_eliminate = FALSE;
00950 if (Index_Variable_Live_At_Exit(do_wn)) {
00951 if (!Upper_Bound_Standardize(WN_end(do_wn), TRUE))
00952 cant_eliminate = TRUE;
00953 else
00954 Finalize_Index_Variable(do_wn, TRUE);
00955 }
00956 if (!cant_eliminate) {
00957 if (Get_Trace(TP_LNOPT,TT_LNO_DEAD)) {
00958 fprintf(TFile,"Do is empty\n");
00959 }
00960
00961 if (Do_Loop_Is_Mp(do_wn)) {
00962 Delete_MP_Region (do_wn, Remove_Region, label_list);
00963 }
00964
00965 result = TRUE;
00966 label_list->Remove_Tree(do_wn);
00967 Remove_Region(do_wn);
00968 }
00969 }
00970 }
00971 info->Reset_Bounds_To(le, eq, c, &kill_array);
00972 return result;
00973 }
00974
00975
00976 static BOOL Eliminate_Dead_If(WN *if_wn,
00977 void Remove_Region(WN *),
00978 COND_BOUNDS_INFO *info,
00979 LABEL_LIST* label_list)
00980 {
00981 BOOL result = FALSE;
00982 WN *kid;
00983 INT le = info->Bounds().Num_Le_Constraints();
00984 INT eq = info->Bounds().Num_Eq_Constraints();
00985 INT c = info->Symbol_Info().Elements();
00986 DYN_ARRAY<WN*> kill_array(&LNO_local_pool);
00987 for (INT i = 0; i < c; i++) {
00988 WN* wn = info->Symbol_Info().Bottom_nth(i).Outer_Nondef;
00989 kill_array.AddElement(wn);
00990 }
00991
00992 info->Collect_If_Info(if_wn, TRUE);
00993 if (!info->Bounds().Is_Consistent()
00994 && !label_list->Has_Targeted_Label(WN_then(if_wn))) {
00995 if (Get_Trace(TP_LNOPT,TT_LNO_DEAD)) {
00996 fprintf(TFile,"then is inconsistent \n");
00997 Dump_WN(if_wn, TFile, 3);
00998 info->Print(TFile);
00999 }
01000 info->Reset_Bounds_To(le, eq, c, &kill_array);
01001
01002
01003 WN *else_block_wn = WN_else(if_wn);
01004 Eliminate_Dead_SCF_rec(else_block_wn, Remove_Region, info,
01005 label_list);
01006
01007
01008
01009 WN *parent = LWN_Get_Parent(if_wn);
01010 while ((kid = WN_last(else_block_wn)) != NULL) {
01011 LWN_Insert_Block_After(parent,if_wn,LWN_Extract_From_Block(kid));
01012 }
01013 result = TRUE;
01014 label_list->Remove_Tree(if_wn);
01015 Remove_Region(if_wn);
01016
01017 info->Reset_Bounds_To(le, eq, c, &kill_array);
01018 } else {
01019 if (Get_Trace(TP_LNOPT,TT_LNO_DEAD)) {
01020 fprintf(TFile,"then is consistent \n");
01021 }
01022
01023 WN *then_block_wn = WN_then(if_wn);
01024 result |= Eliminate_Dead_SCF_rec(then_block_wn, Remove_Region, info,
01025 label_list);
01026 info->Reset_Bounds_To(le, eq, c, &kill_array);
01027
01028 info->Collect_If_Info(if_wn, FALSE);
01029 if (!info->Bounds().Is_Consistent()
01030 && !label_list->Has_Targeted_Label(WN_else(if_wn))) {
01031 if (Get_Trace(TP_LNOPT,TT_LNO_DEAD)) {
01032 fprintf(TFile,"else is inconsistent \n");
01033 Dump_WN(if_wn, TFile, 3);
01034 info->Print(TFile);
01035 }
01036
01037 WN *parent = LWN_Get_Parent(if_wn);
01038 while ((kid = WN_last(then_block_wn)) != NULL) {
01039 LWN_Insert_Block_After(parent,if_wn,LWN_Extract_From_Block(kid));
01040 }
01041 result = TRUE;
01042 label_list->Remove_Tree(if_wn);
01043 Remove_Region(if_wn);
01044 } else {
01045 if (Get_Trace(TP_LNOPT,TT_LNO_DEAD)) {
01046 fprintf(TFile,"else is consistent \n");
01047 }
01048
01049
01050 result |= Eliminate_Dead_SCF_rec(WN_else(if_wn), Remove_Region, info,
01051 label_list);
01052
01053
01054 if (!WN_first(WN_else(if_wn)) && !WN_first(WN_then(if_wn))) {
01055 label_list->Remove_Tree(if_wn);
01056 Remove_Region(if_wn);
01057 if (Get_Trace(TP_LNOPT,TT_LNO_DEAD)) {
01058 fprintf(TFile,"if is empty\n");
01059 }
01060 }
01061 }
01062 info->Reset_Bounds_To(le, eq, c, &kill_array);
01063 }
01064 return result;
01065 }
01066
01067 static void Mark_Dos(WN *do_wn, HASH_TABLE<WN *,BOOL> *htable);
01068 static void Guard_Dos_Rec(WN *do_wn, HASH_TABLE<WN *,BOOL> *htable);
01069 static WN *Highest_Guard_Point(WN *do_wn, DO_LOOP_INFO *dli);
01070 static WN *Highest_Condition_Point(WN *highest_wn, INT non_const_loops);
01071
01072
01073
01074
01075
01076
01077
01078
01079 void Guard_Dos(WN *func_nd)
01080 {
01081 MEM_POOL_Push(&LNO_local_pool);
01082
01083 {
01084 HASH_TABLE<WN *,BOOL> htable(200,&LNO_local_pool);
01085 Mark_Dos(func_nd,&htable);
01086 Guard_Dos_Rec(func_nd,&htable);
01087 }
01088 MEM_POOL_Pop(&LNO_local_pool);
01089 }
01090
01091
01092 static void Mark_Dos(WN *wn, HASH_TABLE<WN *,BOOL> *htable)
01093 {
01094 OPCODE opcode = WN_opcode(wn);
01095 if (opcode == OPC_BLOCK) {
01096 WN *kid = WN_first(wn);
01097 while (kid) {
01098 WN *next = WN_next(kid);
01099 Mark_Dos(kid,htable);
01100 kid = next;
01101 }
01102 } else {
01103 for (INT kidno=0; kidno<WN_kid_count(wn); kidno++) {
01104 WN *kid = WN_kid(wn,kidno);
01105 Mark_Dos(kid,htable);
01106 }
01107 if (opcode == OPC_DO_LOOP) {
01108 if (!Do_Loop_Is_Mp(wn)) {
01109 BOOL guard = FALSE;
01110 MEM_POOL_Push(&LNO_local_pool);
01111
01112 if (COND_Do_Info(wn,&LNO_local_pool) != COND_DO_AT_LEAST_ONCE) {
01113 guard = TRUE;
01114 }
01115 MEM_POOL_Pop(&LNO_local_pool);
01116 if (guard) htable->Enter(wn,TRUE);
01117
01118
01119 if (WN_kid_count(wn) == 6) {
01120 WN *trip_count = WN_LOOP_TripCount(wn);
01121 if (trip_count) {
01122 LWN_Parentize(trip_count);
01123 LWN_Set_Parent(trip_count, NULL);
01124 }
01125 BOOL const_trip = (trip_count) &&
01126 (WN_operator(trip_count) == OPR_INTCONST);
01127 if (!const_trip) LWN_Delete_Tree(trip_count);
01128 WN *loop_info = WN_do_loop_info(wn);
01129 if (loop_info && WN_kid_count(loop_info)) {
01130
01131 if (!const_trip && (WN_kid_count(loop_info) == 2)) {
01132 WN *new_loop_info =
01133 LWN_CreateLoopInfo(LWN_Copy_Tree(WN_kid0(loop_info)),
01134 NULL,0,0,0);
01135 LWN_Delete_Tree(loop_info);
01136 WN_set_do_loop_info(wn,new_loop_info);
01137 LWN_Set_Parent(new_loop_info,wn);
01138 loop_info = new_loop_info;
01139 } else if (const_trip && (WN_kid_count(loop_info)==1)){
01140 WN *new_loop_info = LWN_CreateLoopInfo(
01141 LWN_Copy_Tree(WN_kid0(loop_info)),trip_count,0,0,0);
01142 LWN_Delete_Tree(loop_info);
01143 WN_set_do_loop_info(wn,new_loop_info);
01144 LWN_Set_Parent(new_loop_info,wn);
01145 loop_info = new_loop_info;
01146 } else if (const_trip) {
01147 LWN_Delete_Tree(WN_loop_trip(loop_info));
01148 WN_set_loop_trip(loop_info,trip_count);
01149 LWN_Set_Parent(trip_count,loop_info);
01150 }
01151
01152
01153
01154
01155
01156
01157 extern INT64 Get_Good_Num_Iters (DO_LOOP_INFO *dli);
01158 DO_LOOP_INFO *dli = Get_Do_Loop_Info(wn);
01159 INT64 est = Get_Good_Num_Iters(dli);
01160 WN_loop_trip_est(loop_info) = MIN(UINT16_MAX, est);
01161 if (dli->Num_Iterations_Symbolic) {
01162 WN_Set_Loop_Symb_Trip(loop_info);
01163 } else {
01164 WN_Reset_Loop_Symb_Trip(loop_info);
01165 }
01166 if (dli->Is_Inner) {
01167 WN_Set_Loop_Innermost(loop_info);
01168 } else {
01169 WN_Reset_Loop_Innermost(loop_info);
01170 }
01171 INT depth = 1;
01172 WN *tmp = LWN_Get_Parent(wn);
01173 while (tmp) {
01174 if ((WN_opcode(tmp) == OPC_DO_LOOP) ||
01175 (WN_opcode(tmp) == OPC_DO_WHILE) ||
01176 (WN_opcode(tmp) == OPC_WHILE_DO)) {
01177 depth++;
01178 }
01179 tmp = LWN_Get_Parent(tmp);
01180 }
01181 WN_loop_depth(loop_info) = depth;
01182 WN_Set_Loop_Nz_Trip(loop_info);
01183 if (dli->Is_Cache_Winddown() || dli->Is_In_Cache_Winddown()) {
01184 WN_Set_Loop_Winddown_Cache(loop_info);
01185 } else {
01186 WN_Reset_Loop_Winddown_Cache(loop_info);
01187 }
01188 if (dli->Is_Register_Winddown()||dli->Is_In_Register_Winddown()) {
01189 WN_Set_Loop_Winddown_Reg(loop_info);
01190 } else {
01191 WN_Reset_Loop_Winddown_Reg(loop_info);
01192 }
01193 if (dli->Is_Generally_Unimportant()) {
01194 WN_Set_Loop_Unimportant_Misc(loop_info);
01195 } else {
01196 WN_Reset_Loop_Unimportant_Misc(loop_info);
01197 }
01198 }
01199 }
01200 }
01201 if (WN_kid_count(wn) == 6) {
01202 WN *do_idname = WN_kid0(wn);
01203 WN *loop_info = WN_do_loop_info(wn);
01204 if (WN_kid0(loop_info)) {
01205 WN *idname = WN_kid0(loop_info);
01206
01207 if ((WN_st(idname) != WN_st(do_idname)) ||
01208 (WN_offset(idname) != WN_offset(do_idname))) {
01209 LWN_Delete_Tree(idname);
01210 WN_kid0(loop_info) = NULL;
01211 }
01212 }
01213
01214
01215 if (!WN_kid0(loop_info)) {
01216 WN_kid0(loop_info) =
01217 WN_CreateIdname(WN_offset(do_idname),WN_st(do_idname));
01218 LWN_Set_Parent(WN_kid0(loop_info), loop_info);
01219 }
01220 }
01221 }
01222 }
01223 }
01224
01225
01226 static void Guard_Dos_Rec(WN *wn, HASH_TABLE<WN *,BOOL> *htable)
01227 {
01228 OPCODE opcode = WN_opcode(wn);
01229 if (opcode == OPC_DO_LOOP) {
01230 if (htable->Find(wn)) {
01231 if (!Do_Loop_Is_Mp(wn)) {
01232 Guard_A_Do(wn);
01233 }
01234 }
01235 }
01236 if (opcode == OPC_BLOCK) {
01237 WN *kid = WN_first(wn);
01238 while (kid) {
01239 WN *next = WN_next(kid);
01240 if (!OPCODE_is_expression(WN_opcode(kid)))
01241 Guard_Dos_Rec(kid,htable);
01242 kid = next;
01243 }
01244 } else {
01245 for (INT kidno=0; kidno<WN_kid_count(wn); kidno++) {
01246 WN *kid = WN_kid(wn,kidno);
01247 if (!OPCODE_is_expression(WN_opcode(kid)))
01248 Guard_Dos_Rec(kid,htable);
01249 }
01250 }
01251 }
01252
01253
01254
01255
01256 extern WN* Guard_A_Do(WN *do_wn)
01257 {
01258
01259 WN *lower_stid = WN_start(do_wn);
01260 FmtAssert(WN_operator(lower_stid) == OPR_STID,
01261 ("Lower bound of a DO_LOOP is not an STID"));
01262 WN *lower = WN_kid0(lower_stid);
01263
01264 DO_LOOP_INFO *dli = Get_Do_Loop_Info(do_wn);
01265
01266
01267
01268 WN *test = LWN_Copy_Tree(WN_end(do_wn),TRUE,LNO_Info_Map);
01269 LWN_Copy_Def_Use(WN_end(do_wn),test,Du_Mgr);
01270 if (Array_Dependence_Graph) {
01271 if (!Array_Dependence_Graph->Add_Deps_To_Copy_Block(
01272 WN_end(do_wn),test,FALSE)) {
01273 LNO_Erase_Dg_From_Here_In(do_wn,Array_Dependence_Graph);
01274 }
01275 }
01276 Replace_Ldid_With_Exp_Copy(SYMBOL(lower_stid), test, lower, Du_Mgr,Array_Dependence_Graph);
01277
01278
01279 WN *new_then = WN_CreateBlock();
01280 WN *new_else = WN_CreateBlock();
01281 WN *new_if = LWN_CreateIf(test,new_then,new_else);
01282 WN_Set_If_Guard(new_if);
01283 dli->Guard = new_if;
01284
01285
01286 if (Index_Variable_Live_At_Exit(do_wn)) {
01287 WN *lb = LWN_Copy_Tree(WN_start(do_wn),TRUE,LNO_Info_Map);
01288
01289
01290
01291 LWN_Copy_Def_Use(WN_kid0(WN_start(do_wn)),WN_kid0(lb),Du_Mgr);
01292 if (Array_Dependence_Graph) {
01293 if (!Array_Dependence_Graph->Add_Deps_To_Copy_Block(
01294 WN_kid0(WN_start(do_wn)),WN_kid0(lb),FALSE)) {
01295 LNO_Erase_Dg_From_Here_In(do_wn,Array_Dependence_Graph);
01296 }
01297 }
01298
01299
01300 USE_LIST *uses = Du_Mgr->Du_Get_Use(WN_start(do_wn));
01301 Is_True(uses,("Live variable but no uses "));
01302 USE_LIST_ITER iter(uses);
01303 for (const DU_NODE *node=iter.First(); !iter.Is_Empty(); node=iter.Next()){
01304 WN *use = (WN *) node->Wn();
01305 if (!Is_Descendent(use,do_wn)) {
01306 Du_Mgr->Add_Def_Use(lb,use);
01307 }
01308 }
01309 if (uses->Incomplete()) {
01310 Du_Mgr->Create_Use_List(lb);
01311 USE_LIST *lb_uses = Du_Mgr->Du_Get_Use(lb);
01312 lb_uses->Set_Incomplete();
01313 }
01314
01315
01316 LWN_Insert_Block_Before(new_else,NULL,lb);
01317 }
01318
01319 if (Cur_PU_Feedback) {
01320 Update_Guarded_Do_FB(new_if, do_wn, Cur_PU_Feedback);
01321 }
01322
01323
01324 WN *highest_wn = do_wn;
01325 if (Statically_Safe_Exp(WN_if_test(new_if))) {
01326 WN *wn_block = LWN_Get_Parent(do_wn);
01327 Is_True(WN_opcode(wn_block) == OPC_BLOCK,("Parent must be block "));
01328 if (WN_first(wn_block) == WN_last(wn_block)) {
01329 highest_wn = Highest_Guard_Point(do_wn,dli);
01330 }
01331 }
01332 if (WN_opcode(highest_wn) != OPC_BLOCK) {
01333 LWN_Insert_Block_Before(LWN_Get_Parent(highest_wn),highest_wn,new_if);
01334 LWN_Insert_Block_Before(new_then, NULL,LWN_Extract_From_Block(highest_wn));
01335 } else {
01336 LWN_Insert_Block_Before(highest_wn,NULL,new_if);
01337 WN *wn = WN_first(highest_wn);
01338 while (wn != new_if) {
01339 WN *next = WN_next(wn);
01340 LWN_Insert_Block_After(WN_then(new_if),NULL,LWN_Extract_From_Block(wn));
01341 wn = next;
01342 }
01343 }
01344
01345
01346 IF_INFO *ii = CXX_NEW(IF_INFO(&LNO_default_pool,TRUE,
01347 Find_SCF_Inside(new_if,OPC_REGION)!=NULL),
01348 &LNO_default_pool);
01349 WN_MAP_Set(LNO_Info_Map,new_if,(void *)ii);
01350 DOLOOP_STACK* stack = CXX_NEW(DOLOOP_STACK(&LNO_local_pool),
01351 &LNO_local_pool);
01352 Build_Doloop_Stack(new_if, stack);
01353 LNO_Build_If_Access(new_if, stack);
01354 CXX_DELETE(stack, &LNO_local_pool);
01355 return new_if;
01356 }
01357
01358
01359
01360
01361
01362 static WN *Highest_Guard_Point(WN *do_wn, DO_LOOP_INFO *dli)
01363 {
01364
01365
01366
01367 INT depth = Do_Loop_Depth(do_wn);
01368 ACCESS_ARRAY *lb_array = dli->LB;
01369 ACCESS_ARRAY *ub_array = dli->UB;
01370 if (lb_array->Too_Messy || ub_array->Too_Messy) {
01371 return(do_wn);
01372 }
01373
01374
01375
01376
01377 INT non_const_loops =
01378 MAX(lb_array->Non_Const_Loops(),ub_array->Non_Const_Loops());
01379
01380 INT i;
01381 for (i=0; i<lb_array->Num_Vec(); i++) {
01382 ACCESS_VECTOR *lb = lb_array->Dim(i);
01383 if (lb->Too_Messy) return(do_wn);
01384 for (INT j=non_const_loops; j<depth; j++) {
01385 if (lb->Loop_Coeff(j)) {
01386 non_const_loops = j+1;
01387 }
01388 }
01389 }
01390 for (i=0; i<ub_array->Num_Vec(); i++) {
01391 ACCESS_VECTOR *ub = ub_array->Dim(i);
01392 if (ub->Too_Messy) return(do_wn);
01393 for (INT j=non_const_loops; j<depth; j++) {
01394 if (ub->Loop_Coeff(j)) {
01395 non_const_loops = j+1;
01396 }
01397 }
01398 }
01399
01400
01401
01402
01403
01404
01405 ARRAY_DIRECTED_GRAPH16* dg = Array_Dependence_Graph;
01406 if (dg) {
01407 INT ncl = non_const_loops;
01408 WN_ITER *wni;
01409 for (wni=WN_WALK_TreeIter(WN_end(do_wn)); wni; wni=WN_WALK_TreeNext(wni)) {
01410 WN* ldid = WN_ITER_wn(wni);
01411 if (WN_operator(ldid) == OPR_LDID) {
01412 VINDEX16 v = dg->Get_Vertex(ldid);
01413 if (v) {
01414 EINDEX16 e;
01415 for (e = dg->Get_Out_Edge(v); e; e = dg->Get_Next_Out_Edge(e)) {
01416 WN* sink = dg->Get_Wn(dg->Get_Sink(e));
01417 INT d = Do_Loop_Depth(Enclosing_Do_Loop(sink)) + 1;
01418 non_const_loops = MAX(non_const_loops, d);
01419 }
01420 for (e = dg->Get_In_Edge(v); e; e = dg->Get_Next_In_Edge(e)) {
01421 WN* source = dg->Get_Wn(dg->Get_Source(e));
01422 INT d = Do_Loop_Depth(Enclosing_Do_Loop(source)) + 1;
01423 non_const_loops = MAX(non_const_loops, d);
01424 }
01425 }
01426 }
01427 }
01428 if (ncl != non_const_loops) {
01429 DevWarn(("non_const_loops changed from %d to %d"), ncl, non_const_loops);
01430 }
01431 }
01432
01433 return (Highest_Condition_Point(do_wn,non_const_loops));
01434 }
01435
01436
01437
01438
01439
01440
01441
01442 static WN *Highest_Condition_Point(WN *input_wn, INT non_const_loops)
01443 {
01444 BOOL seen_do = FALSE;
01445
01446 WN *parent_wn=LWN_Get_Parent(input_wn);
01447 WN *wn = input_wn;
01448 BOOL done = FALSE;
01449 OPCODE opcode;
01450 while (!done) {
01451 opcode = WN_opcode(parent_wn);
01452 if (opcode == OPC_BLOCK) {
01453 if (WN_first(parent_wn) != WN_last(parent_wn)) {
01454 done = TRUE;
01455 }
01456 } else if (opcode == OPC_IF) {
01457 if (WN_first(WN_else(parent_wn)) != NULL) {
01458 done = TRUE;
01459 }
01460 } else if (opcode == OPC_DO_LOOP) {
01461
01462 if (Index_Variable_Live_At_Exit(parent_wn)) {
01463 done = TRUE;
01464 } else if (Do_Loop_Is_Mp(parent_wn)) {
01465 done = TRUE;
01466 }
01467 } else if ((opcode != OPC_DO_LOOP) && (opcode != OPC_DO_WHILE) &&
01468 (opcode != OPC_WHILE_DO)) {
01469 done = TRUE;
01470 }
01471 if (WN_opcode(wn) == OPC_DO_LOOP) {
01472 if (Do_Loop_Depth(wn) < non_const_loops) {
01473 return input_wn;
01474 } else if (Do_Loop_Depth(wn) == non_const_loops) {
01475
01476 done = TRUE;
01477 }
01478 seen_do = TRUE;
01479 }
01480 if (!done) {
01481 wn = parent_wn;
01482 parent_wn = LWN_Get_Parent(parent_wn);
01483 }
01484 }
01485 if (!seen_do) return input_wn;
01486 return wn;
01487 }
01488
01489 static INT Non_Const_Loops(WN *expr);
01490
01491
01492
01493
01494
01495
01496
01497 BOOL Hoist_Conditionals(WN *wn)
01498 {
01499 BOOL result = FALSE;
01500 OPCODE opcode = WN_opcode(wn);
01501 if (opcode == OPC_BLOCK) {
01502 WN *kid = WN_first(wn);
01503 while (kid) {
01504 WN *next = WN_next(kid);
01505 result |= Hoist_Conditionals(kid);
01506 kid = next;
01507 }
01508 } else {
01509 for (INT kidno=0; kidno<WN_kid_count(wn); kidno++) {
01510 WN *kid = WN_kid(wn,kidno);
01511 result |= Hoist_Conditionals(kid);
01512 }
01513 }
01514
01515 if ((opcode == OPC_DO_LOOP) && !Do_Loop_Is_Mp(wn)) {
01516 WN *block_wn = WN_do_body(wn);
01517 WN *if_wn = WN_first(block_wn);
01518 if (if_wn && (WN_opcode(if_wn) == OPC_IF) && (if_wn == WN_last(block_wn))) {
01519 if (!WN_first(WN_else(if_wn))) {
01520 if (Statically_Safe_Exp(WN_if_test(if_wn))) {
01521 INT non_const_loops=Non_Const_Loops(WN_if_test(if_wn));
01522 if (non_const_loops != -1) {
01523 WN *new_pos = Highest_Condition_Point(if_wn, non_const_loops);
01524 if (new_pos != if_wn) {
01525 result = TRUE;
01526
01527 WN *wn = WN_first(WN_then(if_wn));
01528 while (wn) {
01529 WN *next = WN_next(wn);
01530 LWN_Insert_Block_Before(block_wn,if_wn,
01531 LWN_Extract_From_Block(wn));
01532 wn = next;
01533 }
01534
01535
01536 LWN_Extract_From_Block(if_wn);
01537 LWN_Copy_Frequency(if_wn,new_pos);
01538 LWN_Copy_Frequency_Tree(WN_if_test(if_wn),new_pos);
01539 if (WN_opcode(new_pos) != OPC_BLOCK) {
01540
01541 LWN_Insert_Block_Before(LWN_Get_Parent(new_pos),new_pos,if_wn);
01542 LWN_Insert_Block_Before(WN_then(if_wn), NULL,
01543 LWN_Extract_From_Block(new_pos));
01544 } else {
01545 LWN_Insert_Block_Before(new_pos,NULL,if_wn);
01546 WN *wn = WN_first(new_pos);
01547 while (wn != if_wn) {
01548 WN *next = WN_next(wn);
01549 LWN_Insert_Block_After(WN_then(if_wn),NULL,
01550 LWN_Extract_From_Block(wn));
01551 wn = next;
01552 }
01553 }
01554
01555 IF_INFO* ii = Get_If_Info(if_wn, TRUE);
01556 ii->Contains_Do_Loops = TRUE;
01557 }
01558 }
01559 }
01560 }
01561 }
01562 }
01563 return result;
01564 }
01565
01566
01567
01568
01569
01570 static INT Non_Const_Loops(WN *expr)
01571 {
01572 int count=0;
01573 int depth;
01574 BOOL first_time=TRUE;
01575 WN *loops = LWN_Get_Parent(expr);
01576 while (loops) {
01577 if (WN_operator(loops) == OPR_DO_LOOP) {
01578 if (first_time) {
01579 depth = Do_Loop_Depth(loops);
01580 first_time = FALSE;
01581 }
01582 if (Is_Loop_Invariant_Exp(expr,loops)) {
01583 count++;
01584 } else {
01585 if (count == 0) {
01586 return -1;
01587 } else {
01588 return depth+1-count;
01589 }
01590 }
01591 }
01592 loops = LWN_Get_Parent(loops);
01593 }
01594 return depth-count+1;
01595 }
01596
01597
01598
01599 BOOL Is_Consistent_Condition(ACCESS_VECTOR *av, WN *expr)
01600 {
01601 Is_True(OPCODE_is_expression(WN_opcode(expr)),
01602 ("Non-expression in Is_Consistent \n"));
01603 if (!OPCODE_is_expression(WN_opcode(expr))) return TRUE;
01604 if (av->Too_Messy || av->Contains_Non_Lin_Symb()) return TRUE;
01605
01606 BOOL answer;
01607 MEM_POOL_Push(&LNO_local_pool);
01608 {
01609 COND_BOUNDS_INFO info(&LNO_local_pool);
01610 WN *statement = LWN_Get_Statement(expr);
01611 info.Collect_Outer_Info(statement);
01612 info.Add_Access(av,expr,statement);
01613 if (info.Bounds().Is_Consistent()) {
01614 answer = TRUE;
01615 } else {
01616 answer = FALSE;
01617 }
01618 }
01619 MEM_POOL_Pop(&LNO_local_pool);
01620 return answer;
01621 }
01622
01623
01624
01625
01626
01627
01628
01629
01630 static void STD_Canonicalize_Upper_Bound(WN* wn_loop)
01631 {
01632 if (Do_Loop_Is_Mp(wn_loop))
01633 return;
01634 OPCODE opc = WN_opcode(WN_end(wn_loop));
01635 OPERATOR opr = OPCODE_operator(opc);
01636 if (UBvar(WN_end(wn_loop)) == NULL)
01637 return;
01638 if (opr == OPR_GT || opr == OPR_GE) {
01639 WN* lhs = WN_kid0(WN_end(wn_loop));
01640 WN* rhs = WN_kid1(WN_end(wn_loop));
01641 WN_kid0(WN_end(wn_loop)) = rhs;
01642 WN_kid1(WN_end(wn_loop)) = lhs;
01643 OPERATOR opr_inv = opr == OPR_GT ? OPR_LT : OPR_LE;
01644 OPCODE opc_inv = OPCODE_make_op(opr_inv, OPCODE_rtype(opc),
01645 OPCODE_desc(opc));
01646 WN_set_opcode(WN_end(wn_loop), opc_inv);
01647 }
01648 if (WN_operator(WN_end(wn_loop)) == OPR_LT) {
01649 if (COND_Do_Info(wn_loop, &LNO_local_pool) != COND_DO_AT_LEAST_ONCE)
01650 Guard_A_Do(wn_loop);
01651 TYPE_ID desc = WN_desc(WN_end(wn_loop));
01652 #ifndef KEY
01653 WN_set_opcode(WN_end(wn_loop),
01654 OPCODE_make_op(OPR_LE, OPCODE_rtype(opc), desc));
01655 #else
01656
01657
01658
01659
01660
01661
01662
01663
01664
01665
01666
01667
01668
01669
01670
01671
01672
01673
01674
01675
01676
01677 TYPE_ID rtype0 = WN_rtype(WN_kid0(WN_end(wn_loop)));
01678 TYPE_ID rtype1 = WN_rtype(WN_kid1(WN_end(wn_loop)));
01679
01680 if (MTYPE_is_unsigned(desc)){
01681 if(MTYPE_is_signed(rtype0) ||
01682 MTYPE_is_signed(rtype1) ||
01683 Is_Target_64bit())
01684 desc = MTYPE_complement(desc);
01685 }
01686
01687 WN_set_opcode(WN_end(wn_loop),
01688 OPCODE_make_op(OPR_LE, OPCODE_rtype(opc), desc));
01689 #endif
01690 OPCODE subop = OPCODE_make_op(OPR_SUB, desc, MTYPE_V);
01691 WN* ub1 = LWN_CreateExp2(subop, WN_kid1(WN_end(wn_loop)),
01692 LWN_Make_Icon(desc, 1));
01693 WN_kid1(WN_end(wn_loop)) = ub1;
01694 LWN_Copy_Frequency_Tree(ub1, WN_end(wn_loop));
01695 LWN_Set_Parent(ub1, WN_end(wn_loop));
01696 }
01697 }
01698
01699
01700
01701
01702
01703
01704
01705 static void STD_Traverse(WN* wn_tree)
01706 {
01707 if (WN_opcode(wn_tree) == OPC_DO_LOOP && Do_Loop_Is_Unsigned(wn_tree))
01708 STD_Canonicalize_Upper_Bound(wn_tree);
01709 if (WN_opcode(wn_tree) == OPC_BLOCK) {
01710
01711
01712
01713 #ifdef KEY
01714 WN *wn = WN_first(wn_tree);
01715 while(wn){
01716 WN *next_wn = WN_next(wn);
01717 STD_Traverse(wn);
01718 wn = next_wn;
01719 }
01720 #else
01721 for (WN* wn = WN_first(wn_tree); wn != NULL; wn = WN_next(wn))
01722 STD_Traverse(wn);
01723 #endif
01724 } else {
01725 for (INT i = 0; i < WN_kid_count(wn_tree); i++)
01726 STD_Traverse(WN_kid(wn_tree, i));
01727 }
01728 }
01729
01730
01731
01732
01733
01734
01735
01736
01737 extern void Canonicalize_Unsigned_Loops(WN* func_nd)
01738 {
01739 STD_Traverse(func_nd);
01740 }
01741
01742
01743
01744
01745
01746
01747
01748
01749
01750 extern BOOL Redundant_Condition(COND_BOUNDS_INFO* info,
01751 WN* wn_cond,
01752 WN* wn_if)
01753 {
01754
01755
01756 WN *wn_cond_parent = LWN_Get_Parent(wn_cond);
01757
01758
01759 INT le = info->Bounds().Num_Le_Constraints();
01760 INT eq = info->Bounds().Num_Eq_Constraints();
01761 INT c = info->Symbol_Info().Elements();
01762 DYN_ARRAY<WN*> kill_array(&LNO_local_pool);
01763 for (INT i = 0; i < c; i++) {
01764 WN* wn = info->Symbol_Info().Bottom_nth(i).Outer_Nondef;
01765 kill_array.AddElement(wn);
01766 }
01767
01768
01769
01770 WN* wn_old_cond = WN_if_test(wn_if);
01771 WN_if_test(wn_if) = wn_cond;
01772 LWN_Set_Parent(wn_cond, wn_if);
01773 DOLOOP_STACK stack1(&LNO_local_pool);
01774 Build_Doloop_Stack(wn_if, &stack1);
01775 LNO_Build_If_Access(wn_if, &stack1);
01776
01777
01778 IF_INFO* ii = Get_If_Info(wn_if, TRUE);
01779 if (ii->Condition->Num_Vec() == 1) {
01780 ACCESS_VECTOR av_cond(ii->Condition->Dim(0), &LNO_local_pool);
01781 av_cond.Negate_Me();
01782 av_cond.Const_Offset--;
01783 info->Add_Access(&av_cond, wn_cond, wn_if);
01784 BOOL return_value = !info->Bounds().Is_Consistent();
01785 info->Reset_Bounds_To(le, eq, c, &kill_array);
01786 WN_if_test(wn_if) = wn_old_cond;
01787 LWN_Set_Parent(wn_old_cond, wn_if);
01788 LWN_Set_Parent(wn_cond, wn_cond_parent);
01789 if (return_value)
01790 return TRUE;
01791 }
01792
01793
01794 info->Collect_If_Info(wn_if, TRUE);
01795 WN_if_test(wn_if) = wn_old_cond;
01796 LWN_Set_Parent(wn_old_cond, wn_if);
01797 LWN_Set_Parent(wn_cond, wn_cond_parent);
01798 return FALSE;
01799 }
01800
01801 extern void Update_Guarded_Do_FB(WN *if_wn, WN *do_wn, FEEDBACK *feedback)
01802 {
01803 Is_True(if_wn && WN_operator(if_wn) == OPR_IF, ("bad if_wn"));
01804 Is_True(do_wn && WN_operator(do_wn) == OPR_DO_LOOP, ("bad do_wn"));
01805 FB_Info_Loop loop_freq = feedback->Query_loop(do_wn);
01806 FB_Info_Branch if_freq(loop_freq.freq_positive, loop_freq.freq_zero);
01807 feedback->Annot_branch(if_wn, if_freq);
01808
01809 loop_freq.freq_zero = FB_FREQ_ZERO;
01810 loop_freq.freq_exit = loop_freq.freq_positive;
01811 feedback->Annot_loop (do_wn, loop_freq);
01812 }
01813
01814 #ifdef KEY
01815
01816
01817
01818
01819
01820
01821
01822
01823
01824
01825
01826
01827
01828
01829
01830
01831
01832
01833
01834
01835
01836
01837
01838
01839
01840
01841
01842
01843
01844
01845
01846
01847
01848
01849
01850
01851
01852
01853
01854
01855
01856
01857
01858
01859
01860
01861
01862
01863
01864
01865
01866
01867
01868
01869
01870
01871
01872
01873
01874
01875
01876
01877
01878
01879
01880
01881
01882
01883
01884
01885
01886 #include "fission.h"
01887 #include "ff_utils.h"
01888 #include "glob.h"
01889 #include "ir_reader.h"
01890 #include "wn_simp.h"
01891
01892 BOOL debug_loop_unswitch = FALSE;
01893 static INT Last_Unswitchable_Loop_Id = 0;
01894
01895
01896 static BOOL Loop_Unswitch_InnerDo (WN *wn)
01897 {
01898 COND_BOUNDS_INFO *info =
01899 CXX_NEW(COND_BOUNDS_INFO(&LNO_local_pool),&LNO_local_pool);
01900 STACK<WN*> stack_of_ifs(&LNO_local_pool);
01901 STACK<INT> stack_of_lbs(&LNO_local_pool);
01902 STACK<INT> stack_of_ubs(&LNO_local_pool);
01903 INT32_INFIN const_lb, const_ub, const_lbi, const_ubi;
01904
01905 info->Collect_Do_Info(wn);
01906 info->Bounds().Copy_To_Work();
01907 if (!info->Bounds().SVPC_Applicable()) {
01908 if (debug_loop_unswitch || LNO_Unswitch_Verbose) {
01909 printf("(%s:%d) ",
01910 Src_File_Name,
01911 Srcpos_To_Line(WN_Get_Linenum(wn)));
01912 printf("Loop has multi-variate constraint. Loop was not unswitched.\n");
01913 }
01914 return FALSE;
01915 }
01916 if (info->Bounds().Work_Cols() != 1) {
01917 if (debug_loop_unswitch || LNO_Unswitch_Verbose) {
01918 printf("(%s:%d) ",
01919 Src_File_Name,
01920 Srcpos_To_Line(WN_Get_Linenum(wn)));
01921 printf("Loop termination condition has multi-variate constraint. Loop was not unswitched.\n");
01922 }
01923 return FALSE;
01924 }
01925
01926
01927 WN *lbd = WN_kid0(WN_start(wn));
01928 WN *ubd = WN_kid1(WN_end(wn));
01929 if(WN_operator(lbd) != OPR_INTCONST ||
01930 WN_operator(ubd) != OPR_INTCONST ){
01931 if (debug_loop_unswitch || LNO_Unswitch_Verbose) {
01932 printf("(%s:%d) ",
01933 Src_File_Name,
01934 Srcpos_To_Line(WN_Get_Linenum(wn)));
01935 printf("Non-constant loop bound exists. Loop was not unswitched.\n");
01936 }
01937 return FALSE;
01938 }
01939
01940
01941 INT le = info->Bounds().Num_Le_Constraints();
01942 INT eq = info->Bounds().Num_Eq_Constraints();
01943 INT c = info->Symbol_Info().Elements();
01944 DYN_ARRAY<WN*> kill_array(&LNO_local_pool);
01945 for (INT i = 0; i < c; i++) {
01946 WN* wn = info->Symbol_Info().Bottom_nth(i).Outer_Nondef;
01947 kill_array.AddElement(wn);
01948 }
01949
01950 const_lb = info->Bounds().Lower_Bound(0);
01951 const_ub = info->Bounds().Upper_Bound(0);
01952
01953
01954
01955 WN* body = WN_do_body(wn);
01956 WN* stmt;
01957 INT number_of_statements = 0;
01958 for (stmt = WN_first(body); stmt; stmt = WN_next(stmt)) {
01959 number_of_statements ++;
01960 if (WN_operator(stmt) != OPR_IF ||
01961 (WN_operator(stmt) == OPR_IF && WN_first(WN_else(stmt))))
01962 continue;
01963 info->Collect_If_Info(stmt, TRUE);
01964 info->Bounds().Copy_To_Work();
01965 if (!info->Bounds().SVPC_Applicable()) {
01966 if (debug_loop_unswitch || LNO_Unswitch_Verbose) {
01967 printf("(%s:%d) ",
01968 Src_File_Name,
01969 Srcpos_To_Line(WN_Get_Linenum(wn)));
01970 printf("If-stmt condition has multi-variate constraint. Loop was not unswitched.\n");
01971 }
01972 return FALSE;
01973 }
01974 const_lbi = info->Bounds().Lower_Bound(0);
01975 const_ubi = info->Bounds().Upper_Bound(0);
01976 #ifdef Is_True_On
01977 if (info->Bounds().Work_Cols() != 1)
01978 DevWarn(("Loop is possibly a candidate for loop unswitching."));
01979 #endif
01980 if ((const_lb != const_lbi || const_ub != const_ubi) &&
01981 info->Bounds().Work_Cols() == 1) {
01982 stack_of_ifs.Push(stmt);
01983 stack_of_lbs.Push(const_lbi.Value());
01984 stack_of_ubs.Push(const_ubi.Value());
01985 }
01986 info->Reset_Bounds_To(le, eq, c, &kill_array);
01987 }
01988
01989 if (stack_of_ifs.Elements() == 0) {
01990 if (debug_loop_unswitch || LNO_Unswitch_Verbose) {
01991 printf("(%s:%d) ",
01992 Src_File_Name,
01993 Srcpos_To_Line(WN_Get_Linenum(wn)));
01994 printf("Loop has no suitable if statements. Loop was not unswitched.\n");
01995 }
01996 return FALSE;
01997 }
01998
01999
02000
02001
02002
02003
02004
02005
02006
02007
02008
02009
02010
02011
02012
02013
02014
02015
02016
02017
02018
02019
02020
02021
02022 WN* loop_copy = LWN_Copy_Tree(wn, TRUE, LNO_Info_Map);
02023 DO_LOOP_INFO* dli=Get_Do_Loop_Info(wn);
02024 DO_LOOP_INFO* new_loop_info =
02025 CXX_NEW(DO_LOOP_INFO(dli,&LNO_local_pool), &LNO_local_pool);
02026 Set_Do_Loop_Info(loop_copy, new_loop_info);
02027 Array_Dependence_Graph->Add_Deps_To_Copy_Block(wn, loop_copy, TRUE);
02028 body = WN_do_body(loop_copy);
02029 WN* current_statement = WN_first(body);
02030 INT curr_if = 0;
02031 while(current_statement) {
02032 WN* next_statement = WN_next(current_statement);
02033 if (WN_operator(current_statement) == OPR_IF) {
02034
02035
02036 stmt = WN_first(WN_then(current_statement));
02037 while(stmt) {
02038 WN* next = WN_next(stmt);
02039 LWN_Insert_Block_Before(body,current_statement,
02040 LWN_Extract_From_Block(stmt));
02041 stmt = next;
02042 }
02043
02044 LWN_Delete_Tree(current_statement);
02045 curr_if ++;
02046 }
02047 current_statement = next_statement;
02048 }
02049 LWN_Set_Parent(loop_copy, LWN_Get_Parent(wn));
02050 LWN_Parentize(loop_copy);
02051 #ifdef TARG_X8664
02052 BOOL Has_Dependencies = !Is_Vectorizable_Loop(loop_copy);
02053 #else
02054 BOOL Has_Dependencies = TRUE;
02055 #endif
02056 LNO_Erase_Dg_From_Here_In(loop_copy, Array_Dependence_Graph);
02057 LNO_Erase_Vertices_In_Loop(loop_copy, Array_Dependence_Graph);
02058 if (Has_Dependencies) {
02059 if (debug_loop_unswitch || LNO_Unswitch_Verbose) {
02060 printf("(%s:%d) ",
02061 Src_File_Name,
02062 Srcpos_To_Line(WN_Get_Linenum(wn)));
02063 printf("Loop may have loop carried dependency. Loop was not unswitched.\n");
02064 }
02065 return FALSE;
02066 }
02067
02068
02069
02070 if (Last_Unswitchable_Loop_Id < LNO_Unswitch_Loop_Skip_Before ||
02071 Last_Unswitchable_Loop_Id > LNO_Unswitch_Loop_Skip_After ||
02072 Last_Unswitchable_Loop_Id == LNO_Unswitch_Loop_Skip_Equal) {
02073 Last_Unswitchable_Loop_Id ++;
02074 printf("(%s:%d) ",
02075 Src_File_Name,
02076 Srcpos_To_Line(WN_Get_Linenum(wn)));
02077 printf("Loop unswitch: skipping loop.\n");
02078 return FALSE;
02079 }
02080
02081 Last_Unswitchable_Loop_Id ++;
02082
02083
02084 WN* tmp_loop1=wn;
02085 INT total_loops = number_of_statements;
02086 WN** wn_starts=CXX_NEW_ARRAY(WN*, total_loops, &LNO_local_pool);
02087 WN** wn_ends=CXX_NEW_ARRAY(WN*, total_loops, &LNO_local_pool);
02088 WN** wn_steps=CXX_NEW_ARRAY(WN*, total_loops, &LNO_local_pool);
02089 WN** new_loops=CXX_NEW_ARRAY(WN*, total_loops, &LNO_local_pool);
02090 DO_LOOP_INFO* loop_info = Get_Do_Loop_Info(wn);
02091
02092 wn_starts[0]=WN_kid0(WN_start(tmp_loop1));
02093 wn_ends[0]=WN_end(tmp_loop1);
02094 wn_steps[0]=WN_kid0(WN_step(tmp_loop1));
02095 new_loops[0]=wn;
02096
02097 body = WN_do_body(wn);
02098 current_statement = WN_first(body);
02099 INT j = 0;
02100 INT i = 0;
02101 DOLOOP_STACK stack(&LNO_local_pool);
02102 Build_Doloop_Stack(wn, &stack);
02103
02104 while(current_statement) {
02105 WN* next_statement = WN_next(current_statement);
02106 WN* tmp_loop2;
02107 Separate(tmp_loop1, current_statement, 1, &tmp_loop2);
02108 if (tmp_loop2) {
02109 LWN_Parentize(tmp_loop2);
02110 DO_LOOP_INFO* new_loop_info =
02111 CXX_NEW(DO_LOOP_INFO(loop_info,&LNO_default_pool), &LNO_default_pool);
02112 Set_Do_Loop_Info(tmp_loop2,new_loop_info);
02113 wn_starts[i+1]=WN_kid0(WN_start(tmp_loop2));
02114 wn_ends[i+1]=WN_end(tmp_loop2);
02115 wn_steps[i+1]=WN_kid0(WN_step(tmp_loop2));
02116 new_loops[i+1]=tmp_loop2;
02117 }
02118
02119 if (j == stack_of_ifs.Elements() ||
02120 current_statement != stack_of_ifs.Bottom_nth(j)) {
02121 current_statement = next_statement;
02122 i ++;
02123 tmp_loop1 = tmp_loop2;
02124 continue;
02125 }
02126
02127 body = WN_do_body(tmp_loop1);
02128 DO_LOOP_INFO* dli = Get_Do_Loop_Info(tmp_loop1);
02129
02130
02131 if (WN_const_val(wn_starts[i]) < stack_of_lbs.Bottom_nth(j)) {
02132 FmtAssert(const_lb == WN_const_val(wn_starts[i]), ("Handle this case"));
02133 WN_const_val(wn_starts[i]) = stack_of_lbs.Bottom_nth(j);
02134 CXX_DELETE(dli->LB, dli->LB->Pool());
02135 INT num_bounds = Num_Lower_Bounds(wn, dli->Step);
02136 dli->LB =
02137 CXX_NEW(ACCESS_ARRAY(num_bounds,stack.Elements(),&LNO_default_pool),
02138 &LNO_default_pool);
02139 dli->LB->Set_LB(WN_kid0(WN_start(tmp_loop1)), &stack,
02140 dli->Step->Const_Offset);
02141 }
02142 FmtAssert(WN_operator(wn_ends[i]) == OPR_LE ||
02143 WN_operator(wn_ends[i]) == OPR_LT,
02144 ("Unhandled loop upperbound in loop unswitch."));
02145
02146
02147 WN_kid1(wn_ends[i]) = WN_Simplify_Tree(WN_kid1(wn_ends[i]));
02148 if (WN_operator(wn_ends[i]) == OPR_LT) {
02149 WN_set_operator(wn_ends[i], OPR_LE);
02150 WN_const_val(WN_kid1(wn_ends[i])) =
02151 WN_const_val(WN_kid1(wn_ends[i])) - 1;
02152 }
02153 if (WN_const_val(WN_kid1(wn_ends[i])) > stack_of_ubs.Bottom_nth(j)) {
02154 WN_const_val(WN_kid1(wn_ends[i])) =
02155 stack_of_ubs.Bottom_nth(j)-(const_ub.Value()-
02156 WN_const_val(WN_kid1(wn_ends[i])));
02157 CXX_DELETE(dli->UB, dli->UB->Pool());
02158 INT num_bounds = Num_Upper_Bounds(wn);
02159 dli->UB = CXX_NEW(ACCESS_ARRAY(num_bounds,stack.Elements(),
02160 &LNO_default_pool),
02161 &LNO_default_pool);
02162 dli->UB->Set_UB(WN_end(tmp_loop1), &stack);
02163 }
02164
02165
02166
02167 stmt = WN_first(WN_then(stack_of_ifs.Bottom_nth(j)));
02168 while(stmt) {
02169 WN* next = WN_next(stmt);
02170 LWN_Insert_Block_Before(body,stack_of_ifs.Bottom_nth(j),
02171 LWN_Extract_From_Block(stmt));
02172 stmt = next;
02173 }
02174
02175
02176 LWN_Delete_Tree(stack_of_ifs.Bottom_nth(j));
02177
02178 current_statement = next_statement;
02179 j ++;
02180 i ++;
02181 tmp_loop1 = tmp_loop2;
02182 }
02183
02184 Fission_DU_Update(Du_Mgr,red_manager,wn_starts,wn_ends,wn_steps,
02185 total_loops,new_loops);
02186 for (i=0; i<total_loops-1; i++)
02187 scalar_rename(LWN_Get_Parent(wn_starts[i]));
02188 Array_Dependence_Graph->Fission_Dep_Update(new_loops[0],total_loops);
02189
02190 if (debug_loop_unswitch || LNO_Unswitch_Verbose) {
02191 printf("(%s:%d) ",
02192 Src_File_Name,
02193 Srcpos_To_Line(WN_Get_Linenum(wn)));
02194 printf("Loop was unswitched.\n");
02195 }
02196
02197 return TRUE;
02198 }
02199
02200 static BOOL Find_Symbol(WN * tree, SYMBOL sym)
02201 {
02202 if(WN_opcode(tree) == OPC_BLOCK){
02203 for(WN *kid = WN_first(tree); kid; kid = WN_next(kid))
02204 if(Find_Symbol(kid, sym))
02205 return TRUE;
02206 return FALSE;
02207 }
02208
02209 if(WN_operator(tree) == OPR_LDID){
02210 if(SYMBOL(tree) == sym){
02211 return TRUE;
02212 }
02213 }
02214
02215 for(INT kidno=0; kidno < WN_kid_count(tree); kidno++)
02216 if(Find_Symbol(WN_kid(tree, kidno), sym)){
02217 return TRUE;
02218 }
02219 return FALSE;
02220 }
02221
02222 static WN * New_Label()
02223 {
02224 LABEL_IDX label;
02225 (void) New_LABEL (CURRENT_SYMTAB, label);
02226 return WN_CreateLabel (label, 0, NULL);
02227 }
02228
02229
02230
02231
02232
02233
02234
02235
02236
02237
02238
02239
02240
02241
02242
02243
02244
02245
02246
02247 static BOOL Gen_Early_Exit(const WN *if_stmt, WN *loop)
02248 {
02249 WN *empty_block = WN_else(if_stmt);
02250 if(!Block_is_empty(empty_block))
02251 empty_block = WN_then(if_stmt);
02252 if(!Block_is_empty(empty_block))
02253 return FALSE;
02254
02255 if(!Find_Symbol(WN_if_test(if_stmt),SYMBOL(WN_index(loop)))){
02256 WN *parent = LWN_Get_Parent(loop);
02257 if(WN_operator(parent) != OPR_BLOCK)
02258 return FALSE;
02259 WN *exit_label = New_Label();
02260 WN_INSERT_BlockAfter(parent, loop, exit_label);
02261 LWN_Set_Parent(exit_label, parent);
02262 WN *exit_goto =
02263 WN_CreateGoto((ST*) NULL,WN_label_number(exit_label));
02264 WN_INSERT_BlockFirst(empty_block,exit_goto);
02265 LWN_Set_Parent(exit_goto, empty_block);
02266 LWN_Parentize(parent);
02267
02268 DO_LOOP_INFO *dli = Get_Do_Loop_Info(loop);
02269 dli->Has_Gotos = TRUE;
02270 dli->Has_Exits = TRUE;
02271 BOOL current_level = TRUE;
02272 while(parent){
02273 if(WN_opcode(parent)==OPC_DO_LOOP){
02274 dli = Get_Do_Loop_Info(parent);
02275 if(dli){
02276 dli->Has_Gotos=TRUE;
02277 if(current_level)
02278 dli->Has_Gotos_This_Level=TRUE;
02279 }
02280 current_level = FALSE;
02281 }
02282 parent = LWN_Get_Parent(parent);
02283 }
02284 }
02285 }
02286
02287
02288
02289
02290
02291
02292 static void
02293 LNO_Remove_Array_Dep (WN * wn)
02294 {
02295 Is_True (OPERATOR_is_expression (WN_operator (wn)),
02296 ("LNO_Remove_Array_Dep: Expression node expected"));
02297
02298 for (int i=0; i<WN_kid_count (wn); i++)
02299 LNO_Remove_Array_Dep (WN_kid (wn,i));
02300
02301 if (!OPERATOR_is_load (WN_operator (wn))) return;
02302
02303 VINDEX16 v = Array_Dependence_Graph->Get_Vertex (wn);
02304
02305 if (v)
02306 Array_Dependence_Graph->Delete_Vertex (v);
02307 }
02308
02309
02310
02311
02312
02313
02314
02315
02316
02317
02318
02319
02320
02321
02322
02323
02324
02325
02326
02327
02328
02329
02330
02331
02332
02333
02334
02335
02336 static BOOL Loop_Simple_Unswitch_InnerDo (WN * wn)
02337 {
02338 Is_True (WN_operator (wn) == OPR_DO_LOOP,
02339 ("Loop_Simple_Unswitch_InnerDo: Expected DO LOOP"));
02340
02341
02342
02343 if(Index_Variable_Live_At_Exit(wn))
02344 return FALSE;
02345
02346 if (Do_Loop_Is_Mp(wn))
02347 return FALSE;
02348
02349 DO_LOOP_INFO * dli = Get_Do_Loop_Info (wn);
02350
02351
02352
02353
02354
02355
02356
02357
02358 if (dli && dli->Has_Barriers)
02359 return FALSE;
02360
02361 WN * body = WN_do_body (wn);
02362
02363 const WN * stmt = WN_first (body);
02364
02365 if (!stmt)
02366 return FALSE;
02367
02368 if (WN_first (body) != WN_last (body))
02369 return FALSE;
02370
02371 if (WN_operator (stmt) != OPR_IF)
02372 return FALSE;
02373
02374 if (!Is_Loop_Invariant_Exp(WN_if_test(stmt), wn)){
02375 Gen_Early_Exit(stmt,wn);
02376 return FALSE;
02377 }
02378
02379
02380 WN * then_loop_copy = LWN_Copy_Tree (wn, TRUE, LNO_Info_Map);
02381 WN * else_loop_copy = LWN_Copy_Tree (wn, TRUE, LNO_Info_Map);
02382
02383 WN * loop_body[3];
02384
02385 loop_body[0] = WN_do_body (wn);
02386 loop_body[1] = WN_do_body (then_loop_copy);
02387 loop_body[2] = WN_do_body (else_loop_copy);
02388
02389
02390 Unrolled_DU_Update (loop_body, 3, Do_Loop_Depth (wn), TRUE, FALSE);
02391
02392
02393 if (Do_Loop_Depth (wn) == 0)
02394 {
02395
02396 LNO_Remove_Array_Dep (WN_if_test (stmt));
02397 }
02398
02399
02400 Array_Dependence_Graph->Add_Deps_To_Copy_Block(wn, then_loop_copy, TRUE);
02401 Array_Dependence_Graph->Add_Deps_To_Copy_Block(wn, else_loop_copy, TRUE);
02402
02403
02404 {
02405 WN * if_stmt = WN_first (WN_do_body (then_loop_copy));
02406 LWN_Insert_Block_Before (WN_do_body (then_loop_copy), if_stmt, WN_then (if_stmt));
02407
02408 WN_then (if_stmt) = WN_CreateBlock();
02409
02410 DO_LOOP_INFO * loop_info_then =
02411 CXX_NEW (DO_LOOP_INFO (dli, dli->Pool()), dli->Pool());
02412 Set_Do_Loop_Info (then_loop_copy, loop_info_then);
02413 }
02414
02415
02416 {
02417 WN * if_stmt = WN_first (WN_do_body (else_loop_copy));
02418 LWN_Insert_Block_Before (WN_do_body (else_loop_copy), if_stmt, WN_else (if_stmt));
02419 WN_else (if_stmt) = WN_CreateBlock();
02420
02421 if_stmt = LWN_Extract_From_Block (WN_do_body (else_loop_copy), if_stmt);
02422 LWN_Delete_Tree (if_stmt);
02423
02424 DO_LOOP_INFO * loop_info_else =
02425 CXX_NEW (DO_LOOP_INFO (dli, dli->Pool()), dli->Pool());
02426 Set_Do_Loop_Info (else_loop_copy, loop_info_else);
02427 }
02428
02429
02430
02431
02432 WN * if_stmt = WN_last (WN_do_body (then_loop_copy));
02433 Is_True (WN_operator (if_stmt) == OPR_IF,
02434 ("Loop_Simple_Unswitch_InnerDo: Expected IF statement"));
02435 LWN_Delete_Tree (WN_else (if_stmt));
02436 WN_else (if_stmt) = WN_CreateBlock();
02437
02438
02439 if_stmt = LWN_Extract_From_Block (WN_do_body (then_loop_copy), if_stmt);
02440
02441
02442 LWN_Insert_Block_Before (WN_then (if_stmt), NULL, then_loop_copy);
02443 LWN_Insert_Block_Before (WN_else (if_stmt), NULL, else_loop_copy);
02444
02445
02446 WN * parent = LWN_Get_Parent (wn);
02447 Is_True (WN_operator (parent) == OPR_BLOCK,
02448 ("Loop_Simple_Unswitch_InnerDo: BLOCK node expected as parent"));
02449 LWN_Insert_Block_Before (parent, wn , if_stmt );
02450
02451 wn = LWN_Extract_From_Block (parent, wn);
02452 LWN_Parentize (parent);
02453
02454 WN * wn_starts[3], * wn_ends[3], * wn_steps[3], * new_loops[3];
02455 wn_starts[0] = WN_kid0 (WN_start (wn));
02456 wn_starts[1] = WN_kid0 (WN_start (then_loop_copy));
02457 wn_starts[2] = WN_kid0 (WN_start (else_loop_copy));
02458
02459 wn_ends[0] = WN_end (wn);
02460 wn_ends[1] = WN_end (then_loop_copy);
02461 wn_ends[2] = WN_end (else_loop_copy);
02462
02463 wn_steps[0] = WN_kid0 (WN_step (wn));
02464 wn_steps[1] = WN_kid0 (WN_step (then_loop_copy));
02465 wn_steps[2] = WN_kid0 (WN_step (else_loop_copy));
02466
02467 new_loops[0] = wn;
02468 new_loops[1] = then_loop_copy;
02469 new_loops[2] = else_loop_copy;
02470
02471 Fission_DU_Update (Du_Mgr, red_manager, wn_starts, wn_ends, wn_steps, 3, new_loops);
02472
02473
02474 scalar_rename(LWN_Get_Parent(wn_starts[0]));
02475 scalar_rename(LWN_Get_Parent(wn_starts[1]));
02476
02477 if (debug_loop_unswitch || LNO_Unswitch_Verbose) {
02478 printf("(%s:%d) ",
02479 Src_File_Name,
02480 Srcpos_To_Line(WN_Get_Linenum(wn)));
02481 printf("LNO Unswitch Second Try: Loop was unswitched.\n");
02482 }
02483
02484 LWN_Delete_Tree (wn);
02485 return TRUE;
02486 }
02487
02488
02489 static BOOL Loop_Unswitch_SCF_rec(WN *wn)
02490 {
02491 BOOL result = FALSE;
02492 OPCODE opcode = WN_opcode(wn);
02493
02494 if (opcode == OPC_BLOCK) {
02495 WN* kid = WN_first(wn);
02496 while(kid) {
02497 WN* next = WN_next(kid);
02498 result |= Loop_Unswitch_SCF_rec(kid);
02499 kid = next;
02500 }
02501 }
02502
02503 else if (opcode == OPC_DO_LOOP) {
02504 DO_LOOP_INFO* dli = Get_Do_Loop_Info(wn);
02505 if (dli->Is_Inner)
02506 {
02507 if (LNO_Run_Unswitch_Phase1)
02508 result |= Loop_Unswitch_InnerDo(wn);
02509 if (LNO_Run_Unswitch_Phase2)
02510 result |= Loop_Simple_Unswitch_InnerDo(wn);
02511 }
02512 else
02513 result |= Loop_Unswitch_SCF_rec(WN_do_body(wn));
02514 }
02515
02516 else if (OPCODE_is_scf(opcode)) {
02517 for (INT kidno=0; kidno<WN_kid_count(wn); kidno++) {
02518 WN *kid = WN_kid(wn,kidno);
02519 result |= Loop_Unswitch_SCF_rec(kid);
02520 }
02521 }
02522
02523 return result;
02524 }
02525
02526 extern BOOL Loop_Unswitch_SCF (WN * func_nd)
02527 {
02528 debug_loop_unswitch = Get_Trace(TP_LNOPT,TT_LNO_LOOP_UNSWITCH);
02529 if (debug_loop_unswitch) {
02530 fprintf(TFile, "=======================================================================\n");
02531 fprintf(TFile, "LNO: \"WHIRL tree before loop unswitch phase\"\n");
02532 fdump_tree (TFile, func_nd);
02533 }
02534 MEM_POOL_Push(&LNO_local_pool);
02535 BOOL result = Loop_Unswitch_SCF_rec(func_nd);
02536 if (debug_loop_unswitch) {
02537 fprintf(TFile, "=======================================================================\n");
02538 fprintf(TFile, "LNO: \"WHIRL tree after loop unswitch phase\"\n");
02539 fdump_tree (TFile, func_nd);
02540 }
02541 MEM_POOL_Pop(&LNO_local_pool);
02542 return result;
02543 }
02544 #endif