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
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063 #ifdef USE_PCH
00064 #include "lno_pch.h"
00065 #endif // USE_PCH
00066 #pragma hdrstop
00067
00068 #define __STDC_LIMIT_MACROS
00069 #include <stdint.h>
00070 #include <sys/types.h>
00071 #include <alloca.h>
00072 #ifdef LNO
00073 #include "lnopt_main.h"
00074 #else
00075 #include "mempool.h"
00076 static MEM_POOL LNO_local_pool;
00077 #endif
00078 #include "mat.h"
00079 #include "access_vector.h"
00080 #include "stab.h"
00081 #include "lwn_util.h"
00082 #include "opt_du.h"
00083 #include "soe.h"
00084 #ifdef LNO
00085 #include "lnoutils.h"
00086 #include "move.h"
00087 #include "errors.h"
00088 #include "erbe.h"
00089 #endif
00090 #include "targ_sim.h"
00091
00092 #ifndef LNO
00093 static DU_MANAGER *Du_Mgr;
00094 extern void Initialize_Access_Vals(DU_MANAGER* du_mgr, FILE *tfile);
00095 extern void Finalize_Access_Vals();
00096 extern WN* LNO_Common_Loop(WN* wn1, WN* wn2);
00097 extern WN* UBvar (WN *end);
00098 template <> MEM_POOL* MAT<mINT32>::_default_pool = &LNO_local_pool;
00099
00100 #pragma weak Add_Def_Use__10DU_MANAGERGP2WNT1
00101 #endif
00102
00103 #ifdef LNO
00104 extern BOOL Is_Consistent_Condition(ACCESS_VECTOR*, WN*);
00105 #endif
00106
00107
00108
00109
00110
00111 INT snprintfs(char* buf,
00112 INT ccount,
00113 INT tcount,
00114 const char* fstring)
00115 {
00116 INT len = strlen(fstring);
00117 if (ccount + len < tcount) {
00118 INT new_char_count = sprintf(buf + ccount, fstring);
00119 return ccount + new_char_count;
00120 }
00121 for (INT i = 0; i < ccount; i++)
00122 sprintf(buf + i, "%c", '&');
00123 sprintf(buf + ccount, "%c", '\0');
00124 return tcount - 1;
00125 }
00126
00127 INT snprintfd(char* buf,
00128 INT ccount,
00129 INT tcount,
00130 INT32 value)
00131 {
00132
00133 const INT int_size = 11;
00134 if (ccount + int_size < tcount) {
00135 INT new_char_count = sprintf(buf + ccount, "%d", value);
00136 return ccount + new_char_count;
00137 }
00138 for (INT i = 0; i < ccount; i++)
00139 sprintf(buf + i, "%c", '&');
00140 sprintf(buf + ccount, "%c", '\0');
00141 return tcount - 1;
00142 }
00143
00144 INT snprintfll(char* buf,
00145 INT ccount,
00146 INT tcount,
00147 INT64 value)
00148 {
00149
00150 const INT ll_size = 21;
00151 if (ccount + ll_size < tcount) {
00152 INT new_char_count = sprintf(buf + ccount, "%lld", value);
00153 return ccount + new_char_count;
00154 }
00155 for (INT i = 0; i < ccount; i++)
00156 sprintf(buf + i, "%c", '&');
00157 sprintf(buf + ccount, "%c", '\0');
00158 return tcount - 1;
00159 }
00160
00161 INT snprintfx(char* buf,
00162 INT ccount,
00163 INT tcount,
00164 INT32 value)
00165 {
00166
00167 const INT x_size = 10;
00168 if (ccount + x_size < tcount) {
00169 INT new_char_count = sprintf(buf + ccount, "0x%x", value);
00170 return ccount + new_char_count;
00171 }
00172 for (INT i = 0; i < ccount; i++)
00173 sprintf(buf + i, "%c", '&');
00174 sprintf(buf + ccount, "%c", '\0');
00175 return tcount - 1;
00176 }
00177
00178 INT Num_Lands(WN *wn);
00179 INT Num_Liors(WN *wn);
00180
00181 BOOL LNO_Debug_Delinearization;
00182 BOOL LNO_Allow_Nonlinear = TRUE;
00183
00184 #define MAX_NAME_SIZE 66
00185
00186 INT Num_Lower_Bounds(WN* wn,
00187 ACCESS_VECTOR* step)
00188 {
00189 INT num_bounds=0;
00190 WN *l = WN_start(wn);
00191 WN *kid = WN_kid(l,0);
00192 if (step->Const_Offset > 0) {
00193 if (WN_operator(kid) == OPR_MAX) {
00194 num_bounds = Num_Maxs(kid);
00195 } else if (WN_operator(kid) == OPR_SUB) {
00196 num_bounds = Num_Maxs(WN_kid0(kid));
00197 } else if (WN_operator(kid) == OPR_ADD) {
00198 num_bounds = Num_Maxs(WN_kid0(kid));
00199 if (!num_bounds) num_bounds = Num_Maxs(WN_kid1(kid));
00200 }
00201 } else {
00202 if (WN_operator(kid) == OPR_MIN) {
00203 num_bounds = Num_Mins(kid);
00204 } else if (WN_operator(kid) == OPR_SUB) {
00205 num_bounds = Num_Mins(WN_kid0(kid));
00206 } else if (WN_operator(kid) == OPR_ADD) {
00207 num_bounds = Num_Mins(WN_kid0(kid));
00208 if (!num_bounds) num_bounds = Num_Maxs(WN_kid1(kid));
00209 }
00210 }
00211 return num_bounds+1;
00212 }
00213
00214 extern INT Num_Upper_Bounds(WN* wn)
00215 {
00216 INT num_bounds = 0;
00217 WN *u = WN_end(wn);
00218 OPERATOR compare = WN_operator(u);
00219 if ((compare == OPR_LE) || (compare == OPR_LT)) {
00220 num_bounds = Num_Mins(WN_kid(u,1));
00221 if (!num_bounds) num_bounds = Num_Maxs(WN_kid(u,0));
00222 } else {
00223 num_bounds = Num_Maxs(WN_kid(u,1));
00224 if (!num_bounds) num_bounds = Num_Mins(WN_kid(u,0));
00225 }
00226 return num_bounds+1;
00227 }
00228
00229 extern BOOL Bound_Is_Too_Messy(ACCESS_ARRAY* aa)
00230 {
00231 if (aa->Too_Messy)
00232 return TRUE;
00233 for (INT i = 0; i < aa->Num_Vec(); i++)
00234 if (aa->Dim(i)->Too_Messy)
00235 return TRUE;
00236 return FALSE;
00237 }
00238
00239 #ifdef LNO
00240
00241 extern BOOL Promote_Messy_Bound(WN* wn_loop,
00242 WN* wn_bound,
00243 char name[],
00244 DU_MANAGER* du)
00245 {
00246 if (UBvar(WN_end(wn_loop)) == NULL)
00247 return FALSE;
00248 WN* wn_parent = LWN_Get_Parent(wn_bound);
00249 INT i;
00250 for (i = 0; i < WN_kid_count(wn_parent); i++)
00251 if (wn_bound == WN_kid(wn_parent, i))
00252 break;
00253 FmtAssert(i < WN_kid_count(wn_parent), ("Could not find kid for parent."));
00254 INT kid = i;
00255 TYPE_ID type = WN_desc(WN_start(wn_loop));
00256 OPCODE preg_s_opcode = OPCODE_make_op(OPR_STID, MTYPE_V, type);
00257 WN_OFFSET preg_num = Create_Preg(type, name);
00258 ST* preg_st = MTYPE_To_PREG(type);
00259 WN* wn_stid = LWN_CreateStid(preg_s_opcode, preg_num, preg_st,
00260 Be_Type_Tbl(type), wn_bound);
00261 LWN_Insert_Block_Before(LWN_Get_Parent(wn_loop), wn_loop, wn_stid);
00262 WN* wn_ldid = LWN_CreateLdid(WN_opcode(UBvar(WN_end(wn_loop))), wn_stid);
00263 WN_kid(wn_parent, kid) = wn_ldid;
00264 LWN_Set_Parent(wn_ldid, wn_parent);
00265 du->Add_Def_Use(wn_stid, wn_ldid);
00266 INT hoist_level = Hoistable_Statement(wn_stid, du);
00267 if (hoist_level < Loop_Depth(wn_stid))
00268 Hoist_Statement(wn_stid, hoist_level);
00269 return TRUE;
00270 }
00271
00272 #endif
00273
00274 void INDX_RANGE::Union(INT64 offset, BOOL offset_valid, INT64 mult, INT64 size)
00275 {
00276 if (Valid) {
00277 if (Size == size) {
00278 if (abs(mult) > abs(Mult)) {
00279 Mult = mult;
00280 if (offset_valid) {
00281 Min = Max = offset;
00282 Min_Max_Valid = TRUE;
00283 } else {
00284 Min_Max_Valid = FALSE;
00285 }
00286 } else if (mult == Mult) {
00287 if (offset_valid && Min_Max_Valid) {
00288 Min = MIN(Min,offset);
00289 Max = MAX(Max,offset);
00290 } else if (offset_valid) {
00291 Min = Max = offset;
00292 Min_Max_Valid = TRUE;
00293 }
00294 }
00295 } else {
00296
00297 if (abs((size+mult-1)/mult) < Maxsize()) {
00298 Mult = mult;
00299 Size = size;
00300 if (offset_valid) {
00301 Min = Max = offset;
00302 Min_Max_Valid = TRUE;
00303 } else {
00304 Min_Max_Valid = FALSE;
00305 }
00306 }
00307 }
00308 } else {
00309 Valid = TRUE;
00310 Mult = mult;
00311 Size = size;
00312 if (offset_valid) {
00313 Min = Max = offset;
00314 Min_Max_Valid = TRUE;
00315 } else {
00316 Min_Max_Valid = FALSE;
00317 }
00318 }
00319 }
00320
00321 INT64 INDX_RANGE::Maxsize() const
00322 {
00323 if (!Valid) return -1;
00324 INT diff = 0;
00325 if (Min_Max_Valid) {
00326 diff = Max-Min;
00327 }
00328 INT64 c = abs(Mult);
00329 INT64 ans = (Size - diff + (c-1))/c;
00330 return ans <= 0 ? -1 : ans;
00331 }
00332
00333
00334
00335 void ACCESS_ARRAY::Print(FILE *fp, BOOL is_bound) const
00336 {
00337 if (Too_Messy) {
00338 fprintf(fp,"Too_Messy\n");
00339 return;
00340 }
00341
00342 for (INT32 i=0; i<_num_vec; i++) {
00343 Dim(i)->Print(fp,is_bound);
00344 }
00345 fprintf(fp,"\n");
00346 }
00347
00348 mUINT16 ACCESS_ARRAY::Non_Const_Loops() const
00349 {
00350 mUINT16 result = Dim(0)->Non_Const_Loops();
00351 for (INT32 i=1; i<_num_vec; i++) {
00352 result = MAX(result, Dim(i)->Non_Const_Loops());
00353 }
00354 return result;
00355 }
00356
00357
00358 ACCESS_ARRAY::ACCESS_ARRAY(const ACCESS_ARRAY *a, MEM_POOL *pool)
00359 {
00360 _dim = NULL;
00361 Init(a,pool);
00362 }
00363
00364 BOOL ACCESS_ARRAY::Has_Formal_Parameter()
00365 {
00366 if (Too_Messy)
00367 return FALSE;
00368 for (INT i = 0; i< _num_vec; i++)
00369 if (Dim(i)->Has_Formal_Parameter())
00370 return TRUE;
00371 return FALSE;
00372 }
00373
00374 BOOL ACCESS_VECTOR::Has_Formal_Parameter()
00375 {
00376 if (Too_Messy)
00377 return FALSE;
00378 if (Lin_Symb != NULL) {
00379 INTSYMB_ITER ii(Lin_Symb);
00380 for (INTSYMB_NODE* nn = ii.First(); !ii.Is_Empty(); nn = ii.Next())
00381 if (nn->Symbol.Is_Formal())
00382 return TRUE;
00383 }
00384 if (Non_Lin_Symb != NULL) {
00385 SUMPROD_ITER ii(Non_Lin_Symb);
00386 for (SUMPROD_NODE* nn = ii.First(); !ii.Is_Empty(); nn = ii.Next()) {
00387 SYMBOL_ITER iii(nn->Prod_List);
00388 for (SYMBOL_NODE* nnn = iii.First(); !iii.Is_Empty(); nnn = iii.Next())
00389 if (nnn->Symbol.Is_Formal())
00390 return TRUE;
00391 }
00392 }
00393 return FALSE;
00394 }
00395
00396 void ACCESS_VECTOR::Substitute(INT formal_number,
00397 WN* wn_sub,
00398 DOLOOP_STACK* stack,
00399 BOOL allow_nonlin)
00400 {
00401 if (Contains_Lin_Symb()) {
00402 INTSYMB_ITER iter(Lin_Symb);
00403 INTSYMB_NODE* nnode = NULL;
00404 INTSYMB_NODE* node = iter.First();
00405 for (; !iter.Is_Empty(); nnode = node, node = iter.Next()) {
00406 if (node->Symbol.Is_Formal()
00407 && node->Symbol.Formal_Number() == formal_number) {
00408 if (wn_sub == NULL) {
00409 Too_Messy = TRUE;
00410 return;
00411 }
00412 OPERATOR opr_sub = WN_operator(wn_sub);
00413 if (opr_sub != OPR_LDID && opr_sub != OPR_LDA) {
00414 Too_Messy = TRUE;
00415 return;
00416 }
00417 SYMBOL sym_sub(WN_st(wn_sub), WN_offset(wn_sub)
00418 + node->Symbol.WN_Offset(), node->Symbol.Type);
00419 INT32 coeff = node->Coeff;
00420 Lin_Symb->Remove(nnode, node);
00421 node = nnode;
00422 Add_Symbol(coeff, sym_sub, stack, NULL);
00423 CXX_DELETE(node, _mem_pool);
00424 }
00425 }
00426 }
00427 if (allow_nonlin && Contains_Non_Lin_Symb()) {
00428 SUMPROD_ITER iter(Non_Lin_Symb);
00429 SUMPROD_NODE* node = iter.First();
00430 for (; !iter.Is_Empty(); node = iter.Next()) {
00431 INT symbol_count = 0;
00432 SYMBOL_ITER iiter(node->Prod_List);
00433 SYMBOL_NODE* snode = iiter.First();
00434 for (; !iiter.Is_Empty(); snode = iiter.Next())
00435 if (snode->Symbol.Is_Formal()
00436 && snode->Symbol.Formal_Number() == formal_number)
00437 symbol_count++;
00438 if (symbol_count > 0) {
00439
00440
00441
00442 DevWarn("ACCESS_VECTOR::Substitute: Found non-linear term");
00443 Too_Messy = TRUE;
00444 return;
00445 }
00446 }
00447 }
00448 }
00449
00450 void ACCESS_ARRAY::Substitute(INT formal_number,
00451 WN* wn_sub,
00452 DOLOOP_STACK* stack,
00453 BOOL allow_nonlin)
00454 {
00455 if (Too_Messy)
00456 return;
00457 for (INT i = 0; i < Num_Vec(); i++)
00458 Dim(i)->Substitute(formal_number, wn_sub, stack, allow_nonlin);
00459 }
00460
00461 ACCESS_ARRAY::ACCESS_ARRAY(
00462 UINT16 num_vec,ACCESS_VECTOR* dim[], MEM_POOL *mem_pool=0)
00463 {
00464 _dim = CXX_NEW_ARRAY(ACCESS_VECTOR,num_vec,mem_pool);
00465 _mem_pool=mem_pool;
00466 for (INT32 i=0; i<num_vec; i++) {
00467 _dim[i].Init(dim[i],mem_pool);
00468 }
00469 Too_Messy = TRUE;
00470 _num_vec = num_vec;
00471 }
00472
00473 ACCESS_ARRAY::ACCESS_ARRAY(
00474 UINT16 num_vec,UINT16 nest_depth,MEM_POOL *mem_pool=0)
00475 {
00476 _dim = CXX_NEW_ARRAY(ACCESS_VECTOR,num_vec,mem_pool);
00477 _mem_pool=mem_pool;
00478 for (INT32 i=0; i<num_vec; i++) {
00479 _dim[i].Init(nest_depth,mem_pool);
00480 }
00481 Too_Messy = TRUE;
00482 _num_vec = num_vec;
00483 }
00484
00485
00486 void ACCESS_ARRAY::Init(const ACCESS_ARRAY *a, MEM_POOL *pool)
00487 {
00488 if (_dim != NULL) {
00489 CXX_DELETE_ARRAY(_dim,_mem_pool);
00490 }
00491 _mem_pool = pool;
00492 Too_Messy = a->Too_Messy;
00493 _num_vec = a->_num_vec;
00494 _dim = CXX_NEW_ARRAY(ACCESS_VECTOR,_num_vec,_mem_pool);
00495
00496 for (INT32 i=0; i<_num_vec; i++) {
00497 _dim[i].Init(a->Dim(i),pool);
00498 }
00499 }
00500
00501 BOOL ACCESS_ARRAY::operator ==(const ACCESS_ARRAY& a) const
00502 {
00503 if (Too_Messy || a.Too_Messy) return (FALSE);
00504 if (_num_vec != a._num_vec) return(FALSE);
00505 for (INT32 i=0; i<_num_vec; i++) {
00506 if (!(*Dim(i) == *a.Dim(i))) {
00507 return(FALSE);
00508 }
00509 }
00510 return(TRUE);
00511 }
00512
00513 void ACCESS_VECTOR::Print(FILE *fp, BOOL is_bound, BOOL print_brackets) const
00514 {
00515 char bf[MAX_TLOG_CHARS];
00516 Print(bf, 0, is_bound, print_brackets);
00517 fprintf(fp, "%s", bf);
00518 }
00519
00520 INT ACCESS_VECTOR::Print(char* bf,
00521 INT ccount,
00522 BOOL is_bound,
00523 BOOL print_brackets) const
00524 {
00525 INT new_ccount = ccount;
00526 if (Too_Messy) {
00527 new_ccount = snprintfs(bf, new_ccount, MAX_TLOG_CHARS, "[Too_Messy]");
00528 return new_ccount;
00529 }
00530 if (!is_bound && print_brackets)
00531 new_ccount = snprintfs(bf, new_ccount, MAX_TLOG_CHARS, "[");
00532
00533
00534 BOOL seen_something = FALSE;
00535 if (!is_bound) {
00536 if (Const_Offset != 0) {
00537 if (print_brackets) {
00538 new_ccount = snprintfll(bf, new_ccount, MAX_TLOG_CHARS, Const_Offset);
00539 new_ccount = snprintfs(bf, new_ccount, MAX_TLOG_CHARS, " ");
00540 } else {
00541 new_ccount = snprintfll(bf, new_ccount, MAX_TLOG_CHARS, Const_Offset);
00542 }
00543 seen_something = TRUE;
00544 }
00545 }
00546 for (INT32 i = 0; i < Nest_Depth(); i++) {
00547 if (Loop_Coeff(i) != 0) {
00548 if (!seen_something) {
00549 seen_something = TRUE;
00550 new_ccount = snprintfd(bf, new_ccount, MAX_TLOG_CHARS, Loop_Coeff(i));
00551 new_ccount = snprintfs(bf, new_ccount, MAX_TLOG_CHARS, "*loop_var");
00552 new_ccount = snprintfd(bf, new_ccount, MAX_TLOG_CHARS, i);
00553 new_ccount = snprintfs(bf, new_ccount, MAX_TLOG_CHARS, " ");
00554 } else {
00555 new_ccount = snprintfs(bf, new_ccount, MAX_TLOG_CHARS, "+ ");
00556 new_ccount = snprintfd(bf, new_ccount, MAX_TLOG_CHARS, Loop_Coeff(i));
00557 new_ccount = snprintfs(bf, new_ccount, MAX_TLOG_CHARS, "*loop_var");
00558 new_ccount = snprintfd(bf, new_ccount, MAX_TLOG_CHARS, i);
00559 new_ccount = snprintfs(bf, new_ccount, MAX_TLOG_CHARS, " ");
00560 }
00561 }
00562 }
00563 if (Lin_Symb != NULL && !Lin_Symb->Is_Empty()) {
00564 if (seen_something) {
00565 new_ccount = snprintfs(bf, new_ccount, MAX_TLOG_CHARS, "+ ");
00566 }
00567 seen_something = TRUE;
00568 new_ccount = Lin_Symb->Print(bf, new_ccount);
00569 }
00570 if (Non_Lin_Symb != NULL && !Non_Lin_Symb->Is_Empty()) {
00571 new_ccount = Non_Lin_Symb->Print(bf, new_ccount);
00572 }
00573 if (!is_bound && (Const_Offset == 0) && !seen_something) {
00574 new_ccount = snprintfs(bf, new_ccount, MAX_TLOG_CHARS, "0");
00575 }
00576 if (!is_bound) {
00577 if (print_brackets)
00578 new_ccount = snprintfs(bf, new_ccount, MAX_TLOG_CHARS, "]");
00579 } else {
00580 new_ccount = snprintfs(bf, new_ccount, MAX_TLOG_CHARS, " <= ");
00581 new_ccount = snprintfll(bf, new_ccount, MAX_TLOG_CHARS, Const_Offset);
00582 new_ccount = snprintfs(bf, new_ccount, MAX_TLOG_CHARS, "; ");
00583 }
00584 if (_non_const_loops) {
00585 new_ccount = snprintfs(bf, new_ccount, MAX_TLOG_CHARS,
00586 " non_const_loops is ");
00587 new_ccount = snprintfd(bf, new_ccount, MAX_TLOG_CHARS, _non_const_loops);
00588 new_ccount = snprintfs(bf, new_ccount, MAX_TLOG_CHARS, " \n");
00589 }
00590 if (Delinearized_Symbol != NULL) {
00591 new_ccount = snprintfs(bf, new_ccount, MAX_TLOG_CHARS,
00592 " delin_symbol is ");
00593 new_ccount = snprintfs(bf, new_ccount, MAX_TLOG_CHARS,
00594 Delinearized_Symbol->Name());
00595 new_ccount = snprintfs(bf, new_ccount, MAX_TLOG_CHARS, " \n");
00596 }
00597 return new_ccount;
00598 }
00599
00600 void ACCESS_VECTOR::Print_Analysis_Info(FILE *fp,
00601 DOLOOP_STACK &do_stack,
00602 BOOL is_bound) const
00603 {
00604 if (Too_Messy) {
00605 fprintf(fp,"Too_Messy\n");
00606 return;
00607 }
00608
00609
00610 BOOL seen_something = FALSE;
00611 if (!is_bound) {
00612 if (Const_Offset != 0) {
00613 fprintf(fp,"%lld ",Const_Offset);
00614 seen_something = TRUE;
00615 }
00616 }
00617
00618
00619
00620 for (INT32 i=0; i< Nest_Depth(); i++) {
00621 if (Loop_Coeff(i) != 0) {
00622
00623 if (i >= do_stack.Elements()) {
00624 FmtAssert(i < do_stack.Elements(), ("Print_Analysis_Info : loop mismatch"));
00625 }
00626
00627 SYMBOL sym(WN_index(do_stack.Bottom_nth(i)));
00628 if (!seen_something) {
00629 seen_something = TRUE;
00630 fprintf(fp,"%d*%s", Loop_Coeff(i), sym.Name());
00631 } else {
00632 fprintf(fp," + %d*%s", Loop_Coeff(i), sym.Name());
00633 }
00634 }
00635 }
00636 if (Lin_Symb != NULL && !Lin_Symb->Is_Empty()) {
00637 if (seen_something) {
00638 fprintf(fp," + ");
00639 }
00640 seen_something = TRUE;
00641 Lin_Symb->Print(fp);
00642 }
00643 if (Non_Lin_Symb != NULL && !Non_Lin_Symb->Is_Empty()) {
00644 Non_Lin_Symb->Print(fp);
00645 }
00646 if (!is_bound && (Const_Offset == 0) && !seen_something) {
00647 fprintf(fp,"0");
00648 }
00649 if (is_bound) {
00650 fprintf(fp," <= %lld; ",Const_Offset);
00651 }
00652 if (_non_const_loops && Lin_Symb && !Lin_Symb->Is_Empty()) {
00653 fprintf(fp,"non_const_loops is %d \n",_non_const_loops);
00654 }
00655 }
00656
00657 BOOL ACCESS_VECTOR::operator ==(const ACCESS_VECTOR& av) const
00658 {
00659 if (Too_Messy || av.Too_Messy) return (FALSE);
00660 if (Const_Offset != av.Const_Offset) return(FALSE);
00661 if (_non_const_loops != av._non_const_loops) return FALSE;
00662 if ((Delinearized_Symbol != 0) != (av.Delinearized_Symbol != 0)) {
00663 return FALSE;
00664 }
00665 if (Delinearized_Symbol &&
00666 (*Delinearized_Symbol != *av.Delinearized_Symbol)) return FALSE;
00667 INT common_depth = MIN(_nest_depth,av._nest_depth);
00668 INT32 i;
00669
00670 for (i=0; i< common_depth; i++) {
00671 if (Loop_Coeff(i) != av.Loop_Coeff(i)) {
00672 return FALSE;
00673 }
00674 }
00675 for (i=common_depth; i<_nest_depth; i++) {
00676 if (Loop_Coeff(i)) {
00677 return FALSE;
00678 }
00679 }
00680 for (i=common_depth; i<av._nest_depth; i++) {
00681 if (av.Loop_Coeff(i)) {
00682 return FALSE;
00683 }
00684 }
00685
00686 if (Lin_Symb != NULL && !Lin_Symb->Is_Empty()) {
00687 if (av.Lin_Symb == NULL || av.Lin_Symb->Is_Empty() ||
00688 !(*Lin_Symb == *av.Lin_Symb)) {
00689 return(FALSE);
00690 }
00691 } else if (av.Lin_Symb != NULL && !av.Lin_Symb->Is_Empty()) {
00692 return(FALSE);
00693 }
00694
00695 if (Non_Lin_Symb != NULL && !Non_Lin_Symb->Is_Empty()) {
00696 if (av.Non_Lin_Symb == NULL || av.Non_Lin_Symb->Is_Empty() ||
00697 !(*Non_Lin_Symb == *av.Non_Lin_Symb)) {
00698 return(FALSE);
00699 }
00700 } else if (av.Non_Lin_Symb != NULL && !av.Non_Lin_Symb->Is_Empty()) {
00701 return(FALSE);
00702 }
00703
00704 return(TRUE);
00705 }
00706
00707
00708
00709
00710 ACCESS_VECTOR::ACCESS_VECTOR(const ACCESS_VECTOR *a, MEM_POOL *pool)
00711 {
00712 Init(a,pool);
00713 }
00714
00715 void ACCESS_VECTOR::Init(const ACCESS_VECTOR *a, MEM_POOL *pool)
00716 {
00717 _mem_pool = pool;
00718 _nest_depth = a->_nest_depth;
00719 _non_const_loops = a->_non_const_loops;
00720 Delinearized_Symbol = a->Delinearized_Symbol;
00721 if (a->_lcoeff) {
00722 _lcoeff = CXX_NEW_ARRAY(mINT32,_nest_depth,_mem_pool);
00723 for (INT i=0; i < _nest_depth; i++) {
00724 _lcoeff[i] = a->_lcoeff[i];
00725 }
00726 } else {
00727 _lcoeff = NULL;
00728 }
00729 Too_Messy = a->Too_Messy;
00730 Const_Offset = a->Const_Offset;
00731 if (a->Lin_Symb) {
00732 Lin_Symb = CXX_NEW(INTSYMB_LIST,_mem_pool);
00733 Lin_Symb->Init(a->Lin_Symb,_mem_pool);
00734 } else {
00735 Lin_Symb = NULL;
00736 }
00737 if (a->Non_Lin_Symb) {
00738 Non_Lin_Symb = CXX_NEW(SUMPROD_LIST,_mem_pool);
00739 Non_Lin_Symb->Init(a->Non_Lin_Symb,_mem_pool);
00740 } else {
00741 Non_Lin_Symb = NULL;
00742 }
00743 }
00744
00745 void ACCESS_VECTOR::Set_Loop_Coeff(UINT16 i, INT32 val)
00746 {
00747 if (!_lcoeff) {
00748 _lcoeff = CXX_NEW_ARRAY(mINT32, _nest_depth, _mem_pool);
00749 for (INT j=0; j < _nest_depth; j++) {
00750 _lcoeff[j] = 0;
00751 }
00752 }
00753 _lcoeff[i] = val;
00754 }
00755
00756 BOOL ACCESS_VECTOR::Is_Const() const
00757 {
00758 if (Too_Messy ||
00759 (Lin_Symb && !Lin_Symb->Is_Empty()) ||
00760 (Non_Lin_Symb && !Non_Lin_Symb->Is_Empty())) {
00761 return(FALSE);
00762 }
00763 if (!_lcoeff) return(TRUE);
00764 for (INT32 i=0; i< _nest_depth; i++) {
00765 if (_lcoeff[i] != 0) return(FALSE);
00766 }
00767 return(TRUE);
00768 }
00769
00770
00771 void INTSYMB_LIST::Print(FILE *fp) const
00772 {
00773 char bf[MAX_TLOG_CHARS];
00774 Print(bf, 0);
00775 fprintf(fp, "%s", bf);
00776 }
00777
00778 INT INTSYMB_LIST::Print(char* bf, INT ccount) const
00779 {
00780 INT new_ccount = ccount;
00781 INTSYMB_CONST_ITER iter(this);
00782 const INTSYMB_NODE* first = iter.First();
00783 for (const INTSYMB_NODE *node=first; !iter.Is_Empty(); node = iter.Next()) {
00784 if (node != first)
00785 new_ccount = snprintfs(bf, new_ccount, MAX_TLOG_CHARS, "+ ");
00786 new_ccount = node->Print(bf, new_ccount);
00787 }
00788 return new_ccount;
00789 }
00790
00791 BOOL INTSYMB_LIST::operator ==(const INTSYMB_LIST& isl) const
00792 {
00793 INTSYMB_CONST_ITER iter(this);
00794 INTSYMB_CONST_ITER iter2(&isl);
00795 const INTSYMB_NODE *node2 = iter2.First();
00796 for (const INTSYMB_NODE *node=iter.First(); !iter.Is_Empty(); ) {
00797 if (iter2.Is_Empty() || !(*node == *node2)) return(FALSE);
00798 node = iter.Next();
00799 node2 = iter2.Next();
00800 }
00801 if (!iter2.Is_Empty()) return(FALSE);
00802 return (TRUE);
00803 }
00804
00805 void INTSYMB_LIST::Init(INTSYMB_LIST *il,MEM_POOL *mem_pool)
00806 {
00807 INTSYMB_ITER iter(il);
00808 for (INTSYMB_NODE *node = iter.First(); !iter.Is_Empty();
00809 node=iter.Next()) {
00810 Append(CXX_NEW(INTSYMB_NODE(node),mem_pool));
00811 }
00812 }
00813
00814
00815
00816
00817 INTSYMB_LIST::~INTSYMB_LIST()
00818 {
00819 while (!Is_Empty()) CXX_DELETE(Remove_Headnode(),Default_Mem_Pool);
00820 }
00821
00822
00823
00824
00825 INTSYMB_LIST *Subtract(INTSYMB_LIST *list1, INTSYMB_LIST *list2,
00826 MEM_POOL *pool)
00827 {
00828 INTSYMB_LIST *res = CXX_NEW(INTSYMB_LIST,pool);
00829 if (list1) res->Init(list1,pool);
00830 if (!list2) return (res);
00831
00832 INTSYMB_ITER iter2(list2);
00833 for (INTSYMB_NODE *node2 = iter2.First(); !iter2.Is_Empty();
00834 node2 = iter2.Next()) {
00835
00836 INTSYMB_ITER iterr(res);
00837 INTSYMB_NODE *noder=iterr.First(), *prevnoder=NULL;
00838 while (!iterr.Is_Empty() && !(noder->Symbol == node2->Symbol)) {
00839 prevnoder = noder;
00840 noder = iterr.Next();
00841 }
00842 if (iterr.Is_Empty()) {
00843 res->Prepend(CXX_NEW(INTSYMB_NODE(node2->Symbol,-node2->Coeff),pool));
00844 } else {
00845 noder->Coeff -= node2->Coeff;
00846 if (noder->Coeff == 0) {
00847 if (noder == iterr.First()) {
00848 CXX_DELETE(res->Remove_Headnode(),pool);
00849 } else {
00850 CXX_DELETE(res->Remove(prevnoder,noder),pool);
00851 }
00852 }
00853 }
00854 }
00855 if (res->Is_Empty()) return (NULL);
00856 return(res);
00857 }
00858
00859
00860
00861
00862 INTSYMB_LIST *Add(INTSYMB_LIST *list1, INTSYMB_LIST *list2,
00863 MEM_POOL *pool)
00864 {
00865 INTSYMB_LIST *res = CXX_NEW(INTSYMB_LIST,pool);
00866 if (list1) res->Init(list1,pool);
00867 if (!list2) return (res);
00868
00869 INTSYMB_ITER iter2(list2);
00870 for (INTSYMB_NODE *node2 = iter2.First(); !iter2.Is_Empty();
00871 node2 = iter2.Next()) {
00872
00873 INTSYMB_ITER iterr(res);
00874 INTSYMB_NODE *noder=iterr.First(), *prevnoder=NULL;
00875 while (!iterr.Is_Empty() && !(noder->Symbol == node2->Symbol)) {
00876 prevnoder = noder;
00877 noder = iterr.Next();
00878 }
00879 if (iterr.Is_Empty()) {
00880 res->Prepend(CXX_NEW(INTSYMB_NODE(node2->Symbol,node2->Coeff),pool));
00881 } else {
00882 noder->Coeff += node2->Coeff;
00883 if (noder->Coeff == 0) {
00884 if (noder == iterr.First()) {
00885 CXX_DELETE(res->Remove_Headnode(),pool);
00886 } else {
00887 CXX_DELETE(res->Remove(prevnoder,noder),pool);
00888 }
00889 }
00890 }
00891 }
00892 if (res->Is_Empty()) return (NULL);
00893 return(res);
00894 }
00895
00896
00897
00898 INTSYMB_LIST *Mul(INT c, INTSYMB_LIST *list, MEM_POOL *pool)
00899 {
00900 if (list == NULL || c == 0)
00901 return NULL;
00902
00903 INTSYMB_LIST *res = CXX_NEW(INTSYMB_LIST,pool);
00904 res->Init(list,pool);
00905
00906 INTSYMB_ITER iter(res);
00907 for (INTSYMB_NODE* node = iter.First(); !iter.Is_Empty(); node = iter.Next())
00908 node->Coeff *= c;
00909
00910 return(res);
00911 }
00912
00913
00914 void INTSYMB_NODE::Print(FILE *fp) const
00915 {
00916 char bf[MAX_TLOG_CHARS];
00917 Print(bf, 0);
00918 fprintf(fp, "%s", bf);
00919 }
00920
00921 INT INTSYMB_NODE::Print(char* bf, INT ccount) const
00922 {
00923 INT new_ccount = ccount;
00924 new_ccount = snprintfd(bf, new_ccount, MAX_TLOG_CHARS, Coeff);
00925 new_ccount = snprintfs(bf, new_ccount, MAX_TLOG_CHARS, "*");
00926 new_ccount = Symbol.Print(bf, new_ccount);
00927 return new_ccount;
00928 }
00929
00930 void SUMPROD_LIST::Print(FILE *fp) const
00931 {
00932 char bf[MAX_TLOG_CHARS];
00933 Print(bf, 0);
00934 fprintf(fp, "%s", bf);
00935 }
00936
00937 INT SUMPROD_LIST::Print(char* bf, INT ccount) const
00938 {
00939 INT new_ccount = ccount;
00940 SUMPROD_CONST_ITER iter(this);
00941 for (const SUMPROD_NODE *node = iter.First(); !iter.Is_Empty();
00942 node = iter.Next()) {
00943 new_ccount = snprintfs(bf, new_ccount, MAX_TLOG_CHARS, "+ ");
00944 new_ccount = node->Print(bf, new_ccount);
00945 }
00946 return new_ccount;
00947 }
00948
00949 INT SUMPROD_LIST::Negate_Me()
00950 {
00951 SUMPROD_ITER iter(this);
00952 for (SUMPROD_NODE *node = iter.First(); !iter.Is_Empty();
00953 node=iter.Next()) {
00954 INT64 coeff = -node->Coeff;
00955 if ((coeff >= (INT32_MAX-1)) || (coeff<=(INT32_MIN+1))) {
00956 return 0;
00957 }
00958 node->Coeff = coeff;
00959 }
00960 return 1;
00961 }
00962
00963 void SUMPROD_LIST::Merge(SUMPROD_LIST *sl)
00964 {
00965 while (!sl->Is_Empty()) Append(sl->Remove_Headnode());
00966 }
00967
00968
00969 BOOL SUMPROD_LIST::operator ==(const SUMPROD_LIST& sl) const
00970 {
00971 SUMPROD_CONST_ITER iter(this);
00972 SUMPROD_CONST_ITER iter2(&sl);
00973 const SUMPROD_NODE *node2 = iter2.First();
00974 for (const SUMPROD_NODE *node=iter.First(); !iter.Is_Empty(); ) {
00975 if (iter2.Is_Empty() || !(*node == *node2)) return(FALSE);
00976 node = iter.Next();
00977 node2 = iter2.Next();
00978 }
00979 if (!iter2.Is_Empty()) return(FALSE);
00980 return (TRUE);
00981 }
00982
00983
00984 void SUMPROD_LIST::Init(SUMPROD_LIST *sp,MEM_POOL *mem_pool)
00985 {
00986 SUMPROD_ITER iter(sp);
00987 for (SUMPROD_NODE *node = iter.First(); !iter.Is_Empty();
00988 node=iter.Next()) {
00989 Append(CXX_NEW(SUMPROD_NODE(node,mem_pool),mem_pool));
00990 }
00991 }
00992
00993 SUMPROD_LIST::~SUMPROD_LIST()
00994 {
00995 while (!Is_Empty()) CXX_DELETE(Remove_Headnode(),Default_Mem_Pool);
00996 }
00997
00998 void SUMPROD_NODE::Print(FILE *fp) const
00999 {
01000 char bf[MAX_TLOG_CHARS];
01001 Print(bf, 0);
01002 fprintf(fp, "%s", bf);
01003 }
01004
01005 INT SUMPROD_NODE::Print(char* bf, INT ccount) const
01006 {
01007 INT new_ccount = ccount;
01008 new_ccount = snprintfd(bf, new_ccount, MAX_TLOG_CHARS, Coeff);
01009 new_ccount = snprintfs(bf, new_ccount, MAX_TLOG_CHARS, "*");
01010 new_ccount = Prod_List->Print(bf, new_ccount, TRUE);
01011 return new_ccount;
01012 }
01013
01014 void SYMBOL_LIST::Print(FILE *fp, BOOL starsep) const
01015 {
01016 char bf[MAX_TLOG_CHARS];
01017 Print(bf, 0, starsep);
01018 fprintf(fp, "%s", bf);
01019 }
01020
01021 INT SYMBOL_LIST::Print(char* bf, INT ccount, BOOL starsep) const
01022 {
01023 INT new_ccount = ccount;
01024 SYMBOL_CONST_ITER iter(this);
01025 for (const SYMBOL_NODE *node = iter.First(); !iter.Is_Empty();
01026 node=iter.Next()) {
01027 new_ccount = node->Print(bf, new_ccount);
01028 if (iter.Peek_Next() != NULL) {
01029 new_ccount = snprintfs(bf, new_ccount, MAX_TLOG_CHARS,
01030 starsep ? "*":",");
01031 }
01032 }
01033 return new_ccount;
01034 }
01035
01036 BOOL SYMBOL_LIST::Contains(const SYMBOL *s)
01037 {
01038 SYMBOL_CONST_ITER iter(this);
01039 for (const SYMBOL_NODE *node = iter.First(); !iter.Is_Empty();
01040 node=iter.Next()) {
01041 if (node->Symbol == *s) return TRUE;
01042 }
01043 return FALSE;
01044 }
01045
01046 BOOL SYMBOL_LIST::operator ==(const SYMBOL_LIST& sl) const
01047 {
01048 SYMBOL_CONST_ITER iter(this);
01049 SYMBOL_CONST_ITER iter2(&sl);
01050 const SYMBOL_NODE *node2 = iter2.First();
01051 for (const SYMBOL_NODE *node=iter.First(); !iter.Is_Empty(); ) {
01052 if (iter2.Is_Empty() || !(*node == *node2)) return(FALSE);
01053 node = iter.Next();
01054 node2 = iter2.Next();
01055 }
01056 if (!iter2.Is_Empty()) return(FALSE);
01057 return (TRUE);
01058 }
01059
01060 void SYMBOL_LIST::Init(const SYMBOL_LIST *sl,MEM_POOL *mem_pool)
01061 {
01062 SYMBOL_CONST_ITER iter(sl);
01063 for (const SYMBOL_NODE *node = iter.First(); !iter.Is_Empty();
01064 node=iter.Next()) {
01065 Append(CXX_NEW(SYMBOL_NODE(node),mem_pool));
01066 }
01067 }
01068
01069 SYMBOL_LIST::~SYMBOL_LIST()
01070 {
01071 while (!Is_Empty()) CXX_DELETE(Remove_Headnode(),Default_Mem_Pool);
01072 }
01073
01074 void SYMBOL_NODE::Print(FILE *fp) const
01075 {
01076 char bf[MAX_TLOG_CHARS];
01077 Print(bf, 0);
01078 fprintf(fp, "%s", bf);
01079 }
01080
01081 INT SYMBOL_NODE::Print(char* bf, INT ccount) const
01082 {
01083 INT new_ccount = ccount;
01084 new_ccount = Symbol.Print(bf, new_ccount);
01085 return new_ccount;
01086 }
01087
01088 void SYMBOL::Print(FILE *fp) const
01089 {
01090 char bf[MAX_TLOG_CHARS];
01091 Print(bf, 0);
01092 fprintf(fp, "%s", bf);
01093 }
01094
01095 INT SYMBOL::Print(char* bf, INT ccount) const
01096 {
01097
01098
01099
01100
01101
01102 INT new_ccount = ccount;
01103 if (_is_formal) {
01104 new_ccount = snprintfs(bf, new_ccount, MAX_TLOG_CHARS, "#");
01105 new_ccount = snprintfd(bf, new_ccount, MAX_TLOG_CHARS, u._formal_number);
01106 } else {
01107 const INT bufsz = 256;
01108 char buf[bufsz];
01109 (void) Name(buf, bufsz);
01110 new_ccount = snprintfs(bf, new_ccount, MAX_TLOG_CHARS, buf);
01111 }
01112 return new_ccount;
01113 }
01114
01115 char* SYMBOL::Name() const
01116 {
01117 const INT bufsz = 128;
01118 static char name[bufsz];
01119 if (_is_formal) {
01120 sprintf(name, "#%d", u._formal_number);
01121 return name;
01122 } else {
01123 return Name(name, bufsz);
01124 }
01125 }
01126
01127 static INT Num_Chars_Needed(INT number)
01128 {
01129 INT value = number;
01130 if (value == 0)
01131 return 2;
01132 INT count = 1;
01133 if (value < 0) {
01134 value = -value;
01135 count++;
01136 }
01137 while (value > 0) {
01138 value /= 10;
01139 count++;
01140 }
01141 return count;
01142 }
01143
01144 char* SYMBOL::Name(char* buf, INT bufsz) const
01145 {
01146 if (buf == NULL) {
01147 DevWarn("SYMBOL::Name(buf, bufsz) shouldn't be called with buf == NULL");
01148 return Name();
01149 }
01150 if (bufsz < 1) {
01151 DevWarn("SYMBOL::Name(buf, bufsz) shouldn't be called with bufsz < 1");
01152 return NULL;
01153 }
01154 if (_is_formal) {
01155 INT chars = Num_Chars_Needed(u._formal_number);
01156 char* goalname = (char*) alloca(chars + 1);
01157 sprintf(goalname, "#%d", u._formal_number);
01158 if (bufsz < chars + 1) {
01159 return NULL;
01160 } else {
01161 strcpy(buf, goalname);
01162 return buf;
01163 }
01164 }
01165
01166 char* goalname;
01167 INT max_woff_len = 3*sizeof(WN_OFFSET);
01168
01169
01170
01171 if (u._st == NULL) {
01172 goalname = (char*) alloca(max_woff_len + strlen("$null_st") + 2);
01173 sprintf(goalname, "$null_st.%d", WN_Offset());
01174 }
01175 else if (ST_class(u._st) == CLASS_PREG) {
01176 const char* name;
01177 BOOL use_woff = TRUE;
01178 if (WN_Offset() > Last_Dedicated_Preg_Offset) {
01179 name = Preg_Name(WN_Offset());
01180 if (name == NULL || name[0] == '\0')
01181 name = "$preg.noname";
01182 else if (strcmp(name,"<preg>") == 0)
01183 name = "preg";
01184 else
01185 use_woff = FALSE;
01186 }
01187 else
01188 name = "$preg.dedicated";
01189 goalname = (char*) alloca(max_woff_len + strlen(name) + 2);
01190 if (use_woff)
01191 sprintf(goalname, "%s%d", name, WN_Offset());
01192 else
01193 sprintf(goalname, "%s", name);
01194 }
01195 else {
01196 BOOL slow = ST_Offset() != 0 || WN_Offset() != 0;
01197 char* true_name = ST_name(u._st);
01198
01199 char* name = 0;
01200 if (ST_Base()) {
01201 name = ST_name(ST_Base());
01202 if (name == NULL || name[0] == '\0') {
01203 name = (char*) alloca(strlen("$noname0x") + 10);
01204 sprintf(name, "$noname0x%p", ST_Base());
01205 }
01206 }
01207 else
01208 name = const_cast<char*>("$nobase");
01209
01210 goalname =
01211 (char*) alloca(strlen(name) + strlen(true_name) + 30 + max_woff_len);
01212 if (slow || ST_Base() != u._st)
01213 sprintf(goalname, "%s(%s.%lld.%d)", true_name,
01214 name, ST_Offset(), WN_Offset());
01215 else
01216 sprintf(goalname, "%s", name);
01217 }
01218
01219
01220
01221 if (strlen(goalname) < bufsz)
01222 strcpy(buf, goalname);
01223 else {
01224 strncpy(buf, goalname, bufsz-1);
01225 buf[bufsz-1] = '\0';
01226 DevWarn("Symbol name %s shortened to %s", goalname, buf);
01227 }
01228
01229 return buf;
01230 }
01231
01232 char* SYMBOL::Prompf_Name() const
01233 {
01234 const INT name_sz = 128;
01235 static char buf[name_sz];
01236 const char* name = NULL;
01237 INT i;
01238
01239 if (_is_formal) {
01240 sprintf(buf, "#%d", u._formal_number);
01241 return buf;
01242 }
01243
01244 if (u._st == NULL) {
01245 name = "<NULL SYMBOL>";
01246 } else if (ST_class(u._st) == CLASS_PREG) {
01247 if (WN_Offset() > Last_Dedicated_Preg_Offset)
01248 name = Preg_Name(WN_Offset());
01249 else
01250 name = "<DEDICATED PREG>";
01251 } else {
01252 name = ST_name(St());
01253 }
01254
01255 for (i = 0; i < name_sz - 1 && name[i] != '\0'; i++)
01256 buf[i] = name[i];
01257 buf[i] = '\0';
01258 return buf;
01259 }
01260
01261
01262
01263
01264 #ifdef LNO
01265 static SRCPOS Find_Line(WN *wn)
01266 {
01267 WN *tmp_wn = wn;
01268 while (OPCODE_is_expression(WN_opcode(tmp_wn))) {
01269 tmp_wn = LWN_Get_Parent(tmp_wn);
01270 }
01271 return WN_Get_Linenum(tmp_wn);
01272 }
01273 #endif
01274
01275
01276
01277 void ACCESS_ARRAY::Set_Array(WN *wn, DOLOOP_STACK *stack)
01278 {
01279 INT32 i;
01280
01281 Is_True(WN_operator(wn) == OPR_ARRAY,
01282 ("ACCESS_ARRAY::Set_Array called on a non-array"));
01283 Is_True(_num_vec == WN_num_dim(wn),
01284 ("ACCESS_ARRAY::Set_Array called with an inconsistent number of dimensions"));
01285 Too_Messy = FALSE;
01286
01287 for (i=0; i<_num_vec; i++) {
01288 _dim[i].Set(WN_array_index(wn,i),stack,1,0,LNO_Allow_Nonlinear);
01289 }
01290
01291 #ifdef LNO
01292 if (LNO_Allow_Delinearize)
01293 Delinearize(stack,wn);
01294 #endif
01295
01296
01297 for (i=0; i<_num_vec; i++) {
01298 if (_dim[i].Contains_Non_Lin_Symb()) {
01299 _dim[i].Update_Non_Const_Loops_Nonlinear(stack);
01300 }
01301 }
01302
01303
01304 WN *base = WN_array_base(wn);
01305 if (WN_operator(base) == OPR_LDID) {
01306 Update_Non_Const_Loops(base,stack);
01307 #ifdef KEY // Bug 5057 - tolerate base addresses of the form (+ const LDID).
01308 } else if (WN_operator(base) == OPR_ADD &&
01309 (WN_operator(WN_kid0(base)) == OPR_INTCONST &&
01310 WN_operator(WN_kid1(base)) == OPR_LDID)) {
01311 Update_Non_Const_Loops(WN_kid1(base),stack);
01312 } else if (WN_operator(base) == OPR_ADD &&
01313 (WN_operator(WN_kid1(base)) == OPR_INTCONST &&
01314 WN_operator(WN_kid0(base)) == OPR_LDID)) {
01315 Update_Non_Const_Loops(WN_kid0(base),stack);
01316 #endif
01317 } else if (WN_operator(base) != OPR_LDA) {
01318 for (INT32 i=0; i<_num_vec; i++) {
01319 Dim(i)->Max_Non_Const_Loops(stack->Elements());
01320 }
01321 }
01322
01323
01324
01325 for (i=1; i<WN_num_dim(wn); i++) {
01326 Update_Non_Const_Loops(WN_array_dim(wn,i),stack);
01327 }
01328
01329
01330
01331
01332
01333
01334 #ifdef LNO
01335 if (_num_vec == 1) {
01336 if (WN_operator(base) == OPR_LDA) {
01337 #ifdef _NEW_SYMTAB
01338 if (ST_base_idx(WN_st(base)) != ST_st_idx(WN_st(base)) &&
01339 #else
01340 if ((ST_sclass(WN_st(base)) == SCLASS_BASED) &&
01341 #endif
01342 (ST_sclass(ST_base(WN_st(base))) == SCLASS_COMMON)) {
01343 WN *array_dim = WN_array_dim(wn,0);
01344 if (WN_operator(array_dim) == OPR_INTCONST) {
01345 INT64 dim = WN_const_val(array_dim);
01346 if (!Too_Messy && !_dim[0].Too_Messy &&
01347 !_dim[0].Contains_Lin_Symb() &&
01348 !_dim[0].Contains_Non_Lin_Symb()) {
01349 INT is_ai= TRUE;
01350 ACCESS_VECTOR *av = &_dim[0];
01351 for (INT i=0; i<av->Nest_Depth()-1; i++) {
01352 if (av->Loop_Coeff(i)) is_ai = FALSE;
01353 }
01354 if (av->Loop_Coeff(av->Nest_Depth()-1) != 1) is_ai = FALSE;
01355
01356 WN *parent = LWN_Get_Parent(wn);
01357 while (WN_opcode(parent) != OPC_DO_LOOP && is_ai) {
01358 if (OPCODE_is_scf(WN_opcode(parent))) is_ai=FALSE;
01359 parent = LWN_Get_Parent(parent);
01360 }
01361 if (is_ai) {
01362 DO_LOOP_INFO *dli = Get_Do_Loop_Info(stack->Top_nth(0));
01363 ACCESS_ARRAY *uba = dli->UB;
01364 if (!uba->Too_Messy) {
01365 if (uba->Num_Vec() == 1) {
01366 ACCESS_VECTOR *ub = uba->Dim(0);
01367 INT const_bound = TRUE;
01368 if (!ub->Too_Messy && !ub->Contains_Lin_Symb() &&
01369 !ub->Contains_Non_Lin_Symb()) {
01370 for (INT i=0; i<ub->Nest_Depth()-1; i++) {
01371 if (ub->Loop_Coeff(i)) const_bound = FALSE;
01372 }
01373 if (ub->Loop_Coeff(ub->Nest_Depth()-1) != 1) {
01374 const_bound = FALSE;
01375 }
01376 if (const_bound) {
01377 if (ub->Const_Offset > dim) {
01378 ErrMsgSrcpos(EC_LNO_Generic,Find_Line(wn),
01379 "Out of bounds array reference, results unpredictable."
01380 );
01381 }
01382 }
01383 }
01384 }
01385 }
01386 }
01387 }
01388 }
01389 }
01390 }
01391 }
01392 #endif
01393 }
01394
01395 #ifdef LNO
01396
01397
01398 void ACCESS_ARRAY::Delinearize(DOLOOP_STACK *stack, WN *wn)
01399 {
01400 if (Too_Messy) return;
01401 INT i=0;
01402 while ((i<_num_vec) &&
01403 (Dim(i)->Too_Messy || !Dim(i)->Contains_Non_Lin_Symb())) i++;
01404
01405
01406 if (i < _num_vec) {
01407 if (LNO_Debug_Delinearization) {
01408 fprintf(TFile,"Trying to delinearize \n");
01409 fprintf(TFile,"Before delinearization the access array was");
01410 Print(TFile); fprintf(TFile,"\n");
01411 }
01412 if (Delinearize(stack,i,wn)) {
01413
01414
01415 Delinearize(stack, wn);
01416 if (LNO_Debug_Delinearization) {
01417 fprintf(TFile,"succeeded \n");
01418 fprintf(TFile,"After delinearization the access array is");
01419 Print(TFile); fprintf(TFile,"\n");
01420 }
01421 } else if (LNO_Debug_Delinearization) {
01422 fprintf(TFile,"failed \n");
01423 }
01424 }
01425 }
01426
01427
01428
01429 INT ACCESS_ARRAY::Delinearize(DOLOOP_STACK *stack, INT dim, WN *wn)
01430 {
01431 ACCESS_VECTOR *av = Dim(dim);
01432 Is_True(av->Non_Lin_Symb && !av->Non_Lin_Symb->Is_Empty(),
01433 ("ACCESS_ARRAY::Delinearize called on linear vector"));
01434
01435
01436
01437
01438 SUMPROD_CONST_ITER tmp_iter(av->Non_Lin_Symb);
01439 SYMBOL_LIST *first = tmp_iter.First()->Prod_List;
01440 SYMBOL_CONST_ITER iter(first);
01441 const SYMBOL *delin_symbol = NULL;
01442 for (const SYMBOL_NODE *node = iter.First(); !iter.Is_Empty();
01443 node=iter.Next()) {
01444 if (!node->Is_Loop_Var) {
01445 delin_symbol = &node->Symbol;
01446 BOOL this_one_good = TRUE;
01447 SUMPROD_CONST_ITER iter2(av->Non_Lin_Symb);
01448 const SUMPROD_NODE *node2 = iter2.First();
01449 for (node2 = iter2.Next(); !iter2.Is_Empty() && this_one_good ;
01450 node2=iter2.Next()) {
01451 this_one_good &= node2->Prod_List->Contains(delin_symbol);
01452 }
01453 if (this_one_good && av->Can_Delinearize(wn,delin_symbol)) {
01454 return Delinearize(stack,dim,delin_symbol);
01455 }
01456 }
01457 }
01458 return FALSE;
01459 }
01460
01461
01462
01463
01464 BOOL ACCESS_VECTOR::Can_Delinearize(WN *wn, const SYMBOL *delin_symbol)
01465 {
01466
01467 MEM_POOL_Push(&LNO_local_pool);
01468 ACCESS_VECTOR *tmp =CXX_NEW(ACCESS_VECTOR(Nest_Depth(),&LNO_local_pool),
01469 &LNO_local_pool);
01470 tmp->Too_Messy = FALSE;
01471 tmp->Const_Offset = Const_Offset;
01472 for (INT i=0; i<Nest_Depth(); i++) {
01473 tmp->Set_Loop_Coeff(i,Loop_Coeff(i));
01474 }
01475
01476 tmp->Lin_Symb = CXX_NEW(INTSYMB_LIST,&LNO_local_pool);
01477 INTSYMB_ITER lin_iter(Lin_Symb);
01478 for (INTSYMB_NODE *lin_node=lin_iter.First(); !lin_iter.Is_Empty();
01479 lin_node = lin_iter.Next()) {
01480 if (!(lin_node->Symbol == *delin_symbol)) {
01481 tmp->Lin_Symb->Append(CXX_NEW(
01482 INTSYMB_NODE(lin_node->Symbol,lin_node->Coeff), &LNO_local_pool));
01483 }
01484 }
01485
01486
01487
01488
01489
01490 tmp->Const_Offset = -tmp->Const_Offset-1;
01491 if (Is_Consistent_Condition(tmp,wn)) {
01492 MEM_POOL_Pop(&LNO_local_pool);
01493 return FALSE;
01494 }
01495
01496
01497 tmp->Const_Offset++;
01498 tmp->Negate_Me();
01499 INTSYMB_NODE *delin_node =
01500 CXX_NEW(INTSYMB_NODE(*delin_symbol,1),&LNO_local_pool);
01501 tmp->Lin_Symb->Prepend(delin_node);
01502
01503 if (Is_Consistent_Condition(tmp,wn)) {
01504 MEM_POOL_Pop(&LNO_local_pool);
01505 return FALSE;
01506 }
01507 MEM_POOL_Pop(&LNO_local_pool);
01508
01509 return TRUE;
01510 }
01511
01512 #endif
01513
01514
01515
01516
01517
01518 void ACCESS_VECTOR::Update_Non_Const_Loops_Nonlinear(DOLOOP_STACK *stack)
01519 {
01520 if (!Non_Lin_Symb) return;
01521 SUMPROD_CONST_ITER sp_iter(Non_Lin_Symb);
01522 for (const SUMPROD_NODE *sp_node=sp_iter.First(); !sp_iter.Is_Empty();
01523 sp_node = sp_iter.Next()) {
01524 SYMBOL_LIST *sl = sp_node->Prod_List;
01525 SYMBOL_CONST_ITER iter(sl);
01526 for (const SYMBOL_NODE *node = iter.First(); !iter.Is_Empty();
01527 node=iter.Next()) {
01528 if (node->Is_Loop_Var) {
01529 SYMBOL symbol = node->Symbol;
01530 INT i = 0;
01531 while (! (SYMBOL(WN_index(stack->Bottom_nth(i))) ==
01532 symbol)) i++;
01533 _non_const_loops = MAX(_non_const_loops,i+1);
01534 }
01535 }
01536 }
01537 }
01538
01539 #ifdef LNO
01540
01541
01542 INT ACCESS_ARRAY::Delinearize(DOLOOP_STACK *stack, INT dim,
01543 const SYMBOL *delin_symbol)
01544 {
01545 ACCESS_VECTOR *av = Dim(dim);
01546
01547
01548
01549 ACCESS_VECTOR *new_dim =
01550 CXX_NEW_ARRAY(ACCESS_VECTOR,Num_Vec()+1,_mem_pool);
01551 INT i;
01552 for (i=0; i<dim; i++) {
01553 new_dim[i].Init(Dim(i),_mem_pool);
01554 }
01555 for (i=dim+1; i<Num_Vec(); i++) {
01556 new_dim[i+1].Init(Dim(i),_mem_pool);
01557 }
01558
01559
01560
01561 new_dim[dim].Init(av->Nest_Depth(),_mem_pool);
01562 new_dim[dim].Too_Messy = FALSE;
01563 new_dim[dim].Delinearized_Symbol = CXX_NEW(SYMBOL(delin_symbol),_mem_pool);
01564
01565
01566 INTSYMB_ITER lin_iter(av->Lin_Symb);
01567 INTSYMB_NODE* lin_node = 0;
01568 for (lin_node=lin_iter.First(); !lin_iter.Is_Empty();
01569 lin_node = lin_iter.Next()) {
01570 if (lin_node->Symbol == *delin_symbol) {
01571 INT64 coeff = new_dim[dim].Const_Offset + lin_node->Coeff;
01572 if ((coeff >= (INT32_MAX-1)) || (coeff<=(INT32_MIN+1))) {
01573 return FALSE;
01574 }
01575 new_dim[dim].Const_Offset = coeff;
01576 }
01577 }
01578
01579
01580 SUMPROD_CONST_ITER nonlin_iter(av->Non_Lin_Symb);
01581 for (const SUMPROD_NODE *nonlin_node= nonlin_iter.First();
01582 !nonlin_iter.Is_Empty(); nonlin_node=nonlin_iter.Next()) {
01583 SYMBOL_LIST *prod_list = nonlin_node->Prod_List;
01584
01585
01586 INT length=prod_list->Len();
01587 if (length == 1) {
01588 INT64 coeff = new_dim[dim].Const_Offset + nonlin_node->Coeff;
01589 if ((coeff >= (INT32_MAX-1)) || (coeff<=(INT32_MIN+1))) {
01590 return FALSE;
01591 }
01592 new_dim[dim].Const_Offset = coeff;
01593 } else if (length==2) {
01594 SYMBOL_CONST_ITER iter(prod_list);
01595 const SYMBOL_NODE *node = iter.First();
01596 if (node->Symbol == *delin_symbol) node = iter.Next();
01597 new_dim[dim].Add_Symbol(nonlin_node->Coeff,node->Symbol,stack,NULL);
01598 if (new_dim[dim].Too_Messy) return FALSE;
01599 } else {
01600 SYMBOL_LIST *new_prod_list = CXX_NEW(SYMBOL_LIST,_mem_pool);
01601 SUMPROD_NODE *new_node =
01602 CXX_NEW(SUMPROD_NODE(new_prod_list,nonlin_node->Coeff),_mem_pool);
01603 SYMBOL_CONST_ITER iter(nonlin_node->Prod_List);
01604 BOOL seen_delin_symbol = FALSE;
01605 for (const SYMBOL_NODE *node= iter.First();
01606 !iter.Is_Empty(); node=iter.Next()) {
01607 if (seen_delin_symbol || !(node->Symbol == *delin_symbol)) {
01608 SYMBOL_NODE *new_symb_node = CXX_NEW(SYMBOL_NODE(node->Symbol,
01609 node->Is_Loop_Var),_mem_pool);
01610 new_prod_list->Append(new_symb_node);
01611 } else {
01612 seen_delin_symbol = TRUE;
01613 }
01614 }
01615 if (!new_dim[dim].Non_Lin_Symb) {
01616 new_dim[dim].Non_Lin_Symb = CXX_NEW(SUMPROD_LIST,_mem_pool);
01617 }
01618 new_dim[dim].Non_Lin_Symb->Append(new_node);
01619 }
01620 }
01621
01622
01623 new_dim[dim+1].Init(av->Nest_Depth(),_mem_pool);
01624 new_dim[dim+1].Too_Messy = FALSE;
01625 new_dim[dim+1].Const_Offset = av->Const_Offset;
01626 for (i=0; i<av->Nest_Depth(); i++) {
01627 new_dim[dim+1].Set_Loop_Coeff(i,av->Loop_Coeff(i));
01628 }
01629 new_dim[dim+1].Lin_Symb = CXX_NEW(INTSYMB_LIST,_mem_pool);
01630 lin_iter.Init(av->Lin_Symb);
01631 for (lin_node=lin_iter.First(); !lin_iter.Is_Empty();
01632 lin_node = lin_iter.Next()) {
01633 if (!(lin_node->Symbol == *delin_symbol)) {
01634 new_dim[dim+1].Lin_Symb->Append(CXX_NEW(
01635 INTSYMB_NODE(lin_node->Symbol,lin_node->Coeff), _mem_pool));
01636 }
01637 }
01638
01639 if (av->Non_Const_Loops()) {
01640 if (new_dim[dim].Contains_Non_Lin_Symb() ||
01641 new_dim[dim].Contains_Lin_Symb()) {
01642 new_dim[dim].Set_Non_Const_Loops(av->Non_Const_Loops());
01643 }
01644 if (new_dim[dim+1].Contains_Non_Lin_Symb() ||
01645 new_dim[dim+1].Contains_Lin_Symb()) {
01646 new_dim[dim+1].Set_Non_Const_Loops(av->Non_Const_Loops());
01647 }
01648 }
01649
01650 _dim = new_dim;
01651 _num_vec++;
01652 return TRUE;
01653 }
01654 #endif
01655
01656
01657 void ACCESS_ARRAY::Set_LB(WN *wn, DOLOOP_STACK *stack, INT64 step)
01658 {
01659 Too_Messy = FALSE;
01660 if (step > 0) {
01661
01662 if ((Num_Vec() == 1) || (WN_operator(wn) == OPR_MAX)) {
01663 Set_LB_r(wn,stack,0,step);
01664
01665 } else if (WN_operator(wn) == OPR_SUB) {
01666 Set_LB_r(WN_kid0(wn),stack,0,step);
01667 for (INT i=0; i<Num_Vec(); i++) {
01668 _dim[i].Add(WN_kid1(wn),stack,-1);
01669 }
01670 } else if (WN_operator(wn) == OPR_ADD) {
01671 if (WN_operator(WN_kid0(wn)) == OPR_MAX) {
01672 Set_LB_r(WN_kid0(wn),stack,0,step);
01673 for (INT i=0; i<Num_Vec(); i++) {
01674 _dim[i].Add(WN_kid1(wn),stack,1);
01675 }
01676 } else {
01677 Set_LB_r(WN_kid1(wn),stack,0,step);
01678 for (INT i=0; i<Num_Vec(); i++) {
01679 _dim[i].Add(WN_kid0(wn),stack,1);
01680 }
01681 }
01682 }
01683 } else {
01684
01685 if ((Num_Vec() == 1) || (WN_operator(wn) == OPR_MIN)) {
01686 Set_LB_r(wn,stack,0,step);
01687
01688 } else if (WN_operator(wn) == OPR_SUB) {
01689 Set_LB_r(WN_kid0(wn),stack,0,step);
01690 for (INT i=0; i<Num_Vec(); i++) {
01691 _dim[i].Add(WN_kid1(wn),stack,1);
01692 }
01693 } else if (WN_operator(wn) == OPR_ADD) {
01694 if (WN_operator(WN_kid0(wn)) == OPR_MIN) {
01695 Set_LB_r(WN_kid0(wn),stack,0,step);
01696 for (INT i=0; i<Num_Vec(); i++) {
01697 _dim[i].Add(WN_kid1(wn),stack,-1);
01698 }
01699 } else {
01700 Set_LB_r(WN_kid1(wn),stack,0,step);
01701 for (INT i=0; i<Num_Vec(); i++) {
01702 _dim[i].Add(WN_kid0(wn),stack,-1);
01703 }
01704 }
01705 }
01706 }
01707 }
01708
01709
01710 INT ACCESS_ARRAY::Set_LB_r(WN *wn, DOLOOP_STACK *stack, INT i, INT64 step)
01711 {
01712 if ((step > 0) && WN_operator(wn) == OPR_MAX) {
01713 INT res = Set_LB_r(WN_kid(wn,0),stack,i,step);
01714 res = Set_LB_r(WN_kid(wn,1),stack,res,step);
01715 return(res);
01716 } else if ((step < 0) && WN_operator(wn) == OPR_MIN) {
01717 INT res = Set_LB_r(WN_kid(wn,0),stack,i,step);
01718 res = Set_LB_r(WN_kid(wn,1),stack,res,step);
01719 return(res);
01720 } else if ((step > 0) && WN_operator(wn) ==
01721 OPR_INTRINSIC_OP) {
01722 INT32 intr = WN_intrinsic(wn);
01723 if ((step > 0) &&
01724 ((intr == INTRN_I4DIVFLOOR) || (intr == INTRN_I8DIVFLOOR) ||
01725 (intr == INTRN_U4DIVFLOOR) || (intr == INTRN_U8DIVFLOOR))) {
01726 WN *const_kid = WN_kid0 (WN_kid1 (wn));
01727 if ((WN_operator (const_kid) == OPR_INTCONST) &&
01728 (WN_const_val (const_kid) > 0) &&
01729 (WN_const_val (const_kid) < INT32_MAX)) {
01730 FmtAssert (OPR_PARM ==
01731 WN_operator (WN_kid0 (wn)),
01732 ("Child of an intrn not a parm!"));
01733 _dim[i].Set(WN_kid0 (WN_kid0 (wn)), stack, 1,
01734 1 - WN_const_val (const_kid));
01735 _dim[i].Const_Offset = - _dim[i].Const_Offset;
01736 INT depth = _dim[i].Nest_Depth();
01737 _dim[i].Set_Loop_Coeff (depth-1, -WN_const_val (const_kid));
01738 _dim[i].Too_Messy = FALSE;
01739 } else
01740 _dim[i].Too_Messy = TRUE;
01741 return (i+1);
01742 } else if ((step > 0) &&
01743 ((intr == INTRN_I4DIVCEIL)||(intr == INTRN_I8DIVCEIL)||
01744 (intr == INTRN_U4DIVCEIL)||(intr == INTRN_U8DIVCEIL))) {
01745 WN *const_kid = WN_kid0 (WN_kid1 (wn));
01746 if ((WN_operator (const_kid) == OPR_INTCONST) &&
01747 (WN_const_val (const_kid) > 0) &&
01748 (WN_const_val (const_kid) < INT32_MAX)) {
01749 FmtAssert (OPR_PARM ==
01750 WN_operator (WN_kid0 (wn)),
01751 ("Child of an intrn not a parm!"));
01752 _dim[i].Set(WN_kid0 (WN_kid0 (wn)), stack, 1, 0);
01753 _dim[i].Const_Offset = - _dim[i].Const_Offset;
01754 INT depth = _dim[i].Nest_Depth();
01755 _dim[i].Set_Loop_Coeff (depth-1, -WN_const_val (const_kid));
01756 _dim[i].Too_Messy = FALSE;
01757 } else
01758 _dim[i].Too_Messy = TRUE;
01759 return (i+1);
01760 } else {
01761 _dim[i+1].Too_Messy = TRUE;
01762 return (i+1);
01763 }
01764 } else {
01765 INT depth = _dim[i].Nest_Depth();
01766 if (step > 0) {
01767 _dim[i].Set(wn,stack,1,0);
01768 if (_dim[i].Loop_Coeff(depth-1)) {
01769 _dim[i].Too_Messy = TRUE;
01770 } else {
01771 _dim[i].Set_Loop_Coeff (depth-1, -1);
01772 _dim[i].Const_Offset = - _dim[i].Const_Offset;
01773 }
01774 } else {
01775 _dim[i].Set(wn,stack,-1,0);
01776 if (_dim[i].Loop_Coeff(depth-1)) {
01777 _dim[i].Too_Messy = TRUE;
01778 } else {
01779 _dim[i].Set_Loop_Coeff (depth-1, 1);
01780 _dim[i].Const_Offset = - _dim[i].Const_Offset;
01781 }
01782 }
01783 return(i+1);
01784 }
01785 }
01786
01787
01788 void ACCESS_ARRAY::Set_UB(WN *compare, DOLOOP_STACK *stack)
01789 {
01790 Too_Messy = FALSE;
01791 INT sign,offset;
01792
01793 if (WN_operator(compare) == OPR_LE) {
01794 sign = 1;
01795 offset = 0;
01796 } else if (WN_operator(compare) == OPR_GE) {
01797 sign = -1;
01798 offset = 0;
01799 } else if (WN_operator(compare) == OPR_LT) {
01800 sign = 1;
01801 offset = 1;
01802 } else if (WN_operator(compare) == OPR_GT) {
01803 sign = -1;
01804 offset = 1;
01805 } else {
01806 Is_True(0, ("ACCESS_ARRAY::Set_UB: Unknown comparison "));
01807 }
01808
01809 if ((WN_operator(WN_kid0(compare)) == OPR_MIN) ||
01810 (WN_operator(WN_kid0(compare)) == OPR_MAX) ||
01811 (WN_operator(WN_kid0(compare)) == OPR_INTRINSIC_OP)) {
01812 for (INT i=0; i<Num_Vec(); i++) {
01813 _dim[i].Set(WN_kid1(compare),stack,-sign,offset);
01814 }
01815 if (!_dim[0].Too_Messy) {
01816 Set_UB_r(WN_kid0(compare),stack,0,-sign);
01817 }
01818 } else {
01819 for (INT i=0; i<Num_Vec(); i++) {
01820 _dim[i].Set(WN_kid0(compare),stack,sign,offset);
01821 }
01822 if (!_dim[0].Too_Messy) {
01823 Set_UB_r(WN_kid1(compare),stack,0,sign);
01824 }
01825 }
01826 }
01827
01828
01829
01830 INT ACCESS_ARRAY::Set_UB_r(WN *wn, DOLOOP_STACK *stack, INT i, INT sign)
01831 {
01832 OPERATOR oper = WN_operator(wn);
01833 if ((sign > 0) && oper == OPR_MIN) {
01834 INT res = Set_UB_r(WN_kid(wn,0),stack,i,sign);
01835 res = Set_UB_r(WN_kid(wn,1),stack,res,sign);
01836 return(res);
01837 } else if ((sign < 0) && oper == OPR_MAX) {
01838 INT res = Set_UB_r(WN_kid(wn,0),stack,i,sign);
01839 res = Set_UB_r(WN_kid(wn,1),stack,res,sign);
01840 return(res);
01841 } else if (oper == OPR_INTRINSIC_OP) {
01842 INT32 intr = WN_intrinsic(wn);
01843 if ((sign > 0) &&
01844 ((intr == INTRN_I4DIVFLOOR) || (intr == INTRN_I8DIVFLOOR) ||
01845 (intr == INTRN_U4DIVFLOOR) || (intr == INTRN_U8DIVFLOOR))) {
01846 WN *const_kid = WN_kid0(WN_kid1(wn));
01847 if ((WN_operator(const_kid) == OPR_INTCONST) &&
01848 (WN_const_val(const_kid) > 0)&&(WN_const_val(const_kid)<INT32_MAX)){
01849 _dim[i].Mul(WN_const_val(const_kid));
01850 _dim[i].Add(WN_kid0(WN_kid0(wn)),stack,-sign);
01851 _dim[i].Const_Offset = -_dim[i].Const_Offset;
01852 return(i+1);
01853 } else {
01854 _dim[i].Too_Messy = TRUE;
01855 return(i+1);
01856 }
01857 } else if ((sign < 0) &&
01858 ((intr == INTRN_I4DIVCEIL) || (intr == INTRN_I8DIVCEIL) ||
01859 (intr == INTRN_U4DIVCEIL) || (intr == INTRN_U8DIVCEIL))) {
01860 WN *const_kid = WN_kid0(WN_kid1(wn));
01861 if ((WN_operator(const_kid) == OPR_INTCONST) &&
01862 (WN_const_val(const_kid) > 0)&&(WN_const_val(const_kid)<INT32_MAX)) {
01863 _dim[i].Mul(WN_const_val(const_kid));
01864 _dim[i].Add(WN_kid0(WN_kid0(wn)),stack,-sign);
01865 _dim[i].Const_Offset = -_dim[i].Const_Offset;
01866 return(i+1);
01867 } else {
01868 _dim[i].Too_Messy = TRUE;
01869 return(i+1);
01870 }
01871 } else {
01872 _dim[i].Too_Messy = TRUE;
01873 return(i+1);
01874 }
01875 } else {
01876 _dim[i].Add(wn,stack,-sign);
01877 _dim[i].Const_Offset = -_dim[i].Const_Offset;
01878 return(i+1);
01879 }
01880 }
01881
01882
01883
01884 INT ACCESS_ARRAY::Set_IF(WN *wn, DOLOOP_STACK *stack, BOOL negate,
01885 BOOL is_and, INT i)
01886 {
01887 Too_Messy = FALSE;
01888 if (is_and && (WN_operator(wn) == OPR_LAND
01889 || WN_operator(wn) == OPR_CAND)) {
01890 INT res = Set_IF(WN_kid0(wn),stack,negate,is_and,i);
01891 return Set_IF(WN_kid1(wn),stack,negate,is_and,res);
01892 }
01893 if (!is_and && (WN_operator(wn) == OPR_LIOR
01894 || WN_operator(wn) == OPR_CIOR)) {
01895 INT res = Set_IF(WN_kid0(wn),stack,negate,is_and,i);
01896 return Set_IF(WN_kid1(wn),stack,negate,is_and,res);
01897 }
01898 _dim[i].Set_Condition(wn,stack,negate);
01899 return(i+1);
01900 }
01901
01902
01903
01904 void ACCESS_VECTOR::Set_Condition(WN *wn, DOLOOP_STACK *stack, BOOL negate)
01905 {
01906 Too_Messy = FALSE;
01907
01908 if (WN_operator(wn) == OPR_LNOT) {
01909 wn = WN_kid0(wn);
01910 negate = !negate;
01911 }
01912
01913
01914
01915
01916
01917 if (OPERATOR_is_compare(WN_operator(wn)) && MTYPE_is_unsigned(WN_desc(wn))) {
01918 Too_Messy = TRUE;
01919 return;
01920 }
01921
01922 INT sign,offset;
01923 sign = negate ? -1 : 1;
01924 if (WN_operator(wn) == OPR_LE) {
01925 offset = sign > 0 ? 0 : 1;
01926 } else if (WN_operator(wn) == OPR_GE) {
01927 offset = sign > 0 ? 0 : 1;
01928 sign = -sign;
01929 } else if (WN_operator(wn) == OPR_LT) {
01930 offset = sign > 0 ? 1 : 0;
01931 } else if (WN_operator(wn) == OPR_GT) {
01932 offset = sign > 0 ? 1 : 0;
01933 sign = -sign;
01934 } else if (WN_operator(wn) == OPR_INTCONST) {
01935 INT is_true = !(WN_const_val(wn) == 0);
01936 if (negate) is_true = !is_true;
01937 Set(wn,stack,0,0);
01938 if (is_true) {
01939 Const_Offset = 0;
01940 } else {
01941 Const_Offset = -1;
01942 }
01943 return;
01944 } else {
01945 Too_Messy = TRUE;
01946 return;
01947 }
01948
01949
01950 Set(WN_kid0(wn),stack,sign,offset);
01951
01952
01953 if (!Too_Messy) {
01954 Add(WN_kid1(wn),stack,-sign);
01955 Const_Offset = -Const_Offset;
01956 }
01957 }
01958
01959
01960
01961
01962
01963
01964
01965
01966 void ACCESS_VECTOR::Set(WN *wn, DOLOOP_STACK *stack,INT8 sign,INT offset,
01967 BOOL allow_nonlin)
01968 {
01969 Too_Messy = FALSE;
01970 Const_Offset = (INT64) offset;
01971 Non_Lin_Symb = NULL;
01972 Delinearized_Symbol = NULL;
01973 Add_Sum(wn,(INT64) sign,stack,allow_nonlin);
01974 }
01975
01976
01977 void ACCESS_VECTOR::Add(WN *wn, DOLOOP_STACK *stack,INT8 sign)
01978 {
01979 #ifdef LNO
01980 Add_Sum(wn,(INT64) sign,stack);
01981 #else
01982 Add_Sum(wn,(INT64) sign,stack,LNO_Allow_Nonlinear);
01983 #endif
01984 }
01985
01986 #ifdef KEY
01987
01988 static BOOL WN_Under_Array(WN *wn)
01989 {
01990 WN* parent = LWN_Get_Parent(wn);
01991 while(parent && WN_operator(parent) != OPR_DO_LOOP) {
01992 if (WN_operator(parent) == OPR_ARRAY)
01993 return TRUE;
01994 parent = LWN_Get_Parent(parent);
01995 }
01996 return FALSE;
01997 }
01998 #endif
01999
02000
02001 void ACCESS_VECTOR::Add_Sum(WN *wn, INT64 coeff, DOLOOP_STACK *stack,
02002 BOOL allow_nonlin)
02003 {
02004 if (Too_Messy) return;
02005
02006 if (WN_operator(wn) == OPR_ADD) {
02007 Add_Sum(WN_kid(wn,0),coeff,stack,allow_nonlin);
02008 Add_Sum(WN_kid(wn,1),coeff,stack,allow_nonlin);
02009 } else if (WN_operator(wn) == OPR_SUB) {
02010 Add_Sum(WN_kid(wn,0),coeff,stack,allow_nonlin);
02011 Add_Sum(WN_kid(wn,1),-coeff,stack,allow_nonlin);
02012 } else if (WN_operator(wn) == OPR_NEG) {
02013 Add_Sum(WN_kid(wn,0),-coeff,stack,allow_nonlin);
02014 } else if (WN_operator(wn) == OPR_MPY) {
02015 if (WN_operator(WN_kid(wn,0)) == OPR_INTCONST) {
02016 Add_Sum(WN_kid(wn,1),coeff*WN_const_val(WN_kid(wn,0)),stack,
02017 allow_nonlin);
02018 } else if (WN_operator(WN_kid(wn,1)) == OPR_INTCONST) {
02019 Add_Sum(WN_kid(wn,0),coeff*WN_const_val(WN_kid(wn,1)),stack,
02020 allow_nonlin);
02021 } else if (allow_nonlin) {
02022 if ((coeff >= (INT32_MAX-1)) || (coeff<=(INT32_MIN+1))) {
02023 Too_Messy = TRUE;
02024 } else {
02025 MEM_POOL_Push(&LNO_local_pool);
02026 if (!Non_Lin_Symb) {
02027 SUMPROD_LIST *list = CXX_NEW(SUMPROD_LIST,_mem_pool);
02028 SYMBOL_LIST *sl= CXX_NEW(SYMBOL_LIST,_mem_pool);
02029 SUMPROD_NODE *node = CXX_NEW(SUMPROD_NODE(sl,coeff),_mem_pool);
02030 list->Append(node);
02031 Non_Lin_Symb = Add_Nonlin(wn,list,stack);
02032 if (!Non_Lin_Symb) {
02033 Too_Messy = TRUE;
02034 }
02035 } else {
02036 SUMPROD_LIST *list = CXX_NEW(SUMPROD_LIST,&LNO_local_pool);
02037 SYMBOL_LIST *sl= CXX_NEW(SYMBOL_LIST,_mem_pool);
02038 SUMPROD_NODE *node = CXX_NEW(SUMPROD_NODE(sl,coeff),_mem_pool);
02039 list->Append(node);
02040 SUMPROD_LIST *tmp = Add_Nonlin(wn,list,stack);
02041 if (tmp) {
02042 Non_Lin_Symb->Merge(tmp);
02043 } else {
02044 Too_Messy = TRUE;
02045 }
02046 }
02047
02048
02049
02050
02051 SUMPROD_ITER sp_iter(Non_Lin_Symb);
02052 SUMPROD_NODE *sp_prev = NULL;
02053 SUMPROD_NODE *sp_next = NULL;
02054 for (SUMPROD_NODE *sp_node=sp_iter.First(); !sp_iter.Is_Empty();
02055 sp_node = sp_next) {
02056 sp_next = sp_iter.Next();
02057 SYMBOL_LIST *sl = sp_node->Prod_List;
02058 INT length=sl->Len();
02059 SYMBOL_ITER iter(sl);
02060 SYMBOL_NODE *node = iter.First();
02061 if (!node) {
02062 Const_Offset += sp_node->Coeff;
02063 if (sp_prev) {
02064 CXX_DELETE(Non_Lin_Symb->Remove(sp_prev,sp_node),_mem_pool);
02065 } else {
02066 CXX_DELETE(Non_Lin_Symb->Remove_Headnode(),_mem_pool);
02067 }
02068 } else if (length==1) {
02069 Add_Symbol(sp_node->Coeff,node->Symbol,stack,NULL);
02070 if (sp_prev) {
02071 CXX_DELETE(Non_Lin_Symb->Remove(sp_prev,sp_node),_mem_pool);
02072 } else {
02073 CXX_DELETE(Non_Lin_Symb->Remove_Headnode(),_mem_pool);
02074 }
02075 } else {
02076 sp_prev = sp_node;
02077 }
02078 }
02079 MEM_POOL_Pop(&LNO_local_pool);
02080 }
02081 } else {
02082 Too_Messy = TRUE;
02083 }
02084 } else if (WN_operator(wn) == OPR_LDID) {
02085 SYMBOL symb(wn);
02086 Add_Symbol((INT64) coeff,symb,stack,wn);
02087 } else if (WN_operator(wn) == OPR_INTCONST) {
02088 if (coeff == 1) {
02089 Const_Offset += WN_const_val(wn);
02090 } else if (coeff == -1) {
02091 Const_Offset -= WN_const_val(wn);
02092 } else {
02093 Const_Offset += coeff*WN_const_val(wn);
02094 }
02095 } else if (WN_operator(wn) == OPR_PAREN) {
02096 Add_Sum(WN_kid(wn,0),coeff,stack,allow_nonlin);
02097 } else if (WN_opcode(wn) == OPC_I8I4CVT
02098 || WN_opcode(wn) == OPC_U8I4CVT ) {
02099
02100 Add_Sum(WN_kid(wn,0),coeff,stack,allow_nonlin);
02101 }
02102 #ifdef KEY
02103
02104
02105
02106
02107
02108 else if (WN_opcode(wn) == OPC_I4U8CVT &&
02109 WN_opcode(WN_kid0(wn)) == OPC_U8CVTL &&
02110 WN_cvtl_bits(WN_kid0(wn)) == 32) {
02111 Add_Sum(WN_kid0(WN_kid0(wn)),coeff,stack,allow_nonlin);
02112 }
02113
02114
02115 else if (WN_operator(wn) == OPR_SHL && WN_Under_Array(wn)){
02116 if (WN_operator(WN_kid(wn,1)) == OPR_INTCONST) {
02117 Add_Sum(WN_kid(wn,0),coeff<<WN_const_val(WN_kid(wn,1)),stack,
02118 allow_nonlin);
02119 }else Too_Messy = TRUE;
02120 }
02121 else if (WN_operator(wn) == OPR_ASHR && WN_Under_Array(wn)){
02122 if (WN_operator(WN_kid(wn,1)) == OPR_INTCONST) {
02123 Add_Sum(WN_kid(wn,0),coeff>>WN_const_val(WN_kid(wn,1)),stack,
02124 allow_nonlin);
02125 }else Too_Messy = TRUE;
02126 }
02127 #endif
02128 else {
02129 Too_Messy = TRUE;
02130 }
02131 }
02132
02133
02134
02135
02136
02137 void ACCESS_VECTOR::Add_Symbol(INT64 coeff, SYMBOL symbol,
02138 DOLOOP_STACK *stack, WN *wn)
02139 {
02140 if (wn && TY_is_volatile(WN_ty(wn))) {
02141 Too_Messy = TRUE;
02142 return;
02143 }
02144
02145 if ((coeff >= (INT32_MAX-1)) || (coeff<=(INT32_MIN+1))) {
02146 Too_Messy = TRUE;
02147 return;
02148 }
02149
02150
02151 BOOL is_iv=FALSE;
02152 INT32 i;
02153
02154 for (i=0; i<stack->Elements() && !is_iv; i++) {
02155 WN *do_wn = stack->Bottom_nth(i);
02156 SYMBOL doloop(WN_index(do_wn));
02157 if (symbol == doloop) {
02158 is_iv = TRUE;
02159 }
02160 }
02161
02162 if (is_iv) {
02163 if (_lcoeff == NULL) {
02164 _lcoeff = CXX_NEW_ARRAY(mINT32,_nest_depth,_mem_pool);
02165 for (INT j=0; j<_nest_depth; j++) {
02166 _lcoeff[j] = 0;
02167 }
02168 }
02169 coeff += _lcoeff[i-1];
02170 if ((coeff >= (INT32_MAX-1)) || (coeff<=(INT32_MIN+1))) {
02171 Too_Messy = TRUE;
02172 return;
02173 }
02174 _lcoeff[i-1] = coeff;
02175 } else {
02176 if (Lin_Symb == NULL) {
02177 Lin_Symb = CXX_NEW(INTSYMB_LIST,_mem_pool);
02178 } else {
02179
02180 INTSYMB_ITER iter(Lin_Symb);
02181 INTSYMB_NODE* prevnode = NULL;
02182 for (INTSYMB_NODE *node = iter.First(); !iter.Is_Empty();
02183 node=iter.Next()) {
02184 if (node->Symbol == symbol) {
02185 coeff += node->Coeff;
02186 if ((coeff >= (INT32_MAX-1)) || (coeff<=(INT32_MIN+1))) {
02187 Too_Messy = TRUE;
02188 return;
02189 }
02190 node->Coeff = coeff;
02191 if (node->Coeff == 0) {
02192 if (node == iter.First()) {
02193 CXX_DELETE(Lin_Symb->Remove_Headnode(),_mem_pool);
02194 } else {
02195 CXX_DELETE(Lin_Symb->Remove(prevnode,node),_mem_pool);
02196 }
02197 }
02198 if (wn) Update_Non_Const_Loops(wn,stack);
02199 return;
02200 }
02201 prevnode = node;
02202 }
02203 }
02204
02205 Lin_Symb->Prepend(CXX_NEW(INTSYMB_NODE(symbol,coeff),_mem_pool));
02206 if (wn) Update_Non_Const_Loops(wn,stack);
02207 }
02208 }
02209
02210
02211
02212
02213
02214
02215 SUMPROD_LIST *ACCESS_VECTOR::Add_Nonlin(WN *wn, SUMPROD_LIST *list,
02216 DOLOOP_STACK *stack)
02217 {
02218 Is_True(list,("Null input list in ACCESS_VECTOR::Add_Nonlin"));
02219 if (Too_Messy) return NULL;
02220 OPERATOR oper = WN_operator(wn);
02221 if (oper == OPR_ADD) {
02222 SUMPROD_LIST *list2 = CXX_NEW(SUMPROD_LIST(list,_mem_pool),
02223 &LNO_local_pool);
02224 list = Add_Nonlin(WN_kid0(wn),list,stack);
02225 list2 = Add_Nonlin(WN_kid1(wn),list2,stack);
02226 if (!Too_Messy) list->Merge(list2);
02227 return list;
02228 }
02229 if (oper == OPR_SUB) {
02230 SUMPROD_LIST *list2 = CXX_NEW(SUMPROD_LIST(list,_mem_pool),
02231 &LNO_local_pool);
02232 list2 = Add_Nonlin(WN_kid1(wn),list2,stack);
02233 if (!list2->Negate_Me()) {
02234 Too_Messy = TRUE;
02235 return NULL;
02236 }
02237 list = Add_Nonlin(WN_kid0(wn),list,stack);
02238 if (!Too_Messy) list->Merge(list2);
02239 return list;
02240 }
02241 if (oper == OPR_NEG) {
02242 if (!list->Negate_Me()) {
02243 Too_Messy = TRUE;
02244 return NULL;
02245 }
02246 return Add_Nonlin(WN_kid0(wn),list,stack);
02247 }
02248 if (oper == OPR_MPY) {
02249 list = Add_Nonlin(WN_kid0(wn),list,stack);
02250 if (list) list = Add_Nonlin(WN_kid1(wn),list,stack);
02251 return list;
02252 }
02253 if (oper == OPR_INTCONST) {
02254 INT64 offset = WN_const_val(wn);
02255 SUMPROD_ITER iter(list);
02256 for (SUMPROD_NODE *node = iter.First(); !iter.Is_Empty();
02257 node = iter.Next()) {
02258 INT64 coeff = node->Coeff*offset;
02259 if ((coeff >= (INT32_MAX-1)) || (coeff<=(INT32_MIN+1))) {
02260 Too_Messy = TRUE;
02261 return NULL;
02262 }
02263 node->Coeff = coeff;
02264 }
02265 return list;
02266 }
02267 if (oper == OPR_LDID) {
02268 SYMBOL symbol(wn);
02269 SUMPROD_ITER iter(list);
02270
02271
02272 BOOL is_iv=FALSE;
02273 for (INT32 i=0; i<stack->Elements() && !is_iv; i++) {
02274 WN *wn = stack->Bottom_nth(i);
02275 SYMBOL doloop(WN_index(wn));
02276 if (symbol == doloop) {
02277 is_iv = TRUE;
02278 }
02279 }
02280
02281 for (SUMPROD_NODE *node = iter.First(); !iter.Is_Empty();
02282 node = iter.Next()) {
02283 node->Prod_List->Append(CXX_NEW(SYMBOL_NODE(symbol,is_iv),_mem_pool));
02284 }
02285
02286
02287
02288 if (!is_iv) {
02289 Update_Non_Const_Loops(wn,stack);
02290 }
02291 return list;
02292 }
02293 Too_Messy = TRUE;
02294 return NULL;
02295 }
02296
02297
02298
02299 void ACCESS_VECTOR::Update_Non_Const_Loops(WN *wn, DOLOOP_STACK *stack)
02300 {
02301 OPCODE opc = WN_opcode(wn);
02302 if (OPCODE_is_load(opc)) {
02303 if (OPCODE_operator(opc) != OPR_LDID) {
02304 _non_const_loops = stack->Elements();
02305 return;
02306 }
02307 } else {
02308 for (INT kidno=0; kidno<WN_kid_count(wn); kidno++) {
02309 Update_Non_Const_Loops(WN_kid(wn,kidno),stack);
02310 }
02311 }
02312
02313
02314
02315 DEF_LIST *defs = Du_Mgr->Ud_Get_Def(wn);
02316
02317
02318
02319
02320 if (!defs) {
02321 _non_const_loops = stack->Elements();
02322 return;
02323 }
02324 DEF_LIST_ITER iter(defs);
02325
02326 for(DU_NODE *node=iter.First(); !iter.Is_Empty(); node=iter.Next()) {
02327 WN *def = node->Wn();
02328
02329
02330 while (def && (WN_opcode(def) != OPC_DO_LOOP)) {
02331 def = LWN_Get_Parent(def);
02332 }
02333 if (def) {
02334 def = LNO_Common_Loop(def,wn);
02335 if (def) {
02336 INT i=0;
02337 INT num_elements = stack->Elements();
02338 while ((i < num_elements) && (def != stack->Bottom_nth(i))) {
02339 i++;
02340 }
02341 if (i < num_elements) {
02342 _non_const_loops = MAX(_non_const_loops,i+1);
02343 }
02344 }
02345 }
02346 }
02347 }
02348
02349
02350
02351
02352 void ACCESS_ARRAY::Update_Non_Const_Loops(WN *wn, DOLOOP_STACK *stack)
02353 {
02354 OPCODE opc = WN_opcode(wn);
02355 if (OPCODE_is_load(opc)) {
02356 if (OPCODE_operator(opc) != OPR_LDID) {
02357 for (INT32 i=0; i<_num_vec; i++) {
02358 Dim(i)->Max_Non_Const_Loops(stack->Elements());
02359 }
02360 return;
02361 }
02362 } else {
02363 for (INT kidno=0; kidno<WN_kid_count(wn); kidno++) {
02364 Update_Non_Const_Loops(WN_kid(wn,kidno),stack);
02365 }
02366 return;
02367 }
02368
02369
02370 DEF_LIST *defs = Du_Mgr->Ud_Get_Def(wn);
02371
02372
02373
02374
02375 if (!defs) {
02376 for (INT32 i=0; i<_num_vec; i++) {
02377 Dim(i)->Max_Non_Const_Loops(stack->Elements());
02378 }
02379 return;
02380 }
02381
02382
02383 DEF_LIST_ITER iter(defs);
02384
02385 INT max = 0;
02386 for(const DU_NODE *node=iter.First(); !iter.Is_Empty(); node=iter.Next()) {
02387 const WN *def = node->Wn();
02388
02389
02390 while (def && (WN_opcode(def) != OPC_DO_LOOP)) {
02391 def = LWN_Get_Parent(def);
02392 }
02393 if (def) {
02394 INT i=0;
02395 INT num_elements = stack->Elements();
02396 while ((i < num_elements) && (def != stack->Bottom_nth(i))) {
02397 i++;
02398 }
02399 if (i < num_elements) {
02400 max = MAX(max,i+1);
02401 }
02402 }
02403 }
02404 if (max > 0) {
02405 for (INT32 i=0; i<_num_vec; i++) {
02406 Dim(i)->Max_Non_Const_Loops(max);
02407 }
02408 }
02409 }
02410
02411
02412
02413 ACCESS_VECTOR *Subtract(ACCESS_VECTOR *v1, ACCESS_VECTOR *v2,
02414 MEM_POOL *mem_pool)
02415 {
02416 Is_True(v1 && v2, ("Access vector subtraction requires non-nil operands"));
02417
02418 if (v1->_nest_depth != v2->_nest_depth)
02419 return NULL;
02420
02421 ACCESS_VECTOR *rv = CXX_NEW(ACCESS_VECTOR, mem_pool);
02422
02423 rv->Too_Messy = (v1->Too_Messy || v2->Too_Messy);
02424
02425 if (rv->Too_Messy)
02426 return rv;
02427
02428
02429
02430
02431
02432 rv->_non_const_loops = MAX(v1->_non_const_loops, v2->_non_const_loops);
02433 rv->_nest_depth = v1->_nest_depth;
02434 rv->_mem_pool = mem_pool;
02435 rv->Const_Offset = v1->Const_Offset - v2->Const_Offset;
02436
02437 rv->_lcoeff = CXX_NEW_ARRAY(mINT32, rv->_nest_depth, rv->_mem_pool);
02438 for (INT i=0; i < rv->_nest_depth; i++)
02439 rv->_lcoeff[i] = (v1->_lcoeff ? v1->_lcoeff[i] : 0) -
02440 (v2->_lcoeff ? v2->_lcoeff[i] : 0);
02441
02442 rv->Lin_Symb = Subtract(v1->Lin_Symb, v2->Lin_Symb, rv->_mem_pool);
02443
02444 rv->Non_Lin_Symb = CXX_NEW(SUMPROD_LIST, rv->_mem_pool);
02445 if (v1->Non_Lin_Symb)
02446 rv->Non_Lin_Symb->Init(v1->Non_Lin_Symb, rv->_mem_pool);
02447 if (v2->Non_Lin_Symb) {
02448 SUMPROD_ITER iter(v2->Non_Lin_Symb);
02449 for (SUMPROD_NODE *node = iter.First(); !iter.Is_Empty();
02450 node=iter.Next()) {
02451
02452
02453 SUMPROD_NODE *n = CXX_NEW(SUMPROD_NODE(node,mem_pool),mem_pool);
02454 n->Coeff = - n->Coeff;
02455 rv->Non_Lin_Symb->Append(n);
02456 }
02457 }
02458
02459 return rv;
02460 }
02461
02462 ACCESS_VECTOR *Add(ACCESS_VECTOR *v1, ACCESS_VECTOR *v2,
02463 MEM_POOL *mem_pool)
02464 {
02465 Is_True(v1 && v2, ("Access vector subtraction requires non-nil operands"));
02466
02467 if (v1->_nest_depth != v2->_nest_depth)
02468 return NULL;
02469
02470 ACCESS_VECTOR *rv = CXX_NEW(ACCESS_VECTOR, mem_pool);
02471
02472 rv->Too_Messy = (v1->Too_Messy || v2->Too_Messy);
02473
02474 if (rv->Too_Messy)
02475 return rv;
02476
02477
02478
02479
02480
02481 rv->_non_const_loops = MAX(v1->_non_const_loops, v2->_non_const_loops);
02482 rv->_nest_depth = v1->_nest_depth;
02483 rv->_mem_pool = mem_pool;
02484 rv->Const_Offset = v1->Const_Offset + v2->Const_Offset;
02485
02486 rv->_lcoeff = CXX_NEW_ARRAY(mINT32, rv->_nest_depth, rv->_mem_pool);
02487 for (INT i=0; i < rv->_nest_depth; i++)
02488 rv->_lcoeff[i] = (v1->_lcoeff ? v1->_lcoeff[i] : 0) +
02489 (v2->_lcoeff ? v2->_lcoeff[i] : 0);
02490
02491 rv->Lin_Symb = Add(v1->Lin_Symb, v2->Lin_Symb, rv->_mem_pool);
02492
02493 rv->Non_Lin_Symb = CXX_NEW(SUMPROD_LIST, rv->_mem_pool);
02494 if (v1->Non_Lin_Symb)
02495 rv->Non_Lin_Symb->Init(v1->Non_Lin_Symb, rv->_mem_pool);
02496 if (v2->Non_Lin_Symb) {
02497 SUMPROD_ITER iter(v2->Non_Lin_Symb);
02498 for (SUMPROD_NODE *node = iter.First(); !iter.Is_Empty();
02499 node=iter.Next()) {
02500
02501
02502 SUMPROD_NODE *n = CXX_NEW(SUMPROD_NODE(node,mem_pool),mem_pool);
02503 rv->Non_Lin_Symb->Append(n);
02504 }
02505 }
02506
02507 return rv;
02508 }
02509
02510 ACCESS_VECTOR *Mul(INT c, ACCESS_VECTOR *v, MEM_POOL *mem_pool)
02511 {
02512 Is_True(v, ("Access vector multiplication requires non-nil operand"));
02513
02514 ACCESS_VECTOR *rv = CXX_NEW(ACCESS_VECTOR(v, mem_pool), mem_pool);
02515
02516 if (rv->Too_Messy)
02517 return rv;
02518
02519 for (INT i=0; i< rv->_nest_depth; i++)
02520 rv->_lcoeff[i] *= c;
02521
02522 rv->Lin_Symb = Mul(c, v->Lin_Symb, rv->_mem_pool);
02523
02524 if (v->Non_Lin_Symb) {
02525 SUMPROD_ITER iter(v->Non_Lin_Symb);
02526 for (SUMPROD_NODE *node = iter.First(); !iter.Is_Empty();
02527 node=iter.Next()) {
02528 node->Coeff *= c;
02529 }
02530 }
02531
02532 return rv;
02533 }
02534
02535 ACCESS_VECTOR *Merge(ACCESS_VECTOR *v1, ACCESS_VECTOR *v2,
02536 MEM_POOL *mem_pool)
02537 {
02538 Is_True(v1 && v2, ("Access vector subtraction requires non-nil operands"));
02539
02540
02541
02542
02543 ACCESS_VECTOR *rv = CXX_NEW(ACCESS_VECTOR, mem_pool);
02544
02545
02546 rv->_nest_depth = MIN(v1->_nest_depth, v2->_nest_depth);
02547 rv->Too_Messy = (v1->Too_Messy || v2->Too_Messy);
02548
02549 if (rv->Too_Messy)
02550 return rv;
02551
02552 rv->_non_const_loops = MAX(v1->_non_const_loops, v2->_non_const_loops);
02553 rv->_mem_pool = mem_pool;
02554 rv->Const_Offset = v1->Const_Offset + v2->Const_Offset;
02555
02556 rv->_lcoeff = CXX_NEW_ARRAY(mINT32, rv->_nest_depth, rv->_mem_pool);
02557 for (INT i=0; i < rv->_nest_depth; i++)
02558 rv->_lcoeff[i] = (v1->_lcoeff ? v1->_lcoeff[i] : 0) +
02559 (v2->_lcoeff ? v2->_lcoeff[i] : 0);
02560
02561 rv->Lin_Symb = Add(v1->Lin_Symb, v2->Lin_Symb, rv->_mem_pool);
02562
02563 rv->Non_Lin_Symb = CXX_NEW(SUMPROD_LIST, rv->_mem_pool);
02564 if (v1->Non_Lin_Symb)
02565 rv->Non_Lin_Symb->Init(v1->Non_Lin_Symb, rv->_mem_pool);
02566 if (v2->Non_Lin_Symb) {
02567 SUMPROD_ITER iter(v2->Non_Lin_Symb);
02568 for (SUMPROD_NODE *node = iter.First(); !iter.Is_Empty();
02569 node=iter.Next()) {
02570
02571
02572 SUMPROD_NODE *n = CXX_NEW(SUMPROD_NODE(node,mem_pool),mem_pool);
02573 rv->Non_Lin_Symb->Append(n);
02574 }
02575 }
02576
02577 return rv;
02578 }
02579
02580 void ACCESS_VECTOR::Mul(INT c)
02581 {
02582 if (Too_Messy) return;
02583 for (INT i=0; i< _nest_depth; i++) {
02584 if (_lcoeff[i]) {
02585 INT64 prod = _lcoeff[i] * c;
02586 if (prod < INT32_MAX) {
02587 _lcoeff[i] = prod;
02588 } else {
02589 Too_Messy = TRUE;
02590 return;
02591 }
02592 }
02593 }
02594 if (Lin_Symb) {
02595 INTSYMB_ITER ii(Lin_Symb);
02596 for (INTSYMB_NODE *in = ii.First(); !ii.Is_Empty(); in = ii.Next()) {
02597 if (in->Coeff == 1) {
02598 in->Coeff = c;
02599 } else {
02600 INT64 prod = in->Coeff * c;
02601 if (prod < INT32_MAX) {
02602 in->Coeff = prod;
02603 } else {
02604 Too_Messy = TRUE;
02605 return;
02606 }
02607 }
02608 }
02609 }
02610 if (Non_Lin_Symb) {
02611 SUMPROD_ITER iter(Non_Lin_Symb);
02612 for (SUMPROD_NODE *node = iter.First(); !iter.Is_Empty();
02613 node=iter.Next()) {
02614 if (node->Coeff == 1) {
02615 node->Coeff = c;
02616 } else {
02617 INT64 prod = node->Coeff * c;
02618 if (prod < INT32_MAX) {
02619 node->Coeff = prod;
02620 } else {
02621 Too_Messy = TRUE;
02622 return;
02623 }
02624 }
02625 }
02626 }
02627 }
02628
02629 void ACCESS_VECTOR::Negate_Me()
02630 {
02631 if (Too_Messy)
02632 return;
02633
02634 Const_Offset = -Const_Offset;
02635
02636 if (_lcoeff) {
02637 for (INT i=0; i<_nest_depth; i++)
02638 _lcoeff[i] = -_lcoeff[i];
02639 }
02640
02641 if (Contains_Lin_Symb()) {
02642 INTSYMB_ITER ii(Lin_Symb);
02643 for (INTSYMB_NODE *in = ii.First(); !ii.Is_Empty(); in = ii.Next())
02644 in->Coeff = -in->Coeff;
02645 }
02646
02647 if (Contains_Non_Lin_Symb()) {
02648 SUMPROD_ITER si(Non_Lin_Symb);
02649 for (SUMPROD_NODE *sn = si.First(); !si.Is_Empty(); sn = si.Next())
02650 sn->Coeff = -sn->Coeff;
02651 }
02652 }
02653
02654 ACCESS_VECTOR *ACCESS_VECTOR::Convert_Bound_To_Exp(MEM_POOL *pool)
02655 {
02656 ACCESS_VECTOR *result = CXX_NEW(ACCESS_VECTOR(this,pool), pool);
02657 if (Too_Messy) return(result);
02658
02659 if(_lcoeff[_nest_depth-1] > 0) {
02660
02661 for (INT i=0; i<_nest_depth-1; i++) {
02662 result->_lcoeff[i] = -_lcoeff[i];
02663 }
02664 INTSYMB_ITER ii(result->Lin_Symb);
02665 for (INTSYMB_NODE *in = ii.First(); !ii.Is_Empty(); in = ii.Next())
02666 in->Coeff = -in->Coeff;
02667
02668 SUMPROD_ITER si(result->Non_Lin_Symb);
02669 for (SUMPROD_NODE *sn = si.First(); !si.Is_Empty(); sn = si.Next())
02670 sn->Coeff = -sn->Coeff;
02671 } else {
02672 result->Const_Offset = -result->Const_Offset;
02673 }
02674 result->_lcoeff[_nest_depth-1] = 0;
02675
02676 return(result);
02677 }
02678
02679
02680
02681
02682 extern INT Num_Maxs(WN *wn)
02683 {
02684 if (WN_operator(wn) == OPR_MAX) {
02685 return(1+Num_Maxs(WN_kid(wn,0))+Num_Maxs(WN_kid(wn,1)));
02686 } else {
02687 return 0;
02688 }
02689 }
02690
02691
02692
02693 extern INT Num_Mins(WN *wn)
02694 {
02695 if (WN_operator(wn) == OPR_MIN) {
02696 return(1+Num_Mins(WN_kid(wn,0))+Num_Mins(WN_kid(wn,1)));
02697 } else {
02698 return 0;
02699 }
02700 }
02701
02702
02703
02704 INT Num_Lands(WN *wn)
02705 {
02706 if (WN_operator(wn) == OPR_LAND
02707 || WN_operator(wn) == OPR_CAND) {
02708 return(1+Num_Lands(WN_kid(wn,0))+Num_Lands(WN_kid(wn,1)));
02709 } else {
02710 return 0;
02711 }
02712 }
02713
02714
02715
02716 INT Num_Liors(WN *wn)
02717 {
02718 if (WN_operator(wn) == OPR_LIOR
02719 || WN_operator(wn) == OPR_CIOR) {
02720 return(1+Num_Liors(WN_kid(wn,0))+Num_Liors(WN_kid(wn,1)));
02721 } else {
02722 return 0;
02723 }
02724 }
02725
02726
02727
02728
02729
02730
02731
02732
02733
02734
02735
02736
02737 ACCESS_VECTOR::ACCESS_VECTOR(const SYSTEM_OF_EQUATIONS *soe,
02738 const INT i, const SYMBOL_LIST *syms,
02739 const INT depth, const INT dim,
02740 const INT non_const_loops,
02741 const INT which_array,
02742 BOOL is_lower_bound, MEM_POOL *pool)
02743 {
02744 INT k;
02745
02746 _mem_pool = pool;
02747 _nest_depth = depth;
02748 _non_const_loops = non_const_loops;
02749
02750
02751 Too_Messy = FALSE;
02752 Non_Lin_Symb = NULL;
02753 Lin_Symb = NULL;
02754 Delinearized_Symbol = NULL;
02755 _lcoeff = CXX_NEW_ARRAY(mINT32,_nest_depth,_mem_pool);
02756
02757 switch (which_array) {
02758 case 0:
02759 {
02760
02761 if (is_lower_bound) {
02762 for (k = 0; k < _nest_depth; ++k)
02763 _lcoeff[k] = soe->Work(i,dim+k);
02764 Const_Offset = -soe->Work_Const(i);
02765
02766
02767 SYMBOL_CONST_ITER iter(syms);
02768
02769 for (const SYMBOL_NODE *s = iter.First();
02770 k+dim < soe->Num_Vars() && !iter.Is_Empty();
02771 ++k, s = iter.Next()) {
02772 if (soe->Work(i,k+dim)) {
02773 if (Lin_Symb == NULL) Lin_Symb = CXX_NEW(INTSYMB_LIST, _mem_pool);
02774 Lin_Symb->Append(CXX_NEW(INTSYMB_NODE(s->Symbol,soe->Work(i,k+dim)),_mem_pool));
02775 }
02776 }
02777 } else {
02778 for (k = 0; k < _nest_depth; ++k)
02779 _lcoeff[k] = -soe->Work(i,dim+k);
02780 Const_Offset = soe->Work_Const(i);
02781
02782
02783 SYMBOL_CONST_ITER iter(syms);
02784
02785 for (const SYMBOL_NODE *s = iter.First();
02786 k+dim < soe->Num_Vars() && !iter.Is_Empty();
02787 ++k, s = iter.Next()) {
02788 if (soe->Work(i,k+dim)) {
02789 if (Lin_Symb == NULL) Lin_Symb = CXX_NEW(INTSYMB_LIST, _mem_pool);
02790 Lin_Symb->Append(CXX_NEW(INTSYMB_NODE(s->Symbol,-soe->Work(i,k+dim)),_mem_pool));
02791 }
02792 }
02793 }
02794 }
02795 break;
02796
02797 case 1:
02798 {
02799 const IMAT &aeq = soe->Aeq();
02800 const INT64 *beq = soe->Beq();
02801
02802
02803 for (k = 0; k < _nest_depth; ++k)
02804 _lcoeff[k] = -aeq(i,dim+k);
02805 Const_Offset = beq[i];
02806
02807
02808 SYMBOL_CONST_ITER iter(syms);
02809
02810 for (const SYMBOL_NODE *s = iter.First();
02811 k+dim < soe->Num_Vars() && !iter.Is_Empty();
02812 ++k, s = iter.Next()) {
02813 if (aeq(i,k+dim)) {
02814 if (Lin_Symb == NULL) Lin_Symb = CXX_NEW(INTSYMB_LIST, _mem_pool);
02815 Lin_Symb->Append(CXX_NEW(INTSYMB_NODE(s->Symbol,aeq(i,k+dim)),_mem_pool));
02816 }
02817 }
02818 }
02819 break;
02820
02821 case 2:
02822 {
02823 const IMAT &ale = soe->Ale();
02824 const INT64 *ble = soe->Ble();
02825
02826 if (is_lower_bound) {
02827 for (k = 0; k < _nest_depth; ++k)
02828 _lcoeff[k] = ale(i,dim+k);
02829 Const_Offset = -ble[i];
02830
02831
02832 SYMBOL_CONST_ITER iter(syms);
02833
02834 for (const SYMBOL_NODE *s = iter.First();
02835 k+dim < soe->Num_Vars() && !iter.Is_Empty();
02836 ++k, s = iter.Next()) {
02837 if (ale(i,k+dim)) {
02838 if (Lin_Symb == NULL) Lin_Symb = CXX_NEW(INTSYMB_LIST, _mem_pool);
02839 Lin_Symb->Append(CXX_NEW(INTSYMB_NODE(s->Symbol,ale(i,k+dim)),_mem_pool));
02840 }
02841 }
02842 } else {
02843 for (k = 0; k < _nest_depth; ++k)
02844 _lcoeff[k] = -ale(i,dim+k);
02845 Const_Offset = ble[i];
02846
02847
02848 SYMBOL_CONST_ITER iter(syms);
02849
02850 for (const SYMBOL_NODE *s = iter.First();
02851 k+dim < soe->Num_Vars() && !iter.Is_Empty();
02852 ++k, s = iter.Next()) {
02853 if (ale(i,k+dim)) {
02854 if (Lin_Symb == NULL) Lin_Symb = CXX_NEW(INTSYMB_LIST, _mem_pool);
02855 Lin_Symb->Append(CXX_NEW(INTSYMB_NODE(s->Symbol,-ale(i,k+dim)),_mem_pool));
02856 }
02857 }
02858 }
02859 }
02860
02861 break;
02862
02863 }
02864
02865 }
02866
02867 #ifndef LNO
02868
02869
02870
02871
02872 void
02873 Initialize_Access_Vals(DU_MANAGER* du_mgr, FILE *tfile)
02874 {
02875 Du_Mgr = du_mgr;
02876 Set_Trace_File_internal(tfile);
02877 MEM_POOL_Initialize(&LNO_local_pool, "Access_Vector_Pool", FALSE);
02878 MEM_POOL_Push (&LNO_local_pool);
02879 }
02880
02881
02882
02883
02884
02885 void
02886 Finalize_Access_Vals()
02887 {
02888 MEM_POOL_Pop(&LNO_local_pool);
02889 MEM_POOL_Delete(&LNO_local_pool);
02890 }
02891
02892 #endif