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 #define __STDC_LIMIT_MACROS
00047 #include <stdint.h>
00048 #ifdef USE_PCH
00049 #include "lno_pch.h"
00050 #endif // USE_PCH
00051 #pragma hdrstop
00052
00053 #define snl_utils_CXX "snl_utils.cxx"
00054 static char *rcs_id = snl_utils_CXX "$Revision: 1.6 $";
00055
00056 #include <sys/types.h>
00057 #include "snl.h"
00058
00059 #include "targ_sim.h"
00060 #include "lwn_util.h"
00061 #include "lnoutils.h"
00062 #include "dep_graph.h"
00063 #include "wintrinsic.h"
00064 #include "opt_du.h"
00065 #include "ff_utils.h"
00066 #include "config_targ.h"
00067 #include "ipa_lno_util.h"
00068
00069 #ifdef Is_True_On
00070 extern char* Cur_PU_Name;
00071 #endif
00072
00073 MEM_POOL SNL_local_pool;
00074
00075 static ARRAY_DIRECTED_GRAPH16* dg;
00076
00077 static void sc_print_debug_stop_here()
00078 {
00079 }
00080
00081 #ifdef Is_True_On
00082 #define SC_PRINT(a,b) ((void) ( (a) ? 0 : \
00083 (printf b , printf("\n"), \
00084 printf("<subroutine %s>\n", Cur_PU_Name), \
00085 fflush(stdout), \
00086 sc_print_debug_stop_here(), 0)))
00087
00088 #define SC_ASSERT SC_PRINT
00089
00090
00091 static void Check_Zero_Linear_Coefficients(WN* wn_ref, ACCESS_VECTOR *av)
00092 {
00093 INTSYMB_ITER lin_iter(av->Lin_Symb);
00094 for (INTSYMB_NODE *lin_node=lin_iter.First(); !lin_iter.Is_Empty();
00095 lin_node = lin_iter.Next())
00096 SC_ASSERT(lin_node->Coeff != 0,
00097 ("Access vector for 0x%p has 0 linear coefficient", wn_ref));
00098 }
00099
00100 #endif
00101
00102 static INT Check_Depth(WN* wn)
00103 {
00104 if (wn == NULL)
00105 return -1;
00106 INT depth = Check_Depth(LWN_Get_Parent(wn));
00107 if (WN_opcode(wn) == OPC_DO_LOOP) {
00108 depth++;
00109 DO_LOOP_INFO* dli = Get_Do_Loop_Info(wn);
00110 FmtAssert(dli->Depth == depth,
00111 ("DO confusion: %d %d (loop %s: 0x%p)",
00112 dli->Depth, depth, SYMBOL(WN_index(wn)).Name(), wn));
00113 return depth;
00114 }
00115 else
00116 return depth;
00117 }
00118
00119 void Print_Do_Stack(FILE* f, const DOLOOP_STACK *stack)
00120 {
00121 fprintf(f, "dostack:");
00122 for (INT i = 0; i < stack->Elements(); i++) {
00123 WN* indx = WN_index(stack->Bottom_nth(i));
00124 fprintf(f, " <|%s,%lld,%d|>",
00125 ST_name(WN_st(indx)),
00126 ST_ofst(WN_st(indx)),
00127 WN_offset(indx));
00128 }
00129 fprintf(f, "\n");
00130 fflush(f);
00131 }
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143 static SNL_MONO mono_union(SNL_MONO a, SNL_MONO b)
00144 {
00145 switch (a) {
00146 default:
00147 FmtAssert(0, ("Impossible SNL_MONO TYPE %d", a));
00148 case SNL_MONO_INVARIANT:
00149 return b;
00150 case SNL_MONO_INC:
00151 if (b == SNL_MONO_INVARIANT || b == SNL_MONO_INC)
00152 return SNL_MONO_INC;
00153 else
00154 return SNL_MONO_OTHER;
00155 case SNL_MONO_DEC:
00156 if (b == SNL_MONO_INVARIANT || b == SNL_MONO_DEC)
00157 return SNL_MONO_DEC;
00158 else
00159 return SNL_MONO_OTHER;
00160 case SNL_MONO_OTHER:
00161 return SNL_MONO_OTHER;
00162 }
00163 }
00164
00165 SNL_MONO Mono(WN* wn, SYMBOL symbol, BOOL neg)
00166 {
00167 SNL_MONO m;
00168 INT64 c;
00169 INT kid;
00170
00171 OPCODE opc = WN_opcode(wn);
00172 OPERATOR opr = OPCODE_operator(opc);
00173
00174 FmtAssert(OPCODE_is_expression(opc) || opr == OPR_STID,
00175 ("Odd opcode %s passed to Mono()", OPCODE_name(opc)));
00176
00177 switch (opr) {
00178 default:
00179 Is_True(0, ("unknown opr %s [no problem -- just implement it!]",
00180 OPERATOR_name(opr)));
00181 m = SNL_MONO_OTHER;
00182 break;
00183
00184 case OPR_IDNAME:
00185 Is_True(0, ("strange opr %s for Mono()",
00186 OPERATOR_name(opr)));
00187 m = SNL_MONO_OTHER;
00188 break;
00189
00190 case OPR_INTRINSIC_OP:
00191 {
00192 m = SNL_MONO_OTHER;
00193 switch (WN_intrinsic(wn)) {
00194 case INTRN_I4DIVFLOOR:
00195 case INTRN_I8DIVFLOOR:
00196 case INTRN_U4DIVFLOOR:
00197 case INTRN_U8DIVFLOOR:
00198 case INTRN_I4DIVCEIL:
00199 case INTRN_I8DIVCEIL:
00200 case INTRN_U4DIVCEIL:
00201 case INTRN_U8DIVCEIL:
00202 FmtAssert(WN_operator(WN_kid0(wn)) == OPR_PARM &&
00203 WN_operator(WN_kid1(wn)) == OPR_PARM,
00204 ("Children of intrinsic op must be parms"));
00205 if (WN_operator(WN_kid0(WN_kid1(wn))) == OPR_INTCONST) {
00206 m = Mono(WN_kid0(WN_kid0(wn)), symbol);
00207 if (WN_const_val(WN_kid0(WN_kid1(wn))) < 0)
00208 neg = !neg;
00209 }
00210 }
00211 }
00212 break;
00213
00214 case OPR_ILOAD:
00215 case OPR_MLOAD:
00216 case OPR_ARRAY:
00217 case OPR_COMPLEX:
00218 case OPR_ABS:
00219 case OPR_SQRT:
00220 case OPR_RECIP:
00221 case OPR_RSQRT:
00222 #ifdef TARG_X8664
00223 case OPR_ATOMIC_RSQRT:
00224 #endif
00225 case OPR_REALPART:
00226 case OPR_IMAGPART:
00227 case OPR_RND:
00228 case OPR_TRUNC:
00229 case OPR_BNOT:
00230 case OPR_LNOT:
00231 case OPR_MOD:
00232 case OPR_REM:
00233 case OPR_EQ:
00234 case OPR_NE:
00235 case OPR_GE:
00236 case OPR_GT:
00237 case OPR_LE:
00238 case OPR_LT:
00239 case OPR_BAND:
00240 case OPR_BIOR:
00241 case OPR_BXOR:
00242 case OPR_LAND:
00243 case OPR_LIOR:
00244 case OPR_CAND:
00245 case OPR_CIOR:
00246 case OPR_LDA:
00247 for (kid = 0; kid < WN_kid_count(wn); kid++) {
00248 FmtAssert(Mono(WN_kid(wn,kid), symbol) == SNL_MONO_INVARIANT,
00249 ("operator %s depends upon %s, violating assumptions",
00250 OPERATOR_name(opr), symbol.Name()));
00251 }
00252 m = SNL_MONO_OTHER;
00253 break;
00254
00255 case OPR_STID:
00256 case OPR_PAREN:
00257 case OPR_TAS:
00258 case OPR_CVT:
00259 case OPR_CVTL:
00260 case OPR_CEIL:
00261 case OPR_FLOOR:
00262 case OPR_PARM:
00263 m = Mono(WN_kid0(wn), symbol);
00264 break;
00265
00266 case OPR_NEG:
00267 m = Mono(WN_kid0(wn), symbol, TRUE);
00268 break;
00269
00270 case OPR_ADD:
00271 case OPR_MAX:
00272 case OPR_MIN:
00273 m = mono_union(Mono(WN_kid0(wn), symbol), Mono(WN_kid1(wn), symbol));
00274 break;
00275
00276 case OPR_SUB:
00277 m = mono_union(Mono(WN_kid0(wn), symbol), Mono(WN_kid1(wn), symbol, TRUE));
00278 break;
00279
00280 case OPR_MPY:
00281 case OPR_DIV:
00282 if (opr == OPR_MPY &&
00283 WN_operator(WN_kid0(wn)) == OPR_INTCONST) {
00284 c = WN_const_val(WN_kid0(wn));
00285 if (c == 0)
00286 m = SNL_MONO_INVARIANT;
00287 else if (c > 0)
00288 m = Mono(WN_kid1(wn), symbol);
00289 else
00290 m = Mono(WN_kid1(wn), symbol, TRUE);
00291 }
00292 else if (WN_operator(WN_kid1(wn)) == OPR_INTCONST) {
00293 c = WN_const_val(WN_kid1(wn));
00294 if (c == 0)
00295 m = SNL_MONO_INVARIANT;
00296 else if (c > 0)
00297 m = Mono(WN_kid0(wn), symbol);
00298 else
00299 m = Mono(WN_kid0(wn), symbol, TRUE);
00300 }
00301 else {
00302 if (Mono(WN_kid0(wn), symbol) == SNL_MONO_INVARIANT &&
00303 Mono(WN_kid1(wn), symbol) == SNL_MONO_INVARIANT)
00304 m = SNL_MONO_INVARIANT;
00305 else
00306 m = SNL_MONO_OTHER;
00307 }
00308 break;
00309
00310 case OPR_SHL:
00311 case OPR_ASHR:
00312 case OPR_LSHR:
00313 if (Mono(WN_kid1(wn), symbol) == SNL_MONO_INVARIANT)
00314 m = Mono(WN_kid0(wn), symbol);
00315 else
00316 m = SNL_MONO_OTHER;
00317 break;
00318
00319 case OPR_LDID:
00320 if (symbol == SYMBOL(wn))
00321 m = SNL_MONO_INC;
00322 else
00323 m = SNL_MONO_INVARIANT;
00324 break;
00325
00326 case OPR_INTCONST:
00327 case OPR_CONST:
00328 return SNL_MONO_INVARIANT;
00329 }
00330
00331 if (neg) {
00332 if (m == SNL_MONO_INC)
00333 m = SNL_MONO_DEC;
00334 else if (m == SNL_MONO_DEC)
00335 m = SNL_MONO_INC;
00336 }
00337
00338 return m;
00339 }
00340
00341
00342 BOOL Is_Lexpos(DEPV_ARRAY* dv)
00343 {
00344 for (INT v = 0; v < dv->Num_Vec(); v++)
00345 if (!Is_Lexpos(dv->Depv(v), dv->Num_Dim()))
00346 return FALSE;
00347 return TRUE;
00348 }
00349
00350
00351
00352
00353
00354 void Increase_By(WN* wn, INT c, WN* parent, INT kid)
00355 {
00356 FmtAssert(wn, ("Bad wn for Increase_By"));
00357
00358 OPCODE opc = WN_opcode(wn);
00359 OPERATOR opr = OPCODE_operator(opc);
00360
00361 if (opr == OPR_STID) {
00362 parent = wn;
00363 kid = 0;
00364 wn = WN_kid0(wn);
00365 opc = WN_opcode(wn);
00366 opr = OPCODE_operator(opc);
00367 }
00368
00369 if (parent == NULL) {
00370 parent = LWN_Get_Parent(wn);
00371 FmtAssert(parent, ("Missing parent in Increase_By"));
00372 }
00373
00374 if (kid < 0) {
00375 for (kid = 0; kid < WN_kid_count(parent); kid++)
00376 if (WN_kid(parent,kid) == wn)
00377 break;
00378 FmtAssert(kid < WN_kid_count(parent),
00379 ("Missing kid: op=%d kc=%d", WN_opcode(wn), WN_kid_count(wn)));
00380 }
00381
00382 switch (opr) {
00383 case OPR_INTCONST:
00384 WN_const_val(wn) += c;
00385 break;
00386 case OPR_MAX:
00387 case OPR_MIN:
00388 Increase_By(WN_kid0(wn), c, wn, 0);
00389 Increase_By(WN_kid1(wn), c, wn, 1);
00390 break;
00391 case OPR_ADD:
00392 case OPR_SUB:
00393 if (WN_operator(WN_kid1(wn)) == OPR_INTCONST) {
00394 if (opr == OPR_ADD)
00395 WN_const_val(WN_kid1(wn)) += c;
00396 else
00397 WN_const_val(WN_kid1(wn)) -= c;
00398 }
00399 else
00400 Increase_By(WN_kid0(wn), c, wn, 0);
00401 break;
00402 default:
00403 FmtAssert(OPCODE_is_expression(opc),
00404 ("Bad opcode %s to Increase_By()", OPCODE_name(opc)));
00405
00406 TYPE_ID wtype = OPCODE_rtype(opc);
00407 OPCODE add = OPCODE_make_op(OPR_ADD, wtype, MTYPE_V);
00408 WN* exp = LWN_CreateExp2(add, wn, LWN_Make_Icon(wtype, c));
00409 LWN_Copy_Frequency_Tree(exp, wn);
00410 LWN_Set_Parent(exp, parent);
00411 WN_kid(parent,kid) = exp;
00412 }
00413 }
00414
00415
00416
00417
00418
00419 WN* LWN_Create_Block_From_Stmts_Above(WN* wn)
00420 {
00421
00422 WN* parent = LWN_Get_Parent(wn);
00423 FmtAssert(parent, ("wn_create_block_from_stmts_above() requires parents"));
00424
00425 WN* block = WN_CreateBlock();
00426 WN* pprev = NULL;
00427 for (WN* prev = WN_prev_executable(wn); prev; prev = pprev) {
00428 pprev = WN_prev(prev);
00429 LWN_Extract_From_Block(parent, prev);
00430 LWN_Insert_Block_After(block, NULL, prev);
00431 }
00432
00433 return block;
00434 }
00435
00436 WN* LWN_Create_Block_From_Stmts_Below(WN* wn)
00437 {
00438
00439 WN* parent = LWN_Get_Parent(wn);
00440 FmtAssert(parent, ("create_block_from_stmts_below() requires parents"));
00441
00442 WN* block = WN_CreateBlock();
00443 WN* nnext = NULL;
00444 for (WN* next = WN_next_executable(wn); next; next = nnext) {
00445 nnext = WN_next(next);
00446 LWN_Extract_From_Block(parent, next);
00447 LWN_Insert_Block_Before(block, NULL, next);
00448 }
00449
00450 return block;
00451 }
00452
00453
00454
00455
00456 INT64 Iterations(WN* loop,
00457 MEM_POOL* pool)
00458 {
00459 INT64 lb = 0;
00460 INT64 ub = 0;
00461 BOOL is_const_lb;
00462 BOOL is_const_ub;
00463 WN* wnconst;
00464
00465 if (!Upper_Bound_Standardize(WN_end(loop), TRUE))
00466 return -1;
00467
00468 FmtAssert(WN_opcode(loop) == OPC_DO_LOOP, ("Bad parameter to Iterations()"));
00469
00470 INT stepsz = Step_Size(loop);
00471 if (stepsz == 0)
00472 return -1;
00473
00474
00475
00476 wnconst = WN_kid0(WN_start(loop));
00477 is_const_lb = WN_operator(wnconst) == OPR_INTCONST;
00478 if (is_const_lb)
00479 lb = WN_const_val(wnconst);
00480
00481 BOOL is_ne;
00482 wnconst = SNL_UBexp(WN_end(loop), &is_ne);
00483 is_const_ub = WN_operator(wnconst) == OPR_INTCONST;
00484 if (is_const_ub) {
00485 ub = WN_const_val(wnconst);
00486 if (is_ne)
00487 ub--;
00488 }
00489
00490 if (is_const_lb && is_const_ub) {
00491 if (stepsz < 0) {
00492 lb = -lb;
00493 ub = -ub;
00494 stepsz = -stepsz;
00495 }
00496 return lb <= ub ? (ub - lb + stepsz)/stepsz: 0;
00497 }
00498
00499
00500
00501
00502
00503 DOLOOP_STACK stack(pool);
00504 stack.Push(loop);
00505
00506 if (WN_operator(WN_kid0(WN_start(loop))) == OPR_MAX)
00507 return -1;
00508 if (WN_operator(SNL_UBexp(WN_end(loop),NULL)) == OPR_MIN)
00509 return -1;
00510
00511 INT rval = -1;
00512
00513 DO_LOOP_INFO* dli = Get_Do_Loop_Info(loop);
00514 ACCESS_VECTOR *av = Add(dli->LB->Dim(0), dli->UB->Dim(0), pool);
00515 if (av->Is_Const()) {
00516 if (stepsz < 0) {
00517 av->Const_Offset = -av->Const_Offset;
00518 stepsz = -stepsz;
00519 }
00520 rval = av->Const_Offset >= 0 ? (av->Const_Offset + stepsz)/stepsz : 0;
00521 }
00522 CXX_DELETE(av, pool);
00523
00524 return rval;
00525 }
00526
00527 extern WN* Find_Next_Innermost_Do_In_Block(WN* wn_block)
00528 {
00529 for (WN* wn = WN_first(wn_block); wn != NULL; wn = WN_next(wn)) {
00530 if (WN_opcode(wn) == OPC_REGION) {
00531 WN* wn_inside = Find_Next_Innermost_Do_In_Block(WN_region_body(wn));
00532 return wn_inside;
00533 }
00534 if (WN_opcode(wn) == OPC_DO_LOOP)
00535 return wn;
00536 }
00537 return NULL;
00538 }
00539
00540 extern WN* Find_Next_Innermost_Do(WN* loop)
00541 {
00542 return Find_Next_Innermost_Do_In_Block(WN_do_body(loop));
00543 }
00544
00545 DOLOOP_STACK* Copy_Dostack(const DOLOOP_STACK& stack, MEM_POOL* pool)
00546 {
00547 DOLOOP_STACK* newstack = CXX_NEW(DOLOOP_STACK(pool), pool);
00548 for (INT i = 0; i < stack.Elements(); i++)
00549 newstack->Push(stack.Bottom_nth(i));
00550 return newstack;
00551 }
00552
00553
00554
00555
00556
00557
00558 extern BOOL Valid_SNL_Region(SNL_REGION region)
00559 {
00560 if (region.First == NULL && region.Last == NULL)
00561 return TRUE;
00562 if (region.First == NULL || region.Last == NULL)
00563 return FALSE;
00564 for (WN* wn = region.First; wn != NULL; wn = WN_next(wn))
00565 if (wn == region.Last)
00566 return TRUE;
00567 return FALSE;
00568 }
00569
00570 #ifdef Is_True_On
00571
00572 struct SANITY_CHECK_RVAL {
00573 mBOOL has_loops;
00574 mBOOL has_regions;
00575 mBOOL has_calls;
00576 mBOOL has_io;
00577 WN* has_bad_mem;
00578
00579 SANITY_CHECK_RVAL() :
00580 has_loops(FALSE), has_regions(FALSE), has_calls(FALSE),
00581 has_bad_mem(NULL), has_io(FALSE) {}
00582 void operator += (const SANITY_CHECK_RVAL r) {
00583 if (r.has_loops)
00584 has_loops = TRUE;
00585 if (r.has_regions)
00586 has_regions = TRUE;
00587 if (r.has_calls)
00588 has_calls = TRUE;
00589 if (r.has_bad_mem)
00590 has_bad_mem = r.has_bad_mem;
00591 if (r.has_io)
00592 has_io = TRUE;
00593 }
00594 };
00595
00596 static SANITY_CHECK_RVAL SNL_Sanity_Check_Block(WN*, INT depth);
00597
00598 static SANITY_CHECK_RVAL SNL_Sanity_Check_Loop(WN* wn, INT depth)
00599 {
00600 FmtAssert(wn, ("Missing loop for sanity check"));
00601 FmtAssert(WN_opcode(wn) == OPC_DO_LOOP,
00602 ("Bad opcode %d for sanity check of block", WN_opcode(wn)));
00603
00604 const INT indexnamesz = 64;
00605 char indexname[indexnamesz];
00606 (SYMBOL(WN_index(wn))).Name(indexname,indexnamesz);
00607
00608 DO_LOOP_INFO* dli = Get_Do_Loop_Info(wn);
00609 SC_ASSERT(dli->LB && dli->UB && dli->Step,
00610 ("sanity check failed: Missing LB, UB or Step (0x%p)", wn));
00611
00612 if (!dli->LB->Too_Messy) {
00613 for (INT i = 0; i < dli->LB->Num_Vec(); i++) {
00614 ACCESS_VECTOR* av = dli->LB->Dim(i);
00615 if (!av->Too_Messy) {
00616 INT lval = av->Loop_Coeff(dli->Depth);
00617 SC_ASSERT(lval < 0,
00618 ("sanity check failed: lbval=%d depth=%d index=%s (0x%p)",
00619 lval, dli->Depth, indexname, wn));
00620 Check_Zero_Linear_Coefficients(wn, av);
00621 }
00622 }
00623 }
00624 if (!dli->UB->Too_Messy) {
00625 for (INT i = 0; i < dli->UB->Num_Vec(); i++) {
00626 ACCESS_VECTOR* av = dli->UB->Dim(i);
00627 if (!av->Too_Messy) {
00628 INT uval = av->Loop_Coeff(dli->Depth);
00629 SC_ASSERT(uval > 0,
00630 ("sanity check failed: ubval=%d depth=%d index=%s (0x%p)",
00631 uval, dli->Depth, indexname, wn));
00632 Check_Zero_Linear_Coefficients(wn, av);
00633 }
00634 }
00635 }
00636
00637 SANITY_CHECK_RVAL r = SNL_Sanity_Check_Block(WN_do_body(wn), depth+1);
00638
00639 if (!r.has_io) {
00640 SC_ASSERT((r.has_loops == FALSE) == (dli->Is_Inner != FALSE),
00641 ("sanity check failed: index=%s (0x%p): has_loops: %d %d",
00642 indexname, wn, r.has_loops, dli->Is_Inner));
00643 #if 0
00644
00645
00646
00647 SC_ASSERT((r.has_calls == FALSE) == (dli->Has_Calls == FALSE),
00648 ("sanity check failed: index=%s (0x%p): has_calls: %d %d",
00649 indexname, wn, r.has_calls, dli->Has_Calls));
00650 #endif
00651 SC_ASSERT(depth+1 == dli->Depth,
00652 ("sanity check failed: index=%s (0x%p): depth: %d %d",
00653 indexname, wn, depth+1, dli->Depth));
00654
00655 SC_ASSERT((dli->Has_Bad_Mem != 0) == (r.has_bad_mem != NULL) ||
00656 (dli->Has_Bad_Mem && (dli->Has_Calls || dli->Has_Gotos)),
00657 ("sanity check failed: index=%s (0x%p): has_bad_mem: %d 0x%p",
00658 indexname, wn, dli->Has_Bad_Mem, r.has_bad_mem));
00659 }
00660
00661 r.has_loops = TRUE;
00662 WN* bad;
00663 if (bad = SNL_Sanity_Check_Exp(WN_start(wn)))
00664 r.has_bad_mem = bad;
00665 if (bad = SNL_Sanity_Check_Exp(WN_end(wn)))
00666 r.has_bad_mem = bad;
00667 if (bad = SNL_Sanity_Check_Exp(WN_step(wn)))
00668 r.has_bad_mem = bad;
00669
00670 return r;
00671 }
00672
00673 static SANITY_CHECK_RVAL SNL_Sanity_Check_If(WN* wn, INT depth)
00674 {
00675 FmtAssert(wn && WN_opcode(wn) == OPC_IF, ("Bad if for sanity check"));
00676
00677 SANITY_CHECK_RVAL r;
00678
00679 WN* bad;
00680 if (bad = SNL_Sanity_Check_Exp(WN_if_test(wn)))
00681 r.has_bad_mem = bad;
00682 SANITY_CHECK_RVAL rt = SNL_Sanity_Check_Block(WN_then(wn), depth);
00683 SANITY_CHECK_RVAL re = SNL_Sanity_Check_Block(WN_else(wn), depth);
00684
00685 IF_INFO* ii = Get_If_Info(wn, TRUE);
00686 FmtAssert(ii, ("Missing IF info annotation"));
00687 FmtAssert(ii->Condition, ("Missing If Condition"));
00688 if (!rt.has_io) {
00689 SC_ASSERT((rt.has_loops||re.has_loops) == (ii->Contains_Do_Loops!=FALSE),
00690 ("Bad if info: has_loops disagreement: %d %d %d 0x%p",
00691 rt.has_loops, re.has_loops, ii->Contains_Do_Loops, wn));
00692 SC_ASSERT((rt.has_regions||re.has_regions) == (ii->Contains_Regions!=FALSE),
00693 ("Bad if info: has_regions disagreement: %d %d %d 0x%p",
00694 rt.has_regions, re.has_regions, ii->Contains_Regions, wn));
00695 }
00696
00697 r += rt;
00698 r += re;
00699 return r;
00700 }
00701
00702
00703 WN* SNL_Sanity_Check_Exp(WN* wn)
00704 {
00705 #ifdef KEY
00706 if (WN_operator(wn) == OPR_ASM_STMT)
00707 return NULL;
00708 #endif
00709 FmtAssert(wn, ("Null wn in SNL_Sanity_Check_Exp"));
00710
00711 WN* rval = NULL;
00712 OPCODE opc = WN_opcode(wn);
00713 OPERATOR opr = OPCODE_operator(opc);
00714
00715 FmtAssert(!OPCODE_is_scf(opc) && opc != OPC_BLOCK,
00716 ("problem in SNL_Sanity_Check, op=%d\n", opc));
00717
00718 if (OPCODE_is_store(opc) || OPCODE_is_load(opc)) {
00719 if (OPCODE_has_1ty(opc) && TY_is_volatile(WN_ty(wn))) {
00720 rval = wn;
00721 } else if (OPCODE_has_2ty(opc)&&(TY_is_volatile(WN_ty(wn)) ||
00722 TY_is_volatile(WN_load_addr_ty(wn)))) {
00723 rval = wn;
00724 }
00725 }
00726
00727 if (opr == OPR_STID) {
00728 #if 0
00729 if (!Alias_Mgr->Id(wn)) {
00730 fprintf(stdout,
00731 "sanity check warning(%s): missing alias for def of %s in\n",
00732 Cur_PU_Name, SYMBOL(wn).Name());
00733 fflush(stdout);
00734 }
00735 #endif
00736 USE_LIST* ul = Du_Mgr->Du_Get_Use(wn);
00737 if ((!ul || (!ul->Incomplete() && ul->Len() == 0)) &&
00738 !((ST_class(WN_st(wn))==CLASS_PREG)
00739 && Preg_Is_Dedicated(WN_offset(wn)))) {
00740 fprintf(stdout,
00741 "sanity check warning(%s): missing uses for def (0x%p) of %s <%s>\n",
00742 Cur_PU_Name, wn, SYMBOL(wn).Name(),
00743 ul ? "empty list" : "missing list");
00744 fflush(stdout);
00745 }
00746 }
00747 else if (opr == OPR_LDID) {
00748 #if 0
00749 if (!Alias_Mgr->Id(wn)) {
00750 fprintf(stdout,
00751 "sanity check warning(%s): missing alias for use of %s in\n",
00752 Cur_PU_Name, SYMBOL(wn).Name());
00753 WN* prnt = LWN_Get_Parent(wn);
00754 fflush(stdout);
00755 }
00756 #endif
00757 DEF_LIST* dl = Du_Mgr->Ud_Get_Def(wn);
00758 if (!dl || dl->Len() == 0) {
00759 fprintf(stdout, "sanity check warning(%s): missing defs for use ",
00760 Cur_PU_Name);
00761 fprintf(stdout, "(0x%p) of %s <%s> <id %d:%d>\n", wn, SYMBOL(wn).Name(),
00762 dl ? "empty list" : "missing list", OPCODE_mapcat(WN_opcode(wn)),
00763 WN_map_id(wn));
00764 WN* prnt = LWN_Get_Parent(wn);
00765 Dump_WN(prnt ? prnt : wn, stdout, 1, 2, 2);
00766 fflush(stdout);
00767 }
00768 }
00769 else if (opr == OPR_INTRINSIC_OP) {
00770 FmtAssert(WN_intrinsic(wn) >= INTRINSIC_FIRST &&
00771 WN_intrinsic(wn) <= INTRINSIC_LAST,
00772 ("Sanity check failed: Bad intrinsic number %d for opcode %s",
00773 WN_intrinsic(wn), OPCODE_name(WN_opcode(wn))));
00774 }
00775 else if (OPCODE_is_load(opc) || OPCODE_is_store(opc) ||
00776 OPCODE_is_call(opc)) {
00777 ::dg = Array_Dependence_Graph;
00778 if (!dg->Get_Vertex(wn))
00779 rval = wn;
00780 } else if (OPCODE_operator(opc) == OPR_ARRAY) {
00781 ::dg = Array_Dependence_Graph;
00782 WN* parent=LWN_Get_Parent(wn);
00783 if (WN_operator(parent) == OPR_PARM) {
00784 if (!dg->Get_Vertex(LWN_Get_Parent(parent))) {
00785 rval = wn;
00786 }
00787 }
00788 ACCESS_ARRAY *aa = (ACCESS_ARRAY *) WN_MAP_Get(LNO_Info_Map, wn);
00789 if (aa != NULL && !aa->Too_Messy) {
00790 for (INT i = 0; i < aa->Num_Vec(); i++) {
00791 ACCESS_VECTOR* av = aa->Dim(i);
00792 if (av->Too_Messy)
00793 continue;
00794 Check_Zero_Linear_Coefficients(wn, av);
00795 }
00796 }
00797 }
00798
00799 for (INT k = 0; k < WN_kid_count(wn); k++) {
00800 WN* bad = SNL_Sanity_Check_Exp(WN_kid(wn,k));
00801 if (bad)
00802 rval = bad;
00803 }
00804
00805 return rval;
00806 }
00807
00808 static SANITY_CHECK_RVAL SNL_Sanity_Check_Block(WN* body, INT depth)
00809 {
00810 WN* bad;
00811
00812 FmtAssert(body, ("Missing body for sanity check"));
00813 FmtAssert(WN_opcode(body) == OPC_BLOCK,
00814 ("Bad opcode %d for sanity check of block", WN_opcode(body)));
00815
00816 SANITY_CHECK_RVAL rval;
00817
00818 for (WN* wn = WN_first(body); wn; wn = WN_next(wn)) {
00819 OPCODE opc = WN_opcode(wn);
00820
00821 switch (opc) {
00822 case OPC_DO_LOOP:
00823 rval += SNL_Sanity_Check_Loop(wn, depth);
00824 break;
00825 case OPC_IF:
00826 rval += SNL_Sanity_Check_If(wn, depth);
00827 break;
00828 case OPC_DO_WHILE:
00829 case OPC_WHILE_DO:
00830 rval += SNL_Sanity_Check_Block(WN_while_body(wn), depth);
00831 if (bad = SNL_Sanity_Check_Exp(WN_while_test(wn)))
00832 rval.has_bad_mem = bad;
00833 break;
00834 case OPC_IO:
00835
00836 rval.has_calls = TRUE;
00837 rval.has_io = TRUE;
00838 break;
00839 case OPC_COMPGOTO:
00840 if (bad = SNL_Sanity_Check_Exp(WN_kid(wn,0)))
00841 rval.has_bad_mem = bad;
00842 break;
00843 case OPC_REGION:
00844 rval += SNL_Sanity_Check_Block(WN_region_body(wn), depth);
00845 rval.has_regions = TRUE;
00846 break;
00847 default:
00848 if (OPCODE_is_call(opc))
00849 rval.has_calls = TRUE;
00850 if (bad = SNL_Sanity_Check_Exp(wn))
00851 rval.has_bad_mem = bad;
00852 break;
00853 }
00854 }
00855
00856 return rval;
00857 }
00858
00859 void SNL_Sanity_Check_Region(SNL_REGION region)
00860 {
00861
00862 if (!Valid_SNL_Region(region)) {
00863 DevWarn("SNL_Sanity_Check_Region: Invalid SNL region 0x%p->0x%p",
00864 region.First, region.Last);
00865 return;
00866 }
00867
00868 if (region.First == NULL && region.Last == NULL)
00869 return;
00870
00871 INT depth = Check_Depth(LWN_Get_Parent(region.First));
00872
00873 for (WN* wn = region.First; wn; wn = wn==region.Last ? NULL : WN_next(wn)) {
00874 OPCODE opc = WN_opcode(wn);
00875
00876 switch (opc) {
00877 case OPC_DO_LOOP:
00878 SNL_Sanity_Check_Loop(wn, depth);
00879 break;
00880 case OPC_IF:
00881 SNL_Sanity_Check_If(wn, depth);
00882 break;
00883 case OPC_DO_WHILE:
00884 case OPC_WHILE_DO:
00885 SNL_Sanity_Check_Block(WN_while_body(wn), depth);
00886 (void) SNL_Sanity_Check_Exp(WN_while_test(wn));
00887 break;
00888 case OPC_IO:
00889 break;
00890 case OPC_COMPGOTO:
00891 break;
00892 default:
00893 (void) SNL_Sanity_Check_Exp(wn);
00894 break;
00895 }
00896 }
00897 }
00898
00899 void SNL_Sanity_Check_Block(WN* wn)
00900 {
00901 SNL_Sanity_Check_Block(wn, Do_Depth(wn));
00902 }
00903
00904 void SNL_Sanity_Check_Func(WN* func_nd)
00905 {
00906 dg = Array_Dependence_Graph;
00907 SNL_Sanity_Check_Block(WN_func_body(func_nd), -1);
00908 Du_Sanity_Check(func_nd);
00909 FB_Sanity_Check(func_nd);
00910 }
00911
00912 void SNL_Sanity_Check_Body(WN* wn)
00913 {
00914 SNL_Sanity_Check_Block(wn, Do_Depth(wn));
00915 }
00916
00917 void SNL_Sanity_Check_Loop(WN* loop)
00918 {
00919 SNL_Sanity_Check_Loop(loop, Do_Depth(loop)-1);
00920 }
00921
00922 void SNL_Sanity_Check_If(WN* wn)
00923 {
00924 SNL_Sanity_Check_If(wn, Do_Depth(wn));
00925 }
00926
00927 #endif
00928
00929 struct RENUMBER_INFO {
00930 INT loops_inside;
00931 INT missing_dg_nodes;
00932 RENUMBER_INFO() : loops_inside(0), missing_dg_nodes(0) {}
00933 RENUMBER_INFO& operator += (const RENUMBER_INFO& a) {
00934 loops_inside += a.loops_inside;
00935 missing_dg_nodes += a.missing_dg_nodes;
00936 return *this;
00937 }
00938 };
00939
00940
00941 INT Renumber_Exp(WN* wn)
00942 {
00943 INT ans = 0;
00944 OPCODE op = WN_opcode(wn);
00945 OPERATOR oper = OPCODE_operator(op);
00946
00947 if (((OPCODE_is_load(op) && OPCODE_operator(op) != OPR_LDID) ||
00948 (OPCODE_is_store(op) && OPCODE_operator(op) != OPR_STID) ||
00949 OPCODE_is_call(op)) &&
00950 !dg->Get_Vertex(wn))
00951 ans++;
00952 if (op == OPC_IO || oper == OPR_FORWARD_BARRIER
00953 || oper == OPR_BACKWARD_BARRIER)
00954 ans++;
00955 for (INT k = 0; k < WN_kid_count(wn); k++)
00956 ans += Renumber_Exp(WN_kid(wn,k));
00957 return ans;
00958 }
00959
00960
00961 static RENUMBER_INFO Renumber_Loops(WN* first, WN* last, INT depth)
00962 {
00963 RENUMBER_INFO info;
00964
00965 if (first == NULL)
00966 return info;
00967
00968 for (WN* wn = first; ; wn = WN_next(wn)) {
00969 FmtAssert(wn, ("last not found for first in Renumber_Loops()"));
00970 switch (WN_opcode(wn)) {
00971 case OPC_IF:
00972 info.missing_dg_nodes += Renumber_Exp(WN_if_test(wn));
00973 info += Renumber_Loops(WN_first(WN_then(wn)),
00974 WN_last(WN_then(wn)),
00975 depth);
00976 info += Renumber_Loops(WN_first(WN_else(wn)),
00977 WN_last(WN_else(wn)),
00978 depth);
00979 break;
00980 case OPC_DO_LOOP:
00981 {
00982 RENUMBER_INFO info2;
00983 info2.missing_dg_nodes += Renumber_Exp(WN_start(wn));
00984 info2.missing_dg_nodes += Renumber_Exp(WN_end(wn));
00985 info2.missing_dg_nodes += Renumber_Exp(WN_step(wn));
00986 info2 += Renumber_Loops(WN_first(WN_do_body(wn)),
00987 WN_last(WN_do_body(wn)),
00988 depth+1);
00989 DO_LOOP_INFO* dli = Get_Do_Loop_Info(wn);
00990 dli->Is_Inner = info2.loops_inside == 0;
00991 dli->Depth = depth + 1;
00992 if (info2.missing_dg_nodes != 0)
00993 dli->Has_Bad_Mem = TRUE;
00994 info += info2;
00995 info.loops_inside++;
00996 }
00997 break;
00998 case OPC_DO_WHILE:
00999 case OPC_WHILE_DO:
01000 info.missing_dg_nodes += Renumber_Exp(WN_while_test(wn));
01001 info += Renumber_Loops(WN_first(WN_while_body(wn)),
01002 WN_last(WN_while_body(wn)),
01003 depth);
01004 break;
01005 case OPC_REGION:
01006 info += Renumber_Loops(WN_first(WN_region_exits(wn)),
01007 WN_last(WN_region_exits(wn)), depth);
01008 info += Renumber_Loops(WN_first(WN_region_pragmas(wn)),
01009 WN_last(WN_region_pragmas(wn)), depth);
01010 info += Renumber_Loops(WN_first(WN_region_body(wn)),
01011 WN_last(WN_region_body(wn)), depth);
01012 break;
01013 default:
01014 info.missing_dg_nodes += Renumber_Exp(wn);
01015 break;
01016 }
01017 if (wn == last)
01018 break;
01019 }
01020
01021 return info;
01022 }
01023
01024 INT Renumber_Loops(WN* first, WN* last, ARRAY_DIRECTED_GRAPH16* dg)
01025 {
01026 ::dg = (dg == NULL) ? Array_Dependence_Graph : dg;
01027
01028 FmtAssert(first && last, ("bad call to Renumber_Loops()"));
01029 FmtAssert(LWN_Get_Parent(first) && LWN_Get_Parent(last),
01030 ("bad call to Renumber_Loops()"));
01031
01032 INT depth = Check_Depth(LWN_Get_Parent(first));
01033 RENUMBER_INFO info = Renumber_Loops(first, last, depth);
01034 if (info.missing_dg_nodes)
01035 Unmapped_Vertices_Here_Out(LWN_Get_Parent(first));
01036
01037 return info.loops_inside;
01038 }
01039
01040 void Dump_WN(SNL_REGION region, FILE* f, INT i1, INT i2, INT i3,
01041 WN** wnp, WN* wn2, ARRAY_DIRECTED_GRAPH16* dg)
01042 {
01043 for (WN* wn = region.First; wn; wn = wn==region.Last ? NULL : WN_next(wn))
01044 Dump_WN(wn, f, i1, i2, i3, dg, wnp, wn2);
01045 }
01046
01047 static void SNL_Add_Du_To_Index_Ldid_Ldid(WN* loop, WN* ldid, DU_MANAGER* du,
01048 BOOL code_in_loop)
01049 {
01050 du->Add_Def_Use(WN_start(loop), ldid);
01051 du->Add_Def_Use(WN_step(loop), ldid);
01052 DEF_LIST* dl = du->Ud_Get_Def(ldid);
01053 dl->Set_loop_stmt(code_in_loop ? loop : NULL);
01054 }
01055
01056 void SNL_Add_Du_To_Index_Ldid(WN* loop, WN* exp, DU_MANAGER* du,
01057 BOOL code_in_loop)
01058 {
01059 if (WN_operator(exp) == OPR_LDID &&
01060 SYMBOL(WN_index(loop)) == SYMBOL(exp)) {
01061 SNL_Add_Du_To_Index_Ldid_Ldid(loop, exp, du, code_in_loop);
01062 FmtAssert(du->Ud_Get_Def(exp), ("failed to add!"));
01063 }
01064
01065 if (WN_opcode(exp) == OPC_BLOCK) {
01066 for (WN* w = WN_first(exp); w; w = WN_next(w))
01067 SNL_Add_Du_To_Index_Ldid(loop, w, du, code_in_loop);
01068 }
01069 else {
01070 for (INT i = 0; i < WN_kid_count(exp); i++)
01071 SNL_Add_Du_To_Index_Ldid(loop, WN_kid(exp,i), du, code_in_loop);
01072 }
01073 }
01074
01075 void SNL_Change_Du_To_Index_Ldid(WN* loop, WN* exp, DU_MANAGER* du,
01076 BOOL code_in_loop)
01077 {
01078 if (WN_operator(exp) == OPR_LDID &&
01079 SYMBOL(WN_index(loop)) == SYMBOL(exp)) {
01080 du->Remove_Use_From_System(exp);
01081 SNL_Add_Du_To_Index_Ldid_Ldid(loop, exp, du, code_in_loop);
01082 FmtAssert(du->Ud_Get_Def(exp), ("failed to add!"));
01083 }
01084
01085 if (WN_opcode(exp) == OPC_BLOCK) {
01086 for (WN* w = WN_first(exp); w; w = WN_next(w))
01087 SNL_Change_Du_To_Index_Ldid(loop, w, du, code_in_loop);
01088 }
01089 else {
01090 for (INT i = 0; i < WN_kid_count(exp); i++)
01091 SNL_Change_Du_To_Index_Ldid(loop, WN_kid(exp,i), du, code_in_loop);
01092 }
01093 }
01094
01095 void SNL_Change_Du_Pointer(WN* oldptr, WN* ptr, WN* wn, DU_MANAGER* du)
01096 {
01097 OPCODE opc = WN_opcode(wn);
01098
01099 if (opc == OPC_BLOCK) {
01100 for (WN* w = WN_first(wn); w; w = WN_next(w))
01101 SNL_Change_Du_Pointer(oldptr, ptr, w, du);
01102 }
01103 else {
01104 if (OPCODE_operator(opc) == OPR_LDID) {
01105 DEF_LIST* dl = Du_Mgr->Ud_Get_Def(wn);
01106 if (dl && dl->Loop_stmt() == oldptr)
01107 dl->Set_loop_stmt(ptr);
01108 }
01109 for (INT i = 0; i < WN_kid_count(wn); i++)
01110 SNL_Change_Du_Pointer(oldptr, ptr, WN_kid(wn,i), du);
01111 }
01112 }
01113
01114 void SNL_Fix_Index_Pointers(WN* loop, WN* wn)
01115 {
01116 OPCODE opc = WN_opcode(wn);
01117
01118 if (opc == OPC_BLOCK) {
01119 for (WN* w = WN_first(wn); w; w = WN_next(w))
01120 SNL_Fix_Index_Pointers(loop, w);
01121 }
01122 else {
01123 if (OPCODE_operator(opc) == OPR_LDID &&
01124 SYMBOL(wn) == SYMBOL(WN_index(loop))) {
01125 DEF_LIST* dl = Du_Mgr->Ud_Get_Def(wn);
01126 if (dl)
01127 dl->Set_loop_stmt(loop);
01128 }
01129 for (INT i = 0; i < WN_kid_count(wn); i++)
01130 SNL_Fix_Index_Pointers(loop, WN_kid(wn,i));
01131 }
01132 }
01133
01134 void SNL_Print_Ldid_Pointers(WN* wn)
01135 {
01136 OPCODE opc = WN_opcode(wn);
01137
01138 if (opc == OPC_BLOCK) {
01139 for (WN* w = WN_first(wn); w; w = WN_next(w))
01140 SNL_Print_Ldid_Pointers(w);
01141 }
01142 else {
01143 if (OPCODE_operator(opc) == OPR_LDID) {
01144 DEF_LIST* dl = Du_Mgr->Ud_Get_Def(wn);
01145 if (dl == NULL)
01146 printf("0x%p <missing deflist>\n", wn);
01147 else {
01148 WN* loop = dl->Loop_stmt();
01149 printf("0x%p 0x%p %s\n", wn, loop,
01150 loop ? SYMBOL(WN_index(loop)).Name() : "<none>");
01151 }
01152 }
01153 for (INT i = 0; i < WN_kid_count(wn); i++)
01154 SNL_Print_Ldid_Pointers(WN_kid(wn,i));
01155 }
01156 }
01157
01158 WN* Find_Use_In_Exp(WN* exp, const SYMBOL& sym)
01159 {
01160 if (WN_operator(exp) == OPR_LDID) {
01161 if (sym == SYMBOL(exp)) {
01162 return exp;
01163 }
01164 }
01165
01166 for (INT k = 0; k < WN_kid_count(exp); k++) {
01167 WN* rv = Find_Use_In_Exp(WN_kid(exp,k), sym);
01168 if (rv)
01169 return rv;
01170 }
01171
01172 return NULL;
01173 }
01174
01175
01176 const DEF_LIST* Find_Def_List_In_Exp(WN* exp, const SYMBOL& sym)
01177 {
01178 const DEF_LIST* l = NULL;
01179 WN* wn = Find_Use_In_Exp(exp, sym);
01180 if (wn) {
01181 l = Du_Mgr->Ud_Get_Def(wn);
01182 FmtAssert(l, ("Missing def list for %s", sym.Name()));
01183 }
01184 return l;
01185 }
01186
01187 WN* SNL_Copy_Exp(WN* wn)
01188 {
01189 WN* new_wn = LWN_Copy_Tree(wn, TRUE, LNO_Info_Map);
01190 LWN_Copy_Def_Use(wn, new_wn, Du_Mgr);
01191 return new_wn;
01192 }
01193
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215 static INT Good_Do_Next_Innermost1(WN* blk, WN** unique_answer)
01216 {
01217 FmtAssert(WN_opcode(blk) == OPC_BLOCK, ("expected block"));
01218
01219 BOOL do_seen = FALSE;
01220 INT val;
01221
01222 for (WN* wn = WN_first(blk); wn; wn = WN_next(wn)) {
01223 switch (WN_opcode(wn)) {
01224 case OPC_IF:
01225 if ((val=Good_Do_Next_Innermost1(WN_then(wn), unique_answer)) != 0 ||
01226 (val=Good_Do_Next_Innermost1(WN_else(wn), unique_answer)) != 0) {
01227 SNL_DEBUG1(3, "Inside if val=%d", val);
01228 return -1;
01229 }
01230 break;
01231 case OPC_DO_WHILE:
01232 case OPC_WHILE_DO:
01233 if ((val=Good_Do_Next_Innermost1(WN_then(wn), unique_answer)) != 0) {
01234 SNL_DEBUG1(3, "Inside do-while val=%d", val);
01235 return -1;
01236 }
01237 break;
01238 case OPC_DO_LOOP:
01239 if (do_seen) {
01240 SNL_DEBUG1(3, "Loop %s is second seen", SYMBOL(WN_index(wn)).Name());
01241 return -1;
01242 }
01243 if (!Do_Loop_Is_Good(wn) || Do_Loop_Has_Gotos(wn)) {
01244 SNL_DEBUG1(3, "Loop %s is bad!", SYMBOL(WN_index(wn)).Name());
01245 return -1;
01246 }
01247 *unique_answer = wn;
01248 do_seen = TRUE;
01249 break;
01250 }
01251 }
01252
01253 return do_seen ? 1 : 0;
01254 }
01255
01256 WN* Good_Do_Next_Innermost(WN* wn)
01257 {
01258 FmtAssert(WN_opcode(wn) == OPC_DO_LOOP, ("expected block"));
01259
01260 WN* answer;
01261 INT val = Good_Do_Next_Innermost1(WN_do_body(wn), &answer);
01262 return (val == 1) ? answer : NULL;
01263 }
01264
01265 static BOOL Wn_Intrinsic_Is_Floor(WN* wn)
01266 {
01267 INT32 intr = WN_intrinsic(wn);
01268
01269 return intr == INTRN_I4DIVFLOOR ||
01270 intr == INTRN_I8DIVFLOOR ||
01271 intr == INTRN_U4DIVFLOOR ||
01272 intr == INTRN_U8DIVFLOOR;
01273 }
01274
01275 static BOOL Wn_Intrinsic_Is_Ceil(WN* wn)
01276 {
01277 INT32 intr = WN_intrinsic(wn);
01278
01279 return intr == INTRN_I4DIVCEIL ||
01280 intr == INTRN_I8DIVCEIL ||
01281 intr == INTRN_U4DIVCEIL ||
01282 intr == INTRN_U8DIVCEIL;
01283 }
01284
01285 static void SNL_Optimize_Bounds(WN* wn)
01286 {
01287 OPERATOR opr = WN_operator(wn);
01288
01289 if (opr == OPR_BLOCK) {
01290 for (WN* w = WN_first(wn); w; w = WN_next(w))
01291 SNL_Optimize_Bounds(w);
01292 }
01293 else if (opr == OPR_DO_LOOP) {
01294
01295
01296
01297
01298
01299 WN* end = WN_end(wn);
01300 OPCODE opend = WN_opcode(end);
01301 OPERATOR oprend = OPCODE_operator(opend);
01302
01303 BOOL less = (oprend == OPR_LE || oprend == OPR_LT);
01304 while (less || (oprend == OPR_GE || oprend == OPR_GT)) {
01305 WN* l = WN_kid0(end);
01306 WN* r = WN_kid1(end);
01307 OPCODE lop = WN_opcode(l);
01308 OPCODE rop = WN_opcode(r);
01309 if (OPCODE_operator(rop) == OPR_INTRINSIC_OP &&
01310 ((Wn_Intrinsic_Is_Floor(r) && less) ||
01311 (Wn_Intrinsic_Is_Ceil(r) && !less)) &&
01312 WN_operator(WN_kid1(r)) == OPR_INTCONST &&
01313 WN_const_val(WN_kid1(r)) > 0) {
01314 WN* rl = WN_kid0(r);
01315 WN* rr = WN_kid1(r);
01316 OPCODE mulop = OPCODE_make_op(OPR_MPY, OPCODE_rtype(rop), MTYPE_V);
01317 WN_Delete(r);
01318 WN_kid0(end) = LWN_CreateExp2(mulop, l, rr);
01319 WN_kid1(end) = rl;
01320 LWN_Set_Parent(WN_kid0(end), end);
01321 LWN_Set_Parent(WN_kid1(end), end);
01322 }
01323 else if (OPCODE_operator(lop) == OPR_INTRINSIC_OP &&
01324 ((Wn_Intrinsic_Is_Floor(l) && less) ||
01325 (Wn_Intrinsic_Is_Ceil(l) && !less)) &&
01326 WN_operator(WN_kid1(l)) == OPR_INTCONST &&
01327 WN_const_val(WN_kid1(l)) > 0) {
01328 WN* ll = WN_kid0(l);
01329 WN* lr = WN_kid1(l);
01330 OPCODE mulop = OPCODE_make_op(OPR_MPY, OPCODE_rtype(lop), MTYPE_V);
01331 WN_Delete(l);
01332 WN_kid0(end) = ll;
01333 WN_kid1(end) = LWN_CreateExp2(mulop, r, lr);
01334 LWN_Set_Parent(WN_kid0(end), end);
01335 LWN_Set_Parent(WN_kid1(end), end);
01336 }
01337 else
01338 break;
01339 }
01340
01341
01342
01343 DO_LOOP_INFO* dli = Get_Do_Loop_Info(wn);
01344 if (!dli->Is_Inner)
01345 SNL_Optimize_Bounds(WN_do_body(wn));
01346 }
01347 else {
01348 for (INT i = 0; i < WN_kid_count(wn); i++)
01349 SNL_Optimize_Bounds(WN_kid(wn,i));
01350 }
01351 }
01352
01353 void SNL_Optimize_Bounds(SNL_REGION region)
01354 {
01355 for (WN* wn = region.First; wn; wn = wn==region.Last ? NULL : WN_next(wn))
01356 SNL_Optimize_Bounds(wn);
01357 }
01358
01359 WN*& SNL_UBexp(WN* snl_end, BOOL* ne)
01360 {
01361 OPERATOR opr = WN_operator(snl_end);
01362
01363 switch (opr) {
01364 default:
01365 FmtAssert(0, ("Bad op %d for SNL_UBexp", WN_opcode(snl_end)));
01366 case OPR_GE:
01367 if (ne) *ne = FALSE;
01368 FmtAssert(WN_operator(WN_kid1(snl_end)) == OPR_LDID,
01369 ("Does not have LDID on opposite side of WN_end"));
01370 return WN_kid0(snl_end);
01371 case OPR_GT:
01372 if (ne) *ne = TRUE;
01373 FmtAssert(WN_operator(WN_kid1(snl_end)) == OPR_LDID,
01374 ("Does not have LDID on opposite side of WN_end"));
01375 return WN_kid0(snl_end);
01376 case OPR_LE:
01377 if (ne) *ne = FALSE;
01378 FmtAssert(WN_operator(WN_kid0(snl_end)) == OPR_LDID,
01379 ("Does not have LDID on opposite side of WN_end"));
01380 return WN_kid1(snl_end);
01381 case OPR_LT:
01382 if (ne) *ne = TRUE;
01383 FmtAssert(WN_operator(WN_kid0(snl_end)) == OPR_LDID,
01384 ("Does not have LDID on opposite side of WN_end"));
01385 return WN_kid1(snl_end);
01386 }
01387 }
01388
01389 WN*& SNL_UBvar(WN* snl_end)
01390 {
01391 OPERATOR opr = WN_operator(snl_end);
01392
01393 switch (opr) {
01394 default:
01395 FmtAssert(0, ("Bad op %d for SNL_UBvar", WN_opcode(snl_end)));
01396 case OPR_LE:
01397 case OPR_LT:
01398 return WN_kid0(snl_end);
01399 case OPR_GE:
01400 case OPR_GT:
01401 return WN_kid1(snl_end);
01402 }
01403 }
01404
01405 extern WN* SNL_Get_Inner_Snl_Loop(WN* outer, INT nloops)
01406 {
01407 Is_True(nloops > 0, ("Bad nloops for SNL_Get_Inner_Snl_Loop()"));
01408 WN* wn = outer;
01409 for (INT curnloops = nloops; curnloops > 1; curnloops--) {
01410 for (wn = WN_first(WN_do_body(wn)); wn; wn = WN_next(wn))
01411 #ifndef KEY
01412 if (WN_opcode(wn) == OPC_DO_LOOP || WN_opcode(wn) == OPC_REGION)
01413 break;
01414 FmtAssert(wn != NULL, ("Sequencing error"));
01415 if (WN_opcode(wn) == OPC_REGION) {
01416 for (wn = WN_first(WN_region_body(wn)); wn; wn = WN_next(wn))
01417 if (WN_opcode(wn) == OPC_DO_LOOP)
01418 break;
01419 }
01420 #else //KEY Bug 10700
01421 {
01422 if (WN_opcode(wn) == OPC_REGION) {
01423 for (WN *tmp = WN_first(WN_region_body(wn)); tmp; tmp = WN_next(tmp))
01424 if (WN_opcode(tmp) == OPC_DO_LOOP){
01425 wn = tmp;
01426 break;
01427 }
01428 }
01429 if (WN_opcode(wn) == OPC_DO_LOOP)
01430 break;
01431 }
01432 #endif
01433 FmtAssert(wn, ("SNL_Get_Inner_Snl_Loop() called with bad parameters"));
01434 }
01435 return wn;
01436 }
01437
01438 extern BOOL SNL_Is_Non_Varying_Access_Array(ACCESS_ARRAY* aa,
01439 INT outer_depth)
01440 {
01441 for (INT dim = 0; dim < aa->Num_Vec(); dim++) {
01442 ACCESS_VECTOR* av = aa->Dim(dim);
01443 if (av->Too_Messy ||
01444 av->Contains_Non_Lin_Symb() ||
01445 av->Non_Const_Loops() > outer_depth) {
01446 return FALSE;
01447 }
01448 }
01449 return TRUE;
01450 }
01451
01452 extern BOOL SNL_Is_Invariant(DOLOOP_STACK *stack,
01453 INT d,
01454 INT dd)
01455 {
01456 DO_LOOP_INFO* dli_dd = Get_Do_Loop_Info(stack->Bottom_nth(dd));
01457
01458 ACCESS_ARRAY* aalb = dli_dd->LB;
01459 ACCESS_ARRAY* aaub = dli_dd->UB;
01460 INT outer_depth = Do_Loop_Depth(stack->Bottom_nth(d));
01461
01462 if (SNL_Is_Non_Varying_Access_Array(aalb, outer_depth)) {
01463 for (INT dimlb = aalb->Num_Vec() - 1; dimlb >= 0; dimlb--) {
01464 ACCESS_VECTOR* avlb = aalb->Dim(dimlb);
01465 if (avlb->Loop_Coeff(d))
01466 return FALSE;
01467 }
01468 } else if (!Is_Loop_Invariant_Exp(WN_start(stack->Bottom_nth(dd)),
01469 stack->Bottom_nth(d))) {
01470 return FALSE;
01471 }
01472
01473 if (SNL_Is_Non_Varying_Access_Array(aaub, outer_depth)) {
01474 for (INT dimub = aaub->Num_Vec() - 1; dimub >= 0; dimub--) {
01475 ACCESS_VECTOR* avub = aaub->Dim(dimub);
01476 if (avub->Loop_Coeff(d))
01477 return FALSE;
01478 }
01479 } else {
01480 WN* wn = UBexp(WN_end(stack->Bottom_nth(dd)));
01481
01482 if (wn == NULL)
01483 return FALSE;
01484 if (!Is_Loop_Invariant_Exp(wn, stack->Bottom_nth(d)))
01485 return FALSE;
01486 }
01487
01488 return TRUE;
01489 }
01490
01491 extern INT SNL_Loop_Count(WN* wn_snl)
01492 {
01493 FmtAssert(WN_opcode(wn_snl) == OPC_DO_LOOP,
01494 ("SNL_Loop_Count: Expected a DO loop"));
01495 DO_LOOP_INFO* dli = Get_Do_Loop_Info(wn_snl);
01496 if (dli->Is_Inner)
01497 return 1;
01498 INT do_count = 0;
01499 INT loop_count = 1;
01500 for (WN* wn = WN_first(WN_do_body(wn_snl)); wn != NULL; wn = WN_next(wn)) {
01501 if (WN_opcode(wn) == OPC_DO_LOOP) {
01502 do_count++;
01503 if (do_count > 1)
01504 return 1;
01505 loop_count = SNL_Loop_Count(wn) + 1;
01506 }
01507 }
01508 return loop_count;
01509 }
01510
01511 extern WN* SNL_Innermost_Do(WN* wn_outer)
01512 {
01513 FmtAssert(WN_opcode(wn_outer) == OPC_DO_LOOP,
01514 ("SNL_Innermost_Do: Expected a DO loop"));
01515 DO_LOOP_INFO* dli = Get_Do_Loop_Info(wn_outer);
01516 if (dli->Is_Inner)
01517 return wn_outer;
01518 INT do_count = 0;
01519 WN* wn_inner = NULL;
01520 for (WN* wn = WN_first(WN_do_body(wn_outer)); wn != NULL; wn = WN_next(wn)) {
01521 if (WN_opcode(wn) == OPC_DO_LOOP) {
01522 do_count++;
01523 if (do_count > 1)
01524 return wn_outer;
01525 wn_inner = wn;
01526 }
01527 }
01528 return SNL_Innermost_Do(wn_inner);
01529 }
01530
01531
01532
01533
01534
01535
01536
01537 extern INT Is_Inner_SNL(WN* wn_loop)
01538 {
01539 switch (WN_opcode(wn_loop)) {
01540 case OPC_DO_LOOP:
01541 {
01542 DO_LOOP_INFO* dli = Get_Do_Loop_Info(wn_loop);
01543 if (dli->Is_Inner)
01544 return 1;
01545 }
01546 break;
01547 case OPC_IF:
01548 case OPC_DO_WHILE:
01549 case OPC_WHILE_DO:
01550 return 0;
01551 case OPC_BLOCK:
01552 case OPC_REGION:
01553 break;
01554 default:
01555 return -1;
01556 }
01557
01558 INT kid_depth = -1;
01559 if (WN_opcode(wn_loop) == OPC_BLOCK) {
01560 for (WN* wn = WN_first(wn_loop); wn != NULL; wn = WN_next(wn)) {
01561 INT local_kid_depth = Is_Inner_SNL(wn);
01562 if (local_kid_depth == 0 || kid_depth != -1 && local_kid_depth != -1)
01563 return 0;
01564 if (local_kid_depth > 0)
01565 kid_depth = local_kid_depth;
01566 }
01567 } else {
01568 for (INT i = 0; i < WN_kid_count(wn_loop); i++) {
01569 WN* wn = WN_kid(wn_loop, i);
01570 INT local_kid_depth = Is_Inner_SNL(wn);
01571 if (local_kid_depth == 0 || kid_depth != -1 && local_kid_depth != -1)
01572 return 0;
01573 if (local_kid_depth > 0)
01574 kid_depth = local_kid_depth;
01575 }
01576 }
01577 return WN_opcode(wn_loop) == OPC_DO_LOOP ? kid_depth + 1 : kid_depth ;
01578 }
01579
01580
01581
01582
01583
01584
01585
01586
01587 extern void SNL_Upper_Bound_Standardize(WN* wn_outer,
01588 INT nloops)
01589 {
01590 INT outer_depth = Do_Loop_Depth(wn_outer);
01591 WN* wn_inner = SNL_Get_Inner_Snl_Loop(wn_outer, nloops);
01592 DOLOOP_STACK stack(&LNO_local_pool);
01593 Build_Doloop_Stack(wn_inner, &stack);
01594 for (INT i = outer_depth; i < outer_depth + nloops; i++) {
01595 WN* wn_loop = stack.Bottom_nth(i);
01596 Upper_Bound_Standardize(WN_end(wn_loop), TRUE);
01597 }
01598 }
01599
01600
01601
01602
01603
01604
01605
01606 extern BOOL Need_Fix_Array_Deps_On_Index_Variable(WN* wn_loop)
01607 {
01608 ARRAY_DIRECTED_GRAPH16* dg = Array_Dependence_Graph;
01609 WN* wn_start = WN_start(wn_loop);
01610 return dg->Get_Vertex(wn_start);
01611 }
01612
01613
01614
01615
01616
01617
01618
01619
01620
01621
01622 static BOOL Can_Fix_Array_Deps_On_Index_Variable(WN* wn_loop)
01623 {
01624 ARRAY_DIRECTED_GRAPH16* dg = Array_Dependence_Graph;
01625 VINDEX16 v = dg->Get_Vertex(WN_start(wn_loop));
01626 EINDEX16 e = 0;
01627 for (e = dg->Get_In_Edge(v); e != 0; e = dg->Get_Next_In_Edge(e)) {
01628 WN* wn = dg->Get_Wn(dg->Get_Source(e));
01629 if (Wn_Is_Inside(wn, wn_loop))
01630 return FALSE;
01631 }
01632 for (e = dg->Get_Out_Edge(v); e != 0; e = dg->Get_Next_Out_Edge(e)) {
01633 WN* wn = dg->Get_Wn(dg->Get_Sink(e));
01634 if (Wn_Is_Inside(wn, wn_loop))
01635 return FALSE;
01636 }
01637 return TRUE;
01638 }
01639
01640
01641
01642
01643
01644
01645
01646
01647 static BOOL Fix_Array_Deps_On_Index_Variable(WN* wn_loop)
01648 {
01649 DU_MANAGER* du = Du_Mgr;
01650 ARRAY_DIRECTED_GRAPH16* dg = Array_Dependence_Graph;
01651 Finalize_Index_Variable(wn_loop);
01652 WN* wn_new = WN_next(wn_loop);
01653 scalar_rename(WN_start(wn_loop));
01654 dg->Add_Vertex(wn_new);
01655 EINDEX16 e = 0;
01656 VINDEX16 v = dg->Get_Vertex(WN_start(wn_loop));
01657 VINDEX16 v1 = dg->Get_Vertex(wn_new);
01658 for (e = dg->Get_In_Edge(v); e != 0; e = dg->Get_Next_In_Edge(e)) {
01659 VINDEX16 v2 = dg->Get_Source(e);
01660 if (!dg->Add_Edge(v1, v2, Create_DEPV_ARRAY(dg->Depv_Array(e),
01661 &LNO_default_pool))) {
01662 LNO_Erase_Dg_From_Here_In(wn_new, dg);
01663 LNO_Erase_Dg_From_Here_In(dg->Get_Wn(dg->Get_Source(e)), dg);
01664 return FALSE;
01665 }
01666 }
01667 for (e = dg->Get_Out_Edge(v); e != 0; e = dg->Get_Next_Out_Edge(e)) {
01668 VINDEX16 v2 = dg->Get_Sink(e);
01669 if (!dg->Add_Edge(v2, v1, Create_DEPV_ARRAY(dg->Depv_Array(e),
01670 &LNO_default_pool))) {
01671 LNO_Erase_Dg_From_Here_In(wn_new, dg);
01672 LNO_Erase_Dg_From_Here_In(dg->Get_Wn(dg->Get_Sink(e)), dg);
01673 return FALSE;
01674 }
01675 }
01676 USE_LIST *use_list = du->Du_Get_Use(WN_start(wn_loop));
01677 const DU_NODE* node = NULL;
01678 USE_LIST_ITER iter(use_list);
01679 for (node = iter.First(); !iter.Is_Empty(); node = iter.Next()) {
01680 WN* wn = node->Wn();
01681 if (WN_operator(wn) == OPR_LDID
01682 && SYMBOL(wn) == SYMBOL(WN_start(wn_loop))) {
01683 VINDEX16 v = dg->Get_Vertex(wn);
01684 if (v != 0) {
01685 while (e = dg->Get_Out_Edge(v))
01686 dg->Remove_Edge(e);
01687 while (e = dg->Get_In_Edge(v))
01688 dg->Remove_Edge(e);
01689 dg->Delete_Vertex(v);
01690 }
01691 }
01692 }
01693 v = dg->Get_Vertex(WN_start(wn_loop));
01694 while (e = dg->Get_Out_Edge(v))
01695 dg->Remove_Edge(e);
01696 while (e = dg->Get_In_Edge(v))
01697 dg->Remove_Edge(e);
01698 dg->Delete_Vertex(v);
01699 v = dg->Get_Vertex(WN_step(wn_loop));
01700 while (e = dg->Get_Out_Edge(v))
01701 dg->Remove_Edge(e);
01702 while (e = dg->Get_In_Edge(v))
01703 dg->Remove_Edge(e);
01704 dg->Delete_Vertex(v);
01705 return TRUE;
01706 }
01707
01708
01709
01710
01711
01712
01713
01714
01715
01716 extern BOOL SNL_Fix_Array_Deps_On_Index_Variable(WN* wn_outer,
01717 INT nloops)
01718 {
01719 WN* wn_inner = SNL_Get_Inner_Snl_Loop(wn_outer, nloops);
01720 for (WN* wn = wn_inner; wn != NULL; wn = LWN_Get_Parent(wn)) {
01721 if (WN_opcode(wn) == OPC_DO_LOOP) {
01722 if (Need_Fix_Array_Deps_On_Index_Variable(wn)
01723 && Can_Fix_Array_Deps_On_Index_Variable(wn))
01724 if (!Fix_Array_Deps_On_Index_Variable(wn))
01725 return FALSE;
01726 }
01727 }
01728 return TRUE;
01729 }
01730
01731
01732
01733
01734
01735
01736
01737 extern WN* Next_SNL_Loop(WN* wn_outer)
01738 {
01739 WN *wn;
01740 for (wn = WN_first(WN_do_body(wn_outer)); wn != NULL; wn = WN_next(wn))
01741 if (WN_opcode(wn) == OPC_DO_LOOP)
01742 break;
01743 return wn;
01744 }
01745
01746
01747
01748
01749
01750
01751
01752 extern IMAT* Permutation_To_Unimodular(INT permutation[],
01753 INT nloops)
01754 {
01755 IMAT* unimodular = CXX_NEW(IMAT(nloops, nloops, &LNO_local_pool),
01756 &LNO_local_pool);
01757 for (INT i = 0; i < nloops; i++)
01758 for (INT j = 0; j < nloops; j++)
01759 (*unimodular)(i,j) = j == permutation[i] ? 1 : 0;
01760 return unimodular;
01761 }
01762
01763
01764
01765
01766
01767
01768
01769 extern INT* Unimodular_To_Permutation(IMAT* unimodular)
01770 {
01771 if (unimodular->Rows() != unimodular->Cols())
01772 return NULL;
01773 INT nloops = unimodular->Rows();
01774 INT* permutation = CXX_NEW_ARRAY(INT, nloops, &LNO_local_pool);
01775 INT i;
01776 for (i = 0; i < nloops; i++)
01777 permutation[i] = -1;
01778 for (i = 0; i < nloops; i++) {
01779 BOOL local_index = -1;
01780 for (INT j = 0; j < nloops; j++) {
01781 if ((*unimodular)(i,j) != 0) {
01782 if (local_index == -1 && (*unimodular)(i,j) == 1) {
01783 local_index = j;
01784 } else {
01785 CXX_DELETE_ARRAY(permutation, &LNO_local_pool);
01786 return NULL;
01787 }
01788 }
01789 }
01790 permutation[i] = local_index;
01791 }
01792 if (!Is_Permutation_Vector(permutation, nloops)) {
01793 CXX_DELETE_ARRAY(permutation, &LNO_local_pool);
01794 return NULL;
01795 }
01796 return permutation;
01797 }
01798
01799
01800
01801
01802
01803 SNL_TILE_INFO::SNL_TILE_INFO(INT nloops, INT strips,
01804 const INT* iloop, const INT* stripsz,
01805 const INT* striplevel,
01806 SNL_INV_CACHE_BLOCK_REASON reason[],
01807 MEM_POOL* pool)
01808 : _pool(pool), _l(nloops, strips, pool), _k(Lcm(stripsz, strips)),
01809 _kht(strips, nloops, pool), _rectangular(TRUE)
01810 {
01811 _l.D_Zero();
01812 _kht.D_Zero();
01813 for (INT j = 0; j < strips; j++) {
01814 INT i = iloop[j];
01815
01816 Is_True(i < nloops && i >= 0, ("strip specified loop outside of range"));
01817 Is_True(_k%stripsz[j] == 0, ("strip size is %d, _k=%d", stripsz[i], _k));
01818 _l(i,j) = stripsz[j];
01819 _kht(j,i) = _k/stripsz[j];
01820
01821 _stripsz[j] = stripsz[j];
01822 _striplevel[j] = striplevel[j];
01823 _iloop[j] = iloop[j];
01824 _reason[j] = reason[j];
01825 }
01826 }
01827
01828 void SNL_TILE_INFO::Print(FILE* f) const
01829 {
01830 Is_True(_rectangular, ("Don't know how to print non-rectangular tile"));
01831 if (_rectangular) {
01832 fprintf(f, "tile info (strips=%d)", _l.Cols());
01833 for (INT j = 0; j < _l.Cols(); j++)
01834 fprintf(f, "<%d,%d>", _iloop[j], _stripsz[j]);
01835 fprintf(f, "\n");
01836 fprintf(f, "_k = %d\n", _k);
01837 fprintf(f, "_l matrix: \n");
01838 _l.Print(f);
01839 fprintf(f, "_kht matrix: \n");
01840 _kht.Print(f);
01841 }
01842 }
01843
01844
01845
01846
01847
01848 static WN* generate_tree_add(WN* tree,
01849 SYMBOL symbol,
01850 INT coeff,
01851 TYPE_ID wtype,
01852 WN* alias_wn)
01853 {
01854
01855
01856 OPCODE op = OPCODE_make_op(OPR_LDID, symbol.Type, symbol.Type);
01857 TY_IDX ty = Be_Type_Tbl(symbol.Type);
01858 WN* ld;
01859
01860 if (alias_wn)
01861 ld = LWN_CreateLdid(op, alias_wn);
01862 else
01863
01864
01865 ld = WN_CreateLdid(op, symbol.WN_Offset(), symbol.St(), ty);
01866
01867 WN* wn = LWN_Int_Type_Conversion(ld, wtype);
01868
01869
01870
01871 if (coeff != 1) {
01872 OPCODE mul_op = OPCODE_make_op(OPR_MPY, wtype, MTYPE_V);
01873 wn = LWN_CreateExp2(mul_op, wn, LWN_Make_Icon(wtype, coeff));
01874 }
01875
01876
01877
01878 if (tree) {
01879 OPCODE add = OPCODE_make_op(OPR_ADD, wtype, MTYPE_V);
01880 wn = LWN_CreateExp2(add, tree, wn);
01881 }
01882
01883
01884
01885 DEF_LIST* def_list = alias_wn ? Du_Mgr->Ud_Get_Def(alias_wn) : NULL;
01886
01887 if (def_list) {
01888 DEF_LIST_CONST_ITER iter(def_list);
01889 for (const DU_NODE* n = iter.First(); !iter.Is_Empty(); n = iter.Next()) {
01890 WN* def = n->Wn();
01891 Du_Mgr->Add_Def_Use(def, ld);
01892 }
01893 DEF_LIST* def_list2 = Du_Mgr->Ud_Get_Def(ld);
01894 FmtAssert(def_list2, ("Impossible missing deflist"));
01895 def_list2->Set_loop_stmt(def_list->Loop_stmt());
01896 }
01897
01898 return wn;
01899 }
01900
01901 extern WN* generate_tree_from_row(const mINT32* m,
01902 SNL_TRANS_INDEX_DATA* td,
01903 INT64 c,
01904 TYPE_ID wtype,
01905 INT part)
01906 {
01907 INT i;
01908 INT e = 0;
01909
01910 WN* tree = c ? LWN_Make_Icon(wtype, c) : NULL;
01911
01912 if (part & UCTILE_T) {
01913 for (i = 0; i < td->t_nloops; i++, e++) {
01914 if (m[e])
01915 tree = generate_tree_add(tree, td->tdata[i].symbol, m[e], wtype,
01916 td->tdata[i].alias_wn);
01917 }
01918 }
01919 if (part & UCTILE_I) {
01920 for (i = 0; i < td->i_nloops; i++, e++) {
01921 if (m[e])
01922 tree = generate_tree_add(tree, td->idata[i].post_symbol, m[e], wtype,
01923 td->idata[i].post_alias_wn);
01924 }
01925 }
01926 if (part & UCTILE_O) {
01927 for (i = 0; i < td->o_nloops; i++, e++) {
01928 if (m[e])
01929 tree = generate_tree_add(tree, td->odata[i].symbol, m[e], wtype,
01930 td->odata[i].alias_wn);
01931 }
01932 }
01933
01934 return tree ? tree : LWN_Make_Icon(wtype, 0);
01935 }
01936
01937 extern WN* generate_tree_from_bounds_info_row(const mINT32* row,
01938 mINT64 con,
01939 BOOL le,
01940 const SNL_BOUNDS_SYMBOL_LIST*vi)
01941 {
01942 DU_MANAGER* du = Du_Mgr;
01943
01944 INT i;
01945 const SNL_BOUNDS_SYMBOL_NODE* n;
01946 WN* tree = NULL;
01947 TYPE_ID wtype = MTYPE_V;
01948 SNL_BOUNDS_SYMBOL_CONST_ITER avi1(vi);
01949
01950 for (i = 0, n = avi1.First(); !avi1.Is_Empty(); i++, n = avi1.Next())
01951 if (row[i])
01952 wtype = Max_Wtype(wtype, n->Symbol.Type);
01953
01954 SNL_BOUNDS_SYMBOL_CONST_ITER avi2(vi);
01955 for (i = 0, n = avi2.First(); !avi2.Is_Empty(); i++, n = avi2.Next()) {
01956 if (row[i])
01957 tree = generate_tree_add(tree, n->Symbol, row[i], wtype, n->Alias_Wn);
01958 }
01959
01960 FmtAssert(tree, ("Zero row in conditionals??"));
01961
01962 OPCODE op = OPCODE_make_op(le ? OPR_LE : OPR_EQ, Boolean_type, wtype);
01963 tree = LWN_CreateExp2(op, tree, LWN_Make_Icon(wtype, con));
01964 return tree;
01965 }
01966
01967
01968
01969
01970
01971 void SNL_TRANS_INDEX_DATA::Print(FILE* f) const
01972 {
01973 INT i;
01974
01975 fprintf(f, "SNL_TRANS_INDEX_DATA printout:\n");
01976
01977 for (i = 0; i < t_nloops; i++)
01978 fprintf(f, "tdata %d: %s\n", i, tdata[i].symbol.Name());
01979
01980 for (i = 0; i < o_nloops; i++)
01981 fprintf(f, "odata %d: %s\n", i, odata[i].symbol.Name());
01982
01983 for (i = 0; i < i_nloops; i++) {
01984 fprintf(f, "idata %d: %s (renamed to %s) -> ",
01985 i, idata[i].pre_symbol.Name(), idata[i].post_symbol.Name());
01986 fprintf(f, " newcode:");
01987 Dump_WN(idata[i].newcode, f, 1, 0, 2);
01988 fprintf(f, " lbtest:");
01989 Dump_WN(idata[i].lbtest, f, 1, 0, 2);
01990 fprintf(f, " ubtest:");
01991 Dump_WN(idata[i].ubtest, f, 1, 0, 2);
01992 }
01993 }
01994
01995 SNL_TRANS_INDEX_DATA::~SNL_TRANS_INDEX_DATA()
01996 {
01997 INT i;
01998 for (i = 0; i < i_nloops; i++) {
01999 if (idata[i].newcode) {
02000 LWN_Delete_Tree(idata[i].newcode);
02001 idata[i].newcode = NULL;
02002 }
02003 if (idata[i].lbtest) {
02004 LWN_Delete_Tree(idata[i].lbtest);
02005 idata[i].lbtest = NULL;
02006 }
02007 if (idata[i].ubtest) {
02008 LWN_Delete_Tree(idata[i].ubtest);
02009 idata[i].ubtest = NULL;
02010 }
02011 }
02012
02013 for (i = 0; i < i_nloops; i++)
02014 if (idata[i].post_alias_wn != NULL &&
02015 idata[i].pre_alias_wn != idata[i].post_alias_wn)
02016 WN_Delete(idata[i].post_alias_wn);
02017 for (i = 0; i < o_nloops; i++)
02018 WN_Delete(odata[i].alias_wn);
02019
02020 if (tdata)
02021 CXX_DELETE_ARRAY(tdata, pool);
02022 if (idata)
02023 CXX_DELETE_ARRAY(idata, pool);
02024 if (odata)
02025 CXX_DELETE_ARRAY(odata, pool);
02026 }
02027
02028 static INT ut_body_exp_pre(WN* wn, SNL_TRANS_INDEX_DATA* td)
02029 {
02030 if (WN_operator(wn) == OPR_LDID) {
02031 for (INT d = 0; d < td->i_nloops; d++) {
02032 if (td->idata[d].pre_symbol == SYMBOL(wn)) {
02033 FmtAssert(td->idata[d].newcode, ("Missing newcode"));
02034 (void) Replace_Wnexp_With_Exp_Copy(wn, td->idata[d].newcode,
02035 Du_Mgr);
02036 return td->idata[d].max_used_depth;
02037 }
02038 }
02039 return -1;
02040 }
02041 else {
02042 INT rv = -1;
02043
02044 for (INT kid = 0; kid < WN_kid_count(wn); kid++) {
02045 INT nrv = ut_body_exp_pre(WN_kid(wn,kid), td);
02046 if (rv < nrv)
02047 rv = nrv;
02048 }
02049 return rv;
02050 }
02051 }
02052
02053 SNL_TRANS_INDEX_DATA::SNL_TRANS_INDEX_DATA(const IMAT* u,
02054 const IMAT* uinv,
02055 const IMAT* kht,
02056 const SNL_BOUNDS_INFO*bi,
02057 DOLOOP_STACK* stack,
02058 INT first_in_stack,
02059 SNL_TILE_INFO* ti,
02060 MEM_POOL* p)
02061 {
02062 pool = p;
02063
02064 INT v;
02065
02066
02067 if (u) {
02068 Is_True(uinv, ("if u supplied, then so should uinv"));
02069 Is_True(u->Rows() == u->Cols() &&
02070 uinv->Rows() == uinv->Cols() &&
02071 u->Rows() == uinv->Rows(), ("bad u, uinv dimensionality"));
02072 Is_True(kht == NULL || kht->Cols() == u->Rows(),
02073 ("u(%d,%d) yet kht(%d,%d)",
02074 u->Rows(), u->Cols(), kht->Rows(), kht->Cols()));
02075 }
02076 else {
02077 Is_True(kht, ("transformation required!"));
02078 }
02079
02080
02081
02082 t_nloops = kht ? kht->Rows() : 0;
02083 i_nloops = kht ? kht->Cols() : u->Rows();
02084 o_nloops = bi->Bounds().Num_Vars() - i_nloops;
02085
02086 tdata = t_nloops ? CXX_NEW_ARRAY(TDATA, t_nloops, p) : NULL;
02087 idata = i_nloops ? CXX_NEW_ARRAY(IDATA, i_nloops, p) : NULL;
02088 odata = o_nloops ? CXX_NEW_ARRAY(ODATA, o_nloops, p) : NULL;
02089
02090 const SNL_BOUNDS_SYMBOL_LIST* sl = &bi->Var_Info();
02091 const SNL_BOUNDS_SYMBOL_NODE* sld = sl->Head();
02092
02093
02094
02095 for (v = 0; v < i_nloops; v++) {
02096 FmtAssert(sld, ("Missing sld"));
02097 idata[v].pre_symbol = sld->Symbol;
02098 idata[v].pre_alias_wn = sld->Alias_Wn;
02099 sld = sld->Next();
02100 }
02101
02102
02103
02104 for (v = 0; v < o_nloops; v++) {
02105 FmtAssert(sld, ("Missing sld"));
02106 odata[v].symbol = sld->Symbol;
02107
02108 OPCODE op = OPCODE_make_op(OPR_LDID, sld->Symbol.Type, sld->Symbol.Type);
02109 odata[v].alias_wn = LWN_CreateLdid(op, sld->Alias_Wn);
02110 DEF_LIST* deflist = Du_Mgr->Ud_Get_Def(sld->Alias_Wn);
02111 if (deflist) {
02112 DEF_LIST_ITER iter(deflist);
02113 for(const DU_NODE *n=iter.First(); !iter.Is_Empty(); n=iter.Next()) {
02114 WN *def = (WN *)n->Wn();
02115 Du_Mgr->Add_Def_Use(def, odata[v].alias_wn);
02116 }
02117 }
02118 sld = sld->Next();
02119 }
02120
02121
02122
02123 for (v = 0; v < i_nloops; v++) {
02124 idata[v].post_symbol = idata[v].pre_symbol;
02125 idata[v].post_alias_wn = idata[v].pre_alias_wn;
02126 idata[v].max_used_depth = -1;
02127 idata[v].newcode = NULL;
02128 idata[v].lbtest = NULL;
02129 idata[v].ubtest = NULL;
02130 }
02131
02132 if (u) {
02133 for (v = 0; v < i_nloops; v++) {
02134 TYPE_ID wtype = MTYPE_V;
02135 INT first_non_zero = -1;
02136
02137 for (INT j = 0; j < i_nloops; j++) {
02138 if ((*u)(v,j)) {
02139 wtype = Max_Wtype(wtype, idata[j].pre_symbol.Type);
02140 if (first_non_zero == -1)
02141 first_non_zero = j;
02142 }
02143 }
02144
02145 Is_True(first_non_zero > -1 || wtype != MTYPE_V,
02146 ("Bad type for new index variable"));
02147
02148 if (first_non_zero != v || wtype != idata[v].pre_symbol.Type) {
02149
02150
02151
02152 const INT symsz = 64;
02153 char buf[symsz+6];
02154
02155 strcpy(buf, "$fake_");
02156 idata[first_non_zero].pre_symbol.Name(buf+6, symsz);
02157 idata[v].post_symbol = Create_Preg_Symbol(buf, wtype);
02158 idata[v].post_alias_wn = NULL;
02159 }
02160 }
02161
02162
02163
02164
02165
02166
02167 INT v;
02168 for (v = 0; v < i_nloops; v++) {
02169 idata[v].newcode = generate_tree_from_row(&(*uinv)(v,0), this, 0,
02170 idata[v].post_symbol.Type,
02171 UCTILE_I);
02172 INT i;
02173 for (i = i_nloops-1; i >= 0; i--) {
02174 if ((*uinv)(v,i)) {
02175 idata[v].max_used_depth = i;
02176 break;
02177 }
02178 }
02179 Is_True(i >= 0, ("Impossible u^(-1)"));
02180 }
02181
02182
02183
02184 for (v = 0; v < i_nloops; v++) {
02185 WN* loop = stack->Bottom_nth(first_in_stack+v);
02186 Upper_Bound_Standardize(WN_end(loop));
02187 WN* lb = LWN_Copy_Tree(WN_kid0(WN_start(loop)), TRUE, LNO_Info_Map); WN* ub = LWN_Copy_Tree(SNL_UBexp(WN_end(loop)), TRUE, LNO_Info_Map);
02188 TYPE_ID wtype = Do_Wtype(loop);
02189 OPCODE opld = OPCODE_make_op(OPR_LDID, wtype, wtype);
02190 OPCODE opeq = OPCODE_make_op(OPR_EQ, Boolean_type, wtype);
02191
02192 WN* ld1 = LWN_CreateLdid(opld, WN_step(loop));
02193 WN* ld2 = LWN_CreateLdid(opld, WN_step(loop));
02194 SNL_Add_Du_To_Index_Ldid(loop, ld1, Du_Mgr, TRUE);
02195 SNL_Add_Du_To_Index_Ldid(loop, ld2, Du_Mgr, TRUE);
02196 idata[v].lbtest = LWN_CreateExp2(opeq, ld1, lb);
02197 idata[v].ubtest = LWN_CreateExp2(opeq, ld2, ub);
02198 ut_body_exp_pre(idata[v].lbtest, this);
02199 ut_body_exp_pre(idata[v].ubtest, this);
02200 }
02201 }
02202
02203
02204
02205 for (v = 0; v < t_nloops; v++) {
02206 TYPE_ID type = MTYPE_V;
02207 for (INT j = 0; j < i_nloops; j++)
02208 if ((*kht)(v,j))
02209 type = Max_Wtype(type, idata[j].post_symbol.Type);
02210 Is_True(type != MTYPE_V, ("Bad type for new tile index variable"));
02211
02212 char buffer[100];
02213 sprintf(buffer, "$tile.%d.%d", ti->Striplevel(v), ti->Iloop(v));
02214 tdata[v].symbol = Create_Preg_Symbol(buffer, type);
02215 tdata[v].alias_wn = NULL;
02216 }
02217 }
02218
02219
02220
02221
02222
02223
02224
02225
02226
02227 static void Fix_Do_Du_Info_X(WN* wn, SNL_TRANS_INDEX_DATA* td,
02228 BOOL recursive, WN* loops,
02229 INT only_in_nloops)
02230 {
02231 OPERATOR opr = WN_operator(wn);
02232
02233 if (opr == OPR_DO_LOOP && only_in_nloops-- > 0) {
02234 Du_Mgr->Remove_Def_From_System(WN_start(wn));
02235 Du_Mgr->Remove_Def_From_System(WN_step(wn));
02236 }
02237
02238 if (opr == OPR_LDID) {
02239 SYMBOL s(wn);
02240 WN* loop = NULL;
02241 if (loops) {
02242 for (loop = loops; loop; loop = LWN_Get_Parent(loop)) {
02243 if (WN_opcode(loop) == OPC_DO_LOOP && s == SYMBOL(WN_index(loop)))
02244 break;
02245 }
02246 }
02247 else {
02248 WN* child = NULL;
02249 for (loop = wn; loop; loop = LWN_Get_Parent(loop)) {
02250 if (WN_opcode(loop) == OPC_DO_LOOP && s == SYMBOL(WN_index(loop))) {
02251 if (child == WN_start(loop))
02252 loop = NULL;
02253 break;
02254 }
02255 child = loop;
02256 }
02257 }
02258 if (loop) {
02259
02260 Du_Mgr->Remove_Use_From_System(wn);
02261 WN* def1 = WN_start(loop);
02262 WN* def2 = WN_step(loop);
02263 Du_Mgr->Add_Def_Use(def1, wn);
02264 Du_Mgr->Add_Def_Use(def2, wn);
02265 DEF_LIST* dl = Du_Mgr->Ud_Get_Def(wn);
02266 FmtAssert(dl, ("Missing deflist"));
02267 if (loops == NULL)
02268 dl->Set_loop_stmt(loop);
02269 else {
02270 dl->Set_loop_stmt(NULL);
02271 while (loop) {
02272 WN *w;
02273 for (w = wn; w && w != loop; w = LWN_Get_Parent(w))
02274 ;
02275 if (w == loop) {
02276 dl->Set_loop_stmt(loop);
02277 break;
02278 }
02279 do {
02280 loop = LWN_Get_Parent(loop);
02281 } while(loop && WN_opcode(loop) != OPC_DO_LOOP);
02282 }
02283 }
02284
02285
02286
02287 if (Aliased(Alias_Mgr, def1, def2) != SAME_LOCATION) {
02288 const INT bufsz = 32;
02289 char buf[bufsz];
02290 FmtAssert(0, ("Bad defs for %s %s",
02291 SYMBOL(def1).Name(buf, bufsz), SYMBOL(def2).Name()));
02292 }
02293 Copy_alias_info(Alias_Mgr, def1, wn);
02294 }
02295 else if (td) {
02296 INT i;
02297 for (i = 0; i < td->o_nloops; i++) {
02298 if (s == td->odata[i].symbol)
02299 break;
02300 }
02301 if (i < td->o_nloops) {
02302 DEF_LIST* deflist = Du_Mgr->Ud_Get_Def(td->odata[i].alias_wn);
02303 DEF_LIST_ITER iter(deflist);
02304 for(const DU_NODE *n=iter.First(); !iter.Is_Empty(); n=iter.Next()) {
02305 WN *def = (WN *)n->Wn();
02306 Du_Mgr->Add_Def_Use(def, wn);
02307 }
02308 DEF_LIST* dl = Du_Mgr->Ud_Get_Def(wn);
02309 FmtAssert(dl, ("Missing deflist"));
02310 dl->Set_loop_stmt(loop);
02311 }
02312 }
02313 }
02314
02315 if (opr == OPR_BLOCK) {
02316 if (recursive) {
02317 for (WN* w = WN_first(wn); w; w = WN_next(w))
02318 Fix_Do_Du_Info_X(w, td, recursive, loops, only_in_nloops);
02319 }
02320 }
02321 else {
02322 for (INT k = WN_kid_count(wn) - 1; k >= 0; k--)
02323 Fix_Do_Du_Info_X(WN_kid(wn,k), td, recursive, loops, only_in_nloops);
02324 }
02325
02326 if (opr == OPR_DO_LOOP) {
02327 FmtAssert(Du_Mgr->Du_Get_Use(WN_start(wn)),
02328 ("Didn't find uses for WN_index=0x%p", WN_index(wn)));
02329 FmtAssert(Du_Mgr->Du_Get_Use(WN_step(wn)),
02330 ("Didn't find uses for WN_step=0x%p", WN_step(wn)));
02331 }
02332 }
02333
02334
02335
02336
02337
02338
02339
02340
02341
02342
02343
02344
02345
02346
02347
02348
02349
02350
02351
02352
02353
02354
02355
02356
02357
02358
02359
02360 extern void Fix_Do_Du_Info(WN* wn, SNL_TRANS_INDEX_DATA* td,
02361 BOOL recursive, WN* loops,
02362 INT only_in_nloops)
02363 {
02364 Fix_Do_Du_Info_X(wn, td, recursive, loops, only_in_nloops);
02365 }
02366
02367
02368
02369
02370
02371
02372
02373 extern void SNL_Rebuild_Access_Arrays(WN* wn_outerloop)
02374 {
02375 ARRAY_DIRECTED_GRAPH16* dg = Array_Dependence_Graph;
02376 DOLOOP_STACK shortstack(&LNO_local_pool);
02377 Build_Doloop_Stack(LWN_Get_Parent(wn_outerloop), &shortstack);
02378 Renumber_Loops(wn_outerloop, wn_outerloop, dg);
02379 LNO_Build_Access(wn_outerloop, &shortstack, &LNO_default_pool);
02380 }
02381