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
00200
00201
00202
00203
00204
00205
00206
00207
00208 #ifdef USE_PCH
00209 #include "lno_pch.h"
00210 #endif // USE_PCH
00211 #pragma hdrstop
00212
00213 #ifdef _KEEP_RCS_ID
00214 static char *rcs_id = "$Source: be/lno/SCCS/s.minvariant.cxx $ $Revision: 1.17 $";
00215 #endif
00216
00217 #include <sys/types.h>
00218 #include <alloca.h>
00219 #include "defs.h"
00220 #include "wn.h"
00221 #include "cxx_memory.h"
00222 #include "dep_graph.h"
00223 #include "lnopt_main.h"
00224 #include "lwn_util.h"
00225 #include "lnoutils.h"
00226 #include "minvariant.h"
00227 #include "optimizer.h"
00228 #include "opt_du.h"
00229 #include "wn_simp.h"
00230 #include "snl_utils.h"
00231
00232 #ifdef TARG_X8664
00233 BOOL Minvariant_Removal_For_Simd = FALSE;
00234 #endif
00235
00236 static MEM_POOL MIR_local_pool;
00237 static BOOL mir_local_pool_initialized = FALSE;
00238
00239 static BOOL Minv_Debug = FALSE;
00240
00241
00242
00243
00244
00245 static WN* Find_Ls(WN *wn, BOOL okay_to_not_find_one = FALSE)
00246 {
00247 for (WN* p = wn; p; p = LWN_Get_Parent(p)) {
00248 OPCODE opc = WN_opcode(p);
00249 if (OPCODE_is_load(opc) || OPCODE_is_store(opc))
00250 return p;
00251 }
00252
00253 FmtAssert(okay_to_not_find_one,
00254 ("Couldn't find a load or store parent for wn=0x%lx", wn));
00255 return NULL;
00256 }
00257
00258
00259
00260 typedef DYN_ARRAY<WN*> WN_ARRAY;
00261
00262 void Unique_AddElement(WN_ARRAY* array, WN* wn, BOOL duplicates_okay)
00263 {
00264 for (INT i = array->Elements() - 1; i >= 0; i--) {
00265 if (wn == (*array)[i]) {
00266 Is_True(duplicates_okay, ("Duplicate wn 0x%lx added in minvariant", wn));
00267 return;
00268 }
00269 }
00270 array->AddElement(wn);
00271 }
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282 struct MIR_REFLIST {
00283 ST* Base;
00284 ACCESS_ARRAY* Aa;
00285 WN* Array;
00286 WN_ARRAY Wnlist;
00287
00288 MIR_REFLIST(ST* base, ACCESS_ARRAY* aa, WN* wn, MEM_POOL* pool) :
00289 Wnlist(pool), Aa(aa), Base(base), Array(wn) {
00290 Unique_AddElement(&Wnlist, wn, FALSE);
00291 }
00292 ~MIR_REFLIST() {}
00293 char* Basename() const {
00294 return SYMBOL(WN_array_base(Wnlist[0])).Name();
00295 }
00296 char* Basename(char* buf, INT bufsz) const {
00297 return SYMBOL(WN_array_base(Wnlist[0])).Name(buf, bufsz);
00298 }
00299 BOOL Same(ST* base, ACCESS_ARRAY* aa, WN* array);
00300 BOOL operator == (const MIR_REFLIST&);
00301 void Print(FILE* f) const;
00302
00303 private:
00304
00305 static BOOL Same_Base(const ST* st1, const ST* st2) {
00306 return (st1 == NULL || st2 == NULL) ? st1 == st2 :
00307 (ST_base(st1) == ST_base(st2) && ST_ofst(st1) == ST_ofst(st2));
00308 }
00309 };
00310
00311
00312 BOOL MIR_REFLIST::Same(ST* base, ACCESS_ARRAY* aa, WN* array)
00313 {
00314 return Same_Base(base, Base) &&
00315 *aa == *Aa &&
00316 DEPV_COMPUTE::Base_Test(Find_Ls(array), NULL, Find_Ls(Array),NULL ) ==
00317 DEP_CONTINUE &&
00318 WN_desc(LWN_Get_Parent(Wnlist[0])) ==
00319 WN_desc(LWN_Get_Parent(array));
00320 }
00321
00322 BOOL MIR_REFLIST::operator == (const MIR_REFLIST& mir)
00323 {
00324 if (Base != mir.Base)
00325 return FALSE;
00326 if (!(*Aa == *mir.Aa))
00327 return FALSE;
00328
00329 INT elts = Wnlist.Elements();
00330 if (elts != mir.Wnlist.Elements())
00331 return FALSE;
00332
00333 mBOOL* used = (mBOOL*) alloca(sizeof(mBOOL)*elts);
00334
00335 INT i;
00336 for (i = 0; i < elts; i++)
00337 used[i] = FALSE;
00338
00339 for (i = 0; i < elts; i++) {
00340 INT j;
00341 for (j = 0; j < elts; j++) {
00342 if (used[j] == FALSE && Wnlist[i] == mir.Wnlist[j]) {
00343 used[j] = TRUE;
00344 break;
00345 }
00346 }
00347 if (j == elts)
00348 return FALSE;
00349 }
00350
00351 return TRUE;
00352 }
00353
00354 void MIR_REFLIST::Print(FILE* f) const
00355 {
00356 INT reads = 0;
00357 INT writes = 0;
00358
00359 for (INT j = 0; j < Wnlist.Elements(); j++) {
00360 WN* wn = Wnlist[j];
00361 WN* parent = LWN_Get_Parent(wn);
00362 OPCODE op = WN_opcode(parent);
00363
00364 if (OPCODE_is_load(op))
00365 reads++;
00366 else if (OPCODE_is_store(op))
00367 writes++;
00368 else
00369 FmtAssert(0, ("Bad parent for array--can't happen (op=%d)", op));
00370 fprintf(f, " <0x%p,0x%p>", parent, wn);
00371 }
00372
00373 fprintf(f, " [r=%d,w=%d]", reads, writes);
00374 fprintf(f, " %s", Basename());
00375 Aa->Print(f);
00376 }
00377
00378 static BOOL MIR_Messy_Subscript(MIR_REFLIST* mr);
00379
00380 static void Print_Lists(FILE* f, const DYN_ARRAY<MIR_REFLIST*>& lists)
00381 {
00382 for (INT i = 0; i < lists.Elements(); i++)
00383 lists[i]->Print(f);
00384 }
00385
00386 #ifdef Is_True_On
00387 static BOOL Compare_Lists(const DYN_ARRAY<MIR_REFLIST*>& lists1,
00388 const DYN_ARRAY<MIR_REFLIST*>& lists2)
00389 {
00390
00391
00392 INT elts = lists1.Elements();
00393
00394 if (lists2.Elements() != elts)
00395 return FALSE;
00396
00397 mBOOL* used = (mBOOL*) alloca(sizeof(mBOOL)*elts);
00398
00399 INT i;
00400 for (i = 0; i < elts; i++)
00401 used[i] = FALSE;
00402
00403 for (i = 0; i < elts; i++) {
00404 INT j;
00405 for (j = 0; j < elts; j++) {
00406 if (used[j] == FALSE && *lists1[i] == *lists2[j]) {
00407 used[j] = TRUE;
00408 break;
00409 }
00410 }
00411 if (j == elts)
00412 return FALSE;
00413 }
00414 return TRUE;
00415 }
00416 #endif
00417
00418
00419
00420 static BOOL MIR_Dep_Subset(DEP d1, DEP d2)
00421 {
00422 if (DEP_IsDistance(d2)) {
00423 if (DEP_IsDistance(d1)) {
00424 if (DEP_Distance(d1) == DEP_Distance(d2)) {
00425 return TRUE;
00426 } else {
00427 return FALSE;
00428 }
00429 } else {
00430 return FALSE;
00431 }
00432 } else {
00433 INT id1 = (INT) DEP_Direction(d1);
00434 INT id2 = (INT) DEP_Direction(d2);
00435 if ((id1 | id2) == id2) {
00436 return TRUE;
00437 } else {
00438 return FALSE;
00439 }
00440 }
00441 }
00442
00443
00444 static BOOL MIR_Depv_Subset(const DEPV* d1, const DEPV* d2, INT dims)
00445 {
00446 for (INT i = 0; i < dims; i++)
00447 if (MIR_Dep_Subset(DEPV_Dep(d1,i), DEPV_Dep(d2,i)) == FALSE)
00448 return FALSE;
00449 return TRUE;
00450 }
00451
00452
00453
00454 static BOOL MIR_Add_Edge(ARRAY_DIRECTED_GRAPH16* dg,
00455 VINDEX16 vsource,
00456 VINDEX16 vsink,
00457 const DEPV_ARRAY* depv_array)
00458 {
00459 MEM_POOL* pool = dg->Pool();
00460
00461
00462
00463 EINDEX16 e;
00464 for (e = dg->Get_Out_Edge(vsource); e;
00465 e = dg->Get_Next_Out_Edge(e)) {
00466 FmtAssert(vsource == dg->Get_Source(e), ("Bad source"));
00467 if (vsink == dg->Get_Sink(e))
00468 break;
00469 }
00470
00471
00472
00473 if (e == 0) {
00474 DEPV_ARRAY* new_depv_array = Create_DEPV_ARRAY(depv_array, pool);
00475 EINDEX16 e2 = dg->Add_Edge(vsource, vsink, new_depv_array);
00476 Is_True(e2, ("Graph ran out of space"));
00477 return e2 != 0;
00478 }
00479
00480
00481
00482
00483
00484
00485
00486 INT ndim = dg->Depv_Array(e)->Num_Dim();
00487 FmtAssert(ndim == depv_array->Num_Dim(),
00488 ("Bad number of dimensions"));
00489 FmtAssert(dg->Depv_Array(e)->Num_Unused_Dim() == depv_array->Num_Unused_Dim(),
00490 ("Bad number of unused dimensions"));
00491
00492 BOOL need_to_add_total = 0;
00493 mBOOL* need_to_add = (mBOOL*) alloca(sizeof(mBOOL) * depv_array->Num_Vec());
00494 for (INT i = 0; i < depv_array->Num_Vec(); i++) {
00495 const DEPV* dv = depv_array->Depv(i);
00496 need_to_add[i] = TRUE;
00497 for (INT j = 0; j < dg->Depv_Array(e)->Num_Vec(); j++) {
00498 if (MIR_Depv_Subset(dv, dg->Depv_Array(e)->Depv(j), ndim)) {
00499 need_to_add[i] = FALSE;
00500 break;
00501 }
00502 }
00503 if (need_to_add[i])
00504 need_to_add_total++;
00505 }
00506 if (need_to_add_total) {
00507 INT nvec = need_to_add_total + dg->Depv_Array(e)->Num_Vec();
00508 if (nvec >= 255) return FALSE;
00509 INT nunused_dim = dg->Depv_Array(e)->Num_Unused_Dim();
00510 DEPV_ARRAY* newdva = Create_DEPV_ARRAY(nvec, ndim, nunused_dim, pool);
00511
00512 INT j;
00513 for (j = 0; j < dg->Depv_Array(e)->Num_Vec(); j++) {
00514 DEPV* newdv = newdva->Depv(j);
00515 DEPV* dv = dg->Depv_Array(e)->Depv(j);
00516 for (INT k = 0; k < ndim; k++)
00517 DEPV_Dep(newdv, k) = DEPV_Dep(dv, k);
00518 }
00519
00520 for (INT jj = 0; jj < depv_array->Num_Vec(); jj++) {
00521 if (need_to_add[jj]) {
00522 DEPV* newdv = newdva->Depv(j++);
00523 const DEPV* dv = depv_array->Depv(jj);
00524 for (INT k = 0; k < ndim; k++)
00525 DEPV_Dep(newdv, k) = DEPV_Dep(dv, k);
00526 }
00527 }
00528
00529 dg->Delete_Array_Edge(e);
00530 dg->Add_Edge(vsource, vsink, newdva);
00531 }
00532
00533 return TRUE;
00534 }
00535
00536 static BOOL MIR_Has_Array_Kid(WN* wn)
00537 {
00538 for (INT i = 0; i < WN_kid_count(wn); i++) {
00539 WN* w = WN_kid(wn,i);
00540 if (WN_operator(w) == OPR_ARRAY)
00541 return TRUE;
00542 if (MIR_Has_Array_Kid(w))
00543 return TRUE;
00544 }
00545 return FALSE;
00546 }
00547
00548 static void MIR_Build_Loop_List_Array(WN* wn,
00549 DYN_ARRAY<MIR_REFLIST*>&lists,
00550 MEM_POOL* pool,
00551 BOOL duplicates_okay);
00552
00553 static void MIR_Maybe_Add_To_List(WN* wn,
00554 DYN_ARRAY<MIR_REFLIST*>& lists,
00555 MEM_POOL* pool,
00556 BOOL duplicates_okay)
00557 {
00558
00559
00560
00561 if (!MIR_Has_Array_Kid(wn)) {
00562 WN* parent = LWN_Get_Parent(wn);
00563 OPERATOR parent_oper = WN_operator(parent);
00564 if (((parent_oper == OPR_ISTORE) && (wn == WN_kid1(parent))) ||
00565 (parent_oper == OPR_ILOAD)){
00566 #ifdef KEY //12404: don't "minvar" for istore/iload of volatiles
00567 if (!WN_Is_Volatile_Mem(parent))
00568 #endif
00569 MIR_Build_Loop_List_Array(wn, lists, pool, duplicates_okay);
00570 }
00571 }
00572 }
00573
00574
00575
00576
00577
00578
00579
00580
00581 static INT Already_On_Stack(STACK<WN*>* stack,
00582 WN* wn_node)
00583 {
00584 INT i;
00585 for (i = 0; i < stack->Elements(); i++)
00586 if (stack->Bottom_nth(i) == wn_node)
00587 break;
00588 return (i < stack->Elements()) ? i : -1;
00589 }
00590
00591
00592
00593
00594
00595
00596
00597 static void Build_Ordered_Stack_Traverse(WN* wn_tree,
00598 STACK<WN*>* stk_deps,
00599 STACK<WN*>* stk_ordered)
00600 {
00601 ARRAY_DIRECTED_GRAPH16* dg = Array_Dependence_Graph;
00602 if (WN_operator(wn_tree) == OPR_BLOCK) {
00603 for (WN* wn = WN_first(wn_tree); wn != NULL; wn = WN_next(wn))
00604 Build_Ordered_Stack_Traverse(wn, stk_deps, stk_ordered);
00605 } else {
00606 for (INT i = 0; i < WN_kid_count(wn_tree); i++)
00607 Build_Ordered_Stack_Traverse(WN_kid(wn_tree, i), stk_deps,
00608 stk_ordered);
00609 if (dg->Get_Vertex(wn_tree)) {
00610 INT stk_count = Already_On_Stack(stk_deps, wn_tree);
00611 if (stk_count >= 0)
00612 stk_ordered->Push(stk_deps->Bottom_nth(stk_count));
00613 }
00614 }
00615 }
00616
00617
00618
00619
00620
00621
00622
00623 static void Build_Ordered_Stack(WN* wn_loop,
00624 STACK<WN*>* stk_deps,
00625 STACK<WN*>* stk_ordered)
00626 {
00627 Build_Ordered_Stack_Traverse(wn_loop, stk_deps, stk_ordered);
00628 }
00629
00630
00631
00632
00633
00634
00635
00636 extern void MIR_Update_Dependences(WN* wn_loop,
00637 DYN_ARRAY<WN*>* new_uses)
00638 {
00639 ARRAY_DIRECTED_GRAPH16* dg = Array_Dependence_Graph;
00640 STACK<WN*>* stk_deps = CXX_NEW(STACK<WN*>(&LNO_local_pool),
00641 &LNO_local_pool);
00642
00643 if (mir_local_pool_initialized == FALSE) {
00644 mir_local_pool_initialized = TRUE;
00645 MEM_POOL_Initialize(&MIR_local_pool, "MIR_local_pool", FALSE);
00646 }
00647
00648 INT i;
00649 for (i = 0; i < new_uses->Elements(); i++) {
00650 for (WN* wn = (*new_uses)[i]; wn != NULL; wn = LWN_Get_Parent(wn))
00651 if (dg->Get_Vertex(wn) && Already_On_Stack(stk_deps, wn) == -1)
00652 stk_deps->Push(wn);
00653 WN* wn_array = Messy_Subscript((*new_uses)[i]);
00654 if (wn_array == NULL)
00655 continue;
00656 WN* wn_dep = LWN_Get_Parent(wn_array);
00657 if (dg->Get_Vertex(wn_dep))
00658 stk_deps->Push(wn_dep);
00659 }
00660 INT original_count = stk_deps->Elements();
00661 for (i = 0; i < original_count; i++) {
00662 WN* wn_dep = stk_deps->Bottom_nth(i);
00663 VINDEX16 v = dg->Get_Vertex(wn_dep);
00664 EINDEX16 e = 0;
00665 for (e = dg->Get_In_Edge(v); e != 0; e = dg->Get_Next_In_Edge(e)) {
00666 WN* wn_source = dg->Get_Wn(dg->Get_Source(e));
00667 if (Already_On_Stack(stk_deps, wn_source) == -1)
00668 stk_deps->Push(wn_source);
00669 }
00670 for (e = dg->Get_Out_Edge(v); e != 0; e = dg->Get_Next_Out_Edge(e)) {
00671 WN* wn_sink = dg->Get_Wn(dg->Get_Sink(e));
00672 if (Already_On_Stack(stk_deps, wn_sink) == -1)
00673 stk_deps->Push(wn_sink);
00674 }
00675 }
00676 WN* wn = 0;
00677 for (wn = wn_loop; wn != NULL; wn = LWN_Get_Parent(wn))
00678 if (WN_opcode(wn) == OPC_DO_LOOP && Do_Depth(wn) == 0)
00679 break;
00680 WN* wn_outer_loop = wn;
00681 STACK<WN*>* stk_ordered = CXX_NEW(STACK<WN*>(&LNO_local_pool),
00682 &LNO_local_pool);
00683 Build_Ordered_Stack(wn_loop, stk_deps, stk_ordered);
00684 for (i = 0; i < stk_ordered->Elements(); i++) {
00685 WN* wn_one = stk_ordered->Bottom_nth(i);
00686 VINDEX16 v1 = dg->Get_Vertex(wn_one);
00687 DOLOOP_STACK stk_one(&LNO_local_pool);
00688 Build_Doloop_Stack(wn_one, &stk_one);
00689 for (INT j = i; j < stk_ordered->Elements(); j++) {
00690 WN* wn_two = stk_ordered->Bottom_nth(j);
00691 DOLOOP_STACK stk_two(&LNO_local_pool);
00692 Build_Doloop_Stack(wn_two, &stk_two);
00693 VINDEX16 v2 = dg->Get_Vertex(wn_two);
00694 if (OPCODE_is_load(WN_opcode(wn_one))
00695 && OPCODE_is_load(WN_opcode(wn_two)))
00696 continue;
00697 BOOL found_edge = FALSE;
00698 EINDEX16 e1 = dg->Get_Edge(v1, v2);
00699 if (e1 != 0) {
00700 found_edge = TRUE;
00701 dg->Delete_Edge(e1);
00702 }
00703 EINDEX16 e2 = dg->Get_Edge(v2, v1);
00704 if (e2 != 0) {
00705 found_edge = TRUE;
00706 dg->Delete_Edge(e2);
00707 }
00708 if (found_edge) {
00709 if (!dg->Add_Edge(wn_one, &stk_one, wn_two, &stk_two, TRUE)) {
00710 LNO_Erase_Dg_From_Here_In(wn_one, dg);
00711 LNO_Erase_Dg_From_Here_In(wn_two, dg);
00712 }
00713 }
00714 }
00715 }
00716 }
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726 static void MIR_Patch_Loop_Stmt(WN* new_load)
00727 {
00728 DEF_LIST* def_list = Du_Mgr->Ud_Get_Def(new_load);
00729 if (def_list != NULL && def_list->Loop_stmt() != NULL) {
00730 WN* wn_start = Enclosing_Proper_Do_Loop(new_load);
00731 WN* wn = 0;
00732 for (wn = wn_start; wn != NULL; wn = LWN_Get_Parent(wn))
00733 if (WN_operator(wn) == OPR_DO_LOOP && wn == def_list->Loop_stmt())
00734 break;
00735 if (wn == NULL) {
00736 Du_Mgr->Ud_Get_Def(new_load)->Set_loop_stmt(wn_start);
00737 }
00738 }
00739 }
00740
00741 static void MIR_Replace(WN* loop,
00742 const MIR_REFLIST* p,
00743 ARRAY_DIRECTED_GRAPH16* dg,
00744 DYN_ARRAY<MIR_REFLIST*>& newly_direct_lists,
00745 MEM_POOL* pool,
00746 BOOL messy_only)
00747 {
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768 static INT unique_mi_num = 0;
00769
00770 char newname[64];
00771 WN* read_tree = NULL;
00772 WN* write_tree = NULL;
00773 VINDEX16 vr = 0;
00774 VINDEX16 vw = 0;
00775 INT gdepth = Good_Do_Depth(loop);
00776 INT j;
00777 BOOL dependence_disaster = FALSE;
00778
00779
00780 TYPE_ID type = WN_desc(LWN_Get_Parent(p->Wnlist[0]));
00781 TY_IDX ty = Be_Type_Tbl(type);
00782 TY_IDX pty = Make_Pointer_Type(ty);
00783
00784 #ifdef TARG_X8664 //bug 11472: memory chunk should be assigned to a temporary instead of a preg
00785 if (Minvariant_Removal_For_Simd || type == MTYPE_M) pty = ty;
00786 #endif
00787 #ifdef KEY
00788
00789
00790
00791 if (type == MTYPE_BS) return;
00792 #endif
00793
00794 if (Minv_Debug) {
00795 fprintf(TFile, "In loop %s, hoisting", SYMBOL(WN_index(loop)).Name());
00796 p->Print(TFile);
00797 }
00798
00799 sprintf(newname, "$mi%d", unique_mi_num++);
00800 #ifdef TARG_X8664
00801 SYMBOL newsym;
00802 if (Minvariant_Removal_For_Simd || type == MTYPE_M) {
00803 ST * st = Gen_Temp_Symbol (MTYPE_TO_TY_array[type], "_misym");
00804 newsym = SYMBOL(st, 0, type);
00805
00806 for (WN* wn = loop; wn != NULL; wn = LWN_Get_Parent(wn)) {
00807 if (Is_Mp_Region(wn)) {
00808 WN *prag = WN_CreatePragma(WN_PRAGMA_LOCAL, newsym.St(),
00809 newsym.WN_Offset(), 0);
00810 WN_set_pragma_compiler_generated(prag);
00811 LWN_Insert_Block_Before(WN_region_pragmas(wn), NULL, prag);
00812 break;
00813 }
00814 }
00815 } else
00816 newsym = Create_Preg_Symbol(newname, type);
00817 #else
00818 SYMBOL newsym = Create_Preg_Symbol(newname, type);
00819 #endif
00820
00821
00822
00823 for (j = 0; j < p->Wnlist.Elements(); j++) {
00824 WN* wn = p->Wnlist[j];
00825 if (OPCODE_is_load(WN_opcode(LWN_Get_Parent(wn))))
00826 break;
00827 }
00828
00829 if (j < p->Wnlist.Elements()) {
00830 WN* the_load = LWN_Get_Parent(p->Wnlist[j]);
00831 WN* new_load = LWN_Copy_Tree(the_load, TRUE, LNO_Info_Map);
00832 LWN_Copy_Def_Use(the_load, new_load, Du_Mgr);
00833 OPCODE op = OPCODE_make_op(OPR_STID, MTYPE_V, type);
00834 read_tree = LWN_CreateStid(op, newsym.WN_Offset(),
00835 newsym.St(), pty, new_load);
00836 #ifdef TARG_X8664
00837 if (Minvariant_Removal_For_Simd || type == MTYPE_M)
00838 Create_alias(Alias_Mgr,read_tree);
00839 #endif
00840 LWN_Copy_Linenumber(LWN_Get_Statement(the_load),read_tree);
00841 LWN_Copy_Frequency_Tree(read_tree,loop);
00842 LWN_Insert_Block_Before(LWN_Get_Parent(loop), loop, read_tree);
00843 if (gdepth > 0) {
00844 vr = dg->Add_Vertex(WN_kid0(read_tree));
00845 if (vr == 0)
00846 dependence_disaster = TRUE;
00847 }
00848 DOLOOP_STACK* stack = CXX_NEW(DOLOOP_STACK(&LNO_local_pool),
00849 &LNO_local_pool);
00850 Build_Doloop_Stack(read_tree, stack);
00851 LNO_Build_Access(read_tree, stack, &LNO_default_pool);
00852 MIR_Patch_Loop_Stmt(new_load);
00853 CXX_DELETE(stack, &LNO_local_pool);
00854 }
00855
00856
00857
00858 for (j = 0; j < p->Wnlist.Elements(); j++) {
00859 WN* wn = p->Wnlist[j];
00860 if (OPCODE_is_store(WN_opcode(LWN_Get_Parent(wn))))
00861 break;
00862 }
00863
00864 if (j < p->Wnlist.Elements()) {
00865 WN* naddr = LWN_Copy_Tree(p->Wnlist[j], TRUE, LNO_Info_Map);
00866 INT naddr_wnoffset = WN_offset(Find_Ls(p->Wnlist[j]));
00867
00868 LWN_Copy_Def_Use(p->Wnlist[j], naddr, Du_Mgr);
00869 OPCODE op = OPCODE_make_op(OPR_LDID, Promote_Type(type), type);
00870 WN* ldid = WN_CreateLdid(op, newsym.WN_Offset(),
00871 newsym.St(), ty);
00872 #ifdef TARG_X8664
00873 if (Minvariant_Removal_For_Simd || type == MTYPE_M)
00874 Create_alias(Alias_Mgr,ldid);
00875 #endif
00876 OPCODE storeop = WN_opcode(LWN_Get_Parent(p->Wnlist[j]));
00877 #ifdef TARG_X8664
00878 pty = Make_Pointer_Type(ty);
00879 #endif
00880 write_tree = LWN_CreateIstore(storeop, naddr_wnoffset, pty, ldid, naddr);
00881 #ifdef TARG_X8664
00882 pty = ty;
00883 #endif
00884 LWN_Insert_Block_After(LWN_Get_Parent(loop), loop, write_tree);
00885 Copy_alias_info(Alias_Mgr, LWN_Get_Parent(p->Wnlist[j]), write_tree);
00886 LWN_Copy_Linenumber(LWN_Get_Parent(p->Wnlist[j]),write_tree);
00887 LWN_Copy_Frequency_Tree(write_tree,loop);
00888 if (gdepth > 0) {
00889 vw = dg->Add_Vertex(write_tree);
00890 if (vw == 0)
00891 dependence_disaster = TRUE;
00892 }
00893 DOLOOP_STACK* stack = CXX_NEW(DOLOOP_STACK(&LNO_local_pool),
00894 &LNO_local_pool);
00895 Build_Doloop_Stack(write_tree, stack);
00896 LNO_Build_Access(write_tree, stack, &LNO_default_pool);
00897 CXX_DELETE(stack, &LNO_local_pool);
00898 }
00899
00900 if (read_tree && write_tree) {
00901 Du_Mgr->Ud_Add_Def(WN_kid0(write_tree), read_tree);
00902 Du_Mgr->Du_Add_Use(read_tree, WN_kid0(write_tree));
00903
00904
00905
00906 if (dependence_disaster == FALSE && vr && vw) {
00907 DOLOOP_STACK stack(&MIR_local_pool);
00908 Build_Doloop_Stack(LWN_Get_Parent(loop), &stack);
00909 if (!dg->Add_Edge(WN_kid0(read_tree), &stack,
00910 write_tree, &stack, TRUE, FALSE))
00911 dependence_disaster = TRUE;
00912 }
00913 }
00914
00915
00916
00917
00918
00919
00920
00921 DYN_ARRAY<WN*> new_uses(&MIR_local_pool);
00922 DYN_ARRAY<WN*> new_defs(&MIR_local_pool);
00923
00924 if (read_tree)
00925 Unique_AddElement(&new_defs, read_tree, FALSE);
00926 if (write_tree)
00927 Unique_AddElement(&new_uses, WN_kid0(write_tree), FALSE);
00928
00929 for (j = 0; j < p->Wnlist.Elements(); j++) {
00930 WN* wn = p->Wnlist[j];
00931 BOOL is_write = OPCODE_is_store(WN_opcode(LWN_Get_Parent(wn)));
00932 VINDEX16 v = dg->Get_Vertex(LWN_Get_Parent(wn));
00933 EINDEX16 e;
00934
00935
00936
00937
00938 BOOL done = FALSE;
00939 for (WN* pwn = wn; !done; pwn = LWN_Get_Parent(pwn)) {
00940 if (WN_opcode(pwn) == OPC_DO_LOOP) {
00941 DO_LOOP_INFO *dli = Get_Do_Loop_Info(pwn);
00942 WN *guard = dli->Guard;
00943 if (guard) {
00944 WN_Reset_If_Guard(guard);
00945 }
00946 if (pwn == loop) {
00947 done = TRUE;
00948 }
00949 }
00950 }
00951
00952
00953
00954 for (e = dg->Get_Out_Edge(v); e; e = dg->Get_Next_Out_Edge(e)) {
00955 VINDEX16 v2 = dg->Get_Sink(e);
00956 INT components = dg->Depv_Array(e)->Num_Dim();
00957 #ifdef Is_True_On
00958 WN* prnt = dg->Get_Wn(v2);
00959 while (prnt && prnt != loop)
00960 prnt = LWN_Get_Parent(prnt);
00961 if ((components <= gdepth) != (prnt == NULL)) {
00962 fprintf(TFile, "Disaster: %d %d 0x%p:", components, gdepth, prnt);
00963 fprintf(TFile, " v=%d 0x%p v2=%d 0x%p e=%d\n",
00964 v, dg->Get_Wn(v), v2, dg->Get_Wn(v2), e);
00965 FmtAssert(0,
00966 ("Inconsistent component count/parent stuff"));
00967 }
00968 #endif
00969 if (components > gdepth)
00970 continue;
00971
00972
00973
00974 VINDEX16 v = is_write ? vw : vr;
00975 if (dependence_disaster == FALSE && v &&
00976 !MIR_Add_Edge(dg, v, v2, dg->Depv_Array(e))) {
00977 dependence_disaster = TRUE;
00978 break;
00979 }
00980 }
00981
00982 for (e = dg->Get_In_Edge(v); e; e = dg->Get_Next_In_Edge(e)) {
00983 VINDEX16 v2 = dg->Get_Source(e);
00984 INT components = dg->Depv_Array(e)->Num_Dim();
00985 #ifdef Is_True_On
00986 WN* prnt = dg->Get_Wn(v2);
00987 while (prnt && prnt != loop)
00988 prnt = LWN_Get_Parent(prnt);
00989 FmtAssert((components <= gdepth) == (prnt == NULL),
00990 ("Inconsistent component count/parent stuff"));
00991 #endif
00992 if (components > gdepth)
00993 continue;
00994
00995
00996
00997 VINDEX16 v = is_write ? vw : vr;
00998 if (dependence_disaster == FALSE && v &&
00999 !MIR_Add_Edge(dg, v2, v, dg->Depv_Array(e))) {
01000 dependence_disaster = TRUE;
01001 break;
01002 }
01003 }
01004
01005
01006
01007 if (is_write) {
01008
01009
01010 OPCODE op = OPCODE_make_op(OPR_STID, MTYPE_V, type);
01011 WN* oldistore = LWN_Get_Parent(wn);
01012 FmtAssert(WN_kid1(oldistore) == wn, ("Bad ISTORE child!"));
01013 WN* newstid = LWN_CreateStid(op, newsym.WN_Offset(),
01014 newsym.St(), pty, WN_kid0(oldistore));
01015 #ifdef TARG_X8664
01016 if (Minvariant_Removal_For_Simd || type == MTYPE_M)
01017 Create_alias(Alias_Mgr, newstid);
01018 #endif
01019 LWN_Copy_Linenumber(oldistore,newstid);
01020 LWN_Copy_Frequency_Tree(newstid,oldistore);
01021
01022
01023 WN_kid0(oldistore) =
01024 WN_CreateIntconst(OPCODE_make_op(OPR_INTCONST, MTYPE_I8, MTYPE_V), 0);
01025 LWN_Set_Parent(WN_kid0(oldistore), oldistore);
01026
01027 LWN_Insert_Block_Before(LWN_Get_Parent(oldistore), oldistore, newstid);
01028 LWN_Extract_From_Block(oldistore);
01029 LWN_Delete_Tree(oldistore);
01030 Unique_AddElement(&new_defs, newstid, FALSE);
01031 }
01032 else {
01033
01034
01035 OPCODE op = OPCODE_make_op(OPR_LDID, Promote_Type(type), type);
01036 WN* oldiload = LWN_Get_Parent(wn);
01037 FmtAssert(WN_kid0(oldiload) == wn, ("Bad iload child!"));
01038 WN* newldid = WN_CreateLdid(op, newsym.WN_Offset(),
01039 newsym.St(), ty);
01040 #ifdef TARG_X8664
01041 if (Minvariant_Removal_For_Simd || type == MTYPE_M)
01042 Create_alias(Alias_Mgr, newldid);
01043 #endif
01044 WN* p_oldiload = LWN_Get_Parent(oldiload);
01045 LWN_Copy_Frequency_Tree(newldid,oldiload);
01046
01047 INT ikid;
01048 for (ikid = 0; ikid < WN_kid_count(p_oldiload); ikid++)
01049 if (WN_kid(p_oldiload,ikid) == oldiload)
01050 break;
01051 FmtAssert(ikid < WN_kid_count(p_oldiload), ("Missing kid!"));
01052
01053 WN_kid(p_oldiload, ikid) = newldid;
01054 LWN_Set_Parent(newldid, p_oldiload);
01055 #ifdef KEY
01056
01057 if ( MTYPE_bit_size( WN_rtype(newldid ) ) == 32 &&
01058 MTYPE_bit_size( WN_rtype(p_oldiload ) ) == 64 &&
01059 !MTYPE_is_float( WN_rtype( newldid ) ) &&
01060 !MTYPE_is_float( WN_rtype( p_oldiload ) ) &&
01061 WN_st( newldid ) ) {
01062 OPCODE cvt_o = OPCODE_make_op(OPR_CVT,WN_rtype(p_oldiload),
01063 WN_rtype(newldid));
01064 WN *cvt = LWN_CreateExp1(cvt_o, newldid);
01065 LWN_Set_Parent(cvt,p_oldiload);
01066 WN_kid(p_oldiload, ikid) = cvt;
01067 }
01068 #endif
01069 LWN_Delete_Tree(oldiload);
01070 Unique_AddElement(&new_uses, newldid, FALSE);
01071 }
01072 }
01073
01074 if (dependence_disaster) {
01075 Is_True(0, ("Dependence graph ran out of space?"));
01076 LNO_Erase_Dg_From_Here_In(LWN_Get_Parent(loop), dg);
01077 }
01078
01079
01080
01081
01082 INT ii = 0;
01083 for (ii = 0; ii < new_defs.Elements(); ii++) {
01084 for (INT jj = 0; jj < new_uses.Elements(); jj++) {
01085 Du_Mgr->Ud_Add_Def(new_uses[jj], new_defs[ii]);
01086 Du_Mgr->Du_Add_Use(new_defs[ii], new_uses[jj]);
01087 }
01088 }
01089 #ifdef TARG_X8664
01090 if (Minvariant_Removal_For_Simd || type == MTYPE_M) {
01091 for (INT jj = 0; jj < new_uses.Elements(); jj++)
01092 if (Wn_Is_Inside(new_uses[jj], loop))
01093 Du_Mgr->Ud_Get_Def(new_uses[jj])->Set_loop_stmt(loop);
01094 }
01095 #endif
01096
01097
01098
01099
01100
01101
01102
01103
01104 for (ii = 0; ii < new_uses.Elements(); ii++) {
01105 WN* parent = LWN_Get_Parent(new_uses[ii]);
01106 for ( ; parent; parent = LWN_Get_Parent(parent)) {
01107 OPCODE opc = WN_opcode(parent);
01108 if (!OPCODE_is_expression(opc))
01109 break;
01110 if (OPCODE_operator(opc) == OPR_ARRAY) {
01111 DOLOOP_STACK* stack = CXX_NEW(DOLOOP_STACK(&LNO_local_pool),
01112 &LNO_local_pool);
01113 Build_Doloop_Stack(parent, stack);
01114 LNO_Build_Access(parent, stack, &LNO_default_pool);
01115 MIR_Maybe_Add_To_List(parent, newly_direct_lists, pool, TRUE);
01116 CXX_DELETE(stack, &LNO_local_pool);
01117 break;
01118 }
01119 }
01120 }
01121
01122
01123
01124
01125
01126 if (messy_only)
01127 MIR_Update_Dependences(loop, &new_uses);
01128
01129 }
01130
01131 static BOOL MIR_Ok_Hoist_Wn_Dependence(WN* other_wn,
01132 const MIR_REFLIST* p,
01133 WN* loop,
01134 ARRAY_DIRECTED_GRAPH16* dg,
01135 EINDEX16 e)
01136 {
01137 INT elts = p->Wnlist.Elements();
01138
01139
01140
01141 for (INT j = 0; j < elts; j++)
01142 if (other_wn == LWN_Get_Parent(p->Wnlist[j]))
01143 return TRUE;
01144
01145
01146
01147 WN* prnt = 0;
01148 for (prnt = other_wn; prnt; prnt = LWN_Get_Parent(prnt))
01149 if (prnt == loop)
01150 break;
01151 if (prnt == NULL)
01152 return TRUE;
01153
01154
01155
01156 DEPV_ARRAY* dv = dg->Depv_Array(e);
01157 INT outer_depth = Do_Depth(loop);
01158 INT unused = dv->Num_Unused_Dim();
01159 INT dim = dv->Num_Dim();
01160
01161 for (INT v = dv->Num_Vec() - 1; v >= 0; v--) {
01162 DEPV* depv = dv->Depv(v);
01163 BOOL carried = FALSE;
01164 for (INT i = 0; i < outer_depth - unused; i++) {
01165 if (DEP_Direction(DEPV_Dep(depv,i)) == DIR_POS) {
01166 carried = TRUE;
01167 break;
01168 }
01169 }
01170 if (carried == FALSE)
01171 return FALSE;
01172 }
01173
01174 return TRUE;
01175 }
01176
01177 static BOOL MIR_Hoistable_Ref(WN* loop,
01178 MIR_REFLIST* p,
01179 ARRAY_DIRECTED_GRAPH16* dg)
01180 {
01181 if (Minv_Debug) {
01182 fprintf(TFile, "In loop %s, trying to hoist", SYMBOL(WN_index(loop)).Name());
01183 p->Print(TFile);
01184 }
01185
01186
01187 for (WN* wn = loop; wn != NULL; wn = LWN_Get_Parent(wn)) {
01188 if (Is_Mp_Region(wn)) {
01189 WN* wn_first = WN_first(WN_region_pragmas(wn));
01190 for (WN* wn = wn_first; wn != NULL; wn = WN_next(wn)) {
01191 if (WN_opcode(wn) == OPC_XPRAGMA
01192 && WN_pragma(wn) == WN_PRAGMA_REDUCTION
01193 && WN_operator(WN_kid0(wn)) == OPR_ARRAY
01194 && SYMBOL(WN_array_base(WN_kid0(wn)))
01195 == SYMBOL(WN_array_base(p->Array))) {
01196 return FALSE;
01197 }
01198 }
01199 }
01200 }
01201
01202
01203
01204
01205
01206 INT depth = Do_Loop_Depth(loop);
01207
01208
01209
01210 for (INT nv = 0; nv < p->Aa->Num_Vec(); nv++) {
01211 ACCESS_VECTOR* av = p->Aa->Dim(nv);
01212 INT nest_depth = av->Nest_Depth();
01213
01214 #ifdef Is_True_On
01215 for (INT ii = nest_depth+1; ii <= depth; ii++) {
01216 Is_True(av->Loop_Coeff(ii) == 0,
01217 ("reference in loop of depth=%d, nest_depth=%d, coeff=%d",
01218 ii, nest_depth, av->Loop_Coeff(ii)));
01219 }
01220 #endif
01221 if (av->Non_Const_Loops() > depth) {
01222 if (Minv_Debug)
01223 fprintf(TFile, " ... failed: non_const_loops problem\n");
01224 return FALSE;
01225 }
01226 }
01227
01228 INT i;
01229 for (i = 0; i < p->Wnlist.Elements(); i++) {
01230 WN* wn_ref = p->Wnlist[i];
01231 #ifdef TARG_X8664
01232 if (WN_operator(wn_ref) == OPR_ARRAY) {
01233 WN *parent = LWN_Get_Parent(wn_ref);
01234 if (WN_operator(parent) == OPR_ILOAD &&
01235 (WN_desc(parent) == MTYPE_V16F4 ||
01236 WN_desc(parent) == MTYPE_V16F8 ||
01237 WN_desc(parent) == MTYPE_V16I1 ||
01238 WN_desc(parent) == MTYPE_V16I2 ||
01239 WN_desc(parent) == MTYPE_V16I4 ||
01240 WN_desc(parent) == MTYPE_V16I8))
01241 return FALSE;
01242 }
01243 #endif
01244 for (WN* wn = wn_ref; wn != NULL; wn = LWN_Get_Parent(wn)) {
01245 if (WN_opcode(wn) == OPC_DO_LOOP) {
01246 for (INT j = 0; j < WN_num_dim(wn_ref); j++)
01247 if (!Is_Loop_Invariant_Exp(WN_array_index(wn_ref, j), wn))
01248 return FALSE;
01249 }
01250 if (wn == loop)
01251 break;
01252 }
01253 }
01254
01255
01256 INT reads = 0;
01257 INT writes = 0;
01258 INT for_sure = p->Wnlist.Elements();
01259 STACK<WN*> stk_good(&MIR_local_pool);
01260
01261 for (INT j = 0; j < p->Wnlist.Elements(); j++) {
01262 WN* wn = p->Wnlist[j];
01263 OPCODE op = WN_opcode(LWN_Get_Parent(wn));
01264
01265 if (OPCODE_is_load(op))
01266 reads++;
01267 else if (OPCODE_is_store(op))
01268 writes++;
01269 else
01270 FmtAssert(0, ("Bad parent for array--can't happen op=%d", op));
01271
01272 WN* pp = NULL;
01273 WN* np = wn;
01274 BOOL for_sure_not = FALSE;
01275 BOOL for_sure_decr = FALSE;
01276 while (np && np != loop && !for_sure_not) {
01277 pp = np, np = LWN_Get_Parent(np);
01278 if (WN_opcode(np) == OPC_DO_LOOP && Do_Loop_Is_Mp(np)) {
01279 for_sure_not = TRUE;
01280 } else if (Is_Mp_Region(np)) {
01281 for_sure_not = TRUE;
01282 }
01283 if (!for_sure_decr && WN_opcode(np) == OPC_IF && WN_if_test(np) != pp) {
01284 for_sure_decr = TRUE;
01285 for_sure--;
01286 }
01287 }
01288
01289 FmtAssert(np, ("Couldn't find parent of 0x%p(opc=%d)!", pp, WN_opcode(pp))); if (!for_sure_not) {
01290 stk_good.Push(wn);
01291 }
01292 }
01293
01294 if (for_sure == 0) {
01295 if (Minv_Debug)
01296 fprintf(TFile, " ... failed: not sure it executes\n");
01297 return FALSE;
01298 }
01299
01300 if (stk_good.Elements() < p->Wnlist.Elements()) {
01301 p->Wnlist.Resetidx();
01302 for (INT k = 0; k < stk_good.Elements(); k++)
01303 p->Wnlist.AddElement(stk_good.Bottom_nth(k));
01304 }
01305
01306 if (stk_good.Elements() == 0) {
01307 if (Minv_Debug)
01308 fprintf(TFile, " ... failed: not sure it executes\n");
01309 return FALSE;
01310 }
01311
01312
01313
01314
01315
01316 INT elts = p->Wnlist.Elements();
01317
01318 for (i = 0; i < elts; i++) {
01319 VINDEX16 v = dg->Get_Vertex(LWN_Get_Parent(p->Wnlist[i]));
01320 if (v == 0) {
01321 if (Minv_Debug)
01322 fprintf(TFile, " ... failed: dependence graph incomplete\n");
01323 return FALSE;
01324 }
01325
01326 EINDEX16 e;
01327 for (e = dg->Get_Out_Edge(v); e; e = dg->Get_Next_Out_Edge(e)) {
01328 WN* other_wn = dg->Get_Wn(dg->Get_Sink(e));
01329 FmtAssert(other_wn && dg->Get_Source(e) == v, ("Broken graph"));
01330 if (MIR_Ok_Hoist_Wn_Dependence(other_wn, p, loop, dg, e) == FALSE) {
01331 if (Minv_Debug)
01332 fprintf(TFile, " ... failed: dependence conflict edge=%d\n", e);
01333 return FALSE;
01334 }
01335 }
01336
01337 for (e = dg->Get_In_Edge(v); e; e = dg->Get_Next_In_Edge(e)) {
01338 WN* other_wn = dg->Get_Wn(dg->Get_Source(e));
01339 FmtAssert(other_wn && dg->Get_Sink(e) == v, ("Broken graph"));
01340 if (MIR_Ok_Hoist_Wn_Dependence(other_wn, p, loop, dg, e) == FALSE) {
01341 if (Minv_Debug)
01342 fprintf(TFile, " ... failed: dependence conflict edge=%d\n", e);
01343 return FALSE;
01344 }
01345 }
01346 }
01347
01348
01349 return TRUE;
01350 }
01351
01352 static BOOL MIR_Hoist_Ref_If_Sensible(WN* loop,
01353 MIR_REFLIST* p,
01354 ARRAY_DIRECTED_GRAPH16* dg,
01355 DYN_ARRAY<MIR_REFLIST*>& newly_direct_lists,
01356 MEM_POOL* pool,
01357 BOOL messy_only)
01358 {
01359 if (messy_only && !MIR_Messy_Subscript(p))
01360 return FALSE;
01361
01362 if (!MIR_Hoistable_Ref(loop, p, dg))
01363 return FALSE;
01364
01365
01366
01367 MIR_Replace(loop, p, dg, newly_direct_lists, pool, messy_only);
01368
01369 if (Minv_Debug)
01370 fprintf(TFile, " ... hoisted!\n");
01371
01372 return TRUE;
01373 }
01374
01375
01376
01377
01378
01379
01380
01381
01382 static void MIR_Build_Loop_List_Array(WN* wn,
01383 DYN_ARRAY<MIR_REFLIST*>& lists,
01384 MEM_POOL* pool,
01385 BOOL duplicates_okay)
01386 {
01387
01388
01389
01390
01391
01392
01393 WN *parent = LWN_Get_Parent(wn);
01394 OPCODE parent_op = WN_opcode(parent);
01395 if (OPCODE_operator(parent_op) == OPR_ADD) {
01396 OPCODE gparent_op = WN_opcode(LWN_Get_Parent(parent));
01397 if (!OPCODE_is_load(gparent_op) && !OPCODE_is_store(gparent_op)) {
01398 return;
01399 }
01400 } else if (!OPCODE_is_load(parent_op) && !OPCODE_is_store(parent_op))
01401 return;
01402
01403 WN* wnbase = WN_array_base(wn);
01404 switch (WN_operator(wnbase)) {
01405 case OPR_LDA:
01406 case OPR_LDID:
01407 break;
01408 default:
01409 return;
01410 }
01411
01412 ACCESS_ARRAY* aa((ACCESS_ARRAY*)WN_MAP_Get(LNO_Info_Map, wn));
01413
01414 if (aa == NULL || aa->Too_Messy)
01415 return;
01416 INT i;
01417 for (i = 0; i < aa->Num_Vec(); i++)
01418 if (aa->Dim(i)->Too_Messy)
01419 return;
01420
01421 ST* base(Get_ST_Base(wnbase));
01422
01423
01424
01425 for (i = 0; i < lists.Elements(); i++) {
01426 MIR_REFLIST* p = lists[i];
01427 if (p->Same(base, aa, wn)) {
01428 Unique_AddElement(&p->Wnlist, wn, duplicates_okay);
01429 return;
01430 }
01431 }
01432
01433
01434
01435 lists.AddElement(CXX_NEW(MIR_REFLIST(base, aa, wn, pool), pool));
01436 }
01437
01438 static void MIR_Build_Loop_List_Walk(WN* wn,
01439 DYN_ARRAY<MIR_REFLIST*>& lists,
01440 MEM_POOL* pool)
01441 {
01442 OPERATOR opr = WN_operator(wn);
01443
01444 if (opr == OPR_ARRAY) {
01445 MIR_Maybe_Add_To_List(wn, lists, pool, FALSE);
01446 }
01447
01448
01449
01450 if (opr == OPR_BLOCK) {
01451 for (WN* w = WN_first(wn); w; w = WN_next(w))
01452 MIR_Build_Loop_List_Walk(w, lists, pool);
01453 }
01454 else if (opr == OPR_IO) {
01455
01456
01457
01458 #ifdef Is_True_On
01459 while (WN_opcode(wn) != OPC_DO_LOOP)
01460 wn = LWN_Get_Parent(wn);
01461 FmtAssert(Get_Do_Loop_Info(wn)->Has_Calls, ("IO error in minvariant"));
01462 #endif
01463 }
01464 else {
01465 for (INT i = 0; i < WN_kid_count(wn); i++)
01466 MIR_Build_Loop_List_Walk(WN_kid(wn,i), lists, pool);
01467 }
01468 }
01469
01470 static DYN_ARRAY<MIR_REFLIST*>* MIR_Build_Loop_List(WN* wn, MEM_POOL* pool)
01471 {
01472 DYN_ARRAY<MIR_REFLIST*>* lists =
01473 CXX_NEW(DYN_ARRAY<MIR_REFLIST*>(pool), pool);
01474 MIR_Build_Loop_List_Walk(wn, *lists, pool);
01475 return lists;
01476 }
01477
01478 static BOOL MIR_Try_Hoist(WN* loop,
01479 DYN_ARRAY<MIR_REFLIST*>& lists,
01480 ARRAY_DIRECTED_GRAPH16* dg,
01481 MEM_POOL* pool,
01482 BOOL messy_only)
01483 {
01484 #ifdef KEY // bug 8076: do not hoist if index variable is marked addr_saved
01485 if (ST_addr_saved(WN_st(WN_kid0(loop))))
01486 return FALSE;
01487 #endif
01488 BOOL did_hoisting = FALSE;
01489 INT i = 0;
01490
01491 DYN_ARRAY<MIR_REFLIST*>* newly_direct_lists =
01492 CXX_NEW(DYN_ARRAY<MIR_REFLIST*>(pool), pool);
01493
01494 while (i < lists.Elements()) {
01495 BOOL hoisted = MIR_Hoist_Ref_If_Sensible(loop, lists[i], dg,
01496 *newly_direct_lists, pool, messy_only);
01497 #if Is_True_On
01498 LWN_Check_Parentize(loop);
01499 #endif
01500 if (hoisted) {
01501
01502 did_hoisting = TRUE;
01503 if (i < lists.Elements() - 1)
01504 lists[i] = lists[lists.Elements() - 1];
01505 lists.Decidx();
01506
01507 for (INT ii = newly_direct_lists->Elements() - 1; ii >= 0; ii--) {
01508 INT newx = lists.Newidx();
01509 lists[newx] = (*newly_direct_lists)[ii];
01510 (*newly_direct_lists).Decidx();
01511 }
01512 }
01513 else {
01514 i++;
01515 }
01516 }
01517
01518 CXX_DELETE(newly_direct_lists, pool);
01519
01520 return did_hoisting;
01521 }
01522
01523 static DYN_ARRAY<MIR_REFLIST*>*
01524 MIR_Partition_Lists(WN* loop,
01525 MEM_POOL* pool)
01526 {
01527 if (Minv_Debug) {
01528 fprintf(TFile, "MIR_Partition_Lists for loop %s, depth %d:\n",
01529 SYMBOL(WN_index(loop)).Name(), Do_Depth(loop));
01530 #if 0
01531 fprintf(TFile, "old lists:\n");
01532 Print_Lists(TFile, old_lists);
01533 #endif
01534 }
01535
01536 DYN_ARRAY<MIR_REFLIST*>* rval = MIR_Build_Loop_List(loop, pool);
01537
01538 if (Minv_Debug) {
01539 fprintf(TFile, "new lists:\n");
01540 Print_Lists(TFile, *rval);
01541 }
01542
01543 return rval;
01544 }
01545
01546
01547 static void MIR_Go_Inside(WN* body,
01548 const DYN_ARRAY<MIR_REFLIST*>& lists,
01549 ARRAY_DIRECTED_GRAPH16* dg,
01550 BOOL messy_only)
01551 {
01552 FmtAssert(WN_opcode(body) == OPC_BLOCK,
01553 ("Bad block for MIR_Iterate_Outer_Loops()"));
01554
01555 for (WN* wn = WN_first(body); wn; wn = WN_next(wn)) {
01556 switch (WN_opcode(wn)) {
01557 case OPC_DO_LOOP:
01558 {
01559 DYN_ARRAY<MIR_REFLIST*>* sublists =
01560 MIR_Partition_Lists(wn, &MIR_local_pool);
01561 DO_LOOP_INFO* dli = Get_Do_Loop_Info(wn);
01562 if (!dli->Has_Bad_Mem && !dli->Has_Gotos)
01563 MIR_Try_Hoist(wn, *sublists, dg, &MIR_local_pool, messy_only);
01564 MIR_Go_Inside(WN_do_body(wn), *sublists, dg, messy_only);
01565 while (sublists->Elements() > 0)
01566 sublists->Decidx();
01567 CXX_DELETE(sublists, &MIR_local_pool);
01568 }
01569 break;
01570 case OPC_IF:
01571 MIR_Go_Inside(WN_then(wn), lists, dg, messy_only);
01572 MIR_Go_Inside(WN_else(wn), lists, dg, messy_only);
01573 break;
01574 case OPC_DO_WHILE:
01575 case OPC_WHILE_DO:
01576 MIR_Go_Inside(WN_while_body(wn), lists, dg, messy_only);
01577 break;
01578 case OPC_REGION:
01579 MIR_Go_Inside(WN_region_body(wn), lists, dg, messy_only);
01580 break;
01581 }
01582 }
01583 }
01584
01585 static void MIR_Iterate_Outer_Loops(WN* body,
01586 ARRAY_DIRECTED_GRAPH16* dg,
01587 BOOL messy_only)
01588 {
01589 FmtAssert(WN_opcode(body) == OPC_BLOCK,
01590 ("Bad block for MIR_Iterate_Outer_Loops()"));
01591
01592 for (WN* wn = WN_first(body); wn; wn = WN_next(wn)) {
01593 switch (WN_opcode(wn)) {
01594 case OPC_DO_LOOP:
01595 {
01596 MEM_POOL_Push_Freeze(&MIR_local_pool);
01597 DYN_ARRAY<MIR_REFLIST*>* lists =
01598 MIR_Build_Loop_List(wn, &MIR_local_pool);
01599 DO_LOOP_INFO* dli = Get_Do_Loop_Info(wn);
01600 if (!dli->Has_Bad_Mem && !dli->Has_Gotos)
01601 MIR_Try_Hoist(wn, *lists, dg, &MIR_local_pool, messy_only);
01602 MIR_Go_Inside(WN_do_body(wn), *lists, dg, messy_only);
01603 while (lists->Elements() > 0)
01604 lists->Decidx();
01605 CXX_DELETE(lists, &MIR_local_pool);
01606 MEM_POOL_Pop_Unfreeze(&MIR_local_pool);
01607 }
01608 break;
01609 case OPC_IF:
01610 MIR_Iterate_Outer_Loops(WN_then(wn), dg, messy_only);
01611 MIR_Iterate_Outer_Loops(WN_else(wn), dg, messy_only);
01612 break;
01613 case OPC_DO_WHILE:
01614 case OPC_WHILE_DO:
01615 MIR_Iterate_Outer_Loops(WN_while_body(wn), dg, messy_only);
01616 break;
01617 case OPC_REGION:
01618 MIR_Iterate_Outer_Loops(WN_region_body(wn), dg, messy_only);
01619 break;
01620 }
01621 }
01622 }
01623
01624 extern void Minvariant_Removal(WN *func_nd, ARRAY_DIRECTED_GRAPH16 *dg)
01625 {
01626 if (mir_local_pool_initialized == FALSE) {
01627 mir_local_pool_initialized = TRUE;
01628 MEM_POOL_Initialize(&MIR_local_pool, "MIR_local_pool", FALSE);
01629 }
01630
01631 Minv_Debug = Get_Trace(TP_LNOPT, TT_LNO_MINVARIANT_DEBUG);
01632
01633 #ifdef Is_True_On
01634 LWN_Check_Parentize(func_nd);
01635 #endif
01636 MIR_Iterate_Outer_Loops(WN_func_body(func_nd), dg, FALSE);
01637 #ifdef Is_True_On
01638 LWN_Check_Parentize(func_nd);
01639 #endif
01640 }
01641
01642
01643
01644
01645
01646
01647
01648
01649 static BOOL MIR_Messy_Subscript(MIR_REFLIST* mr)
01650 {
01651 for (INT i = 0; i < mr->Wnlist.Elements(); i++) {
01652 WN* wn_array = mr->Wnlist[i];
01653 if (Messy_Subscript(wn_array))
01654 return TRUE;
01655 }
01656 return FALSE;
01657 }
01658
01659
01660
01661
01662
01663
01664
01665
01666
01667
01668 static void MIR_Test_Hoist(WN* loop,
01669 DYN_ARRAY<MIR_REFLIST*>& lists,
01670 ARRAY_DIRECTED_GRAPH16* dg,
01671 INT can_hoist[],
01672 INT lowest_depth[])
01673 {
01674 for (INT i = 0; i < lists.Elements(); i++) {
01675 if (MIR_Messy_Subscript(lists[i])
01676 && MIR_Hoistable_Ref(loop, lists[i], dg)) {
01677 INT index = Do_Loop_Depth(Enclosing_Do_Loop(lists[i]->Array));
01678 can_hoist[index]++;
01679 if (Do_Loop_Depth(loop) < lowest_depth[index])
01680 lowest_depth[index] = Do_Loop_Depth(loop);
01681 }
01682 }
01683 }
01684
01685
01686
01687
01688
01689
01690
01691
01692
01693 static void MIR_Test_Outer_Loops(WN* body,
01694 ARRAY_DIRECTED_GRAPH16* dg,
01695 INT can_hoist[],
01696 INT lowest_depth[])
01697 {
01698 FmtAssert(WN_opcode(body) == OPC_BLOCK,
01699 ("MIR_Test_Outer_Loops(): Bad block"));
01700
01701 for (WN* wn = WN_first(body); wn; wn = WN_next(wn)) {
01702 switch (WN_opcode(wn)) {
01703 case OPC_DO_LOOP:
01704 {
01705 MEM_POOL_Push(&LNO_local_pool);
01706 DYN_ARRAY<MIR_REFLIST*>* lists =
01707 MIR_Build_Loop_List(wn, &LNO_local_pool);
01708 DO_LOOP_INFO* dli = Get_Do_Loop_Info(wn);
01709 if (!dli->Has_Bad_Mem && !dli->Has_Gotos)
01710 MIR_Test_Hoist(wn, *lists, dg, can_hoist, lowest_depth);
01711 MIR_Test_Outer_Loops(WN_do_body(wn), dg, can_hoist, lowest_depth);
01712 while (lists->Elements() > 0)
01713 lists->Decidx();
01714 CXX_DELETE(lists, &LNO_local_pool);
01715 MEM_POOL_Pop(&LNO_local_pool);
01716 }
01717 break;
01718 case OPC_IF:
01719 MIR_Test_Outer_Loops(WN_then(wn), dg, can_hoist, lowest_depth);
01720 MIR_Test_Outer_Loops(WN_else(wn), dg, can_hoist, lowest_depth);
01721 break;
01722 case OPC_DO_WHILE:
01723 case OPC_WHILE_DO:
01724 MIR_Test_Outer_Loops(WN_while_body(wn), dg, can_hoist, lowest_depth);
01725 break;
01726 case OPC_REGION:
01727 MIR_Test_Outer_Loops(WN_region_body(wn), dg, can_hoist, lowest_depth);
01728 break;
01729 }
01730 }
01731 }
01732
01733
01734
01735
01736
01737
01738
01739
01740
01741 static void MIR_Test_SNL(WN* wn_loop,
01742 ARRAY_DIRECTED_GRAPH16* dg,
01743 INT can_hoist[],
01744 INT lowest_depth[])
01745 {
01746 MEM_POOL_Push(&LNO_local_pool);
01747 DYN_ARRAY<MIR_REFLIST*>* lists =
01748 MIR_Build_Loop_List(wn_loop, &LNO_local_pool);
01749 DO_LOOP_INFO* dli = Get_Do_Loop_Info(wn_loop);
01750 if (!dli->Has_Bad_Mem && !dli->Has_Gotos)
01751 MIR_Test_Hoist(wn_loop, *lists, dg, can_hoist, lowest_depth);
01752 MIR_Test_Outer_Loops(WN_do_body(wn_loop), dg, can_hoist, lowest_depth);
01753 while (lists->Elements() > 0)
01754 lists->Decidx();
01755 CXX_DELETE(lists, &LNO_local_pool);
01756 MEM_POOL_Pop(&LNO_local_pool);
01757 }
01758
01759
01760
01761
01762
01763
01764
01765
01766
01767
01768
01769
01770 extern void MIR_Has_Messy_Subscript(WN* wn_loop,
01771 INT can_hoist[],
01772 INT lowest_depth[],
01773 BOOL initialize)
01774 {
01775 ARRAY_DIRECTED_GRAPH16* dg = Array_Dependence_Graph;
01776 INT count = SNL_Loop_Count(wn_loop);
01777 WN* wn_inner = SNL_Get_Inner_Snl_Loop(wn_loop, count);
01778 INT inner_depth = Do_Loop_Depth(wn_inner);
01779
01780 if (mir_local_pool_initialized == FALSE) {
01781 mir_local_pool_initialized = TRUE;
01782 MEM_POOL_Initialize(&MIR_local_pool, "MIR_local_pool", FALSE);
01783 }
01784
01785 if (initialize) {
01786 for (INT i = 0; i <= inner_depth; i++) {
01787 can_hoist[i] = 0;
01788 lowest_depth[i] = i;
01789 }
01790 }
01791 MIR_Test_SNL(wn_loop, dg, can_hoist, lowest_depth);
01792 }
01793
01794
01795
01796
01797
01798
01799
01800 extern void MIR_Hoist_Messy_Subscripts(WN* wn_loop)
01801 {
01802 ARRAY_DIRECTED_GRAPH16* dg = Array_Dependence_Graph;
01803 if (mir_local_pool_initialized == FALSE) {
01804 mir_local_pool_initialized = TRUE;
01805 MEM_POOL_Initialize(&MIR_local_pool, "MIR_local_pool", FALSE);
01806 }
01807 MIR_Iterate_Outer_Loops(LWN_Get_Parent(wn_loop), dg, TRUE);
01808 }