00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 #define __STDC_LIMIT_MACROS
00043 #include <stdint.h>
00044 #ifdef USE_PCH
00045 #include "lno_pch.h"
00046 #endif // USE_PCH
00047 #pragma hdrstop
00048
00049 #define snl_utils_CXX "snl_utils.cxx"
00050 const static char *rcs_id = snl_utils_CXX "$Revision: 1.5 $";
00051
00052 #include <sys/types.h>
00053 #include "snl.h"
00054 #include "lwn_util.h"
00055 #include "dep_graph.h"
00056
00057
00058
00059
00060
00061 void Print(FILE* f, const SNL_DEP_INFO_BAD_DEPS& bad_deps)
00062 {
00063 for (INT i = bad_deps.Lastidx(); i >= 0; i--) {
00064 fprintf(f, "<e=%d,loop=%d>", bad_deps[i].e, bad_deps[i].loop);
00065 }
00066 }
00067
00068
00069
00070
00071
00072 SNL_DEP operator * (INT a, const SNL_DEP& d)
00073 {
00074 SNL_DEP dd;
00075 dd.Distance = a * d.Distance;
00076 if (a == 0 || d.Moreless == SNL_DEP::SNL_DEP_EXACT)
00077 dd.Moreless = SNL_DEP::SNL_DEP_EXACT;
00078 else if (a > 0)
00079 dd.Moreless = d.Moreless;
00080 else {
00081 switch (d.Moreless) {
00082 case SNL_DEP::SNL_DEP_PLUS:
00083 dd.Moreless = SNL_DEP::SNL_DEP_MINUS;
00084 break;
00085 case SNL_DEP::SNL_DEP_MINUS:
00086 dd.Moreless = SNL_DEP::SNL_DEP_PLUS;
00087 break;
00088 case SNL_DEP::SNL_DEP_STAR:
00089 dd.Moreless = SNL_DEP::SNL_DEP_STAR;
00090 break;
00091 default:
00092 FmtAssert(0, ("Impossible"));
00093 }
00094 }
00095 return dd;
00096 }
00097
00098 SNL_DEP operator + (const SNL_DEP& d, const SNL_DEP& dd)
00099 {
00100 SNL_DEP ddd;
00101 ddd.Distance = d.Distance + dd.Distance;
00102 if (d.Moreless == SNL_DEP::SNL_DEP_EXACT || d.Moreless == dd.Moreless)
00103 ddd.Moreless = dd.Moreless;
00104 else if (dd.Moreless == SNL_DEP::SNL_DEP_EXACT)
00105 ddd.Moreless = d.Moreless;
00106 else
00107 ddd.Moreless = SNL_DEP::SNL_DEP_STAR;
00108 return ddd;
00109 }
00110
00111 void SNL_DEP::operator += (const SNL_DEP& d)
00112 {
00113 Distance += d.Distance;
00114 if (Moreless == SNL_DEP::SNL_DEP_EXACT || Moreless == d.Moreless)
00115 Moreless = d.Moreless;
00116 else if (d.Moreless == SNL_DEP::SNL_DEP_EXACT)
00117 ;
00118 else
00119 Moreless = SNL_DEP::SNL_DEP_STAR;
00120 }
00121
00122 DEP SNL_DEP::Dep() const
00123 {
00124 switch (Moreless) {
00125 case SNL_DEP_EXACT:
00126 return DEP_SetDistance(Distance);
00127 case SNL_DEP_PLUS:
00128 if (Distance == 0)
00129 return DEP_SetDirection(DIR_POSEQ);
00130 else if (Distance > 0)
00131 return DEP_SetDirection(DIR_POS);
00132 case SNL_DEP_MINUS:
00133 if (Distance == 0)
00134 return DEP_SetDirection(DIR_NEGEQ);
00135 else if (Distance < 0)
00136 return DEP_SetDirection(DIR_NEG);
00137 }
00138 return DEP_SetDirection(DIR_STAR);
00139 }
00140
00141 void SNL_DEP::Print(FILE* f) const
00142 {
00143 switch (Moreless) {
00144 case SNL_DEP_PLUS:
00145 fprintf(f, "%d+", Distance);
00146 break;
00147 case SNL_DEP_MINUS:
00148 fprintf(f, "%d-", Distance);
00149 break;
00150 case SNL_DEP_EXACT:
00151 fprintf(f, "%d", Distance);
00152 break;
00153 case SNL_DEP_STAR:
00154 fprintf(f, "*");
00155 break;
00156 }
00157 }
00158
00159 SNL_DEP::SNL_DEP(DEP d)
00160 {
00161 if (DEP_IsDistance(d)) {
00162 Distance = DEP_Distance(d); Moreless = SNL_DEP_EXACT;
00163 }
00164 else
00165 switch (DEP_Direction(d)) {
00166 case DIR_POS:
00167 Distance = 1; Moreless = SNL_DEP_PLUS; break;
00168 case DIR_NEG:
00169 Distance = -1; Moreless = SNL_DEP_MINUS; break;
00170 case DIR_POSEQ:
00171 Distance = 0; Moreless = SNL_DEP_PLUS; break;
00172 case DIR_NEGEQ:
00173 Distance = 0; Moreless = SNL_DEP_MINUS; break;
00174 case DIR_EQ:
00175 Is_True(0, ("Impossible"));
00176 default:
00177 Distance = 0; Moreless = SNL_DEP_STAR; break;
00178 }
00179 }
00180
00181
00182
00183
00184
00185 SNL_DEP_MATRIX::SNL_DEP_MATRIX(const SNL_DEP_INFO& info, MEM_POOL* pool)
00186 : _pool(pool),
00187 _ndep(info.Dv_List().Len()),
00188 _nloops(info.Nloops()),
00189 _deps(CXX_NEW_ARRAY(SNL_DEP, info.Dv_List().Len()*info.Nloops(), pool))
00190 {
00191 DEPV_CONST_ITER dit(&info.Dv_List());
00192 const DEPV_NODE* n;
00193 INT d = 0;
00194 for (n = dit.First(); !dit.Is_Empty(); n = dit.Next(), d++) {
00195 for (INT i = 0; i < _nloops; i++)
00196 (*this)(d,i) = SNL_DEP(DEPV_Dep(n->Depv,i));
00197 }
00198 }
00199
00200 SNL_DEP_MATRIX::SNL_DEP_MATRIX(const SNL_DEP_MATRIX* m, MEM_POOL* pool)
00201 : _pool(pool),
00202 _ndep(m->_ndep),
00203 _nloops(m->_nloops),
00204 _deps(CXX_NEW_ARRAY(SNL_DEP, m->_ndep*m->_nloops, pool))
00205 {
00206 for (INT d = 0; d < _ndep; d++)
00207 for (INT i = 0; i < _nloops; i++)
00208 (*this)(d,i) = (*m)(d,i);
00209 }
00210
00211 void SNL_DEP_MATRIX::Print(FILE* f) const
00212 {
00213 for (INT d = 0; d < _ndep; d++) {
00214 fprintf(f, "[");
00215 for (INT i = 0; i < _nloops; i++) {
00216 (*this)(d,i).Print(f);
00217 fprintf(f, "%s", i == _nloops - 1 ? "]" : " ");
00218 }
00219 }
00220 fprintf(f, "\n");
00221 }
00222
00223 BOOL SNL_DEP_MATRIX::Is_Legal() const
00224 {
00225 for (INT d = 0; d < _ndep; d++) {
00226 for (INT i = 0; i < _nloops; i++) {
00227 SNL_DEP dep = (*this)(d,i);
00228 if (dep.Unbounded_Min() || dep.Min() < 0)
00229 return FALSE;
00230 else if (dep.Min() > 0)
00231 break;
00232 }
00233 }
00234 return TRUE;
00235 }
00236
00237 void SNL_DEP_MATRIX::Apply(const IMAT& u, INT first)
00238 {
00239 FmtAssert(u.Rows() == u.Cols(), ("Bad u for Apply()"));
00240 FmtAssert(first + u.Rows() <= _nloops, ("Bad first for Apply()"));
00241 for (INT d = 0; d < Ndep(); d++) {
00242 SNL_DEP newd[SNL_MAX_LOOPS];
00243 INT i;
00244 for (i = 0; i < u.Rows(); i++) {
00245 for (INT j = 0; j < u.Rows(); j++)
00246 newd[i] += u(i,j) * (*this)(d,j+first);
00247 }
00248 for (i = 0 ; i < u.Rows(); i++)
00249 (*this)(d,i+first) = newd[i];
00250 }
00251 }
00252
00253 void SNL_DEP_MATRIX::Apply(const INT* permutation)
00254 {
00255 FmtAssert(_pool != &SNL_local_pool, ("Pool problem"));
00256
00257 MEM_POOL_Push_Freeze(&SNL_local_pool);
00258 {
00259 SNL_DEP_MATRIX tmp(this, &SNL_local_pool);
00260 for (INT d = 0; d < Ndep(); d++) {
00261 for (INT i = 0; i < Nloops(); i++)
00262 (*this)(d,i) = tmp(d,permutation[i]);
00263 }
00264 }
00265 MEM_POOL_Pop_Unfreeze(&SNL_local_pool);
00266 }
00267
00268
00269
00270 SNL_DEP_MATRIX::~SNL_DEP_MATRIX()
00271 {
00272 CXX_DELETE_ARRAY(_deps, _pool);
00273 }
00274
00275 BOOL SNL_DEP_MATRIX::Is_Fully_Permutable(INT from, INT to) const
00276 {
00277 if (!Is_Legal())
00278 return FALSE;
00279
00280 for (INT d = 0; d < Ndep(); d++) {
00281 INT i;
00282 for (i = 0; i < from; i++) {
00283 if ((*this)(d,i).Min() >= 1)
00284 break;
00285 }
00286
00287 if (i != from)
00288 continue;
00289
00290 for ( ; i <= to; i++) {
00291 if ((*this)(d,i).Unbounded_Min() || (*this)(d,i).Min() < 0)
00292 return FALSE;
00293 }
00294 }
00295
00296 return TRUE;
00297 }
00298
00299
00300
00301
00302
00303 SNL_DEP_INFO::SNL_DEP_INFO(INT firstc, INT nloops, INT num_unused_dim,
00304 const DOLOOP_STACK& stk, MEM_POOL* pool)
00305 : _first_component(firstc), _all_stars(FALSE), _nloops(nloops), _pool(pool),
00306 _dv_list(nloops, num_unused_dim, pool), _stack1(pool), _stack2(pool),
00307 _bad_deps(pool)
00308 {
00309 for (INT i = 0; i < nloops + firstc + num_unused_dim; i++) {
00310 _stack1.Push(stk.Bottom_nth(i));
00311 _stack2.Push(stk.Bottom_nth(i));
00312 }
00313 }
00314
00315 void SNL_DEP_INFO::Print(FILE* f) const
00316 {
00317 if (All_Stars())
00318 fprintf(f, "<all stars>\n");
00319 else {
00320 _dv_list.Print(f);
00321 fprintf(f, "\n");
00322 }
00323 fprintf(f, "bad_deps:");
00324 ::Print(f, _bad_deps);
00325 fprintf(f, "\n");
00326 }
00327
00328 void SNL_DEP_INFO::Enter(const DEPV_ARRAY* dv, EINDEX16 edge, BOOL parallel)
00329 {
00330 for (INT i = 0; i < dv->Num_Vec(); i++)
00331 Enter(dv->Depv(i), dv->Num_Dim(), edge, parallel);
00332 }
00333
00334 void SNL_DEP_INFO::Enter(const DEPV* dv, INT components, EINDEX16 edge,
00335 BOOL parallel)
00336 {
00337 FmtAssert(components >= Nloops() + First_Component(),
00338 ("Too short dependence vector for SNL_DEP_INFO::Enter()"));
00339
00340
00341
00342 if (!LNO_Analysis) {
00343 if (All_Stars())
00344 return;
00345 }
00346
00347
00348
00349
00350 INT d;
00351 for (d = 0; d < First_Component(); d++) {
00352 if (DEP_Direction(DEPV_Dep(dv,d)) == DIR_POS)
00353 return;
00354 }
00355
00356
00357
00358
00359 switch (DEP_Direction(DEPV_Dep(dv,First_Component()))) {
00360 case DIR_POS:
00361 if (!parallel) {
00362 for (d = 1; d < Nloops(); d++) {
00363 if (DEP_Direction(DEPV_Dep(dv,First_Component()+d)) != DIR_STAR)
00364 break;
00365 }
00366 if (d == Nloops()) {
00367 _all_stars = TRUE;
00368 INT entry = _bad_deps.Newidx();
00369 _bad_deps[entry].e = edge;
00370 _bad_deps[entry].loop = Nloops() - 1;
00371 return;
00372 }
00373 }
00374 break;
00375 case DIR_EQ:
00376 for (d = 1; d < Nloops(); d++) {
00377 if (DEP_Direction(DEPV_Dep(dv,First_Component()+d)) != DIR_EQ)
00378 break;
00379 }
00380 if (d == Nloops())
00381 return;
00382 break;
00383 }
00384
00385
00386
00387
00388
00389 if (LNO_Analysis) {
00390 INT negloop = -1;
00391 for (d = 0; d < Nloops(); d++) {
00392 if (DEP_Direction(DEPV_Dep(dv,First_Component()+d)) & DIR_NEG)
00393 negloop = d;
00394 }
00395 if (negloop >= 0) {
00396 INT entry = _bad_deps.Newidx();
00397 _bad_deps[entry].e = edge;
00398 _bad_deps[entry].loop = negloop;
00399 }
00400 }
00401
00402
00403
00404 if (All_Stars())
00405 return;
00406
00407
00408
00409 DEPV_ITER iter(&_dv_list);
00410 for (DEPV_NODE *n = iter.First(); !iter.Is_Empty(); n = iter.Next()) {
00411 INT d;
00412 for (d = 0; d < Nloops(); d++) {
00413 DEP d1 = DEPV_Dep(n->Depv,d);
00414 DEP d2 = DEPV_Dep(dv,First_Component()+d);
00415 if (DEP_IsDistance(d1)) {
00416 if (DEP_IsDistance(d2) && DEP_Distance(d1) == DEP_Distance(d2))
00417 continue;
00418 }
00419 else {
00420 if (!DEP_IsDistance(d2) && DEP_Direction(d1) == DEP_Direction(d2))
00421 continue;
00422 }
00423 break;
00424 }
00425 if (d == Nloops())
00426 return;
00427 }
00428
00429 DEPV* newdv = DEPV_Create(Pool(), Nloops());
00430 for (d = 0; d < Nloops(); d++)
00431 DEPV_Dep(newdv,d) = DEPV_Dep(dv,d+First_Component());
00432
00433 _dv_list.Append(CXX_NEW(DEPV_NODE(newdv), Pool()));
00434 }
00435
00436 IMAT* SNL_DEP_INFO::U_Fully_Permutable(INT from, INT to, MEM_POOL* pool) const
00437 {
00438 FmtAssert(pool != &SNL_local_pool, ("Pool problem"));
00439
00440 if (All_Stars())
00441 return NULL;
00442
00443 MEM_POOL_Push_Freeze(&SNL_local_pool);
00444
00445
00446
00447
00448 IMAT* m = CXX_NEW(IMAT(to-from+1, to-from+1, pool), pool);
00449 m->D_Identity();
00450
00451
00452
00453
00454 INT veccnt = Dv_List().Len();
00455 INT dcnt = to-from+1;
00456 INT* per_vector_info = CXX_NEW_ARRAY(INT, veccnt, &SNL_local_pool);
00457
00458 DEPV_CONST_ITER dit(&Dv_List());
00459 INT v = 0;
00460 INT vmax = 0;
00461 const DEPV_NODE* n = 0;
00462 for (n = dit.First(); !dit.Is_Empty(); n = dit.Next()) {
00463 INT d;
00464 for (d = 0; d < from; d++) {
00465 DEP d1 = DEPV_Dep(n->Depv,d);
00466 if (DEP_Direction(d1) == DIR_POS)
00467 break;
00468 }
00469
00470 per_vector_info[v++] = (d == from);
00471 if (d == from)
00472 vmax++;
00473 }
00474
00475 SNL_DEP* deps = CXX_NEW_ARRAY(SNL_DEP, vmax * dcnt, &SNL_local_pool);
00476 #define DP(i,j) (deps[(i) + (j)*(vmax)])
00477
00478 v = 0;
00479 INT vv = 0;
00480 for (n = dit.First(); !dit.Is_Empty(); n = dit.Next()) {
00481 if (per_vector_info[v++]) {
00482 for (INT d = from; d <= to; d++)
00483 DP(vv,d-from) = SNL_DEP(DEPV_Dep(n->Depv,d));
00484 vv++;
00485 }
00486 }
00487
00488 Is_True(vv == vmax, ("Bug in U_Fully_Permute"));
00489
00490
00491
00492 INT d;
00493 for (d = 0; d < dcnt; d++) {
00494 INT unbounded_max = 0;
00495 INT unbounded_min = 0;
00496 INT minneg = 0;
00497 INT maxpos = 0;
00498
00499 INT v;
00500 for (v = 0; v < vmax; v++) {
00501 SNL_DEP dep = DP(v,d);
00502 if (dep.Unbounded_Max())
00503 unbounded_max = 1;
00504 else if (dep.Max() > maxpos)
00505 maxpos = dep.Max();
00506 if (dep.Unbounded_Min())
00507 unbounded_min = 1;
00508 else if (dep.Min() < minneg)
00509 minneg = dep.Min();
00510 }
00511
00512 if (unbounded_max && unbounded_min)
00513 break;
00514
00515 if (unbounded_min) {
00516
00517
00518
00519 for (v = 0; v < vmax; v++)
00520 DP(v,d).Negate_Me();
00521
00522
00523
00524 #ifdef Is_True_On
00525 for (INT x = 0; x < dcnt; x++)
00526 Is_True((*m)(d,x) == (x==d), ("Confusion with matrix"));
00527 #endif
00528 (*m)(d,d) = -1;
00529
00530
00531
00532 unbounded_min = 0;
00533 unbounded_max = 1;
00534
00535 INT tmp = minneg;
00536 minneg = -maxpos;
00537 maxpos = -tmp;
00538 }
00539
00540
00541
00542 if (minneg == 0)
00543 continue;
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559 INT factors[SNL_MAX_LOOPS];
00560 INT dd;
00561 for(dd = 0; dd < d; dd++)
00562 factors[dd] = 0;
00563
00564 for (v = 0; v < vmax; v++) {
00565 INT mindist = DP(v,d).Min();
00566 if (mindist >= 0)
00567 continue;
00568
00569
00570
00571
00572
00573 INT ddpos = -1;
00574 INT ddposmin = 0;
00575
00576 per_vector_info[v] = 1;
00577 for (dd = 0; dd < d; dd++) {
00578 INT ddmin = DP(v,dd).Min();
00579 FmtAssert(ddmin >= 0, ("Make fully permutable bug"));
00580 if(ddmin > 0) {
00581 if(ddpos == -1) {
00582 ddpos = dd;
00583 ddposmin = ddmin;
00584 }
00585 else {
00586 ddpos = -2;
00587 per_vector_info[v] = 0;
00588 }
00589 }
00590 }
00591
00592 FmtAssert(ddpos != -1, ("Make fully permutable bug2"));
00593 if (ddpos != -2) {
00594 INT newfactor = (-mindist + ddposmin - 1)/ddposmin;
00595 if (newfactor > factors[ddpos])
00596 factors[ddpos] = newfactor;
00597 }
00598 }
00599
00600
00601
00602
00603
00604
00605 for (v = 0; v < vmax; v++) {
00606 if (per_vector_info[v])
00607 continue;
00608
00609 INT vdist = DP(v,d).Min();
00610 Is_True(vdist < 0, ("I'm confused"));
00611 INT ddpos = -1;
00612 INT ddposmin;
00613 for (INT dd = 0; dd < d; dd++) {
00614 INT ddmin = DP(v,dd).Min();
00615 FmtAssert(ddmin >= 0, ("Make fully permutable bug"));
00616 if(ddmin > 0) {
00617 ddpos = dd;
00618 ddposmin = ddmin;
00619 vdist += factors[dd] * ddmin;
00620 }
00621 Is_True(ddpos >= 0, ("I'm so confused"));
00622 if (vdist < 0)
00623 factors[ddpos] += (-vdist + ddposmin - 1)/ddposmin;
00624 }
00625 }
00626
00627 const INT maxskew = 3;
00628
00629
00630
00631 BOOL ok = TRUE;
00632 for (dd = 0; dd < d; dd++) {
00633 if (factors[dd] > maxskew) {
00634 ok = FALSE;
00635 break;
00636 }
00637 }
00638 if (!ok)
00639 break;
00640
00641 for (v = 0; v < vmax; v++) {
00642 INT dmin = DP(v,d).Min();
00643 INT d_isconst = !DP(v,d).Unbounded_Max();
00644 for (dd = 0; dd < d; dd++) {
00645 if (d_isconst)
00646 d_isconst = !DP(v,dd).Unbounded_Max();
00647 dmin += factors[dd] * DP(v,dd).Min();
00648 }
00649 DP(v,d).Distance = dmin;
00650 DP(v,d).Moreless = d_isconst ? SNL_DEP::SNL_DEP_EXACT : SNL_DEP::SNL_DEP_PLUS;
00651 }
00652
00653
00654
00655 INT newrow[SNL_MAX_LOOPS];
00656 INT i;
00657 for (i = 0; i < Nloops(); i++) {
00658 newrow[i] = (*m)(d,i);
00659 for (dd = 0; dd < d; dd++)
00660 newrow[i] += factors[dd] * (*m)(dd,i);
00661 }
00662 for (i = 0; i < Nloops(); i++)
00663 (*m)(d,i) = newrow[i];
00664 }
00665
00666 CXX_DELETE_ARRAY(deps, &SNL_local_pool);
00667 CXX_DELETE_ARRAY(per_vector_info, &SNL_local_pool);
00668 MEM_POOL_Pop_Unfreeze(&SNL_local_pool);
00669
00670 if (d == Nloops()) {
00671 FmtAssert(SNL_DEP_MATRIX(*this, Pool()).Is_Fully_Permutable(from, to) == m->Is_Identity(),
00672 ("Fully permutable nest if and only if identity transf."));
00673 return m;
00674 }
00675 else {
00676 CXX_DELETE(m, pool);
00677 return NULL;
00678 }
00679 }
00680
00681
00682
00683
00684
00685 static BOOL is_eventually_a_parent(WN* wn, WN* par)
00686 {
00687 while (wn && wn != par)
00688 wn = LWN_Get_Parent(wn);
00689 return wn != NULL;
00690 }
00691
00692 static INT nest_depth(WN* wn)
00693 {
00694 INT rv;
00695 for (rv = -1; wn; wn = LWN_Get_Parent(wn)) {
00696 if (WN_opcode(wn) == OPC_DO_LOOP)
00697 rv++;
00698 }
00699 return rv;
00700 }
00701
00702 SNL_ANAL_INFO::SNL_ANAL_INFO(const SNL_NEST_INFO* ni,
00703 BOOL gtransform,
00704 ARRAY_DIRECTED_GRAPH16* dg,
00705 MEM_POOL* pool)
00706 : _body_deps(ni->Depth_Inner() + 1 - ni->Num_Bad() -
00707 (gtransform ? ni->Nloops_General() : ni->Nloops_Invariant()),
00708 gtransform ? ni->Nloops_General() : ni->Nloops_Invariant(),
00709 ni->Num_Bad(), ni->Dostack(), pool),
00710 _imperfect_deps(ni->Depth_Inner() + 1 - ni->Num_Bad() -
00711 (gtransform ? ni->Nloops_General() : ni->Nloops_Invariant()),
00712 gtransform ? ni->Nloops_General() : ni->Nloops_Invariant(),
00713 ni->Num_Bad(), ni->Dostack(), pool),
00714 _lexinfo(HT_ELTS, pool),
00715 _pool(pool),
00716 _above_is_distributable(gtransform ? ni->Above_Is_Distributable() : TRUE),
00717 _below_is_distributable(gtransform ? ni->Below_Is_Distributable() : TRUE),
00718 _inner_loop(ni->Dostack().Bottom_nth(ni->Depth_Inner())),
00719 _depth_inner(ni->Depth_Inner()),
00720 _ci(&ni->Dostack())
00721 {
00722
00723
00724 INT outer_depth = ni->Depth_Inner() + 1 -
00725 (gtransform ? ni->Nloops_General() : ni->Nloops_Invariant());
00726 INT lexcount = 0;
00727 WN* loop = ni->Dostack().Bottom_nth(outer_depth);
00728 WN* innerloop = ni->Dostack().Bottom_nth(_depth_inner);
00729 _lex_last_above_innermost = -1;
00730 _lex_first_below_innermost = -1;
00731
00732 for (LWN_ITER* wi = LWN_WALK_TreeIter(loop);
00733 wi; wi = LWN_WALK_TreeNext(wi)) {
00734 if (_lex_last_above_innermost == -1 && wi->wn == innerloop)
00735 _lex_last_above_innermost = lexcount;
00736 OPCODE op = WN_opcode(wi->wn);
00737 if (OPCODE_is_load(op) || OPCODE_is_store(op) || OPCODE_is_call(op)) {
00738 if (_lex_last_above_innermost != -1) {
00739 if (_lex_first_below_innermost == -1) {
00740 if (!is_eventually_a_parent(wi->wn, innerloop)) {
00741 _lex_first_below_innermost = lexcount + 1;
00742 Is_True(nest_depth(wi->wn) < nest_depth(innerloop), ("bug"));
00743 }
00744 else {
00745 Is_True(nest_depth(wi->wn) >= nest_depth(innerloop), ("bug"));
00746 }
00747 }
00748 else {
00749 Is_True(!is_eventually_a_parent(wi->wn, innerloop), ("wierd bug"));
00750 Is_True(nest_depth(wi->wn) < nest_depth(innerloop), ("bug"));
00751 }
00752 }
00753 OPERATOR opr = OPCODE_operator(op);
00754 if (OPCODE_is_load(op) || OPCODE_is_store(op) || OPCODE_is_call(op)) {
00755 if (dg->Get_Vertex(wi->wn))
00756 Enter_Lex(wi->wn, LEX_DEPTH(++lexcount, nest_depth(wi->wn)));
00757 else if (opr != OPR_LDID && opr != OPR_STID) {
00758 BOOL imperfect = (_lex_last_above_innermost == -1 ||
00759 _lex_first_below_innermost != -1);
00760 SNL_DEP_INFO* dinfo = imperfect ? &_imperfect_deps : &_body_deps;
00761 INT entry = dinfo->_bad_deps.Newidx();
00762 dinfo->_bad_deps[entry].e = 0;
00763 dinfo->_bad_deps[entry].loop = _body_deps.Nloops() - (imperfect?2:1);
00764 dinfo->_all_stars = TRUE;
00765 }
00766 }
00767 }
00768 }
00769 Is_True(_lex_last_above_innermost >= 0, ("Missing inner loop"));
00770 if (_lex_first_below_innermost == -1)
00771 _lex_first_below_innermost = lexcount + 1;
00772
00773
00774
00775
00776
00777 HASH_TABLE_ITER<WN*,LEX_DEPTH> lit(&_lexinfo);
00778 WN* wn;
00779 LEX_DEPTH ld;
00780 while ((LNO_Analysis || !_body_deps.All_Stars()) && lit.Step(&wn, &ld)) {
00781 Enter_Deps(wn, ld);
00782 if (snl_debug >= 3) {
00783 fprintf(TFile, "snl_deps: insertion of 0x%p (lex depth %d)\n",
00784 wn, ld.Depth);
00785 Print(TFile);
00786 fflush(TFile);
00787 }
00788 }
00789 }
00790
00791 SNL_ANAL_INFO::~SNL_ANAL_INFO()
00792 {
00793 }
00794
00795 void SNL_ANAL_INFO::Print(FILE* f) const
00796 {
00797 HASH_TABLE_ITER<WN*,LEX_DEPTH> lit(&_lexinfo);
00798 WN* wn;
00799 LEX_DEPTH ld;
00800
00801 INT mrefs;
00802 for (mrefs = 0; lit.Step(&wn, &ld); mrefs++)
00803 ;
00804
00805 fprintf(f, "SNL_ANAL_INFO: <%d memrefs>\n", mrefs);
00806 Body_Deps().Print(f);
00807 Imperfect_Deps().Print(f);
00808 _ci.Print(f);
00809 }
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820 void SNL_ANAL_INFO::Enter_Deps(WN* wn, LEX_DEPTH ld)
00821 {
00822 VINDEX16 v = Array_Dependence_Graph->Get_Vertex(wn);
00823 Is_True(v, ("Source has null vertex"));
00824
00825
00826
00827
00828
00829
00830
00831
00832 Is_True(ld.Lex > 0 && ld.Depth >= 0, ("Bad call to Enter_Deps()"));
00833
00834 INT ab = 1;
00835 if (Above_Main_Nest(ld.Lex))
00836 ab = 0;
00837 else if (Below_Main_Nest(ld.Lex))
00838 ab = 2;
00839
00840 EINDEX16 enext = 0;
00841 for (EINDEX16 e = Array_Dependence_Graph->Get_Out_Edge(v); e; e = enext) {
00842 enext = Array_Dependence_Graph->Get_Next_Out_Edge(e);
00843 VINDEX16 v2 = Array_Dependence_Graph->Get_Sink(e);
00844 Is_True(v2, ("Sink has null vertex"));
00845 WN* wn2 = Array_Dependence_Graph->Get_Wn(v2);
00846 Is_True(wn2, ("Sink has missing WN"));
00847 LEX_DEPTH ld2 = Find_Lex(wn2);
00848 INT components = Array_Dependence_Graph->Depv_Array(e)->Num_Dim();
00849
00850 FmtAssert((components <= _body_deps.First_Component()) ==
00851 (ld2.Lex == 0), ("Bad component count %d %d %d v%d->v%d",
00852 components,
00853 _body_deps.First_Component(), ld2.Depth,
00854 v, v2));
00855
00856
00857
00858 if (ld2.Lex == 0)
00859 continue;
00860
00861
00862
00863 if (red_manager &&
00864 red_manager->Which_Reduction(wn) &&
00865 red_manager->Which_Reduction(wn2) &&
00866 (red_manager->Which_Reduction(wn) ==
00867 red_manager->Which_Reduction(wn2))) {
00868 continue;
00869 }
00870
00871 INT ab2 = 1;
00872 if (Above_Main_Nest(ld2.Lex))
00873 ab2 = 0;
00874 else if (Below_Main_Nest(ld2.Lex))
00875 ab2 = 2;
00876
00877 if (components >= _body_deps.First_Component() + _body_deps.Nloops()) {
00878 _body_deps.Enter(Array_Dependence_Graph->Depv_Array(e), e);
00879 if (_body_deps.All_Stars())
00880 return;
00881 }
00882 else {
00883 OPCODE opc = WN_opcode(wn);
00884 OPCODE opc2 = WN_opcode(wn2);
00885 OPERATOR opr = OPCODE_operator(opc);
00886 OPERATOR opr2 = OPCODE_operator(opc2);
00887
00888 if (OPCODE_is_call(opc) || OPCODE_is_call(opc2) ||
00889 opr == OPR_LDID || opr2 == OPR_LDID ||
00890 opr == OPR_STID || opr2 == OPR_STID) {
00891 _imperfect_deps._all_stars = TRUE;
00892 return;
00893 }
00894 MEM_POOL_Push_Freeze(&SNL_local_pool);
00895 DEPV_LIST* dvl = CXX_NEW(DEPV_LIST(wn, wn2,
00896 _imperfect_deps.Stack1().Elements(),
00897 _imperfect_deps.First_Component() +
00898 _imperfect_deps.Nloops(),
00899 TRUE,
00900 &SNL_local_pool,
00901 &_imperfect_deps.Stack1(),
00902 &_imperfect_deps.Stack2()),
00903 &SNL_local_pool);
00904
00905
00906
00907 INT missing = _depth_inner - MAX(ld.Depth,ld2.Depth);
00908 Is_True((missing == 0) == (ab == 1 || ab2 == 1), ("Bug in snl_deps"));
00909 if (ab != 1 && ab2 != 1) {
00910
00911
00912
00913
00914
00915
00916
00917
00918 DEPV_ITER iter(dvl);
00919 for (DEPV_NODE *n = iter.First(); !iter.Is_Empty(); n = iter.Next()) {
00920 for (INT d = _imperfect_deps.Nloops() - missing;
00921 d < _imperfect_deps.Nloops(); d++) {
00922 BOOL is_improvable = TRUE;
00923 INT depth_this_component = _depth_inner + 1 -
00924 _imperfect_deps.Nloops() + d;
00925 if (ab == 0 || ab2 == 0) {
00926 for (INT i = 0; is_improvable && i < depth_this_component; i++) {
00927 if (!_ci.Lbconst(depth_this_component, i)) {
00928 INT dc = (_imperfect_deps.Nloops() - 1) - (_depth_inner - i);
00929 if (dc < 0 ||
00930 DEP_IsDistance(DEPV_Dep(n->Depv, dc)) == FALSE ||
00931 DEP_Distance(DEPV_Dep(n->Depv, dc)) != 0)
00932 is_improvable = FALSE;
00933 }
00934 }
00935 }
00936 if (ab == 2 || ab2 == 2) {
00937 for (INT i = 0; is_improvable && i < depth_this_component; i++) {
00938 if (!_ci.Ubconst(depth_this_component, i)) {
00939 INT dc = (_imperfect_deps.Nloops() - 1) - (_depth_inner - i);
00940 if (dc < 0 ||
00941 DEP_IsDistance(DEPV_Dep(n->Depv, dc)) == FALSE ||
00942 DEP_Distance(DEPV_Dep(n->Depv, dc)) != 0)
00943 is_improvable = FALSE;
00944 }
00945 }
00946 }
00947 if (is_improvable) {
00948 DEPV_Dep(n->Depv, _imperfect_deps.First_Component()+d) =
00949 (ab == ab2) ? DEP_SetDistance(0) :
00950 (ab < ab2) ? DEP_SetDirection(DIR_POSEQ) :
00951 DEP_SetDirection(DIR_NEGEQ);
00952 }
00953 }
00954 }
00955 }
00956
00957 DEPV_LIST* pos = CXX_NEW(DEPV_LIST(_imperfect_deps.First_Component() +
00958 _imperfect_deps.Nloops(),
00959 _imperfect_deps.Dv_List().Num_Unused_Dim(),
00960 &SNL_local_pool),
00961 &SNL_local_pool);
00962 DEPV_LIST* neg = CXX_NEW(DEPV_LIST(_imperfect_deps.First_Component() +
00963 _imperfect_deps.Nloops(),
00964 _imperfect_deps.Dv_List().Num_Unused_Dim(),
00965 &SNL_local_pool),
00966 &SNL_local_pool);
00967 dvl->Lex_Pos_Decompose(&SNL_local_pool, pos, neg,
00968 ld.Lex < ld2.Lex, ld.Lex > ld2.Lex);
00969
00970 if (!pos->Is_Empty()) {
00971 DEPV_ARRAY *array = Create_DEPV_ARRAY(pos, Pool());
00972 _imperfect_deps.Enter(array, e);
00973 if (snl_debug >= 3) {
00974 fprintf(TFile, "snl_deps: after inserting edge %d: ", e);
00975 _imperfect_deps.Print(TFile);
00976 }
00977 }
00978
00979 CXX_DELETE(dvl, &SNL_local_pool);
00980 CXX_DELETE(pos, &SNL_local_pool);
00981 CXX_DELETE(neg, &SNL_local_pool);
00982
00983 MEM_POOL_Pop_Unfreeze(&SNL_local_pool);
00984 }
00985 }
00986 }
00987
00988 SNL_ANAL_INFO::CONST_BOUNDS_INFO::CONST_BOUNDS_INFO(const DOLOOP_STACK* s)
00989 {
00990 INT d;
00991 for (d = 0; d < 64; d++) {
00992 _lbconst[d] = INT64(-1);
00993 _ubconst[d] = INT64(-1);
00994 }
00995
00996 for (d = 0; d < MIN(s->Elements(),64); d++) {
00997 DO_LOOP_INFO* dli = Get_Do_Loop_Info(s->Bottom_nth(d));
00998 ACCESS_ARRAY* aalb = dli->LB;
00999 ACCESS_ARRAY* aaub = dli->UB;
01000
01001 if (aalb->Too_Messy)
01002 _lbconst[d] = 0;
01003 else {
01004 for (INT dimlb = 0; dimlb < aalb->Num_Vec(); dimlb++) {
01005 ACCESS_VECTOR* av = aalb->Dim(dimlb);
01006 if (av->Too_Messy || av->Contains_Non_Lin_Symb())
01007 _lbconst[d] = 0;
01008 else {
01009 for (INT dd = 0; dd < d; dd++)
01010 if (av->Loop_Coeff(dd))
01011 _lbconst[d] &= ~(INT64(1)<<dd);
01012 Is_True(av->Loop_Coeff(d), ("Bad access vector"));
01013 }
01014 }
01015 }
01016
01017 if (aaub->Too_Messy)
01018 _ubconst[d] = 0;
01019 else {
01020 for (INT dimub = 0; dimub < aaub->Num_Vec(); dimub++) {
01021 ACCESS_VECTOR* av = aaub->Dim(dimub);
01022 if (av->Too_Messy || av->Contains_Non_Lin_Symb())
01023 _ubconst[d] = 0;
01024 else {
01025 for (INT dd = 0; dd < d; dd++)
01026 if (av->Loop_Coeff(dd))
01027 _ubconst[d] &= ~(INT64(1)<<dd);
01028 Is_True(av->Loop_Coeff(d), ("Bad access vector"));
01029 }
01030 }
01031 }
01032 }
01033 }
01034
01035 void SNL_ANAL_INFO::CONST_BOUNDS_INFO::Print(FILE* f) const
01036 {
01037 fprintf(f, "CONST BOUNDS INFO:\n");
01038 for (INT i = 0; i < 64; i++) {
01039 if (_lbconst[i] == INT64(-1) && _ubconst[i] == INT64(-1))
01040 continue;
01041
01042 fprintf(f, "Indices modified at depth %d:", i);
01043 fprintf(f, " LB:");
01044 INT ii;
01045 for (ii = 0; ii < i; ii++) {
01046 if (Lbconst(i,ii) == FALSE)
01047 fprintf(f, " %d", ii);
01048 }
01049 fprintf(f, " UB:");
01050 for (ii = 0; ii < i; ii++) {
01051 if (Ubconst(i,ii) == FALSE)
01052 fprintf(f, " %d", ii);
01053 }
01054 fprintf(f, "\n");
01055 }
01056 }
01057