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
00054 #ifdef USE_PCH
00055 #include "lno_pch.h"
00056 #endif // USE_PCH
00057 #pragma hdrstop
00058
00059 #define snl_nest_CXX "snl_nest.cxx"
00060 const static char *rcs_id = snl_nest_CXX "$Revision$";
00061
00062 #include <sys/types.h>
00063 #include "fiz_fuse.h"
00064 #include "lwn_util.h"
00065 #include "dep_graph.h"
00066 #include "snl.h"
00067 #include "snl_nest.h"
00068 #include "snl_xbounds.h"
00069 #include "scalar_expand.h"
00070 #include "wn_simp.h"
00071 #include "lnoutils.h"
00072
00073
00074
00075
00076
00077 void SNL_NEST_INFO::Print(FILE* f) const
00078 {
00079 fprintf(f, "Nest Info Begin\n");
00080 fprintf(f, "\t_nloops=%d _nloops_invariant=%d _nloops_general=%d\n",
00081 _nloops, _nloops_invariant, _nloops_general);
00082 fprintf(f, "\t_above_is_distributable=%d _below_is_distributable=%d\n",
00083 _above_is_distributable, _below_is_distributable);
00084 fprintf(f, "\tLoops:");
00085 for (INT i = _depth_inner - _nloops + 1; i <= _depth_inner; i++) {
00086 fprintf(f, " ");
00087 (SYMBOL(WN_index(Dostack().Bottom_nth(i)))).Print(f);
00088 }
00089 fprintf(f, "\n");
00090 if (_bi)
00091 _bi->Print(f);
00092 _privatizability_info.Print(f);
00093 fprintf(f, "Nest Info End\n");
00094 }
00095
00096 SNL_NEST_INFO::~SNL_NEST_INFO()
00097 {
00098 if (_bi)
00099 CXX_DELETE(_bi, _pool);
00100 }
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129 static BOOL SNL_Is_Transformable(WN* wn, INT outer_depth, DO_LOOP_INFO* dli)
00130 {
00131 FmtAssert(WN_opcode(wn) == OPC_DO_LOOP, ("is_transformable requires DO"));
00132
00133 SYMBOL index_symbol = SYMBOL(WN_index(wn));
00134 const INT index_name_sz = 128;
00135 char index_name[index_name_sz];
00136 index_symbol.Name(index_name, index_name_sz);
00137
00138 if (!Upper_Bound_Standardize(WN_end(wn), TRUE))
00139 return FALSE;
00140
00141
00142
00143
00144
00145 BOOL live_at_entry = Index_Variable_Live_At_Entry(wn);
00146 BOOL live_at_exit = Index_Variable_Live_At_Exit(wn);
00147
00148 if (!live_at_entry && live_at_exit) {
00149 Finalize_Index_Variable(wn, TRUE);
00150 index_symbol = SYMBOL(WN_index(wn));
00151 index_symbol.Name(index_name, index_name_sz);
00152 }
00153
00154 if (live_at_entry) {
00155 SNL_DEBUG2(3, "Loop %s(0x%p) not transformable: live on entry/exit",
00156 index_name, wn);
00157 return FALSE;
00158 }
00159
00160 if (Step_Size(wn) != 1) {
00161 SNL_DEBUG1(2, "Index %s has non-unit step", index_name);
00162 return FALSE;
00163 }
00164
00165 if (!SNL_Is_Non_Varying_Access_Array(dli->LB, outer_depth)) {
00166 SNL_DEBUG1(3, "Loop %s not transformable: varying bound lb", index_name);
00167 return FALSE;
00168 }
00169 if (!SNL_Is_Non_Varying_Access_Array(dli->UB, outer_depth)) {
00170 SNL_DEBUG1(3, "Loop %s not transformable: varying bound ub", index_name);
00171 return FALSE;
00172 }
00173
00174 if (WN_start(wn) == NULL ||
00175 WN_operator(WN_start(wn)) != OPR_STID ||
00176 SYMBOL(WN_start(wn)) != index_symbol) {
00177 FmtAssert(0, ("Loop %s has bad lower bound", index_name));
00178 return FALSE;
00179 }
00180
00181 if (WN_end(wn) == NULL) {
00182 FmtAssert(0, ("Loop %s (0x%p) has missing upper bound", index_name, wn));
00183 }
00184
00185 if (Mono(SNL_UBexp(WN_end(wn)), index_symbol) != SNL_MONO_INVARIANT ||
00186 WN_operator(SNL_UBvar(WN_end(wn))) != OPR_LDID ||
00187 SYMBOL(SNL_UBvar(WN_end(wn))) != index_symbol) {
00188 DevWarn("Loop %s (0x%p) has surprising form for upper bound",
00189 index_name, wn);
00190 return FALSE;
00191 }
00192
00193 switch (Do_Wtype(wn)) {
00194 case MTYPE_I8:
00195 case MTYPE_I4:
00196 case MTYPE_U8:
00197 case MTYPE_U4:
00198 break;
00199 case MTYPE_I2:
00200 case MTYPE_I1:
00201 case MTYPE_U2:
00202 case MTYPE_U1:
00203
00204
00205 DevWarn("Not transforming loop because index type too short: lame");
00206 return FALSE;
00207 default:
00208 Is_True(0, ("Loop %s of non-integral type %d", index_name, Do_Wtype(wn)));
00209 return FALSE;
00210 }
00211
00212 return TRUE;
00213 }
00214
00215 SNL_NEST_INFO::SNL_NEST_INFO(WN* outer, INT nloops, MEM_POOL* pool,
00216 BOOL inner_only)
00217 : _nloops(0),
00218 _bi(0),
00219 _pool(pool),
00220 _dostack(pool),
00221 _num_bad(0),
00222 _above_is_distributable(TRUE),
00223 _below_is_distributable(TRUE),
00224 _nloops_general(0),
00225 _nloops_invariant(0),
00226 _depth_inner(0),
00227 _privatizability_info(pool),
00228 _problem(NULL)
00229 {
00230 FmtAssert(nloops <= SNL_MAX_LOOPS,
00231 ("SNL_NEST_INFO constructor: nloops %d > %d",
00232 nloops, SNL_MAX_LOOPS));
00233 FmtAssert(pool != &SNL_local_pool, ("Bad pool for SNL_NEST_INFO()"));
00234
00235 MEM_POOL_Push(&SNL_local_pool);
00236
00237 if (nloops == 0 || nloops == 1)
00238 goto return_point;
00239
00240 {
00241 WN* inner = SNL_Get_Inner_Snl_Loop(outer, nloops);
00242 Build_Doloop_Stack(inner, &_dostack);
00243 _innermost = Get_Do_Loop_Info(inner)->Is_Inner;
00244
00245 _depth_inner = Dostack().Elements() - 1;
00246 _num_bad = _depth_inner - Good_Do_Depth(inner);
00247 _nloops = nloops;
00248
00249 if (inner_only && !_innermost)
00250 goto return_point;
00251
00252 {
00253 DO_LOOP_INFO* dli[LNO_MAX_DO_LOOP_DEPTH];
00254 for (INT d = Dostack().Elements() - 1; d >= 0; d--)
00255 dli[d] = Get_Do_Loop_Info(Dostack().Bottom_nth(d));
00256
00257
00258
00259
00260
00261 FmtAssert(nloops == Do_Loop_Depth(inner) - Do_Loop_Depth(outer) + 1,
00262 ("outer, inner, and nloops not consistent"));
00263 _privatizability_info.Make_Sx_Info(outer, nloops);
00264 _problem = CXX_NEW_ARRAY(SNL_LOOP_PROBLEM_INFO, _depth_inner+1, pool);
00265 INT ii;
00266 for (ii = 0; ii <= _depth_inner; ii++)
00267 _problem[ii] = SNL_LOOP_PROBLEM_INFO(SNL_LOOP_PROBLEM_NONE);
00268
00269
00270
00271
00272 const SX_PNODE* pnode = NULL;
00273 INT outer_scalar_loop =
00274 Privatizability_Info().First_Transformable_Depth( &pnode);
00275 INT i;
00276 for (i = 0; i < _nloops; i++) {
00277 INT d = _depth_inner - i;
00278 if (d < outer_scalar_loop)
00279 break;
00280 }
00281 for (ii = i; ii < _nloops; ii++) {
00282 INT d = _depth_inner - ii;
00283 _problem[d] = SNL_LOOP_PROBLEM_INFO(SNL_LOOP_PROBLEM_SCALAR);
00284 }
00285
00286 for (ii = 0; ii < i; ii++) {
00287 INT d = _depth_inner - ii;
00288 if (!SNL_Is_Transformable(Dostack().Bottom_nth(d),
00289 _depth_inner - _nloops + 1, dli[d]))
00290 break;
00291 }
00292 _nloops_general = ii;
00293 _nloops_invariant = ii;
00294
00295
00296 for (i = 2; i <= _nloops_invariant; i++) {
00297 INT d = _depth_inner + 1 - i;
00298
00299 INT dd;
00300 for (dd = d + 1; dd <= _depth_inner; dd++) {
00301 if (!SNL_Is_Invariant(&Dostack(), d, dd))
00302 break;
00303 }
00304 if (dd <= _depth_inner)
00305 break;
00306 }
00307
00308
00309 _nloops_invariant = i - 1;
00310
00311
00312
00313
00314
00315
00316 _above_is_distributable = TRUE;
00317 _below_is_distributable = TRUE;
00318
00319 INT _nloops_max = _nloops_general > _nloops_invariant
00320 ? _nloops_general : _nloops_invariant;
00321 for (i = 2; i <= _nloops_max; i++) {
00322 INT d = _depth_inner + 1 - i;
00323 WN* wnd = Dostack().Bottom_nth(d);
00324 BOOL above_ok = _above_is_distributable;
00325 INT dd;
00326 for (dd = d+1; above_ok && dd <= _depth_inner; dd++) {
00327 WN* wn1 = Dostack().Bottom_nth(dd-1);
00328 WN* wn = Dostack().Bottom_nth(dd);
00329 if (WN_prev_executable(wn) &&
00330 !SNL_Is_Distributable(wnd, wn1, wn, TRUE))
00331 above_ok = FALSE;
00332 }
00333
00334 BOOL below_ok = _below_is_distributable;
00335 for (dd = d+1; below_ok && dd <= _depth_inner; dd++) {
00336 WN* wn1 = Dostack().Bottom_nth(dd-1);
00337 WN* wn = Dostack().Bottom_nth(dd);
00338 if (WN_next_executable(wn) &&
00339 !SNL_Is_Distributable(wnd,wn1, wn, FALSE))
00340 below_ok = FALSE;
00341 }
00342
00343 if (above_ok == FALSE || below_ok == FALSE) {
00344 if (_nloops_invariant >= i)
00345 _nloops_invariant = i - 1;
00346
00347 if (i <= _nloops_general) {
00348 if (above_ok == FALSE && below_ok == FALSE) {
00349 _nloops_general = i - 1;
00350 if (_nloops_general < _nloops_invariant)
00351 _problem[_depth_inner - i + 1] =
00352 SNL_LOOP_PROBLEM_INFO(SNL_LOOP_PROBLEM_DISTRIBUTION);
00353 break;
00354 }
00355 else if (above_ok == FALSE)
00356 _above_is_distributable = FALSE;
00357 else
00358 _below_is_distributable = FALSE;
00359 }
00360 }
00361 }
00362
00363 if (_nloops_general < 2)
00364
00365 ;
00366 else if (_above_is_distributable && _below_is_distributable) {
00367
00368
00369
00370 INT outer_depth = _depth_inner + 1 - _nloops_general;
00371
00372 _bi = CXX_NEW(SNL_BOUNDS_INFO(Pool()), Pool());
00373 _bi->Outermost_Depth() = outer_depth;
00374 for (INT d = outer_depth; d <= _depth_inner; d++)
00375 _bi->Collect_Do_Info(Dostack().Bottom_nth(d));
00376 _bi->Conditionals().Add_Vars(_bi->Bounds().Num_Vars() -
00377 _bi->Conditionals().Num_Vars());
00378 _bi->Canonicize(_nloops_general, &Dostack(), outer_depth);
00379 }
00380 else {
00381 while (1) {
00382 try_while_again:
00383 INT inner_depth = _depth_inner;
00384 INT outer_depth = _depth_inner + 1 - _nloops_general;
00385 WN* outer = Dostack().Bottom_nth(outer_depth);
00386
00387
00388 INT i;
00389 for (i = _nloops_general - 2; i >= 0; i--) {
00390 INT d = _depth_inner - i;
00391 WN* wnd = Dostack().Bottom_nth(d);
00392 if ((!_above_is_distributable && WN_prev_executable(wnd)) ||
00393 (!_below_is_distributable && WN_next_executable(wnd)))
00394 break;
00395 }
00396
00397
00398 if (i == -1) {
00399 _above_is_distributable = _below_is_distributable = TRUE;
00400 outer_depth = _depth_inner + 1 - _nloops_general;
00401 _bi = CXX_NEW(SNL_BOUNDS_INFO(Pool()), Pool());
00402 _bi->Outermost_Depth() = outer_depth;
00403 for (INT d = outer_depth; d <= _depth_inner; d++)
00404 _bi->Collect_Do_Info(Dostack().Bottom_nth(d));
00405 _bi->Conditionals().Add_Vars(_bi->Bounds().Num_Vars() -
00406 _bi->Conditionals().Num_Vars());
00407 _bi->Canonicize(_nloops_general, &Dostack(), outer_depth);
00408 break;
00409 }
00410 else if (_nloops_general < 2)
00411 break;
00412
00413 SNL_BOUNDS_INFO ebounds(&SNL_local_pool);
00414 ebounds.Outermost_Depth() = outer_depth;
00415 ebounds.Collect_Outer_Info(outer);
00416
00417 for (INT d = outer_depth; d <= inner_depth; d++) {
00418
00419
00420
00421
00422
00423
00424
00425 WN* wn = Dostack().Bottom_nth(d);
00426
00427 for (INT dimlb = 0; dimlb < dli[d]->LB->Num_Vec(); dimlb++) {
00428 ACCESS_VECTOR* avlb = dli[d]->LB->Dim(dimlb);
00429 for(INT dimub = 0; dimub < dli[d]->UB->Num_Vec(); dimub++) {
00430 ACCESS_VECTOR* avub = dli[d]->UB->Dim(dimub);
00431 ACCESS_VECTOR* nox = Difference_Inequality(avlb, avub, d,
00432 DIFFERENCE_EXEC_NEVER,
00433 &SNL_local_pool);
00434
00435 ACCESS_VECTOR* yesx = Difference_Inequality(avlb, avub, d,
00436 DIFFERENCE_EXEC_ALWAYS,
00437 &SNL_local_pool);
00438
00439 ebounds.Add_Access(nox, FALSE);
00440 BOOL is_consistent = ebounds.Bounds().Is_Consistent();
00441 ebounds.Bounds().Remove_Last_Le(1);
00442 if (!is_consistent)
00443 continue;
00444
00445
00446
00447
00448
00449 BOOL is_const = TRUE;
00450 for (INT dd = outer_depth; dd < d; dd++) {
00451 if (nox->Loop_Coeff(dd))
00452 is_const = FALSE;
00453 }
00454
00455 if (is_const == FALSE) {
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470 BOOL peeled=0;
00471
00472
00473
00474 if (d == outer_depth + 1 &&
00475 dli[outer_depth]->UB->Num_Vec() == 1 &&
00476 dli[d]->LB->Num_Vec() == 1 &&
00477 dli[d]->UB->Num_Vec() == 1 &&
00478 dli[outer_depth]->UB->Dim(0)->Loop_Coeff(outer_depth)
00479 ==1){
00480
00481 ACCESS_VECTOR* ub = dli[outer_depth]->UB->Dim(0);
00482
00483
00484
00485
00486
00487
00488
00489 ACCESS_VECTOR last_iter(ub, &SNL_local_pool);
00490 last_iter.Negate_Me();
00491 ebounds.Add_Access(&last_iter, FALSE);
00492 ebounds.Add_Access(yesx, FALSE);
00493 is_consistent = ebounds.Bounds().Is_Consistent();
00494 ebounds.Bounds().Remove_Last_Le(2);
00495
00496 if (!is_consistent) {
00497
00498
00499
00500
00501
00502 ACCESS_VECTOR ub2(ub, &SNL_local_pool);
00503 ub2.Const_Offset--;
00504 ebounds.Add_Access(&ub2, FALSE);
00505 ebounds.Add_Access(nox, FALSE);
00506 is_consistent = ebounds.Bounds().Is_Consistent();
00507 ebounds.Bounds().Remove_Last_Le(1);
00508 if (!is_consistent)
00509 peeled = 2;
00510 else
00511 ebounds.Bounds().Remove_Last_Le(1);
00512 }
00513 }
00514
00515
00516
00517 if (peeled == 0 &&
00518 d == outer_depth + 1 &&
00519 dli[outer_depth]->LB->Num_Vec() == 1 &&
00520 dli[d]->LB->Num_Vec() == 1 &&
00521 dli[d]->UB->Num_Vec() == 1 &&
00522 dli[outer_depth]->LB->Dim(0)->Loop_Coeff(outer_depth)
00523 == 1) {
00524
00525 ACCESS_VECTOR* lb = dli[outer_depth]->LB->Dim(0);
00526
00527
00528
00529
00530
00531
00532
00533 ACCESS_VECTOR first_iter(lb, &SNL_local_pool);
00534 first_iter.Negate_Me();
00535 ebounds.Add_Access(&first_iter, FALSE);
00536 ebounds.Add_Access(yesx, FALSE);
00537 is_consistent = ebounds.Bounds().Is_Consistent();
00538 ebounds.Bounds().Remove_Last_Le(2);
00539
00540 if (!is_consistent) {
00541
00542
00543
00544
00545
00546 ACCESS_VECTOR lb2(lb, &SNL_local_pool);
00547 lb2.Const_Offset--;
00548 ebounds.Add_Access(&lb2, FALSE);
00549 ebounds.Add_Access(nox, FALSE);
00550 is_consistent = ebounds.Bounds().Is_Consistent();
00551 ebounds.Bounds().Remove_Last_Le(1);
00552 if (!is_consistent)
00553 peeled = 1;
00554 else
00555 ebounds.Bounds().Remove_Last_Le(1);
00556 }
00557 }
00558
00559 if (peeled) {
00560 WN* peel_wn = Dostack().Bottom_nth(outer_depth);
00561 SNL_DEBUG1(1, "Peeling last iteration of %s",
00562 SYMBOL(WN_index(peel_wn)).Name());
00563 SNL_Peel_Iteration(peel_wn, peeled==1);
00564 continue;
00565 }
00566
00567 _problem[_depth_inner - _nloops_general + 1] =
00568 SNL_LOOP_PROBLEM_INFO(
00569 SNL_LOOP_PROBLEM_INNER_MIGHT_NOT_GO);
00570 SNL_DEBUG1(1, "Not enough iterations to use loop %s",
00571 SYMBOL(WN_index(wn)).Name());
00572 _nloops_general--;
00573 goto try_while_again;
00574 }
00575
00576
00577
00578
00579 ebounds.Add_Access(yesx, TRUE);
00580
00581 if (snl_debug >= 2) {
00582 SNL_DEBUG0(2, "Added in a conditional: ");
00583 ebounds.Print(TFile);
00584 }
00585 }
00586 }
00587
00588 ebounds.Collect_Do_Info(wn);
00589 ebounds.Conditionals().Add_Vars(ebounds.Bounds().Num_Vars() -
00590 ebounds.Conditionals().Num_Vars());
00591
00592 if (!ebounds.Bounds().Is_Consistent()) {
00593 SNL_DEBUG1(0, "Loop %s appears to never execute.",
00594 SYMBOL(WN_index(wn)).Name());
00595 _problem[_depth_inner - _nloops_general + 1] =
00596 SNL_LOOP_PROBLEM_INFO(SNL_LOOP_PROBLEM_INNER_DOES_NOT_GO);
00597 _nloops_general--;
00598 goto try_while_again;
00599 }
00600 }
00601
00602
00603
00604 FmtAssert(_bi==NULL,
00605 ("Confusion in SNL_NEST_INFO::SNL_NEST_INFO()"));
00606 _bi = CXX_NEW(SNL_BOUNDS_INFO(&ebounds, Pool()), Pool());
00607
00608 _bi->Canonicize(_nloops_general, &Dostack(),
00609 _depth_inner + 1 - _nloops_general);
00610 break;
00611 }
00612 }
00613
00614 }
00615 }
00616 return_point:
00617 MEM_POOL_Pop(&SNL_local_pool);
00618
00619 if (snl_debug >= 3) {
00620 fprintf(TFile, "Nest info creation:\n");
00621 Print(TFile);
00622 }
00623 }
00624
00625 void SNL_NEST_INFO::Exclude_Outer_Loops(INT how_many)
00626 {
00627 FmtAssert(how_many > 0, ("Bad call to Exclude_Outer_Loops(INT)"));
00628
00629 _nloops -= how_many;
00630 _nloops_invariant = MIN(_nloops, _nloops_invariant);
00631 FmtAssert(_nloops >= 1, ("Too many loops being excluded"));
00632
00633 if (_nloops_general > _nloops) {
00634 if (_bi)
00635 _bi->Exclude_Outer_Loops(_nloops_general - _nloops);
00636 _nloops_general = _nloops;
00637 }
00638 if (_nloops_general == _nloops_invariant) {
00639 _above_is_distributable = TRUE;
00640 _below_is_distributable = TRUE;
00641 }
00642 }
00643