00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00048 #define __STDC_LIMIT_MACROS
00049 #include <stdint.h>
00050 #ifdef USE_PCH
00051 #include "lno_pch.h"
00052 #endif // USE_PCH
00053 #pragma hdrstop
00054
00055 #define snl_dist_CXX "snl_dist.cxx"
00056 const static char *rcs_id = snl_dist_CXX "$Revision: 1.5 $";
00057
00058 #include <sys/types.h>
00059 #include <alloca.h>
00060 #include <ctype.h>
00061 #include <limits.h>
00062
00063 #include "pu_info.h"
00064 #include "snl.h"
00065 #include "snl_dist.h"
00066 #include "lwn_util.h"
00067 #include "lnoutils.h"
00068 #include "lnopt_main.h"
00069 #include "opt_du.h"
00070 #include "lego.h"
00071 #include "lego_opts.h"
00072 #include "permute.h"
00073 #include "snl_dist.h"
00074 #include "debug.h"
00075 #include "anl_driver.h"
00076 #include "prompf.h"
00077
00078 #pragma weak New_Construct_Id
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092 extern void SNL_GEN_Distribute(WN* wn_outer,
00093 INT split_depth,
00094 INT nloops,
00095 BOOL above_is_distributable,
00096 BOOL below_is_distributable,
00097 WN** wn_new_first,
00098 WN** wn_new_last)
00099 {
00100 DU_MANAGER* du = Du_Mgr;
00101 ARRAY_DIRECTED_GRAPH16* dg = Array_Dependence_Graph;
00102 WN* wn_inner = SNL_Get_Inner_Snl_Loop(wn_outer, nloops);
00103 INT first_in_stack = Do_Loop_Depth(wn_inner) - nloops + 1;
00104 DOLOOP_STACK stack(&LNO_local_pool);
00105 Build_Doloop_Stack(wn_inner, &stack);
00106
00107 WN* newup = NULL;
00108 WN* newdown = NULL;
00109 INT start_depth = split_depth == -1 ? first_in_stack + 1 : split_depth;
00110 for (INT lp = start_depth; lp < first_in_stack + nloops; lp++) {
00111 WN* wn = stack.Bottom_nth(lp);
00112 if (above_is_distributable && WN_prev(wn)) {
00113 if (newup == NULL)
00114 newup = SNL_Distribute(&stack, lp, first_in_stack, TRUE);
00115 else
00116 SNL_Distribute(&stack, lp, first_in_stack, TRUE);
00117 }
00118 if (below_is_distributable && WN_next(wn)) {
00119 if (newdown == NULL)
00120 newdown = SNL_Distribute(&stack, lp, first_in_stack, FALSE);
00121 else
00122 SNL_Distribute(&stack, lp, first_in_stack, FALSE);
00123 }
00124 }
00125 *wn_new_first = newup;
00126 *wn_new_last = newdown;
00127 }
00128
00129
00130
00131
00132
00133
00134
00135 extern INT Split_Depth(WN* wn_outer,
00136 INT nloops)
00137 {
00138 INT outer_depth = Do_Loop_Depth(wn_outer);
00139 INT split_depth = outer_depth + nloops;
00140 WN* wn_inner = SNL_Get_Inner_Snl_Loop(wn_outer, nloops);
00141 DOLOOP_STACK stack(&LNO_local_pool);
00142 Build_Doloop_Stack(wn_inner, &stack);
00143 for (INT i = stack.Elements() - 1; i >= outer_depth; i--) {
00144 WN* wn_split = stack.Bottom_nth(i);
00145 if (!SNL_Is_Distributable(wn_outer, wn_outer, wn_split, TRUE))
00146 break;
00147 if (!SNL_Is_Distributable(wn_outer, wn_outer, wn_split, FALSE))
00148 break;
00149 split_depth = Do_Loop_Depth(wn_split);\
00150 }
00151 if (split_depth == outer_depth)
00152 split_depth = -1;
00153 return split_depth;
00154 }
00155
00156
00157
00158
00159
00160
00161
00162
00163 extern void SNL_INV_Distribute(WN* wn_outer,
00164 INT split_depth,
00165 INT nloops,
00166 WN** wn_new_first,
00167 WN** wn_new_last)
00168 {
00169 WN* newup = NULL;
00170 WN* newdown = NULL;
00171 DU_MANAGER* du = Du_Mgr;
00172 ARRAY_DIRECTED_GRAPH16* dg = Array_Dependence_Graph;
00173 WN* wn_inner = SNL_Get_Inner_Snl_Loop(wn_outer, nloops);
00174 INT first_in_stack = Do_Loop_Depth(wn_inner) - nloops + 1;
00175 DOLOOP_STACK stack(&LNO_local_pool);
00176 Build_Doloop_Stack(wn_inner, &stack);
00177
00178 INT start_depth = split_depth == -1 ? first_in_stack + 1 : split_depth;
00179 for (INT lp = start_depth; lp < first_in_stack + nloops; lp++) {
00180 WN* wn = stack.Bottom_nth(lp);
00181 if (WN_prev_executable(wn)) {
00182 if (newup == NULL)
00183 newup = SNL_Distribute(&stack, lp, first_in_stack, TRUE);
00184 else
00185 SNL_Distribute(&stack, lp, first_in_stack, TRUE);
00186 }
00187 if (WN_next_executable(wn)) {
00188 if (newdown == NULL)
00189 newdown = SNL_Distribute(&stack, lp, first_in_stack, FALSE);
00190 else
00191 SNL_Distribute(&stack, lp, first_in_stack, FALSE);
00192 }
00193 }
00194 *wn_new_first = newup;
00195 *wn_new_last = newdown;
00196 }
00197
00198
00199
00200
00201
00202
00203
00204
00205 static BOOL Dep_Carried_Outside_Or_Zero(INT loopd,
00206 EINDEX16 e)
00207 {
00208 ARRAY_DIRECTED_GRAPH16* dg = Array_Dependence_Graph;
00209
00210 DEPV_ARRAY* dv = dg->Depv_Array(e);
00211 for (INT d = 0; d < dv->Num_Vec(); d++) {
00212 BOOL ok = FALSE;
00213 DEPV* dd = dv->Depv(d);
00214 INT i;
00215 for (i = 0; !ok && (i < loopd - dv->Num_Unused_Dim()); i++) {
00216 if (i == dv->Num_Dim())
00217 return FALSE;
00218 switch (DEP_Direction(DEPV_Dep(dd, i))) {
00219 case DIR_POS:
00220 ok = TRUE;
00221 break;
00222 case DIR_EQ:
00223 case DIR_POSEQ:
00224 break;
00225 default:
00226 Is_True(0, ("Impossible lexpos dependence"));
00227 }
00228 }
00229 if (ok == FALSE) {
00230
00231 for ( ; i < dv->Num_Dim(); i++) {
00232 DIRECTION dir = DEP_Direction(DEPV_Dep(dd,i));
00233 if (dir != DIR_EQ)
00234 return FALSE;
00235 }
00236 }
00237 }
00238 return TRUE;
00239 }
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250 static BOOL In_Same_SNL_Section(WN* wn1, WN* wn2)
00251 {
00252 WN *wn;
00253 for (wn = wn1; wn != NULL; wn = LWN_Get_Parent(wn))
00254 if (WN_opcode(LWN_Get_Parent(wn)) == OPC_BLOCK)
00255 break;
00256 WN* wn1_stat = wn;
00257 for (wn = wn2; wn != NULL; wn = LWN_Get_Parent(wn))
00258 if (WN_opcode(LWN_Get_Parent(wn)) == OPC_BLOCK)
00259 break;
00260 WN* wn2_stat = wn;
00261 if (LWN_Get_Parent(wn1_stat) != LWN_Get_Parent(wn2_stat))
00262 return FALSE;
00263 WN* wn_first = WN_first(LWN_Get_Parent(wn1_stat));
00264 INT stat_count = 0;
00265 for (wn = wn_first; wn != NULL; wn = WN_next(wn)) {
00266 if (wn == wn1_stat)
00267 stat_count++;
00268 if (wn == wn2_stat)
00269 stat_count++;
00270 if (WN_opcode(wn) == OPC_DO_LOOP)
00271 return stat_count == 0 || stat_count == 2;
00272 }
00273 FmtAssert(stat_count == 2, ("Must see both statements"));
00274 return TRUE;
00275 }
00276
00277
00278
00279
00280
00281
00282
00283 static BOOL Wn_Is_Above(WN* wn_one,
00284 WN* wn_two)
00285 {
00286 if (wn_one == wn_two)
00287 return FALSE;
00288 WN* wn_common = Common_Ancestor(wn_one, wn_two);
00289 WN* wn_sibling_one = NULL;
00290 WN *wn;
00291 for (wn = wn_one; wn != wn_common; wn = LWN_Get_Parent(wn))
00292 wn_sibling_one = wn;
00293 WN* wn_sibling_two = NULL;
00294 for (wn = wn_two; wn != wn_common; wn = LWN_Get_Parent(wn))
00295 wn_sibling_two = wn;
00296 if (WN_opcode(wn_common) == OPC_BLOCK) {
00297 for (WN* wn = WN_next(wn_sibling_one); wn != NULL; wn = WN_next(wn))
00298 if (wn == wn_sibling_two)
00299 return TRUE;
00300 return FALSE;
00301 } else {
00302 for (INT i = 0; i < WN_kid_count(wn_common); i++) {
00303 if (WN_kid(wn_common, i) == wn_sibling_one)
00304 return TRUE;
00305 if (WN_kid(wn_common, i) == wn_sibling_two)
00306 return FALSE;
00307 }
00308 return FALSE;
00309 }
00310 }
00311
00312
00313
00314
00315
00316
00317
00318 static BOOL Wn_Is_Below(WN* wn_one,
00319 WN* wn_two)
00320 {
00321 if (wn_one == wn_two)
00322 return FALSE;
00323 return !Wn_Is_Above(wn_one, wn_two);
00324 }
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343 static BOOL SNL_Is_Distributable_Tree(WN* wn_tree,
00344 WN* wn_dist,
00345 WN* wn_inner,
00346 BOOL above)
00347 {
00348 INT dist_depth = Do_Loop_Depth(wn_dist);
00349 ARRAY_DIRECTED_GRAPH16* dg = Array_Dependence_Graph;
00350 LWN_ITER* itr = LWN_WALK_TreeIter(wn_tree);
00351 for (; itr != NULL; itr = LWN_WALK_TreeNext(itr)) {
00352 WN* wn = itr->wn;
00353
00354
00355 if (!OPCODE_is_load(WN_opcode(wn)) && !OPCODE_is_store(WN_opcode(wn))
00356 && !OPCODE_is_call(WN_opcode(wn)))
00357 continue;
00358
00359
00360 VINDEX16 v = dg->Get_Vertex(wn);
00361 if (v == 0) {
00362
00363 if (WN_operator(wn) == OPR_LDID
00364 || WN_operator(wn) == OPR_STID)
00365 #ifdef KEY
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384 if(WN_operator(wn) == OPR_STID && !above)
00385 return FALSE;
00386 else
00387 #endif
00388 continue;
00389 return FALSE;
00390 }
00391
00392
00393 if (above) {
00394 for (EINDEX16 e = dg->Get_In_Edge(v); e; e = dg->Get_Next_In_Edge(e)) {
00395 VINDEX16 v2 = dg->Get_Source(e);
00396 WN* wn2 = dg->Get_Wn(v2);
00397 if ((Wn_Is_Inside(wn2, wn_inner) || Wn_Is_Below(wn2, wn_inner))
00398 && !Dep_Carried_Outside_Or_Zero(dist_depth, e)
00399 && !In_Same_SNL_Section(wn, wn2))
00400 return FALSE;
00401 }
00402 } else {
00403 for (EINDEX16 e = dg->Get_Out_Edge(v); e; e = dg->Get_Next_Out_Edge(e)) {
00404 VINDEX16 v2 = dg->Get_Sink(e);
00405 WN* wn2 = dg->Get_Wn(v2);
00406 if ((Wn_Is_Inside(wn2, wn_inner) || Wn_Is_Above(wn2, wn_inner))
00407 && !Dep_Carried_Outside_Or_Zero(dist_depth, e)
00408 && !In_Same_SNL_Section(wn, wn2))
00409 return FALSE;
00410 }
00411 }
00412 }
00413 return TRUE;
00414 }
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427 static BOOL SNL_Is_Distributable_Traverse(WN* wn_loop,
00428 WN* wn_dist,
00429 WN* wn_inner,
00430 BOOL above)
00431 {
00432 FmtAssert(WN_opcode(wn_loop) == OPC_DO_LOOP,
00433 ("SNL_Is_Distributable_Traverse: First arg must be do loop"));
00434 if (wn_loop == wn_inner)
00435 return TRUE;
00436 WN* wn_first = WN_first(WN_do_body(wn_loop));
00437 if (above) {
00438 WN *wn;
00439 #ifdef KEY //bug 11671: we may not find a do loop, especially for APO
00440 for (wn = wn_first; wn && WN_opcode(wn) != OPC_DO_LOOP; wn = WN_next(wn))
00441 #else
00442 for (wn = wn_first; WN_opcode(wn) != OPC_DO_LOOP; wn = WN_next(wn))
00443 #endif
00444 if (!SNL_Is_Distributable_Tree(wn, wn_dist, wn_inner, above))
00445 return FALSE;
00446 #ifdef KEY //bug 11671: even though wn_loop is not inner, but inner is hidden in region
00447 if(wn==NULL)
00448 return FALSE;
00449 #endif
00450 if (!SNL_Is_Distributable_Traverse(wn, wn_dist, wn_inner, TRUE))
00451 return FALSE;
00452 } else {
00453 WN *wn;
00454 #ifdef KEY //bug 11671
00455 for (wn = wn_first; wn && WN_opcode(wn) != OPC_DO_LOOP; wn = WN_next(wn));
00456 if(wn==NULL)
00457 return FALSE;
00458 #else
00459 for (wn = wn_first; wn && WN_opcode(wn) != OPC_DO_LOOP; wn = WN_next(wn));
00460 #endif
00461 if (!SNL_Is_Distributable_Traverse(wn, wn_dist, wn_inner, FALSE))
00462 return FALSE;
00463 for (wn = WN_next(wn); wn != NULL; wn = WN_next(wn))
00464 if (!SNL_Is_Distributable_Tree(wn, wn_dist, wn_inner, FALSE))
00465 return FALSE;
00466 }
00467 return TRUE;
00468 }
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482 extern BOOL SNL_Is_Distributable(WN* wn_dist,
00483 WN* wn_outer,
00484 WN* wn_inner,
00485 BOOL above)
00486 {
00487 return SNL_Is_Distributable_Traverse(wn_outer, wn_dist, wn_inner, above);
00488 }
00489
00490
00491
00492
00493
00494
00495
00496 static void Print_Distribution(FILE* file,
00497 DOLOOP_STACK* stack,
00498 INT outer,
00499 INT inner,
00500 BOOL above)
00501 {
00502 if (above)
00503 fprintf(file, "Distributing Above (");
00504 else
00505 fprintf(file, "Distributing Below (");
00506
00507 INT i;
00508 for (i = outer; i <= inner; i++) {
00509 fprintf(file, "%s", WB_Whirl_Symbol(stack->Bottom_nth(i)));
00510 if (i < inner)
00511 fprintf(file, ",");
00512 }
00513 fprintf(file, ") at (");
00514 for (i = outer; i <= inner; i++) {
00515 fprintf(file, "%d", (INT) WN_linenum(stack->Bottom_nth(i)));
00516 if (i < inner)
00517 fprintf(file, ",");
00518 }
00519 fprintf(file, ")\n");
00520 }
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561 WN* SNL_Distribute(DOLOOP_STACK* stack, INT inner, INT loopd, BOOL above)
00562 {
00563 ARRAY_DIRECTED_GRAPH16* dg = Array_Dependence_Graph;
00564 DU_MANAGER* du = Du_Mgr;
00565
00566 INT imperfect = loopd;
00567 INT i;
00568 for (i = loopd+1; i <= inner; i++) {
00569 if (( above && WN_prev_executable(stack->Bottom_nth(i))) ||
00570 (!above && WN_next_executable(stack->Bottom_nth(i))))
00571 imperfect = i;
00572 }
00573
00574 if (imperfect == loopd)
00575 return NULL;
00576
00577 if (LNO_Verbose) {
00578 Print_Distribution(stdout, stack, imperfect, inner, above);
00579 Print_Distribution(TFile, stack, imperfect, inner, above);
00580 }
00581
00582
00583
00584 WN* wn_inner = stack->Bottom_nth(inner);
00585 WN* newdo = NULL;
00586
00587 WN* newdos[SNL_MAX_LOOPS];
00588 SYMBOL newsyms[SNL_MAX_LOOPS];
00589
00590
00591 INT new_loop_count = 0;
00592 INT old_ids[SNL_MAX_LOOPS];
00593 INT new_ids[SNL_MAX_LOOPS];
00594 STACK<WN*> old_loops(&LNO_local_pool);
00595 STACK<WN*> new_loops(&LNO_local_pool);
00596 PROMPF_LINES* old_lines[SNL_MAX_LOOPS];
00597 PROMPF_LINES* new_lines[SNL_MAX_LOOPS];
00598
00599 for (i = imperfect; i > loopd; i--) {
00600 WN* loop = stack->Bottom_nth(i);
00601 WN* loopp = LWN_Get_Parent(loop);
00602 WN* newblk = WN_CreateBlock();
00603 WN* next = NULL;
00604
00605 for (WN* wn = above ? WN_first(loopp) : WN_next(loop);
00606 wn && wn != loop;
00607 wn = next) {
00608 next = WN_next(wn);
00609 LWN_Extract_From_Block(loopp, wn);
00610 LWN_Insert_Block_Before(newblk, NULL, wn);
00611 }
00612
00613 if (newdo) {
00614 if (above)
00615 LWN_Insert_Block_Before(newblk, NULL, newdo);
00616 else
00617 LWN_Insert_Block_After(newblk, NULL, newdo);
00618 }
00619
00620
00621
00622 WN* olddo = stack->Bottom_nth(i-1);
00623 newdo = LWN_CreateDO(LWN_Copy_Tree(WN_index(olddo)),
00624 LWN_Copy_Tree(WN_start(olddo)),
00625 LWN_Copy_Tree(WN_end(olddo)),
00626 LWN_Copy_Tree(WN_step(olddo)),
00627 newblk);
00628
00629 if (Prompf_Info != NULL && Prompf_Info->Is_Enabled()) {
00630 INT old_id = WN_MAP32_Get(Prompf_Id_Map, olddo);
00631 INT new_id = New_Construct_Id();
00632 WN_MAP32_Set(Prompf_Id_Map, newdo, new_id);
00633 old_ids[new_loop_count] = old_id;
00634 new_ids[new_loop_count++] = new_id;
00635 old_loops.Push(olddo);
00636 new_loops.Push(newdo);
00637 }
00638
00639 LWN_Copy_Linenumber(olddo, newdo);
00640 LWN_Copy_Def_Use(WN_kid0(WN_start(olddo)), WN_kid0(WN_start(newdo)), du);
00641 dg->Add_Deps_To_Copy_Block(WN_kid0(WN_start(olddo)),
00642 WN_kid0(WN_start(newdo)), FALSE);
00643 LWN_Copy_Def_Use(WN_end(olddo), WN_end(newdo), du);
00644 dg->Add_Deps_To_Copy_Block(WN_end(olddo), WN_end(newdo), FALSE);
00645 LWN_Copy_Def_Use(WN_kid0(WN_step(olddo)), WN_kid0(WN_step(newdo)), du);
00646 dg->Add_Deps_To_Copy_Block(WN_kid0(WN_step(olddo)),
00647 WN_kid0(WN_step(newdo)), FALSE);
00648
00649 newdos[i-loopd-1] = newdo;
00650 newsyms[i-loopd-1] = SYMBOL(WN_index(newdo));
00651 DO_LOOP_INFO* olddli = Get_Do_Loop_Info(olddo);
00652 ACCESS_ARRAY* newlb = CXX_NEW(ACCESS_ARRAY(olddli->LB, &LNO_default_pool),
00653 &LNO_default_pool);
00654 ACCESS_ARRAY* newub = CXX_NEW(ACCESS_ARRAY(olddli->UB, &LNO_default_pool),
00655 &LNO_default_pool);
00656 ACCESS_VECTOR* newstep = CXX_NEW(ACCESS_VECTOR(olddli->Step,
00657 &LNO_default_pool),
00658 &LNO_default_pool);
00659
00660 DO_LOOP_INFO* dli = CXX_NEW(DO_LOOP_INFO(&LNO_default_pool,
00661 newlb, newub, newstep, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
00662 (i == imperfect)), &LNO_default_pool);
00663 if (olddli->Lego_Info != NULL)
00664 dli->Lego_Info = CXX_NEW(LEGO_INFO(olddli->Lego_Info, LEGO_pool),
00665 LEGO_pool);
00666 Set_Do_Loop_Info(newdo, dli);
00667 DO_LOOP_INFO* innerdli = Get_Do_Loop_Info(stack->Bottom_nth(i));
00668 if (innerdli->Est_Num_Iterations > 20 &&
00669 innerdli->Num_Iterations_Symbolic == FALSE) {
00670
00671
00672 dli->Set_Generally_Unimportant();
00673 }
00674 FmtAssert(olddli->Depth == i-1,
00675 ("Strange depth %d vs %d", olddli->Depth, i-1));
00676 }
00677
00678
00679
00680 WN* wn_outer = stack->Bottom_nth(loopd);
00681 if (above)
00682 LWN_Insert_Block_Before(LWN_Get_Parent(wn_outer), wn_outer, newdo);
00683 else
00684 LWN_Insert_Block_After(LWN_Get_Parent(wn_outer), wn_outer, newdo);
00685
00686 if (Prompf_Info != NULL && Prompf_Info->Is_Enabled()) {
00687 INT i;
00688 for (i = 0; i < old_loops.Elements(); i++) {
00689 WN* wn_loop = old_loops.Bottom_nth(i);
00690 PROMPF_LINES* pl = CXX_NEW(PROMPF_LINES(wn_loop, &PROMPF_pool),
00691 &PROMPF_pool);
00692 old_lines[i] = pl;
00693 }
00694 for (i = 0; i < new_loops.Elements(); i++) {
00695 WN* wn_loop = new_loops.Bottom_nth(i);
00696 PROMPF_LINES* pl = CXX_NEW(PROMPF_LINES(wn_loop, &PROMPF_pool),
00697 &PROMPF_pool);
00698 new_lines[i] = pl;
00699 }
00700 Prompf_Info->Distribution(old_ids, old_lines, new_ids, new_lines,
00701 new_loop_count);
00702 }
00703
00704
00705
00706 DOLOOP_STACK dostack(&SNL_local_pool);
00707 Build_Doloop_Stack(LWN_Get_Parent(newdo), &dostack);
00708 LNO_Build_Access(newdo, &dostack, &LNO_default_pool);
00709
00710
00711
00712 for (i = imperfect; i > loopd; i--) {
00713 WN* the_do = newdos[i-loopd-1];
00714 DOLOOP_STACK stk(&SNL_local_pool);
00715 Build_Doloop_Stack(LWN_Get_Parent(the_do), &stk);
00716 DO_LOOP_INFO* dli = Get_Do_Loop_Info(the_do);
00717 DO_LOOP_INFO* olddli = Get_Do_Loop_Info(stack->Bottom_nth(i));
00718 dli->Set_Est_Num_Iterations(&stk);
00719 dli->Is_Ivdep = olddli->Is_Ivdep;
00720 dli->Depth = i - 1;
00721 }
00722
00723
00724
00725
00726
00727
00728 for (LWN_ITER* iter = LWN_WALK_TreeIter(newdo);
00729 iter;
00730 iter = LWN_WALK_TreeNext(iter)) {
00731
00732 WN* wn = iter->wn;
00733 OPCODE opc = WN_opcode(wn);
00734 OPERATOR opr = OPCODE_operator(opc);
00735
00736
00737
00738
00739 if (opr == OPR_LDID) {
00740 SYMBOL s(wn);
00741 INT i;
00742 for (i = 0; i < imperfect - loopd; i++) {
00743 if (newsyms[i] == s) {
00744 LWN_Update_Def_Use_Delete_Tree(wn, du);
00745 SNL_Add_Du_To_Index_Ldid(newdos[i], wn, du, TRUE);
00746 break;
00747 }
00748 }
00749 if (du->Ud_Get_Def(wn) != NULL) {
00750 WN* loop_stmt = du->Ud_Get_Def(wn)->Loop_stmt();
00751 for (i = 0; i < imperfect - loopd; i++) {
00752 WN* loop = stack->Bottom_nth(i+loopd);
00753 if (loop_stmt == loop) {
00754 du->Ud_Get_Def(wn)->Set_loop_stmt(newdos[i]);
00755 SNL_DEBUG2(3, "SNL_Distribute: loop_stmt(0x%p)->0x%p",
00756 loop_stmt, newdos[i]);
00757 }
00758 }
00759 }
00760 }
00761
00762
00763
00764 if (!OPCODE_is_load(opc) && !OPCODE_is_store(opc) && !OPCODE_is_call(opc))
00765 continue;
00766
00767 VINDEX16 v = dg->Get_Vertex(wn);
00768 if (v == 0) {
00769 FmtAssert(opr == OPR_LDID || opr == OPR_STID,
00770 ("How can we distribute with missing dependence data?"));
00771 continue;
00772 }
00773
00774
00775 for (INT do_out = 0; do_out <= 1; do_out++) {
00776
00777 for (EINDEX16 e = do_out ? dg->Get_Out_Edge(v) : dg->Get_In_Edge(v);
00778 e != 0;
00779 e = do_out ? dg->Get_Next_Out_Edge(e) : dg->Get_Next_In_Edge(e)) {
00780 VINDEX16 v2 = do_out ? dg->Get_Sink(e) : dg->Get_Source(e);
00781 FmtAssert(v == (do_out ? dg->Get_Source(e) : dg->Get_Sink(e)),
00782 ("Bad sink on in list"));
00783
00784 WN *wn;
00785 for (wn = dg->Get_Wn(v2); wn; wn = LWN_Get_Parent(wn))
00786 if (wn == wn_outer)
00787 break;
00788
00789 if (wn) {
00790
00791
00792 DEPV_ARRAY* dv = dg->Depv_Array(e);
00793 INT max_depvector_length = loopd - dv->Num_Unused_Dim();
00794 INT new_num_vec = 0;
00795
00796 if (max_depvector_length <= 0) {
00797 dg->Delete_Array_Edge(e);
00798 }
00799 else if (dv->Num_Dim() > max_depvector_length) {
00800 DEPV_ARRAY* dvnew = Create_DEPV_ARRAY(dv->Num_Vec(),
00801 max_depvector_length,
00802 dv->Num_Unused_Dim(),
00803 dg->Pool());
00804 for (INT d = 0; d < dv->Num_Vec(); d++)
00805 for (INT i = 0; i < max_depvector_length; i++)
00806 DEPV_Dep(dvnew->Depv(d), i) = DEPV_Dep(dv->Depv(d), i);
00807 Delete_DEPV_ARRAY(dv, dg->Pool());
00808 dg->Set_Depv_Array(e, dvnew);
00809 }
00810 }
00811 }
00812 }
00813 }
00814
00815 FmtAssert(newdo, ("SNL_Distribute: where's the loop??"));
00816 Renumber_Loops(newdo, newdo, dg);
00817 return newdo;
00818 }
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842 extern BOOL SNL_Permutation_Is_Distributable(WN* wn_outer,
00843 INT permutation[],
00844 INT nloops)
00845 {
00846 DOLOOP_STACK stack(&LNO_local_pool);
00847 WN* wn_inner = SNL_Get_Inner_Snl_Loop(wn_outer, nloops);
00848 Build_Doloop_Stack(wn_inner, &stack);
00849 INT outer_index = Do_Loop_Depth(wn_outer);
00850 INT last = -1;
00851 for (INT first = 0; first < nloops; first = last + 1) {
00852 last = Permutation_Last(first, permutation, nloops);
00853 if (first == last) {
00854 WN* wn_loop = stack.Bottom_nth(outer_index + first);
00855 DO_LOOP_INFO* dli = Get_Do_Loop_Info(wn_loop);
00856 if (dli->Has_Exits)
00857 return FALSE;
00858 continue;
00859 }
00860 WN* wn_local_outer = stack.Bottom_nth(outer_index + first);
00861 WN* wn_local_inner = stack.Bottom_nth(outer_index + last);
00862 for (INT i = first; i <= last; i++) {
00863 WN* wn_loop = stack.Bottom_nth(outer_index + i);
00864 DO_LOOP_INFO* dli = Get_Do_Loop_Info(wn_loop);
00865 if (dli->Has_Gotos || dli->Has_Gotos_This_Level || dli->Has_Exits)
00866 return FALSE;
00867 }
00868 INT local_nloops = Do_Loop_Depth(wn_local_inner)
00869 - Do_Loop_Depth(wn_local_outer) + 1;
00870 if (!SNL_Is_Distributable(wn_local_outer, local_nloops))
00871 return FALSE;
00872 }
00873 return TRUE;
00874 }
00875
00876
00877
00878
00879
00880
00881
00882 static BOOL SNL_Has_Sandwiched_Code(WN* wn_outer,
00883 WN* wn_inner)
00884 {
00885 WN* wnn = NULL;
00886 for (WN* wn = wn_inner; wn != wn_outer; wn = wnn) {
00887 if (WN_prev_executable(wn) != NULL || WN_next_executable(wn) != NULL)
00888 return TRUE;
00889 wnn = LWN_Get_Parent(wn);
00890 FmtAssert(WN_opcode(wnn) == OPC_BLOCK, ("Did not find block"));
00891 wnn = LWN_Get_Parent(wnn);
00892 if (WN_opcode(wnn) != OPC_DO_LOOP)
00893 return TRUE;
00894 }
00895 return FALSE;
00896 }
00897
00898
00899
00900
00901
00902
00903
00904
00905 extern BOOL SNL_Permutation_Needs_Distribution(WN* wn_outer,
00906 INT permutation[],
00907 INT nloops)
00908 {
00909 DOLOOP_STACK stack(&LNO_local_pool);
00910 WN* wn_inner = SNL_Get_Inner_Snl_Loop(wn_outer, nloops);
00911 Build_Doloop_Stack(wn_inner, &stack);
00912 INT outer_index = Do_Loop_Depth(wn_outer);
00913 INT last = -1;
00914 for (INT first = 0; first < nloops; first = last + 1) {
00915 last = Permutation_Last(first, permutation, nloops);
00916 if (first == last)
00917 continue;
00918 WN* wn_local_outer = stack.Bottom_nth(outer_index + first);
00919 WN* wn_local_inner = stack.Bottom_nth(outer_index + last);
00920 if (SNL_Has_Sandwiched_Code(wn_local_outer, wn_local_inner))
00921 return TRUE;
00922 }
00923 return FALSE;
00924 }
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952 extern void SNL_Distribute_For_Permutation(WN* wn_outer,
00953 WN* wn_inner,
00954 INT permutation[],
00955 INT nloops,
00956 DOLOOP_STACK* new_stack)
00957 {
00958 if (nloops == 0)
00959 return;
00960 DOLOOP_STACK stack(&LNO_local_pool);
00961 Build_Doloop_Stack(wn_inner, &stack);
00962 INT last = -1;
00963 INT outer_index = Do_Loop_Depth(wn_outer);
00964 for (INT first = 0; first < nloops; first = last + 1) {
00965 last = Permutation_Last(first, permutation, nloops);
00966 INT first_depth = outer_index + first;
00967 INT last_depth = outer_index + last;
00968 WN* wn_new_above = SNL_Distribute(&stack, last_depth, first_depth, TRUE);
00969 if (new_stack != NULL && wn_new_above != NULL
00970 && stack.Bottom_nth(first_depth) != wn_new_above)
00971 new_stack->Push(wn_new_above);
00972 WN* wn_new_below = SNL_Distribute(&stack, last_depth, first_depth, FALSE);
00973 if (new_stack != NULL && wn_new_below != NULL
00974 && stack.Bottom_nth(first_depth) != wn_new_below)
00975 new_stack->Push(wn_new_below);
00976 }
00977 }
00978
00979
00980
00981
00982
00983
00984
00985
00986 extern void SNL_Distribute_By_Splitting(WN* wn_outer,
00987 WN* wn_inner,
00988 INT nloops,
00989 INT split_depth,
00990 DOLOOP_STACK* stack)
00991 {
00992 if (wn_outer == NULL || nloops == 0)
00993 return;
00994 INT outer_depth = Do_Loop_Depth(wn_outer);
00995 if (split_depth == -1 || split_depth == outer_depth)
00996 return;
00997 DOLOOP_STACK local_stack(&LNO_local_pool);
00998 Build_Doloop_Stack(wn_inner, &local_stack);
00999 WN* wn_new = SNL_Distribute(&local_stack, split_depth, outer_depth, TRUE);
01000 if (wn_new != NULL)
01001 stack->Push(wn_new);
01002 wn_new = SNL_Distribute(&local_stack, split_depth, outer_depth, FALSE);
01003 if (wn_new != NULL)
01004 stack->Push(wn_new);
01005 }
01006
01007
01008
01009
01010
01011
01012
01013
01014 extern BOOL SNL_Is_Distributable(WN* wn_outer,
01015 INT nloops)
01016 {
01017 WN* wn_inner = SNL_Get_Inner_Snl_Loop(wn_outer, nloops);
01018 DOLOOP_STACK stack(&LNO_local_pool);
01019 Build_Doloop_Stack(wn_inner, &stack);
01020 INT depth_inner = Do_Loop_Depth(wn_outer) + nloops - 1;
01021 for (INT i = 2; i <= nloops; i++) {
01022 INT d = depth_inner + 1 - i;
01023 WN* wn_dist = stack.Bottom_nth(d);
01024 INT dd;
01025 for (dd = d + 1; dd <= depth_inner; dd++) {
01026 WN* wn_outer = stack.Bottom_nth(dd - 1);
01027 WN* wn_inner = stack.Bottom_nth(dd);
01028 if (WN_prev_executable(wn_inner)
01029 && !SNL_Is_Distributable(wn_dist, wn_outer, wn_inner, TRUE))
01030 return FALSE;
01031 }
01032 for (dd = d + 1; dd <= depth_inner; dd++) {
01033 WN* wn_outer = stack.Bottom_nth(dd - 1);
01034 WN* wn_inner = stack.Bottom_nth(dd);
01035 if (WN_next_executable(wn_inner)
01036 && !SNL_Is_Distributable(wn_dist, wn_outer, wn_inner, FALSE))
01037 return FALSE;
01038 }
01039 }
01040 return TRUE;
01041 }