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 #ifdef USE_PCH
00041 #include "lno_pch.h"
00042 #endif // USE_PCH
00043 #pragma hdrstop
00044
00045 #define lnoutils_CXX "lnoutils.cxx"
00046
00047 #include <alloca.h>
00048 #include <sys/types.h>
00049 #include <ctype.h>
00050 #include <limits.h>
00051
00052 #include "pu_info.h"
00053 #include "lnoutils.h"
00054 #include "config.h"
00055 #include "config_cache.h"
00056 #include "config_lno.h"
00057 #include "lnopt_main.h"
00058 #include "stab.h"
00059 #include "targ_const.h"
00060 #include "wn_simp.h"
00061 #include "stdlib.h"
00062 #include "lwn_util.h"
00063 #include "strtab.h"
00064 #include "targ_sim.h"
00065 #include "optimizer.h"
00066 #include "opt_du.h"
00067 #include "name.h"
00068 #include "wintrinsic.h"
00069 #include "lno_bv.h"
00070 #include "region_util.h"
00071 #include "fb_whirl.h"
00072 #include "lego_gen.h"
00073 #include "snl_utils.h"
00074 #include "dep_graph.h"
00075 #include "wn_pragmas.h"
00076 #include "ff_utils.h"
00077 #include "move.h"
00078 #include "w2op.h"
00079 #include "prompf.h"
00080 #include "anl_driver.h"
00081 #include "ipa_lno_util.h"
00082 #include "debug.h"
00083 #include "wutil.h"
00084 #ifdef KEY
00085 #include "be_symtab.h"
00086 #endif
00087 #include "intrn_info.h"
00088
00089 #pragma weak New_Construct_Id
00090
00091 extern void LWN_Parentize_One_Level(const WN* wn);
00092
00093 extern WN* LWN_Make_Icon(TYPE_ID wtype, INT64 i)
00094 {
00095 OPCODE intconst_opc = OPCODE_make_op(OPR_INTCONST, wtype, MTYPE_V);
00096 return WN_CreateIntconst(intconst_opc, i);
00097 }
00098
00099 extern TYPE_ID Do_Wtype(WN* wn)
00100 {
00101 Is_True(WN_opcode(wn) == OPC_DO_LOOP, ("Do_Wtype: requires do parameter"));
00102 Is_True(WN_start(wn) && WN_operator(WN_start(wn)) == OPR_STID,
00103 ("Do_Wtype: bad do start, op=%d", WN_opcode(WN_start(wn))));
00104 return WN_desc(WN_start(wn));
00105 }
00106
00107
00108
00109
00110
00111
00112
00113
00114 extern INT64 Step_Size(WN* loop,
00115 INT64 newstep)
00116 {
00117 WN* step;
00118
00119 if (WN_opcode(loop) == OPC_DO_LOOP) {
00120 step = WN_step(loop);
00121 WN* index = WN_index(loop);
00122
00123 if (WN_st(step) != WN_st(index) || WN_offset(step) != WN_offset(index)) {
00124 DevWarn("Index %s/%d but assignment to %s/%d in step",
00125 ST_name(WN_st(step)), WN_offset(step),
00126 ST_name(WN_st(index)), WN_offset(index));
00127 FmtAssert(newstep == 0, ("Bug in Step_Size"));
00128 return 0;
00129 }
00130 }
00131 else {
00132 step = loop;
00133 }
00134
00135 if (WN_operator(step) != OPR_STID) {
00136 DevWarn("Step expression operator not STID: %s",
00137 OPERATOR_name(WN_operator(step)));
00138 FmtAssert(newstep == 0, ("Bug in Step_Size"));
00139 return 0;
00140 }
00141
00142 WN* kid = WN_kid0(step);
00143
00144 OPERATOR opr = WN_operator(kid);
00145 if (opr != OPR_ADD && opr != OPR_SUB) {
00146 FmtAssert(newstep == 0,
00147 ("Require ADD or SUB for step, but saw `%s'",
00148 OPERATOR_name(opr)));
00149 return 0;
00150 }
00151
00152 BOOL neg = (opr == OPR_SUB);
00153
00154 WN* ldkid = WN_kid0(kid);
00155 WN* constkid = WN_kid1(kid);
00156 INT constkidno = 1;
00157
00158 if (WN_operator(ldkid) != OPR_LDID) {
00159 if (!neg) {
00160 WN* tmp = ldkid;
00161 ldkid = constkid;
00162 constkid = tmp;
00163 constkidno = 0;
00164 }
00165 if (WN_operator(ldkid) != OPR_LDID) {
00166 FmtAssert(newstep == 0, ("Saw the add, but not of the right thing"));
00167 return 0;
00168 }
00169 }
00170
00171 if (WN_operator(constkid) != OPR_INTCONST) {
00172 if (newstep != 0) {
00173 LWN_Delete_Tree(constkid);
00174 WN_kid(kid,constkidno) = LWN_Make_Icon(Do_Wtype(loop),
00175 neg?-newstep:newstep);
00176 LWN_Set_Parent(WN_kid(kid,constkidno), kid);
00177 }
00178 return 0;
00179 }
00180 else {
00181 INT64 rval = WN_const_val(constkid);
00182 if (newstep != 0)
00183 WN_const_val(constkid) = neg ? -newstep : newstep;
00184 return neg ? -rval : rval;
00185 }
00186 }
00187
00188
00189
00190
00191
00192
00193
00194 extern INT64 Step_Size(WN* loop)
00195 {
00196 return Step_Size((WN*)loop, 0);
00197 }
00198
00199
00200
00201
00202
00203
00204
00205 static void Add_Barrier_Vertex(WN* wn_barrier)
00206 {
00207 WN *loop = Enclosing_Do_Loop(wn_barrier);
00208 if (loop && Do_Loop_Is_Good(loop)) {
00209 VINDEX16 v = Array_Dependence_Graph->Add_Vertex(wn_barrier);
00210 if (!v)
00211 LNO_Erase_Dg_From_Here_In(wn_barrier, Array_Dependence_Graph);
00212 }
00213 }
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228 extern void Create_Single_Region(WN* wn_single,
00229 WN* wn_end)
00230 {
00231
00232 WN* wn_block = WN_CreateBlock();
00233 WN* wn_parent = LWN_Get_Parent(wn_single);
00234 WN* wn_prag_before = WN_CreateBarrier(TRUE, 0);
00235 LWN_Insert_Block_Before(wn_parent, wn_single, wn_prag_before);
00236 Add_Barrier_Vertex(wn_prag_before);
00237 WN* wnn = NULL;
00238
00239 WN *wn;
00240 for (wn = wn_single; wn != wn_end; wn = wnn) {
00241 wnn = WN_next(wn);
00242 LWN_Extract_From_Block(wn);
00243 LWN_Insert_Block_Before(wn_block, NULL, wn);
00244 }
00245 WN* wn_prag_after = WN_CreateBarrier(FALSE, 0);
00246 LWN_Insert_Block_After(wn_parent, wn_prag_before, wn_prag_after);
00247 Add_Barrier_Vertex(wn_prag_after);
00248
00249
00250 RID* p_rid = Get_Enclosing_Region_ID(wn_prag_before);
00251 FmtAssert(p_rid, ("Can't find parent RID"));
00252 WN* wn_region = WN_CreateRegion(REGION_KIND_MP, wn_block,
00253 NULL, NULL, RID_CREATE_NEW_ID,
00254 (INITO_IDX) NULL);
00255 REGION_INFO* rgi = CXX_NEW(REGION_INFO(TRUE),
00256 &LNO_default_pool);
00257 WN_MAP_Set(LNO_Info_Map, wn_region, (void *) rgi);
00258 LWN_Parentize(wn_region);
00259 LWN_Insert_Block_After(wn_parent, wn_prag_before,
00260 wn_region);
00261 WN* wn_prag_sp = WN_CreatePragma(WN_PRAGMA_SINGLE_PROCESS_BEGIN,
00262 (ST_IDX) NULL, 0, 0);
00263 WN_set_pragma_compiler_generated(wn_prag_sp);
00264 LWN_Insert_Block_After(WN_region_pragmas(wn_region), NULL,
00265 wn_prag_sp);
00266 RID *rid = RID_Create(WN_region_id(wn_region),
00267 RID_depth(p_rid)+1, wn_region);
00268 RID_level(rid) = RL_LNO;
00269 RID_TYPE_mp_Set(rid);
00270 WN_MAP_Set(RID_map, wn_region, (void *)rid);
00271 RID_Add_kid(rid, p_rid);
00272
00273
00274 WN* wn_first = NULL;
00275 for (wn = wn_region; wn != NULL; wn = LWN_Get_Parent(wn)) {
00276 if (WN_opcode(wn) == OPC_REGION) {
00277 wn_first = WN_first(WN_region_pragmas(wn));
00278 if (wn_first != NULL && WN_opcode(wn_first) == OPC_PRAGMA
00279 && WN_pragma(wn_first) == WN_PRAGMA_PARALLEL_BEGIN)
00280 break;
00281 }
00282 }
00283 BOOL set_omp = TRUE;
00284 if (wn != NULL && !WN_pragma_omp(wn_first))
00285 set_omp = FALSE;
00286 if (set_omp)
00287 WN_set_pragma_omp(wn_prag_sp);
00288
00289
00290 wn_parent = LWN_Get_Parent(wn_single);
00291 wn_prag_before = WN_CreateBarrier(FALSE, 0);
00292 LWN_Insert_Block_After(wn_parent, NULL, wn_prag_before);
00293 wn_prag_after = WN_CreateBarrier(TRUE, 0);
00294 LWN_Insert_Block_Before(wn_parent, NULL, wn_prag_after);
00295 Add_Barrier_Vertex(wn_prag_before);
00296 Add_Barrier_Vertex(wn_prag_after);
00297
00298 if (Prompf_Info != NULL && Prompf_Info->Is_Enabled()) {
00299 INT new_id = New_Construct_Id();
00300 WN_MAP32_Set(Prompf_Id_Map, wn_prag_sp, new_id);
00301 WN_MAP32_Set(Prompf_Id_Map, wn_region, new_id);
00302 PROMPF_LINES* pl = CXX_NEW(PROMPF_LINES(&PROMPF_pool),
00303 &PROMPF_pool);
00304 for (WN* wn = WN_first(wn_block); wn != NULL; wn = WN_next(wn))
00305 pl->Add_Lines(wn);
00306 Prompf_Info->Single_Process(new_id, pl);
00307 }
00308 }
00309
00310
00311
00312
00313
00314 INT32 Dot_Product(const mINT32* v1, const mINT32* v2, INT cnt)
00315 {
00316 INT32 s = 0;
00317 for (INT i = 0; i < cnt; i++)
00318 s += *v1++ * *v2++;
00319 return s;
00320 }
00321
00322 INT64 Dot_Product(const mINT64* v1, const mINT64* v2, INT cnt)
00323 {
00324 INT64 s = 0;
00325 for (INT i = 0; i < cnt; i++)
00326 s += *v1++ * *v2++;
00327 return s;
00328 }
00329
00330 INT64 Dot_Product(const mINT32* v1, const mINT64* v2, INT cnt)
00331 {
00332 INT64 s = 0;
00333 for (INT i = 0; i < cnt; i++)
00334 s += *v1++ * *v2++;
00335 return s;
00336 }
00337
00338 INT64 Dot_Product(const mINT64* v1, const mINT32* v2, INT cnt)
00339 {
00340 INT64 s = 0;
00341 for (INT i = 0; i < cnt; i++)
00342 s += *v1++ * *v2++;
00343 return s;
00344 }
00345
00346
00347
00348
00349
00350 static void printws(FILE* f, INT ws)
00351 {
00352 char buf[80];
00353
00354 INT i;
00355 for (i = 0; i < MIN(ws,79); i++)
00356 buf[i] = ' ';
00357 buf[i] = 0;
00358 fprintf(f, "%s", buf);
00359 }
00360
00361 extern void wn_dumpexpr(WN* wn, INT fancy, FILE* f,
00362 ARRAY_DIRECTED_GRAPH16* dg,
00363 WN** list, WN* parent, BOOL recursive)
00364 {
00365 BOOL printed = FALSE;
00366
00367 if (wn == NULL) {
00368 Is_True(0, ("wn_dumpexpr dumping a null expression"));
00369 fprintf(f, "<null>");
00370 return;
00371 }
00372
00373 OPCODE opc = WN_opcode(wn);
00374 OPERATOR opr = OPCODE_operator(opc);
00375
00376 fprintf(f, "(");
00377
00378 if (list) {
00379 for (WN** listmem = list; *listmem; listmem++)
00380 if (*listmem == wn)
00381 fprintf(f, "**0x%p**", wn);
00382 }
00383
00384 if (fancy > 3 && parent != LWN_Get_Parent(wn)) {
00385 fprintf(f, "%%%%%%%% parent=%p, real parent=%p %%%%%%%%",
00386 LWN_Get_Parent(wn), parent);
00387 }
00388
00389 if (fancy) {
00390 printed = TRUE;
00391 switch(opr) {
00392 case OPR_CONST:
00393 switch (OPCODE_rtype(opc)) {
00394 case MTYPE_F4:
00395 fprintf(f, "%g", STC_val(WN_st(wn)).vals.fval);
00396 break;
00397 case MTYPE_F8:
00398 fprintf(f, "%g", STC_val(WN_st(wn)).vals.dval);
00399 break;
00400 default:
00401 printed = FALSE;
00402 break;
00403 }
00404 break;
00405 case OPR_INTCONST:
00406 fprintf(f, "%lld", WN_const_val(wn));
00407 break;
00408 case OPR_LDID:
00409 fprintf(f, "%s", SYMBOL(wn).Name());
00410 if (fancy >= 2) {
00411 DEF_LIST* deflist = Du_Mgr->Ud_Get_Def(wn);
00412 if (deflist == NULL)
00413 fprintf(f, " <<missing DU defs>>");
00414 else if (deflist->Incomplete())
00415 fprintf(f, " <<incomplete DU defs>>");
00416 else if (fancy >= 3) {
00417 WN* stmt = deflist->Loop_stmt();
00418 if (stmt == NULL)
00419 fprintf(f, "<<loop_stmt=NULL>>");
00420 else
00421 if (WN_opcode(stmt)==OPC_DO_LOOP) {
00422 fprintf(f, "<<loop_stmt=%s(0x%p)>>",
00423 SYMBOL(WN_index(stmt)).Name(), stmt);
00424 } else {
00425 fprintf(f, "<<loop_stmt=%%%%(0x%p)>>", stmt);
00426 }
00427 }
00428 }
00429 break;
00430 case OPR_ADD:
00431 fprintf(f, "+");
00432 break;
00433 case OPR_SUB:
00434 fprintf(f, "-");
00435 break;
00436 case OPR_MPY:
00437 fprintf(f, "*");
00438 break;
00439 case OPR_DIV:
00440 fprintf(f, "/");
00441 break;
00442 default:
00443 printed = FALSE;
00444 break;
00445 }
00446 }
00447
00448 VINDEX16 v = dg ? dg->Get_Vertex(wn) : 0;
00449 if (v)
00450 fprintf(f, "[v%d]", v);
00451
00452 if (!printed) {
00453 FmtAssert(strncmp(OPCODE_name(opc), "OPC_", 4) == 0,
00454 ("opname=%s", OPCODE_name(opc)));
00455
00456 fprintf(f, "%s", OPCODE_name(opc) + 4);
00457 if (OPCODE_has_sym(opc))
00458 fprintf(f, " %s", SYMBOL(wn).Name());
00459 if (fancy >= 2 && OPERATOR(opc) == OPR_STID) {
00460 if (Du_Mgr->Du_Get_Use(wn) == NULL &&
00461 !((ST_class(WN_st(wn))==CLASS_PREG) &&
00462 Preg_Is_Dedicated(WN_offset(wn))))
00463 fprintf(f, " <<missing DU uses>>");
00464 else if (Du_Mgr->Du_Get_Use(wn)->Incomplete() )
00465 fprintf(f, " <<incomplete DU uses>>");
00466 }
00467 if (OPCODE_has_label(opc))
00468 fprintf(f, " LAB%d", WN_offset(wn));
00469 if (opr == OPR_INTRINSIC_OP || opr == OPR_INTRINSIC_CALL) {
00470 INTRINSIC i = (INTRINSIC) WN_intrinsic(wn);
00471 if (i >= INTRINSIC_FIRST && i <= INTRINSIC_LAST)
00472 fprintf(f, "<%s>", INTRINSIC_name(i));
00473 else
00474 fprintf(f, "<bad intr #=%d>", i);
00475 }
00476 else if (opr == OPR_IO)
00477 fprintf(f, "<io=%d>", WN_io_statement(wn));
00478 else if (opr == OPR_IO_ITEM)
00479 fprintf(f, "<io item=%d>", WN_io_item(wn));
00480 }
00481
00482 if (fancy >= 3)
00483 fprintf(f, " [0x%p]", wn);
00484
00485 if (recursive) {
00486 for (INT k = 0; k < WN_kid_count(wn); k++) {
00487 fprintf(f, " ");
00488 wn_dumpexpr(WN_kid(wn, k), fancy, f, dg, list, wn, recursive);
00489 }
00490 }
00491
00492 fprintf(f, ")");
00493
00494 fflush(f);
00495 }
00496
00497 void Dump_WN(WN* wn, FILE* f, INT fancy, INT ws, INT ws_inc,
00498 ARRAY_DIRECTED_GRAPH16* dg, WN** list, WN* parent,
00499 BOOL recursive)
00500 {
00501 if (list) {
00502 for (WN** listmem = list; *listmem; listmem++)
00503 if (*listmem == wn) {
00504 fprintf(f, "**0x%p**", wn);
00505 fflush(f);
00506 }
00507 }
00508
00509 if (parent && parent != LWN_Get_Parent(wn)) {
00510 fprintf(f, "%%%%%% parent=%p, real parent=%p %%%%%%",
00511 LWN_Get_Parent(wn), parent);
00512 fflush(f);
00513 }
00514
00515 INT32 line = 0;
00516 if (OPCODE_has_next_prev(WN_opcode(wn))) {
00517 line = WN_Get_Linenum(wn);
00518 if (line == 0)
00519 DevWarn("Missing line number for wn=0x%p (opr=%s)",
00520 wn, OPERATOR_name(WN_operator(wn)));
00521 }
00522
00523 switch (WN_opcode(wn)) {
00524 case OPC_BLOCK:
00525 {
00526 for (WN* w = WN_first(wn); w; w = WN_next(w))
00527 Dump_WN(w, f, fancy, ws, ws_inc, dg, list, wn, recursive);
00528 }
00529 break;
00530
00531 case OPC_DO_LOOP:
00532 printws(f, ws);
00533 fprintf(f, "FOR");
00534 if (fancy >= 2)
00535 fprintf(f, " [0x%p]", wn);
00536 fprintf(f, " indx=");
00537 fflush(f);
00538 wn_dumpexpr(WN_index(wn), fancy, f, dg, list, wn, recursive);
00539 fprintf(f, " (Line=%d)\n", line);
00540 if (fancy >= 3) {
00541 DO_LOOP_INFO* dli = Get_Do_Loop_Info(wn, TRUE);
00542 if (dli)
00543 dli->Print(f, ws+4);
00544 printws(f, ws+4);
00545 fprintf(f, "lb=");
00546 fflush(f);
00547 wn_dumpexpr(WN_start(wn), fancy, f, dg, list, wn, recursive);
00548 fprintf(f, "\n");
00549 printws(f, ws+4);
00550 fprintf(f, "ub=");
00551 fflush(f);
00552 wn_dumpexpr(WN_end(wn), fancy, f, dg, list, wn, recursive);
00553 fprintf(f, "\n");
00554 printws(f, ws+4);
00555 fprintf(f, "step=");
00556 fflush(f);
00557 wn_dumpexpr(WN_step(wn), fancy, f, dg, list, wn, recursive);
00558 fprintf(f, "\n");
00559 fflush(f);
00560 }
00561 if (fancy >= 3)
00562 Dump_WN(WN_do_body(wn), f, fancy, ws+ws_inc, ws_inc, dg, list, wn,
00563 recursive);
00564 printws(f, ws);
00565 fprintf(f, "END FOR\n");
00566 break;
00567
00568 case OPC_IF:
00569 printws(f, ws);
00570 fprintf(f, "IF ");
00571 if (fancy >= 2)
00572 fprintf(f, "[0x%p] ", wn);
00573 fflush(f);
00574 wn_dumpexpr(WN_if_test(wn), fancy, f, dg, list, wn, recursive);
00575 fprintf(f, "THEN (Line=%d)\n", line);
00576 Dump_WN(WN_then(wn), f, fancy, ws+ws_inc, ws_inc, dg, list, wn, recursive);
00577 printws(f, ws);
00578 fprintf(f, "ELSE\n");
00579 fflush(f);
00580 Dump_WN(WN_else(wn), f, fancy, ws+ws_inc, ws_inc, dg, list, wn, recursive);
00581 printws(f, ws);
00582 fprintf(f, "END IF\n");
00583 break;
00584
00585 case OPC_WHILE_DO:
00586 printws(f, ws);
00587 fprintf(f, "WHILE ");
00588 if (fancy >= 2)
00589 fprintf(f, "[0x%p] ", wn);
00590 fflush(f);
00591 wn_dumpexpr(WN_while_test(wn), fancy, f, dg, list, wn, recursive);
00592 fprintf(f, "DO (Line=%d)\n", line);
00593 Dump_WN(WN_while_body(wn), f, fancy, ws+ws_inc, ws_inc, dg, list, wn,
00594 recursive);
00595 printws(f, ws);
00596 fprintf(f, "END WHILEDO\n");
00597 fflush(f);
00598 break;
00599
00600 case OPC_DO_WHILE:
00601 printws(f, ws);
00602 fprintf(f, "DO");
00603 if (fancy >= 2)
00604 fprintf(f, " [0x%p]", wn);
00605 fprintf(f, " (Line=%d)\n", line);
00606 fflush(f);
00607 Dump_WN(WN_while_body(wn), f, fancy, ws+ws_inc, ws_inc, dg, list, wn,
00608 recursive);
00609 fprintf(f, "WHILE\n");
00610 wn_dumpexpr(WN_while_test(wn), fancy, f, dg, list, wn, recursive);
00611 fprintf(f, "\n");
00612 printws(f, ws);
00613 fprintf(f, "END DOWHILE\n");
00614 fflush(f);
00615 break;
00616
00617 case OPC_COMPGOTO:
00618 printws(f, ws);
00619 fprintf(f, "COMPGOTO");
00620 if (fancy >= 2)
00621 fprintf(f, " [0x%p]", wn);
00622 fprintf(f, " switch=");
00623 wn_dumpexpr(WN_kid(wn,0), fancy, f, dg, list, wn, recursive);
00624 fprintf(f, " (Line=%d)\n", line);
00625 Dump_WN(WN_kid(wn,1), f, fancy, ws+ws_inc, ws_inc, dg, list, wn, recursive);
00626 if (WN_kid_count(wn) == 3) {
00627 printws(f, ws);
00628 fprintf(f, " default_label=");
00629 wn_dumpexpr(WN_kid(wn,2), fancy, f, dg, list, wn, recursive);
00630 fprintf(f, "\n");
00631 }
00632 break;
00633
00634 case OPC_FUNC_ENTRY:
00635 {
00636 printws(f, ws);
00637 fprintf(f, "FUNCTION ");
00638 if (fancy >= 2)
00639 fprintf(f, "[0x%p] ", wn);
00640 fflush(f);
00641 for (INT i = 0; i < WN_kid_count(wn) - 1; i++)
00642 wn_dumpexpr(WN_kid(wn,i), fancy, f, dg, list, wn, recursive);
00643 fprintf(f, "\n");
00644 printws(f, ws);
00645 Dump_WN(WN_kid(wn,WN_kid_count(wn)-1), f, fancy, ws+ws_inc, ws_inc,
00646 dg, list, wn, recursive);
00647 fprintf(f, "END FUNCTION\n");
00648 fflush(f);
00649 }
00650 break;
00651
00652 case OPC_REGION:
00653 printws(f, ws);
00654 if (line) {
00655 fprintf(f, "(Line=%d) ", line);
00656 }
00657 wn_dumpexpr(wn, fancy, f, dg, list, parent, recursive);
00658 fprintf(f, "\n");
00659 Dump_WN(WN_region_body(wn), f, fancy, ws+ws_inc, ws_inc,
00660 dg, list, wn, recursive);
00661 break;
00662
00663 default:
00664 printws(f, ws);
00665 if (line) {
00666 fprintf(f, "(Line=%d) ", line);
00667 }
00668 wn_dumpexpr(wn, fancy, f, dg, list, parent, recursive);
00669 fprintf(f, "\n");
00670 break;
00671 }
00672
00673 fflush(f);
00674 }
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690 TYPE_ID Max_Wtype(TYPE_ID a, TYPE_ID b)
00691 {
00692
00693 if (a == MTYPE_V)
00694 return b;
00695 if (b == MTYPE_V)
00696 return a;
00697
00698
00699 if (a == MTYPE_U1 || a == MTYPE_U2)
00700 a = MTYPE_U4;
00701 else if (a == MTYPE_I1 || a == MTYPE_I2)
00702 a = MTYPE_I4;
00703
00704 if (b == MTYPE_U1 || b == MTYPE_U2)
00705 b = MTYPE_U4;
00706 else if (b == MTYPE_I1 || b == MTYPE_I2)
00707 b = MTYPE_I4;
00708
00709
00710
00711 if (a == b)
00712 return a;
00713 if (a == MTYPE_U4)
00714 return b;
00715 if (b == MTYPE_U4)
00716 return a;
00717 return MTYPE_I8;
00718 }
00719
00720
00721
00722
00723 INT Do_Depth(WN* wn, WN** loops, INT mx)
00724 {
00725 if (wn == NULL)
00726 return -1;
00727
00728 INT depth = Do_Depth(LWN_Get_Parent(wn), loops, mx);
00729 if (WN_opcode(wn) == OPC_DO_LOOP) {
00730 if (loops) {
00731 FmtAssert(depth < mx, ("Do_Depth: too deep"));
00732 loops[depth] = wn;
00733 }
00734 depth++;
00735 }
00736
00737 return depth;
00738 }
00739
00740
00741
00742
00743
00744 INT Good_Do_Depth(WN* wn, WN** loops, INT mx)
00745 {
00746 if (wn == NULL)
00747 return -1;
00748
00749 INT depth = Good_Do_Depth(LWN_Get_Parent(wn), loops, mx);
00750 if (WN_opcode(wn) == OPC_DO_LOOP) {
00751 if (!Do_Loop_Is_Good(wn))
00752 depth = -1;
00753 else {
00754 if (loops) {
00755 FmtAssert(depth < mx, ("Do_Depth: too deep"));
00756 loops[depth] = wn;
00757 }
00758 depth++;
00759 }
00760 }
00761
00762 return depth;
00763 }
00764
00765 static void Build_Doloop_Stack_Rec(WN* wn, WN *parent,DOLOOP_STACK* stack)
00766 {
00767 if (parent) {
00768 Build_Doloop_Stack_Rec(parent,LWN_Get_Parent(parent),stack);
00769 if (WN_opcode(parent) == OPC_DO_LOOP &&
00770 WN_do_body(parent) == wn) {
00771 stack->Push(parent);
00772 }
00773 }
00774 }
00775
00776 void Build_Doloop_Stack(WN* wn, DOLOOP_STACK* stack)
00777 {
00778 if (wn) {
00779 WN *parent = LWN_Get_Parent(wn);
00780 Build_Doloop_Stack_Rec(wn,parent,stack);
00781 if (WN_opcode(wn) == OPC_DO_LOOP) {
00782 stack->Push(wn);
00783 }
00784 }
00785 }
00786
00787 void Replace_Symbol(WN* wn, SYMBOL symold, SYMBOL symnew,
00788 WN* alias_wn, WN* ancestor)
00789 {
00790 OPCODE op = WN_opcode(wn);
00791
00792 if (op == OPC_BLOCK) {
00793 for (WN* w = WN_first(wn); w; w = WN_next(w))
00794 Replace_Symbol(w, symold, symnew, alias_wn, ancestor);
00795 }
00796 else {
00797 if (OPCODE_has_sym(op) && symold == SYMBOL(wn)) {
00798 OPERATOR opr = OPCODE_operator(op);
00799 WN_st_idx(wn) = ST_st_idx(symnew.St());
00800 WN_offset(wn) = symnew.WN_Offset();
00801 if (opr == OPR_LDID || opr == OPR_STID) {
00802 if (alias_wn == NULL) {
00803 Is_True(ST_class(symnew.St()) == CLASS_PREG,
00804 ("symnew must be a preg if NULL alias_wn"));
00805 Create_alias(Alias_Mgr, wn);
00806 }
00807 else {
00808 if (symnew.St() != SYMBOL(alias_wn).St()) {
00809
00810 const INT bufsz = 64;
00811 char buf[bufsz];
00812 DevWarn("Replace Symbol: syspect symbols %s and %s",
00813 symnew.Name(), SYMBOL(alias_wn).Name(buf, bufsz));
00814 }
00815 FmtAssert(alias_wn != wn || symold == symnew, ("Ridiculous"));
00816 Copy_alias_info(Alias_Mgr, alias_wn, wn);
00817 }
00818 if (ancestor) {
00819 if (opr == OPR_LDID) {
00820 DEF_LIST *def_list = Du_Mgr->Ud_Get_Def(wn);
00821 DEF_LIST_ITER iter(def_list);
00822 const DU_NODE* nnext = NULL;
00823 const DU_NODE* node = NULL;
00824 for (node = iter.First(); !iter.Is_Empty(); node = nnext) {
00825 nnext = iter.Next();
00826 WN *def = node->Wn();
00827 WN *p;
00828 for (p = def; p; p = LWN_Get_Parent(p)) {
00829 if (p == ancestor)
00830 break;
00831 }
00832 if (p == NULL) {
00833 Du_Mgr->Delete_Def_Use(def,wn);
00834 }
00835 }
00836 }
00837 else {
00838 USE_LIST *use_list = Du_Mgr->Du_Get_Use(wn);
00839 USE_LIST_ITER iter(use_list);
00840 const DU_NODE* nnext = NULL;
00841 const DU_NODE* node = NULL;
00842 for (node = iter.First(); !iter.Is_Empty(); node = nnext) {
00843 nnext = iter.Next();
00844 WN *use = node->Wn();
00845 WN *p;
00846 for (p = use; p; p = LWN_Get_Parent(p)) {
00847 if (p == ancestor)
00848 break;
00849 }
00850 if (p == NULL) {
00851 Du_Mgr->Delete_Def_Use(wn, use);
00852 }
00853 }
00854 }
00855 }
00856 }
00857 }
00858 for (INT k = 0; k < WN_kid_count(wn); k++)
00859 Replace_Symbol(WN_kid(wn,k), symold, symnew, alias_wn, ancestor);
00860 }
00861 }
00862
00863 void Replace_Symbols(WN* wn, SYMBOL* sold, SYMBOL* snew, INT count,
00864 WN** alias_wn, WN** ancestors)
00865 {
00866 #if 0 // same thing, but much less efficient. Good for testing though.
00867 for (INT i = 0; i < count; i++) {
00868 WN* al = alias_wn ? alias_wn[i] : NULL;
00869 WN* an = ancestors ? ancestors[i] : NULL;
00870 Replace_Symbol(wn, sold[i], snew[i], al, an);
00871 }
00872 #else
00873 OPCODE op = WN_opcode(wn);
00874
00875 if (op == OPC_BLOCK) {
00876 for (WN* w = WN_first(wn); w; w = WN_next(w))
00877 Replace_Symbols(w, sold, snew, count, alias_wn, ancestors);
00878 }
00879 else {
00880 if (OPCODE_has_sym(op)) {
00881 for (INT i = 0; i < count; i++) {
00882 if (sold[i] == SYMBOL(wn)) {
00883 OPERATOR opr = OPCODE_operator(op);
00884 WN_st_idx(wn) = ST_st_idx(snew[i].St());
00885 WN_offset(wn) = snew[i].WN_Offset();
00886 if (opr == OPR_LDID || opr == OPR_STID) {
00887 if (alias_wn == NULL || alias_wn[i] == NULL) {
00888 Is_True(ST_class(snew[i].St()) == CLASS_PREG,
00889 ("snew must be a preg if no alias info passed in"));
00890 Create_alias(Alias_Mgr, wn);
00891 }
00892 else {
00893 if (snew[i].St() != SYMBOL(alias_wn[i]).St()) {
00894
00895 const INT bufsz = 64;
00896 char buf[bufsz];
00897 DevWarn("Replace Symbol: syspect symbols %s and %s",
00898 snew[i].Name(), SYMBOL(alias_wn[i]).Name(buf, bufsz));
00899 }
00900 FmtAssert(alias_wn[i] != wn || snew[i] == sold[i], ("Ridiculous"));
00901 Copy_alias_info(Alias_Mgr, alias_wn[i], wn);
00902 }
00903 if (ancestors && ancestors[i]) {
00904 if (opr == OPR_LDID) {
00905 DEF_LIST *def_list = Du_Mgr->Ud_Get_Def(wn);
00906 DEF_LIST_ITER iter(def_list);
00907 const DU_NODE* nnext = NULL;
00908 const DU_NODE* node = NULL;
00909 for (node = iter.First(); !iter.Is_Empty(); node = nnext) {
00910 nnext = iter.Next();
00911 WN *def = node->Wn();
00912 WN *p;
00913 for (p = def; p; p = LWN_Get_Parent(p)) {
00914 if (p == ancestors[i])
00915 break;
00916 }
00917 if (p == NULL) {
00918 Du_Mgr->Delete_Def_Use(def,wn);
00919 }
00920 }
00921 }
00922 else {
00923 USE_LIST *use_list = Du_Mgr->Du_Get_Use(wn);
00924 USE_LIST_ITER iter(use_list);
00925 const DU_NODE* nnext = NULL;
00926 const DU_NODE* node = NULL;
00927 for (node = iter.First(); !iter.Is_Empty(); node = nnext) {
00928 nnext = iter.Next();
00929 WN *use = node->Wn();
00930 WN *p;
00931 for (p = use; p; p = LWN_Get_Parent(p)) {
00932 if (p == ancestors[i])
00933 break;
00934 }
00935 if (p == NULL) {
00936 Du_Mgr->Delete_Def_Use(wn, use);
00937 }
00938 }
00939 }
00940 }
00941 }
00942 break;
00943 }
00944 }
00945 }
00946 for (INT k = 0; k < WN_kid_count(wn); k++)
00947 Replace_Symbols(WN_kid(wn,k), sold, snew, count, alias_wn, ancestors);
00948 }
00949 #endif
00950 }
00951
00952
00953
00954 BOOL Add_To_Symbol(WN* wn, INT64 i, SYMBOL sym, BOOL stok)
00955 {
00956 INT k;
00957 BOOL rval = FALSE;
00958
00959 OPERATOR opr = WN_operator(wn);
00960
00961 if (opr == OPR_BLOCK) {
00962 for (WN* w = WN_first(wn); w; w = WN_next(w)) {
00963 if (Add_To_Symbol(w, i, sym, stok)) {
00964 WN* w2 = WN_Simplify_Tree(w);
00965 Is_True(w == w2, ("WN_Simplify_Tree() on stmt not returning itself?"));
00966 LWN_Parentize(w);
00967
00968
00969 }
00970 }
00971 }
00972 else {
00973
00974 for (k = 0; k < WN_kid_count(wn); k++) {
00975 WN* kid = WN_kid(wn,k);
00976 if (Add_To_Symbol(kid, i, sym, stok)) {
00977 if (OPCODE_is_stmt(WN_opcode(wn))) {
00978 kid = WN_Simplify_Tree(WN_kid(wn,k));
00979 WN_kid(wn,k) = kid;
00980 LWN_Set_Parent(kid, wn);
00981 LWN_Parentize(kid);
00982 }
00983 else
00984 rval = TRUE;
00985 }
00986 }
00987
00988 if (opr == OPR_LDID) {
00989 if (SYMBOL(wn) == sym) {
00990
00991 WN* parent = LWN_Get_Parent(wn);
00992 for (k = 0; k < WN_kid_count(parent); k++)
00993 if (WN_kid(parent,k) == wn)
00994 break;
00995 Is_True(k < WN_kid_count(parent), ("Missing kid!"));
00996
00997 WN* wcon = LWN_Make_Icon(WN_rtype(wn), i);
00998 OPCODE add_opc = OPCODE_make_op(OPR_ADD, WN_rtype(wn), MTYPE_V);
00999 WN* addnode = LWN_CreateExp2(add_opc, wn, wcon);
01000 LWN_Set_Parent(addnode, parent);
01001 WN_kid(parent,k) = addnode;
01002
01003 rval = TRUE;
01004 }
01005 }
01006 else if (opr == OPR_STID) {
01007 FmtAssert(stok || SYMBOL(wn) != sym,
01008 ("Writing to %s in Add_To_Symbol()", sym.Name()));
01009 }
01010 }
01011
01012 return rval;
01013 }
01014
01015
01016 BOOL Add_To_Symbol(WN* wn, INT64 i, ST* st,
01017 WN_OFFSET offset, TYPE_ID wtype, BOOL stok)
01018 {
01019 static INT printed_warning = FALSE;
01020 if (printed_warning == FALSE) {
01021 printed_warning = TRUE;
01022 printf("Using obsolete version of Add_To_Symbol() -- ok for now\n");
01023 }
01024
01025 SYMBOL sym(st, offset, wtype);
01026 return Add_To_Symbol(wn, i, sym, stok);
01027 }
01028
01029
01030 WN* Replace_Wnexp_With_Exp_Copy(WN* wn, WN* expr, DU_MANAGER* du,
01031 BOOL* added_cvt, ARRAY_DIRECTED_GRAPH16 *dep_graph)
01032 {
01033 #ifdef KEY
01034
01035
01036 BOOL make_unsigned = FALSE;
01037 if (WN_operator(wn) == OPR_LDID && WN_operator(expr) == OPR_ILOAD &&
01038 MTYPE_byte_size(WN_rtype(wn)) == MTYPE_byte_size(WN_rtype(expr)) &&
01039 MTYPE_byte_size(WN_desc(wn)) == MTYPE_byte_size(WN_desc(expr)) &&
01040 !MTYPE_is_signed(WN_rtype(wn)) && !MTYPE_is_signed(WN_desc(wn)) &&
01041 MTYPE_is_signed(WN_rtype(expr)) && MTYPE_is_signed(WN_desc(expr)))
01042 make_unsigned = TRUE;
01043 #endif
01044 Is_True(OPCODE_is_expression(WN_opcode(wn)), ("wn must be expression"));
01045 INT added_convert = FALSE;
01046 WN* parent = LWN_Get_Parent(wn);
01047 INT k = 0;
01048 if (parent != NULL) {
01049 for (k = 0; k < WN_kid_count(parent); k++) {
01050 if (WN_kid(parent,k) == wn)
01051 break;
01052 }
01053 Is_True(k < WN_kid_count(parent), ("broken parent pointer"));
01054 }
01055
01056 WN* copy = NULL;
01057 if (dep_graph != NULL)
01058 copy = LWN_Copy_Tree(expr, TRUE, LNO_Info_Map);
01059 else
01060 copy = LWN_Copy_Tree(expr);
01061 LWN_Copy_Frequency_Tree(expr,wn);
01062 if (du != NULL)
01063 LWN_Copy_Def_Use(expr, copy, du);
01064 if (dep_graph != NULL) {
01065 if (!dep_graph->Add_Deps_To_Copy_Block(expr,copy,FALSE)) {
01066 LNO_Erase_Dg_From_Here_In(expr,dep_graph);
01067 }
01068 }
01069 TYPE_ID mtype = WN_rtype(wn);
01070 TYPE_ID ctype = WN_rtype(copy);
01071 if (mtype != ctype && MTYPE_is_integral(mtype)) {
01072 WN* new_copy = LWN_Int_Type_Conversion(copy, mtype);
01073 if (copy != new_copy &&
01074 (WN_operator(new_copy) == OPR_CVT ||
01075 WN_operator(new_copy) == OPR_CVTL))
01076 added_convert = TRUE;
01077 copy = new_copy;
01078 }
01079
01080 LWN_Delete_Tree(wn);
01081 if (parent != NULL) {
01082 WN_kid(parent, k) = copy;
01083 LWN_Set_Parent(WN_kid(parent, k), parent);
01084 }
01085 if (added_cvt != NULL)
01086 *added_cvt = added_convert;
01087
01088 #ifdef KEY
01089
01090 if (make_unsigned) {
01091 WN_set_rtype(copy, MTYPE_complement(WN_rtype(copy)));
01092 WN_set_desc(copy, MTYPE_complement(WN_desc(copy)));
01093 }
01094 #endif
01095 return copy;
01096 }
01097
01098 WN* Replace_Scalar_Store_With_Array_Store(WN* scalar_store,
01099 WN* array_store,
01100 DU_MANAGER* du)
01101 {
01102 WN* wn_store = LWN_Copy_Tree(array_store);
01103 LWN_Copy_Frequency_Tree(array_store,scalar_store);
01104 if (du != NULL)
01105 LWN_Copy_Def_Use(WN_kid1(array_store), WN_kid1(wn_store), du);
01106 WN* wn_rhs_new = WN_kid0(wn_store);
01107 WN* wn_rhs_old = WN_kid0(scalar_store);
01108 WN_kid0(wn_store) = wn_rhs_old;
01109 WN_kid0(scalar_store) = wn_rhs_new;
01110 LWN_Set_Parent(wn_rhs_old, wn_store);
01111 LWN_Set_Parent(wn_rhs_new, scalar_store);
01112 LWN_Insert_Block_Before(LWN_Get_Parent(scalar_store), scalar_store, wn_store);
01113 LWN_Extract_From_Block(scalar_store);
01114 LWN_Delete_Tree(scalar_store);
01115 return wn_store;
01116 }
01117
01118
01119
01120 void Replace_Ldid_With_Exp_Copy(SYMBOL symbol, WN* wn, WN* expr,
01121 DU_MANAGER* du,ARRAY_DIRECTED_GRAPH16 *dep_graph)
01122 {
01123 switch (WN_operator(wn)) {
01124 case OPR_BLOCK:
01125 {
01126 for (WN* wn2 = WN_first(wn); wn2; wn2 = WN_next(wn2))
01127 Replace_Ldid_With_Exp_Copy(symbol, wn2, expr, du,dep_graph);
01128 }
01129 break;
01130 case OPR_IF:
01131 Replace_Ldid_With_Exp_Copy(symbol, WN_if_test(wn), expr, du,dep_graph);
01132 Replace_Ldid_With_Exp_Copy(symbol, WN_then(wn), expr, du,dep_graph);
01133 Replace_Ldid_With_Exp_Copy(symbol, WN_else(wn), expr, du,dep_graph);
01134 break;
01135 case OPR_DO_WHILE:
01136 case OPR_WHILE_DO:
01137 Replace_Ldid_With_Exp_Copy(symbol, WN_while_test(wn), expr, du,dep_graph);
01138 Replace_Ldid_With_Exp_Copy(symbol, WN_while_body(wn), expr, du,dep_graph);
01139 break;
01140 case OPR_DO_LOOP:
01141 Replace_Ldid_With_Exp_Copy(symbol, WN_start(wn), expr, du,dep_graph);
01142 Replace_Ldid_With_Exp_Copy(symbol, WN_end(wn), expr, du,dep_graph);
01143 Replace_Ldid_With_Exp_Copy(symbol, WN_step(wn), expr, du,dep_graph);
01144 Replace_Ldid_With_Exp_Copy(symbol, WN_do_body(wn), expr, du,dep_graph);
01145 break;
01146 case OPR_LDID:
01147 if (symbol == SYMBOL(wn))
01148 (void) Replace_Wnexp_With_Exp_Copy(wn, expr, du,NULL,dep_graph);
01149 break;
01150 default:
01151 for (INT k = 0; k < WN_kid_count(wn); k++)
01152 Replace_Ldid_With_Exp_Copy(symbol, WN_kid(wn,k), expr, du,dep_graph);
01153 break;
01154 }
01155 }
01156
01157
01158
01159
01160
01161 inline
01162 INT sz(TYPE_ID wtype)
01163 {
01164 switch (wtype) {
01165 default:
01166 FmtAssert(0, ("bad call to LWN_Integer_Cast: %d", wtype));
01167 case MTYPE_I8:
01168 case MTYPE_U8:
01169 return 64;
01170 case MTYPE_I4:
01171 case MTYPE_U4:
01172 return 32;
01173 }
01174 }
01175
01176 static INT bitcount(TYPE_ID wtype)
01177 {
01178 switch (wtype) {
01179 case MTYPE_I8:
01180 case MTYPE_U8:
01181 return 64;
01182 case MTYPE_I4:
01183 case MTYPE_U4:
01184 return 32;
01185 case MTYPE_U2:
01186 case MTYPE_I2:
01187 return 16;
01188 case MTYPE_U1:
01189 case MTYPE_I1:
01190 return 8;
01191 default:
01192 FmtAssert(0, ("bad call to bitcount: %d", wtype));
01193 return 0;
01194 }
01195 }
01196
01197 static WN* LWN_Short_Integer_Cast(WN* tree, TYPE_ID* to, TYPE_ID from)
01198 {
01199 WN* wn_new = NULL;
01200 WN* result = NULL;
01201 TYPE_ID restype = MTYPE_UNKNOWN;
01202 switch (from) {
01203 case MTYPE_I1:
01204 wn_new = WN_CreateCvtl(OPC_I4CVTL, 8, tree);
01205 restype = MTYPE_I4;
01206 break;
01207 case MTYPE_I2:
01208 wn_new = WN_CreateCvtl(OPC_I4CVTL, 16, tree);
01209 restype = MTYPE_I4;
01210 break;
01211 case MTYPE_U1:
01212 wn_new = WN_CreateCvtl(OPC_U4CVTL, 8, tree);
01213 restype = MTYPE_U4;
01214 break;
01215 case MTYPE_U2:
01216 wn_new = WN_CreateCvtl(OPC_U4CVTL, 16, tree);
01217 restype = MTYPE_U4;
01218 break;
01219 default:
01220 wn_new = tree;
01221 restype = MTYPE_UNKNOWN;
01222 }
01223 *to = restype;
01224 LWN_Parentize_One_Level(wn_new);
01225 return wn_new;
01226 }
01227
01228 extern WN* LWN_Integer_Cast(WN* tree, TYPE_ID to, TYPE_ID from)
01229 {
01230 INT szfrom = sz(from);
01231 INT szto = sz(to);
01232
01233 if (szfrom != szto)
01234 return LWN_CreateExp1(OPCODE_make_op(OPR_CVT, to, from), tree);
01235 else
01236 return tree;
01237 }
01238
01239 extern WN* LWN_Integer_Casts(WN* tree, TYPE_ID to, TYPE_ID from)
01240 {
01241 TYPE_ID local_to = MTYPE_UNKNOWN;
01242 if (bitcount(to) < bitcount(from)) {
01243 if (bitcount(to) < 32) {
01244 switch (from) {
01245 case MTYPE_I8:
01246 tree = LWN_Integer_Cast(tree, MTYPE_I4, MTYPE_I8);
01247 switch (to) {
01248 case MTYPE_I1:
01249 case MTYPE_U1:
01250 tree = WN_CreateCvtl(OPC_I4CVTL, 8, tree);
01251 break;
01252 case MTYPE_I2:
01253 case MTYPE_U2:
01254 tree = WN_CreateCvtl(OPC_I4CVTL, 16, tree);
01255 break;
01256 default:
01257 FmtAssert(FALSE, ("Bad TO type"));
01258 }
01259 break;
01260 case MTYPE_U8:
01261 tree = LWN_Integer_Cast(tree, MTYPE_U4, MTYPE_U8);
01262 switch (to) {
01263 case MTYPE_I1:
01264 case MTYPE_U1:
01265 tree = WN_CreateCvtl(OPC_U4CVTL, 8, tree);
01266 break;
01267 case MTYPE_I2:
01268 case MTYPE_U2:
01269 tree = WN_CreateCvtl(OPC_U4CVTL, 16, tree);
01270 break;
01271 default:
01272 FmtAssert(FALSE, ("Bad TO type"));
01273 }
01274 break;
01275 default:
01276 FmtAssert(FALSE, ("LWN_Integer_Cast: Bad FROM type"));
01277 }
01278 LWN_Parentize_One_Level(tree);
01279 return tree;
01280 } else {
01281 return LWN_Integer_Cast(tree, to, from);
01282 }
01283 }
01284 if (from != to) {
01285 switch (from) {
01286 case MTYPE_I1:
01287 case MTYPE_I2:
01288 case MTYPE_U1:
01289 case MTYPE_U2:
01290 tree = LWN_Short_Integer_Cast(tree, &local_to, from);
01291 }
01292 }
01293 TYPE_ID new_to = local_to == MTYPE_UNKNOWN ? to : local_to;
01294 tree = LWN_Integer_Cast(tree, new_to, from);
01295 return tree;
01296 }
01297
01298 SYMBOL Create_Preg_Symbol(const char* name, TYPE_ID type)
01299 {
01300 #ifdef _NEW_SYMTAB
01301 PREG_NUM reg = Create_Preg(type, (char*)name);
01302 #else
01303 PREG_NUM reg = Create_Preg(type, (char*)name, NULL);
01304 #endif
01305 return SYMBOL(MTYPE_To_PREG(type), reg, type);
01306 }
01307
01308 SYMBOL Create_Stack_Symbol(const char *name, TYPE_ID type)
01309 {
01310 ST* st = New_ST(CURRENT_SYMTAB);
01311 ST_Init (st,
01312 Save_Str((char*)name),
01313 CLASS_VAR,
01314 SCLASS_AUTO,
01315 EXPORT_LOCAL,
01316 Be_Type_Tbl(type));
01317 Set_ST_is_temp_var(st);
01318 return SYMBOL(st, 0, type);
01319 }
01320
01321
01322 ST* Lookup_Function_Name(const char* name)
01323 {
01324 ST* st;
01325 INT i;
01326
01327 FmtAssert(0,("Function untested with new symbol table"));
01328
01329 FOREACH_SYMBOL (GLOBAL_SYMTAB,st,i) {
01330 if (ST_class(st) == CLASS_FUNC && strcmp(ST_name(st), name)==0)
01331 return st;
01332 }
01333
01334 st = New_ST(GLOBAL_SYMTAB);
01335 #ifdef _NEW_SYMTAB
01336 TY_IDX ty_idx;
01337 TY& ty = New_TY (ty_idx);
01338 TY_Init (ty,
01339 0,
01340 KIND_FUNCTION,
01341 MTYPE_UNKNOWN,
01342 Save_Str("__intrinsic_lno"));
01343 Set_TY_align(ty_idx, 0);
01344 #else
01345 st = New_ST(TRUE);
01346 ST_name(st) = Save_Str((char*)name);
01347 ST_class(st) = CLASS_FUNC;
01348 TY *ty = New_TY(TRUE);
01349 TY_name(ty) = Save_Str("__intrinsic_lno");
01350 TY_kind(ty) = KIND_FUNCTION;
01351 Set_TY_align(ty, 0);
01352 Set_TY_size(ty, 0);
01353 #endif
01354
01355
01356 #ifdef _NEW_SYMTAB
01357
01358 TYLIST_IDX tylist_idx;
01359 TYLIST& tylist_head = New_TYLIST (tylist_idx);
01360 TY_IDX ret_type_idx;
01361 if (strcmp(ST_name(st), "__builtin_malloc")==0)
01362 {
01363 ret_type_idx = Make_Pointer_Type(Be_Type_Tbl(MTYPE_U1));
01364 } else if (strcmp(ST_name(st), "__builtin_free")==0) {
01365 ret_type_idx = Void_Type;
01366 } else {
01367 ret_type_idx = Be_Type_Tbl(MTYPE_I4);
01368 }
01369 Tylist_Table [tylist_idx] = ret_type_idx;
01370 TYLIST_IDX first_tylist_idx = tylist_idx;
01371 TYLIST& tylist_tail = New_TYLIST (tylist_idx);
01372 Tylist_Table [tylist_idx] = 0;
01373 Set_TY_tylist (ty, first_tylist_idx);
01374
01375 ST_Init (st,
01376 Save_Str(name),
01377 CLASS_FUNC,
01378 SCLASS_EXTERN,
01379 EXPORT_PREEMPTIBLE,
01380 ty_idx);
01381
01382 #else
01383 TY_ftinfo(ty) = New_FTI(0, TRUE);
01384 Enter_TY(ty);
01385 if (strcmp(ST_name(st), "__builtin_malloc")==0)
01386 {
01387
01388
01389
01390
01391 TY_ret_type(ty) = Make_Pointer_Type(Be_Type_Tbl(MTYPE_U1));
01392 } else if (strcmp(ST_name(st), "__builtin_free")==0) {
01393 TY_ret_type(ty) = Void_Type;
01394 } else {
01395
01396
01397
01398
01399 TY_ret_type(ty) = Be_Type_Tbl(MTYPE_I4);
01400 }
01401 ST_type(st) = ty;
01402 #endif
01403
01404 Set_ST_sclass(st, SCLASS_TEXT);
01405 Enter_ST(st);
01406 return st;
01407 }
01408
01409 static void reset_do(WN* body, INT depth)
01410 {
01411 Is_True(body && WN_opcode(body) == OPC_BLOCK, ("Bad call to reset_do"));
01412 for (WN* wn = WN_first(body); wn; wn = WN_next(wn)) {
01413 switch (WN_opcode(wn)) {
01414 case OPC_DO_LOOP:
01415 Reset_Do_Loop_Depths(wn, depth);
01416 break;
01417 case OPC_IF:
01418 reset_do(WN_then(wn), depth);
01419 reset_do(WN_else(wn), depth);
01420 break;
01421 case OPC_DO_WHILE:
01422 case OPC_WHILE_DO:
01423 reset_do(WN_while_body(wn), depth);
01424 reset_do(WN_while_test(wn), depth);
01425 break;
01426 }
01427 }
01428 }
01429
01430 void Reset_Do_Loop_Depths(WN* loop, INT depth)
01431 {
01432 Is_True(loop && WN_opcode(loop) == OPC_DO_LOOP,
01433 ("Bad loop passed to Reset_Do_Loop_Depths()"));
01434 DO_LOOP_INFO *dli = Get_Do_Loop_Info(loop);
01435 dli->Depth = depth;
01436 if (!dli->Is_Inner)
01437 reset_do(WN_do_body(loop), depth+1);
01438 }
01439
01440 ACCESS_VECTOR* Difference_Inequality(ACCESS_VECTOR* lb,
01441 ACCESS_VECTOR* ub,
01442 INT var,
01443 DIFFERENCE_KIND code,
01444 MEM_POOL* pool)
01445 {
01446 ACCESS_VECTOR* lb2 = lb;
01447 ACCESS_VECTOR* ub2 = ub;
01448
01449 INT lval = lb->Loop_Coeff(var);
01450 INT uval = ub->Loop_Coeff(var);
01451
01452 Is_True(lval < 0,
01453 ("Setup_Difference_Inequality(): lval=%d depth=%d", lval, var));
01454 Is_True(uval > 0,
01455 ("Setup_Difference_Inequality(): rval=%d depth=%d", uval, var));
01456
01457 INT lcm = Lcm(lval, uval);
01458 Is_True(lcm > 0, ("Setup_Difference_Inequality(): lcm=%d", lcm));
01459
01460 if (lcm != 1) {
01461 lb2 = Mul(lcm/-lval, CXX_NEW(ACCESS_VECTOR(lb, pool),pool), pool);
01462 ub2 = Mul(lcm/uval, CXX_NEW(ACCESS_VECTOR(ub, pool),pool), pool);
01463 }
01464
01465
01466 ACCESS_VECTOR* x = Add(lb2, ub2, pool);
01467
01468 if (lb2 != lb)
01469 CXX_DELETE(lb2, pool);
01470 if (ub2 != ub)
01471 CXX_DELETE(ub2, pool);
01472
01473 switch (code) {
01474 case DIFFERENCE_EXEC_NEVER_OR_ONCE:
01475 x->Negate_Me();
01476 x->Const_Offset += (lcm - 1);
01477 break;
01478 case DIFFERENCE_EXEC_NEVER:
01479 x->Negate_Me();
01480 x->Const_Offset--;
01481 break;
01482 case DIFFERENCE_EXEC_ALWAYS:
01483 break;
01484 }
01485
01486 return x;
01487 }
01488
01489
01490
01491
01492
01493
01494
01495 extern BOOL Statically_Safe_Node(WN* wn)
01496 {
01497 return WN_Can_Be_Speculative(wn, Alias_Mgr);
01498 }
01499
01500
01501
01502
01503
01504
01505
01506 extern BOOL Statically_Safe_Exp(WN *wn)
01507 {
01508 return WN_Expr_Can_Be_Speculative(wn, Alias_Mgr);
01509 }
01510
01511
01512 void Print_Def_Use(WN *wn, FILE *fp)
01513 {
01514 OPCODE opcode = WN_opcode(wn);
01515 if (opcode == OPC_BLOCK) {
01516 WN *kid = WN_first (wn);
01517 while (kid) {
01518 Print_Def_Use(kid,fp);
01519 kid = WN_next(kid);
01520 }
01521 } else {
01522 if (opcode != OPC_IO) {
01523 for (INT kidno=0; kidno<WN_kid_count(wn); kidno++) {
01524 WN *kid = WN_kid(wn,kidno);
01525 Print_Def_Use(kid,fp);
01526 }
01527 }
01528 OPERATOR opr=OPCODE_operator(opcode);
01529 switch (opr) {
01530 case OPR_LDID:
01531 case OPR_ILOAD:
01532 case OPR_ISTORE:
01533 case OPR_IO:
01534 case OPR_RETURN:
01535 #ifdef KEY
01536 case OPR_GOTO_OUTER_BLOCK:
01537 #endif
01538 case OPR_CALL:
01539 case OPR_ICALL:
01540 case OPR_INTRINSIC_CALL:
01541 fprintf(fp,"Visiting %s ", OPERATOR_name(opr));
01542 Dump_WN(wn, fp, 3, 0, 2, NULL, NULL, LWN_Get_Parent(wn));
01543 DEF_LIST *defs = Du_Mgr->Ud_Get_Def(wn);
01544 WN *loop_stmt = NULL;
01545 if (defs) {
01546 loop_stmt = defs->Loop_stmt();
01547 } else {
01548 if (opr == OPR_LDID) DevWarn("WARNING NO DEF LIST ");
01549 }
01550 if (loop_stmt) {
01551 if (WN_opcode(loop_stmt)==OPC_DO_LOOP) {
01552 fprintf(fp,"with loop_stmt for loop ");
01553 wn_dumpexpr(WN_index(loop_stmt), 3, fp, NULL, NULL, loop_stmt,
01554 TRUE);
01555 fprintf(fp,"\n");
01556 } else {
01557 DevWarn("WARNING loop_stmt is not a DO_LOOP (0x%p,ls=0x%p)",
01558 wn, loop_stmt);
01559 Dump_WN(loop_stmt,fp,3,4,2,NULL,NULL,LWN_Get_Parent(loop_stmt));
01560 }
01561 }
01562 if (defs && defs->Incomplete()) {
01563 fprintf(fp,"Its def list is incomplete \n");
01564 }
01565 fprintf(fp,"Its list of defs is \n");
01566 DEF_LIST_ITER iter(defs);
01567 if (iter.Is_Empty() && (opr == OPR_LDID)) {
01568 DevWarn("WARNING Empty DEF LIST ");
01569 }
01570 for(const DU_NODE *node=iter.First();!iter.Is_Empty();node=iter.Next()){
01571 WN *def = (WN *) node->Wn();
01572 if (WN_opcode(def) == OPC_FUNC_ENTRY) {
01573 fprintf(fp,"ENTRY \n");
01574 } else {
01575 Dump_WN(def, fp, 3, 4, 2, NULL, NULL, LWN_Get_Parent(def));
01576 }
01577 }
01578 fprintf(fp,"\n");
01579 }
01580 switch (opr) {
01581 case OPR_STID:
01582 case OPR_ISTORE:
01583 case OPR_IO:
01584 case OPR_FUNC_ENTRY:
01585 case OPR_CALL:
01586 case OPR_ICALL:
01587 case OPR_INTRINSIC_CALL:
01588 fprintf(fp,"Visiting %s ", OPERATOR_name(opr));
01589 if (opr != OPR_FUNC_ENTRY) {
01590 Dump_WN(wn, fp, 3, 0, 2, NULL, NULL, LWN_Get_Parent(wn));
01591 }
01592 fprintf(fp,"Its list of uses is \n");
01593 USE_LIST *uses = Du_Mgr->Du_Get_Use(wn);
01594 if (uses == NULL) {
01595 if (opr == OPR_STID) DevWarn("WARNING NO USES LIST ");
01596 }
01597 USE_LIST_ITER iter(uses);
01598 if (iter.Is_Empty() && (opr == OPR_STID)) {
01599 DevWarn("WARNING Empty USE LIST ");
01600 }
01601 if (uses && uses->Incomplete()) {
01602 fprintf(fp,"Its use list is incomplete \n");
01603 }
01604 for(const DU_NODE *node=iter.First();!iter.Is_Empty();node=iter.Next()){
01605 WN *use = (WN *) node->Wn();
01606 Dump_WN(use, fp, 3, 4, 2, NULL, NULL, LWN_Get_Parent(use));
01607 }
01608 fprintf(fp,"\n");
01609 }
01610 }
01611 }
01612
01613
01614
01615
01616
01617
01618
01619
01620
01621 static void Unrolled_DU_Update_V(WN **bodies, UINT u,
01622 HASH_TABLE<WN *,WN **> *hash_table,
01623 STACK<WN *> *load_stack, STACK<WN *> *store_stack)
01624 {
01625 if (bodies[0] == NULL)
01626 return;
01627
01628 OPCODE opc = WN_opcode(bodies[0]);
01629 OPERATOR opr = OPCODE_operator(opc);
01630
01631 if (OPCODE_is_load(opc) || OPCODE_is_store(opc) ||
01632 OPCODE_is_call(opc) || (opr == OPR_IO) || (opr == OPR_DO_LOOP)
01633 || (opr == OPR_PARM)) {
01634 DEF_LIST *def_list = Du_Mgr->Ud_Get_Def(bodies[0]);
01635 if (def_list) {
01636 DEF_LIST_ITER iter(def_list);
01637 if (!iter.Is_Empty()) {
01638 load_stack->Push(bodies[0]);
01639 } else {
01640 if (opr == OPR_LDID && !def_list->Incomplete()) {
01641 DevWarn("LDID %s without defs in Unrolled_DU_Update_V",
01642 SYMBOL(bodies[0]).Name());
01643 }
01644 }
01645 } else {
01646 if (opr == OPR_LDID) {
01647 DevWarn("LDID %s without def_list in Unrolled_DU_Update_V",
01648 SYMBOL(bodies[0]).Name());
01649 }
01650 }
01651 USE_LIST *use_list = Du_Mgr->Du_Get_Use(bodies[0]);
01652 if (use_list) {
01653 USE_LIST_ITER iter(use_list);
01654 if (!iter.Is_Empty()) {
01655 store_stack->Push(bodies[0]);
01656 } else {
01657 if (opr == OPR_STID)
01658 if (!use_list->Incomplete())
01659 DevWarn("STID without uses in Unrolled_DU_Update_V");
01660 #ifdef KEY // bug 8155
01661 else store_stack->Push(bodies[0]);
01662 #endif
01663 }
01664 } else {
01665 if(opr == OPR_STID) {
01666 DevWarn("STID without use_list in Unrolled_DU_Update_V");
01667 }
01668 }
01669
01670 WN **newwn = CXX_NEW_ARRAY(WN*,u,&LNO_local_pool);
01671 for (INT i=0; i<u; i++) {
01672 newwn[i] = bodies[i];
01673 }
01674 hash_table->Enter(bodies[0],newwn);
01675 }
01676
01677
01678
01679 if (opr == OPR_BLOCK) {
01680 WN **new_bodies = CXX_NEW_ARRAY(WN *,u,&LNO_local_pool);
01681 for (INT i=0; i<u; i++) {
01682 new_bodies[i] = WN_first(bodies[i]);
01683 }
01684 while (new_bodies[0]) {
01685 Unrolled_DU_Update_V(new_bodies, u,hash_table,load_stack,store_stack);
01686 for (INT i=0; i<u; i++) {
01687 new_bodies[i] = WN_next(new_bodies[i]);
01688 }
01689 }
01690 } else if (WN_kid_count(bodies[0]) && (opr != OPR_IO)) {
01691 WN **new_bodies = CXX_NEW_ARRAY(WN *,u,&LNO_local_pool);
01692 for (INT kidno=0; kidno<WN_kid_count(bodies[0]); kidno++) {
01693 for (INT i=0; i<u; i++) {
01694 new_bodies[i] = WN_kid(bodies[i],kidno);
01695 }
01696 Unrolled_DU_Update_V(new_bodies, u,hash_table,load_stack,store_stack);
01697 }
01698 }
01699 }
01700
01701
01702
01703
01704
01705
01706
01707
01708
01709
01710
01711
01712 static void Unrolled_DU_Update_E(UINT u, INT loopno,
01713 HASH_TABLE<WN *,WN **> *hash_table,
01714 STACK<WN *> *load_stack, STACK<WN *> *store_stack,
01715 BOOL update_pointers, SYMBOL *index_loopno)
01716 {
01717
01718
01719 #ifdef KEY // bug 8155
01720
01721
01722 #endif
01723 for (INT s=0; s<store_stack->Elements(); s++) {
01724 WN *stid = store_stack->Bottom_nth(s);
01725 USE_LIST *use_list = Du_Mgr->Du_Get_Use(stid);
01726
01727 WN **stid_array = hash_table->Find(stid);
01728
01729 if (use_list && use_list->Incomplete()) {
01730 for (INT i=1; i<u; i++) {
01731 Du_Mgr->Create_Use_List(stid_array[i]);
01732 USE_LIST *unrolled_use_list = Du_Mgr->Du_Get_Use(stid_array[i]);
01733 unrolled_use_list->Set_Incomplete();
01734 }
01735 }
01736
01737 USE_LIST_ITER iter(use_list);
01738 for(const DU_NODE *node=iter.First();!iter.Is_Empty();node=iter.Next()){
01739 WN *use = (WN *) node->Wn();
01740 WN **ldid_array = hash_table->Find(use);
01741
01742 if (!ldid_array) {
01743 for (INT i=1; i<u; i++) {
01744 Du_Mgr->Add_Def_Use(stid_array[i],use);
01745 }
01746 }
01747 }
01748 }
01749
01750
01751 for (INT l=0; l<load_stack->Elements(); l++) {
01752 WN *ldid = load_stack->Bottom_nth(l);
01753 DEF_LIST *def_list = Du_Mgr->Ud_Get_Def(ldid);
01754
01755
01756 BOOL copy_in_edges = FALSE;
01757 WN *loop_stmt = def_list->Loop_stmt();
01758 if (loop_stmt) {
01759 INT loop_stmt_number = Do_Loop_Depth(loop_stmt);
01760 if (loop_stmt_number <= loopno) {
01761 copy_in_edges = TRUE;
01762 }
01763 }
01764 if (WN_operator(ldid) == OPR_LDID) {
01765 if (index_loopno && ((*index_loopno) == SYMBOL(ldid))) {
01766 copy_in_edges = FALSE;
01767 }
01768 }
01769
01770 WN **ldid_array = hash_table->Find(ldid);
01771
01772 if (def_list->Incomplete()) {
01773 for (INT i=1; i<u; i++) {
01774 Du_Mgr->Create_Def_List(ldid_array[i]);
01775 DEF_LIST *unrolled_def_list = Du_Mgr->Ud_Get_Def(ldid_array[i]);
01776 unrolled_def_list->Set_Incomplete();
01777 }
01778 }
01779
01780 typedef STACK<WN *> WN_STACK;
01781 WN_STACK *ldid_zero_defs =
01782 CXX_NEW(WN_STACK(&LNO_local_pool),&LNO_local_pool);
01783
01784 DEF_LIST_ITER iter(def_list);
01785 const DU_NODE *node = iter.First();
01786 Is_True(!iter.Is_Empty(),("Empty def list in Unrolled_DU_Update_E"));
01787 for(; !iter.Is_Empty();node=iter.Next()){
01788 WN *def = (WN *) node->Wn();
01789 WN **stid_array = hash_table->Find(def);
01790
01791 if (!stid_array) {
01792 for (INT i=1; i<u; i++) {
01793 Du_Mgr->Add_Def_Use(def,ldid_array[i]);
01794 }
01795 } else {
01796
01797 for (INT i=1; i<u; i++) {
01798 Du_Mgr->Add_Def_Use(stid_array[i],ldid_array[i]);
01799 }
01800 if (copy_in_edges) {
01801 INT i;
01802 for (i=1; i<u; i++) {
01803 for (INT j=i+1; j<u; j++) {
01804 Du_Mgr->Add_Def_Use(stid_array[j],ldid_array[i]);
01805 Du_Mgr->Add_Def_Use(stid_array[i],ldid_array[j]);
01806 }
01807 }
01808 i = 0;
01809 for (INT j=i+1; j<u; j++) {
01810
01811
01812 ldid_zero_defs->Push(stid_array[j]);
01813
01814 Du_Mgr->Add_Def_Use(stid_array[i],ldid_array[j]);
01815 }
01816 }
01817 }
01818 }
01819
01820
01821 for (INT j=0; j<ldid_zero_defs->Elements(); j++) {
01822 Du_Mgr->Add_Def_Use(ldid_zero_defs->Bottom_nth(j),ldid_array[0]);
01823 }
01824
01825
01826 if (loop_stmt) {
01827 for (INT i=1; i<u; i++) {
01828 DEF_LIST *def_list_copy = Du_Mgr->Ud_Get_Def(ldid_array[i]);
01829 if (update_pointers) {
01830 WN** stmt_array = hash_table->Find(loop_stmt);
01831 #ifdef KEY
01832
01833
01834
01835
01836
01837
01838
01839
01840
01841 WN* stmt;
01842 if (stmt_array)
01843 stmt = stmt_array[i];
01844 else {
01845 if (!loop_stmt || WN_opcode(loop_stmt) != OPC_DO_LOOP)
01846 stmt = loop_stmt;
01847 else {
01848
01849
01850
01851 DO_LOOP_INFO* loop_info = Get_Do_Loop_Info(loop_stmt, FALSE);
01852 if (loop_info->Is_Inner) {
01853 if (Wn_Is_Inside (ldid_array[i], loop_stmt))
01854 stmt = loop_stmt;
01855 else
01856 stmt = NULL;
01857 } else
01858 stmt = loop_stmt;
01859 }
01860 }
01861 #else
01862 WN* stmt = stmt_array ? stmt_array[i] : loop_stmt;
01863 #endif
01864 def_list_copy->Set_loop_stmt(stmt);
01865 }
01866 else
01867 def_list_copy->Set_loop_stmt(loop_stmt);
01868 }
01869 }
01870 }
01871 }
01872
01873
01874
01875
01876
01877
01878
01879
01880
01881 void Unrolled_DU_Update(WN **bodies, UINT u, INT loopno, BOOL update_pointers,
01882 BOOL cross_index)
01883 {
01884 MEM_POOL_Push(&LNO_local_pool);
01885
01886
01887
01888 typedef HASH_TABLE<WN*, WN**> HTABLE_TYPE;
01889 HTABLE_TYPE *hash_table =
01890 CXX_NEW(HTABLE_TYPE(131,&LNO_local_pool), &LNO_local_pool);
01891
01892
01893 typedef STACK<WN *> WN_STACK;
01894 WN_STACK *load_stack = CXX_NEW(WN_STACK(&LNO_local_pool),&LNO_local_pool);
01895 WN_STACK *store_stack = CXX_NEW(WN_STACK(&LNO_local_pool),&LNO_local_pool);
01896
01897 Unrolled_DU_Update_V(bodies,u,hash_table,load_stack,store_stack);
01898
01899 SYMBOL *index_loopno = NULL;
01900 if (!cross_index && (load_stack->Elements())) {
01901 WN *tmp = load_stack->Bottom_nth(0);
01902 BOOL done = FALSE;
01903 while (tmp && !done) {
01904 if (WN_opcode(tmp) == OPC_DO_LOOP) {
01905 if (Do_Loop_Depth(tmp) == loopno) {
01906 index_loopno = CXX_NEW(SYMBOL(WN_index(tmp)),
01907 &LNO_local_pool);
01908 done = TRUE;
01909 }
01910 }
01911 tmp = LWN_Get_Parent(tmp);
01912 }
01913 }
01914
01915 Unrolled_DU_Update_E(u,loopno,hash_table,load_stack,store_stack,
01916 update_pointers,index_loopno);
01917
01918 CXX_DELETE(hash_table,&LNO_local_pool);
01919 MEM_POOL_Pop(&LNO_local_pool);
01920 }
01921
01922
01923 static ST *Get_ST_Base(ST *st)
01924 {
01925 ST *base = ST_base(st);
01926 if (base == st) return base;
01927 ST *tmp= ST_base(base);
01928 while (tmp != base) {
01929 base = tmp;
01930 tmp = ST_base(tmp);
01931 }
01932 return base;
01933 }
01934
01935
01936
01937
01938
01939
01940
01941
01942
01943 ST *Get_ST_Base(WN *load)
01944 {
01945 OPERATOR opr = WN_operator(load);
01946 if (opr == OPR_LDA) {
01947 return Get_ST_Base(WN_st(load));
01948 } else if (opr == OPR_LDID) {
01949 DEF_LIST *defs = Du_Mgr->Ud_Get_Def(load);
01950 if (!defs || defs->Incomplete()) return NULL;
01951 DEF_LIST_ITER iter(defs);
01952 const DU_NODE *node=iter.First();
01953 if (iter.Next()) {
01954 return NULL;
01955 }
01956 #ifdef KEY // bug 7624
01957 if (iter.Is_Empty())
01958 return NULL;
01959 #endif
01960 WN *def = (WN *) node->Wn();
01961 if (WN_operator(def) == OPR_STID) {
01962 return Get_ST_Base(WN_kid0(def));
01963 } else {
01964 return NULL;
01965 }
01966 } else {
01967 return NULL;
01968 }
01969 }
01970
01971
01972
01973
01974
01975
01976
01977
01978
01979 static BOOL All_Uses_Within(WN* def, WN* region)
01980 {
01981 USE_LIST *uses = Du_Mgr->Du_Get_Use(def);
01982 if (uses->Incomplete()) return FALSE;
01983 USE_LIST_ITER iter(uses);
01984
01985 for (const DU_NODE* n = iter.First(); !iter.Is_Empty(); n = iter.Next()) {
01986 const WN *use = n->Wn();
01987 while (use != region) {
01988 use = LWN_Get_Parent(use);
01989 if (use == NULL)
01990 return FALSE;
01991 }
01992 }
01993 return TRUE;
01994 }
01995
01996 BOOL Index_Variable_Live_At_Exit(WN* loop)
01997 {
01998 return (!All_Uses_Within(WN_step(loop), loop) ||
01999 !All_Uses_Within(WN_start(loop), loop));
02000 }
02001
02002 static BOOL Is_Used(WN* wn, const SYMBOL& sym)
02003 {
02004 switch (WN_operator(wn)) {
02005 case OPR_BLOCK:
02006 {
02007 for (WN* w = WN_first(wn); w; w = WN_next(w))
02008 if (Is_Used(w, sym))
02009 return TRUE;
02010 }
02011 return FALSE;
02012 case OPR_LDID:
02013 return SYMBOL(wn) == sym;
02014 default:
02015 for (INT i = 0; i < WN_kid_count(wn); i++)
02016 if (Is_Used(WN_kid(wn,i), sym))
02017 return TRUE;
02018 return FALSE;
02019 }
02020 }
02021
02022 BOOL Index_Variable_Live_At_Entry(WN* loop)
02023 {
02024 return Is_Used(WN_start(loop), SYMBOL(WN_index(loop)));
02025 }
02026
02027 extern INT Symbol_Count(WN* wn, const SYMBOL& sym)
02028 {
02029 INT rval = (WN_operator(wn) == OPR_LDID && sym == SYMBOL(wn))
02030 ? 1 : 0;
02031 for (INT k = 0; k < WN_kid_count(wn); k++)
02032 rval += Symbol_Count(WN_kid(wn,k), sym);
02033 return rval;
02034 }
02035
02036 static void Flip_Le_And_Ge(WN* wn)
02037 {
02038 OPCODE opc = WN_opcode(wn);
02039 OPERATOR opr = OPCODE_operator(opc);
02040
02041 switch (opr) {
02042 case OPR_GE: opr = OPR_LE; break;
02043 case OPR_LE: opr = OPR_GE; break;
02044 case OPR_GT: opr = OPR_LT; break;
02045 case OPR_LT: opr = OPR_GT; break;
02046 default: FmtAssert(0, ("Bad call to Flip_Le_And_Ge")); break;
02047 }
02048
02049 WN_set_opcode(wn, OPCODE_make_op(opr, OPCODE_rtype(opc), OPCODE_desc(opc)));
02050 }
02051
02052 BOOL Solve_For(WN* wn_top, const SYMBOL& sym)
02053 {
02054 BOOL ok = FALSE;
02055
02056 INT lcount = Symbol_Count(WN_kid0(wn_top), sym);
02057 INT rcount = Symbol_Count(WN_kid1(wn_top), sym);
02058
02059 OPERATOR opr_base = WN_operator(wn_top);
02060 FmtAssert(opr_base == OPR_GT || opr_base == OPR_LT || opr_base == OPR_LE
02061 || opr_base == OPR_GE, ("Solve_For() called with bad RELOP"));
02062
02063 if (!(lcount == 1 && rcount == 0) && !(lcount == 0 && rcount == 1)) {
02064 return FALSE;
02065 }
02066
02067
02068 if (rcount) {
02069 Flip_Le_And_Ge(wn_top);
02070 WN* wn0 = WN_kid0(wn_top);
02071 WN_kid0(wn_top) = WN_kid1(wn_top);
02072 WN_kid1(wn_top) = wn0;
02073 }
02074
02075 WN* l = WN_kid0(wn_top);
02076 WN* r = WN_kid1(wn_top);
02077
02078 while (1) {
02079
02080
02081
02082 OPCODE lopc = WN_opcode(l);
02083 OPERATOR lopr = OPCODE_operator(lopc);
02084
02085
02086 if (OPCODE_is_load(lopc)) {
02087 ok = TRUE;
02088 break;
02089 }
02090
02091 if (lopr == OPR_NEG) {
02092 Flip_Le_And_Ge(wn_top);
02093 TYPE_ID type = WN_rtype(r);
02094 OPCODE negop = OPCODE_make_op(OPR_NEG, type, MTYPE_V);
02095 r = WN_CreateExp1(negop, r);
02096 l = WN_kid0(l);
02097 continue;
02098 }
02099
02100
02101
02102 if (lopr == OPR_CVT || WN_kid_count(l) == 1)
02103 return FALSE;
02104
02105 lcount = Symbol_Count(WN_kid0(l), sym);
02106 rcount = Symbol_Count(WN_kid1(l), sym);
02107
02108 Is_True((lcount == 1 && rcount == 0) ||
02109 (lcount == 0 && rcount == 1),
02110 ("Impossible: Counts messed up %d %d", lcount, rcount));
02111
02112 if (rcount) {
02113 if (lopr == OPR_SUB) {
02114
02115
02116 Flip_Le_And_Ge(wn_top);
02117 TYPE_ID type = WN_rtype(r);
02118 #ifdef TARG_X8664
02119
02120
02121
02122 if (MTYPE_is_unsigned(type)) type = MTYPE_complement(type);
02123 #endif
02124 OPCODE negop = OPCODE_make_op(OPR_NEG, type, MTYPE_V);
02125 r = WN_CreateExp1(negop, r);
02126 }
02127 else if (lopr != OPR_ADD && lopr != OPR_MPY)
02128 break;
02129 WN* wn0 = WN_kid0(l);
02130 WN_kid0(l) = WN_kid1(l);
02131 WN_kid1(l) = wn0;
02132 }
02133
02134 WN* ll = WN_kid0(l);
02135 WN* lr = WN_kid1(l);
02136
02137 if (lopr == OPR_MPY) {
02138 TYPE_ID type = OPCODE_rtype(lopc);
02139
02140 switch (type) {
02141 case MTYPE_I4:
02142 case MTYPE_I8:
02143 break;
02144 default:
02145 goto out;
02146 }
02147
02148
02149
02150
02151
02152 OPCODE lropc = WN_opcode(lr);
02153 if (OPCODE_operator(lropc) != OPR_INTCONST)
02154 break;
02155
02156 INT v = WN_const_val(lr);
02157 if (v < 0) {
02158 Flip_Le_And_Ge(wn_top);
02159 WN_const_val(lr) = -v;
02160 OPCODE negop = OPCODE_make_op(OPR_NEG, OPCODE_rtype(lropc), MTYPE_V);
02161 r = WN_CreateExp1(negop, r);
02162 }
02163
02164 BOOL use_ceil = WN_operator(wn_top) == OPR_GE
02165 || WN_operator(wn_top) == OPR_LT;
02166 if (use_ceil)
02167 r = LWN_CreateDivceil(type, r, lr);
02168 else
02169 r = LWN_CreateDivfloor(type, r, lr);
02170
02171 WN_Delete(l);
02172 l = ll;
02173 }
02174 else if (lopr == OPR_ADD || lopr == OPR_SUB) {
02175 WN_kid0(l) = r;
02176 WN_kid1(l) = lr;
02177 r = l;
02178 l = ll;
02179 WN_set_opcode(r, OPCODE_make_op(lopr == OPR_ADD ? OPR_SUB : OPR_ADD,
02180 OPCODE_rtype(lopc), OPCODE_desc(lopc)));
02181 }
02182 else
02183 return FALSE;
02184 }
02185
02186 out:
02187
02188 #if 0
02189
02190
02191 BOOL simp_state_save = WN_Simplifier_Enable(TRUE);
02192 r = WN_Simplify_Tree(r);
02193 (void) WN_Simplifier_Enable(simp_state_save);
02194 #endif
02195
02196 WN_kid0(wn_top) = l;
02197 WN_kid1(wn_top) = r;
02198 LWN_Parentize(wn_top);
02199
02200 return ok;
02201 }
02202
02203
02204
02205
02206
02207
02208
02209
02210 extern BOOL Do_Loop_Is_Unsigned(WN* wn_loop)
02211 {
02212 FmtAssert(WN_opcode(wn_loop) == OPC_DO_LOOP,
02213 ("Do_Loop_Is_Unsigned() called on a non-do-loop."));
02214 TYPE_ID type = WN_desc(WN_end(wn_loop));
02215 return MTYPE_is_unsigned(type);
02216 }
02217
02218 extern BOOL Upper_Bound_Standardize(WN* ub, BOOL ok_to_fail)
02219 {
02220 WN* doloop = LWN_Get_Parent(ub);
02221 FmtAssert(WN_opcode(doloop) == OPC_DO_LOOP, ("Bad ub passed"));
02222 if (Do_Loop_Is_Unsigned(doloop)
02223 && (UBvar(ub) == NULL || WN_operator(ub) != OPR_LE)) {
02224 FmtAssert(ok_to_fail,
02225 ("Upper bound of unsigned do loop should already be standardized."));
02226 return FALSE;
02227 }
02228
02229 BOOL ok = Solve_For(ub, SYMBOL(WN_index(doloop)));
02230 if (ok == FALSE) {
02231 FmtAssert(ok_to_fail, ("Upper_Bound_Standardize() could not solve for %s",
02232 SYMBOL(WN_index(doloop)).Name()));
02233 return FALSE;
02234 }
02235
02236 OPCODE opc = WN_opcode(ub);
02237 OPERATOR opr = OPCODE_operator(opc);
02238 if (opr != OPR_LT && opr != OPR_LE) {
02239 FmtAssert(ok_to_fail,
02240 ("surprise operator %s returned from Solve_For()",
02241 OPCODE_name(opc)));
02242 return FALSE;
02243 }
02244
02245 if (opr == OPR_LT) {
02246 if (MTYPE_is_integral(OPCODE_desc(opc))) {
02247
02248 TYPE_ID desc = OPCODE_desc(opc);
02249 WN_set_opcode(ub, OPCODE_make_op(OPR_LE, OPCODE_rtype(opc), desc));
02250 OPCODE subop = OPCODE_make_op(OPR_SUB, desc, MTYPE_V);
02251 WN* ub1 = NULL;
02252 ub1 = LWN_CreateExp2(subop, WN_kid1(ub), LWN_Make_Icon(desc, 1));
02253 WN_kid1(ub) = ub1;
02254 LWN_Copy_Frequency_Tree(ub1, ub);
02255 LWN_Set_Parent(ub1, ub);
02256 } else {
02257 FmtAssert(ok_to_fail, ("Cannot convert LT to LE"));
02258 return FALSE;
02259 }
02260 }
02261
02262 return ok;
02263 }
02264
02265
02266
02267
02268
02269
02270
02271 WN* Outermost_Enclosing_Loop(WN* loop)
02272 {
02273 WN* outerloop = loop;
02274 while (Do_Loop_Depth(outerloop) > 0) {
02275 outerloop = LWN_Get_Parent(outerloop);
02276 while (WN_opcode(outerloop) != OPC_DO_LOOP) {
02277 outerloop = LWN_Get_Parent(outerloop);
02278 }
02279 }
02280 return outerloop;
02281 }
02282
02283
02284
02285
02286
02287
02288
02289 WN* Outermost_Enclosing_Good_Loop(WN* loop)
02290 {
02291 if (!Do_Loop_Is_Good(loop))
02292 return NULL;
02293
02294 WN* last_good_loop = loop;
02295 WN* outerloop = loop;
02296 while (Do_Loop_Depth(outerloop) > 0) {
02297 outerloop = LWN_Get_Parent(outerloop);
02298 while (WN_opcode(outerloop) != OPC_DO_LOOP) {
02299 outerloop = LWN_Get_Parent(outerloop);
02300 }
02301 if (!Do_Loop_Is_Good(outerloop))
02302 break;
02303 last_good_loop = outerloop;
02304 }
02305 return last_good_loop;
02306 }
02307
02308
02309
02310
02311
02312
02313
02314 static void Patch_Uses_In_Loop(WN* wn_asg,
02315 WN* wn_loop)
02316 {
02317 LWN_ITER* itr = LWN_WALK_TreeIter(wn_loop);
02318 for (; itr != NULL; itr = LWN_WALK_TreeNext(itr)) {
02319 WN* wn = itr->wn;
02320 if (OPCODE_is_load(WN_opcode(wn))
02321 && (Aliased(Alias_Mgr, wn_asg, wn) != NOT_ALIASED))
02322 Du_Mgr->Add_Def_Use(wn_asg, wn);
02323 }
02324 }
02325
02326
02327
02328
02329
02330
02331
02332 static void Update_Nest_Depth_Traverse(WN* wn_tree)
02333 {
02334 if (OPCODE_operator(WN_opcode(wn_tree)) == OPR_ARRAY) {
02335 INT loop_count = 0;
02336 for (WN* wn = wn_tree; wn != NULL; wn = LWN_Get_Parent(wn))
02337 if (WN_opcode(wn) == OPC_DO_LOOP)
02338 loop_count++;
02339 ACCESS_ARRAY* aa = (ACCESS_ARRAY*) WN_MAP_Get(LNO_Info_Map, wn_tree);
02340 for (INT i = 0; i < aa->Num_Vec(); i++)
02341 aa->Dim(i)->Set_Nest_Depth(loop_count);
02342 }
02343
02344 if (WN_opcode(wn_tree) == OPC_BLOCK) {
02345 for (WN* wn = WN_first(wn_tree); wn != NULL; wn = WN_next(wn))
02346 Update_Nest_Depth_Traverse(wn);
02347 } else {
02348 for (INT i = 0; i < WN_kid_count(wn_tree); i++)
02349 Update_Nest_Depth_Traverse(WN_kid(wn_tree, i));
02350 }
02351 }
02352
02353
02354
02355
02356
02357
02358
02359 static void Update_Nest_Depth(WN* wn_tree)
02360 {
02361 Update_Nest_Depth_Traverse(wn_tree);
02362 }
02363
02364
02365
02366
02367
02368
02369
02370
02371
02372
02373 extern WN* global_fd;
02374
02375 void Finalize_Index_Variable(WN* loop, BOOL insert_after_loop, BOOL try_sink)
02376 {
02377
02378 WN* start_exp = WN_kid0(WN_start(loop));
02379 SYMBOL index = SYMBOL(WN_start(loop));
02380 Upper_Bound_Standardize(WN_end(loop));
02381 FmtAssert(WN_operator(WN_end(loop)) == OPR_LE,
02382 ("Comparison for DO is not .LE. after standardization"));
02383
02384 WN* stop_exp = WN_kid1(WN_end(loop));
02385 WN* step_add = WN_kid0(WN_step(loop));
02386 WN* step_exp = WN_operator(WN_kid0(step_add)) == OPR_LDID
02387 && SYMBOL(WN_kid0(step_add)) == index
02388 ? WN_kid1(step_add) : WN_kid0(step_add);
02389
02390
02391
02392 TYPE_ID wtype = Do_Wtype(loop);
02393 WN* start_new = LWN_Copy_Tree(start_exp, TRUE, LNO_Info_Map);
02394 LWN_Copy_Def_Use(start_exp,start_new,Du_Mgr);
02395 if (Array_Dependence_Graph != NULL) {
02396 if (!Array_Dependence_Graph->
02397 Add_Deps_To_Copy_Block(start_exp, start_new, FALSE))
02398 LNO_Erase_Dg_From_Here_In(loop,Array_Dependence_Graph);
02399 }
02400 WN* stop_new = LWN_Copy_Tree(stop_exp, TRUE, LNO_Info_Map);
02401 LWN_Copy_Def_Use(stop_exp,stop_new,Du_Mgr);
02402 if (Array_Dependence_Graph != NULL) {
02403 if (!Array_Dependence_Graph->
02404 Add_Deps_To_Copy_Block(stop_exp, stop_new, FALSE))
02405 LNO_Erase_Dg_From_Here_In(loop,Array_Dependence_Graph);
02406 }
02407 WN* step_new = LWN_Copy_Tree(step_exp, TRUE, LNO_Info_Map);
02408 LWN_Copy_Def_Use(step_exp,step_new,Du_Mgr);
02409 OPCODE add = OPCODE_make_op(OPR_ADD, Promote_Type(wtype), MTYPE_V);
02410 OPCODE sub = OPCODE_make_op(OPR_SUB, Promote_Type(wtype), MTYPE_V);
02411 WN* diff = LWN_CreateExp2(sub, stop_new, start_new);
02412 WN* iters = LWN_CreateExp2(add, diff, step_new);
02413 if (!(WN_operator(step_exp) == OPR_INTCONST
02414 && WN_const_val(step_exp) == 1)) {
02415 step_new = LWN_Copy_Tree(step_exp, TRUE, LNO_Info_Map);
02416 LWN_Copy_Def_Use(step_exp,step_new,Du_Mgr);
02417 OPCODE div = OPCODE_make_op(OPR_DIV, Promote_Type(wtype), MTYPE_V);
02418 iters = LWN_CreateExp2(div, iters, step_new);
02419
02420 if (MTYPE_is_float(OPCODE_rtype(div))) {
02421
02422 TYPE_ID rtype;
02423 switch (OPCODE_rtype(div)) {
02424 case MTYPE_F4:
02425 rtype = MTYPE_I4;
02426 break;
02427 case MTYPE_F8:
02428 rtype = MTYPE_I8;
02429 break;
02430 default:
02431 FmtAssert(FALSE,
02432 ("Weird floating-point index: cannot compute tripcount\n"));
02433 break;
02434 }
02435 iters = LWN_CreateExp1(OPCODE_make_op(OPR_TRUNC,rtype,OPCODE_rtype(div)),
02436 iters);
02437
02438
02439
02440 OPCODE cvt_op = OPCODE_make_op(OPR_CVT, OPCODE_rtype(div), rtype);
02441 iters = LWN_CreateExp1(cvt_op, iters);
02442 }
02443
02444 step_new = LWN_Copy_Tree(step_exp, TRUE, LNO_Info_Map);
02445 LWN_Copy_Def_Use(step_exp,step_new,Du_Mgr);
02446 OPCODE mul = OPCODE_make_op(OPR_MPY, Promote_Type(wtype), MTYPE_V);
02447 iters = LWN_CreateExp2(mul, iters, step_new);
02448 }
02449 start_new = LWN_Copy_Tree(start_exp, TRUE, LNO_Info_Map);
02450 LWN_Copy_Def_Use(start_exp,start_new,Du_Mgr);
02451 if (Array_Dependence_Graph != NULL) {
02452 if (!Array_Dependence_Graph->
02453 Add_Deps_To_Copy_Block(start_exp, start_new, FALSE))
02454 LNO_Erase_Dg_From_Here_In(loop,Array_Dependence_Graph);
02455 }
02456 WN* final_lhs = LWN_Copy_Tree(start_exp, TRUE, LNO_Info_Map);
02457 LWN_Copy_Def_Use(start_exp, final_lhs, Du_Mgr);
02458 if (Array_Dependence_Graph != NULL) {
02459 if (!Array_Dependence_Graph->
02460 Add_Deps_To_Copy_Block(start_exp, final_lhs, FALSE))
02461 LNO_Erase_Dg_From_Here_In(loop,Array_Dependence_Graph);
02462 }
02463 add = OPCODE_make_op(OPR_ADD, Promote_Type(wtype), MTYPE_V);
02464 WN* final_rhs = LWN_CreateExp2(add, start_new, iters);
02465 OPCODE max = OPCODE_make_op(OPR_MAX, Promote_Type(wtype), MTYPE_V);
02466 WN* final = LWN_CreateExp2(max, final_lhs, final_rhs);
02467 OPCODE final_op = OPCODE_make_op(OPR_STID, MTYPE_V, wtype);
02468 WN* final_store = LWN_CreateStid(final_op, WN_start(loop), final);
02469 Du_Mgr->Create_Use_List(final_store);
02470
02471 if (insert_after_loop) {
02472
02473 LWN_Insert_Block_After(LWN_Get_Parent(loop), loop, final_store);
02474 } else {
02475
02476 LWN_Insert_Block_Before(LWN_Get_Parent(loop), loop, final_store);
02477 }
02478 Update_Nest_Depth(final_store);
02479
02480
02481 WN* start_asg = WN_start(loop);
02482 WN* stop_opr = WN_end(loop);
02483 USE_LIST* use_list = Du_Mgr->Du_Get_Use(start_asg);
02484 USE_LIST_ITER iter(use_list);
02485 for (DU_NODE *use_node=(DU_NODE *)iter.First(); !iter.Is_Empty(); ) {
02486 WN* use=use_node->Wn();
02487 use_node=(DU_NODE *)iter.Next();
02488 WN* new_loop=use;
02489 while (new_loop !=loop && WN_opcode(new_loop)!=OPC_FUNC_ENTRY)
02490 new_loop=LWN_Get_Parent(new_loop);
02491 if (new_loop!=loop) {
02492
02493 Du_Mgr->Delete_Def_Use(WN_start(loop),use);
02494 Du_Mgr->Delete_Def_Use(WN_step(loop),use);
02495 Du_Mgr->Add_Def_Use(final_store,use);
02496 }
02497 }
02498
02499
02500
02501 USE_LIST* local_use_list = Du_Mgr->Du_Get_Use(WN_start(loop));
02502 if (local_use_list->Incomplete())
02503 Patch_Uses_In_Loop(WN_start(loop), loop);
02504 local_use_list = Du_Mgr->Du_Get_Use(WN_step(loop));
02505 if (local_use_list->Incomplete())
02506 Patch_Uses_In_Loop(WN_step(loop), loop);
02507
02508 if (use_list->Incomplete())
02509 Du_Mgr->Du_Get_Use(final_store)->Set_Incomplete();
02510 if (!Do_Loop_Has_Calls(loop)) {
02511 use_list->Reset_Incomplete();
02512 use_list = Du_Mgr->Du_Get_Use(WN_step(loop));
02513 use_list->Reset_Incomplete();
02514 }
02515 scalar_rename(WN_start(loop));
02516
02517 if (insert_after_loop && try_sink) {
02518 WN* wn_sink_loop = NULL;
02519 #ifndef KEY
02520 for (WN* wn = LWN_Get_Parent(loop); wn != NULL; wn = LWN_Get_Parent(wn))
02521 #else
02522
02523 for (WN* wn = LWN_Get_Parent(loop);
02524 wn != NULL && WN_operator(wn) != OPR_IF;
02525 wn = LWN_Get_Parent(wn))
02526 #endif
02527 if (WN_opcode(wn) == OPC_DO_LOOP
02528 && Statement_Sinkable_Out_Of_Loop(final_store, wn))
02529 wn_sink_loop = wn;
02530 if (wn_sink_loop != NULL)
02531 Sink_Out_Sandwiched_Statement(final_store, wn_sink_loop);
02532 }
02533 }
02534
02535
02536
02537
02538
02539
02540
02541 void Finalize_Index_Variable_For_Remove_Unity_Trip_Loop(WN* loop,
02542 BOOL insert_after_loop, BOOL try_sink)
02543 {
02544
02545 WN* start_exp = WN_kid0(WN_start(loop));
02546 SYMBOL index = SYMBOL(WN_start(loop));
02547
02548
02549
02550 TYPE_ID wtype = Do_Wtype(loop);
02551 WN* start_new = LWN_Copy_Tree(start_exp, TRUE, LNO_Info_Map);
02552 LWN_Copy_Def_Use(start_exp, start_new, Du_Mgr);
02553 if (Array_Dependence_Graph != NULL) {
02554 if (!Array_Dependence_Graph->
02555 Add_Deps_To_Copy_Block(start_exp, start_new, FALSE))
02556 LNO_Erase_Dg_From_Here_In(loop,Array_Dependence_Graph);
02557 }
02558 WN* step_add = WN_kid0(WN_step(loop));
02559 WN* step_exp = WN_operator(WN_kid0(step_add)) == OPR_LDID
02560 && SYMBOL(WN_kid0(step_add)) == index
02561 ? WN_kid1(step_add) : WN_kid0(step_add);
02562 WN* step_new = LWN_Copy_Tree(step_exp, TRUE, LNO_Info_Map);
02563 LWN_Copy_Def_Use(step_exp,step_new,Du_Mgr);
02564 OPCODE add = OPCODE_make_op(OPR_ADD, Promote_Type(wtype), MTYPE_V);
02565 WN* final = LWN_CreateExp2(add, start_new, step_new);
02566 OPCODE final_op = OPCODE_make_op(OPR_STID, MTYPE_V, wtype);
02567 WN* final_store = LWN_CreateStid(final_op, WN_start(loop), final);
02568 Du_Mgr->Create_Use_List(final_store);
02569
02570 if (insert_after_loop) {
02571
02572 LWN_Insert_Block_After(LWN_Get_Parent(loop), loop, final_store);
02573 } else {
02574
02575 LWN_Insert_Block_Before(LWN_Get_Parent(loop), loop, final_store);
02576 }
02577
02578
02579 WN* start_asg = WN_start(loop);
02580 USE_LIST* use_list = Du_Mgr->Du_Get_Use(start_asg);
02581 USE_LIST_ITER iter(use_list);
02582 for (DU_NODE *use_node=(DU_NODE *)iter.First(); !iter.Is_Empty(); ) {
02583 WN* use=use_node->Wn();
02584 use_node=(DU_NODE *)iter.Next();
02585 WN* new_loop=use;
02586 while (new_loop !=loop && WN_opcode(new_loop)!=OPC_FUNC_ENTRY)
02587 new_loop=LWN_Get_Parent(new_loop);
02588 if (new_loop!=loop) {
02589
02590 Du_Mgr->Delete_Def_Use(WN_start(loop),use);
02591 Du_Mgr->Delete_Def_Use(WN_step(loop),use);
02592 Du_Mgr->Add_Def_Use(final_store,use);
02593 }
02594 }
02595
02596
02597
02598 USE_LIST* local_use_list = Du_Mgr->Du_Get_Use(WN_start(loop));
02599 if (local_use_list->Incomplete())
02600 Patch_Uses_In_Loop(WN_start(loop), loop);
02601 local_use_list = Du_Mgr->Du_Get_Use(WN_step(loop));
02602 if (local_use_list->Incomplete())
02603 Patch_Uses_In_Loop(WN_step(loop), loop);
02604
02605 if (use_list->Incomplete())
02606 Du_Mgr->Du_Get_Use(final_store)->Set_Incomplete();
02607 if (!Do_Loop_Has_Calls(loop)) {
02608 use_list->Reset_Incomplete();
02609 use_list = Du_Mgr->Du_Get_Use(WN_step(loop));
02610 use_list->Reset_Incomplete();
02611 }
02612 scalar_rename(WN_start(loop));
02613
02614 if (insert_after_loop && try_sink) {
02615 WN* wn_sink_loop = NULL;
02616 for (WN* wn = LWN_Get_Parent(loop); wn != NULL; wn = LWN_Get_Parent(wn))
02617 if (WN_opcode(wn) == OPC_DO_LOOP
02618 && Statement_Sinkable_Out_Of_Loop(final_store, wn))
02619 wn_sink_loop = wn;
02620 if (wn_sink_loop != NULL)
02621 Sink_Out_Sandwiched_Statement(final_store, wn_sink_loop);
02622 }
02623 }
02624 #ifdef Is_True_On
02625
02626
02627
02628
02629
02630 static BOOL LNO_Check_Du_HT(WN* orig,
02631 WN* copy,
02632 HASH_TABLE<WN*,WN*>* ht)
02633 {
02634 #if 0
02635 FmtAssert(orig && copy,
02636 ("lnoutils detects PREOPT II failure: missing orig or copy"));
02637 FmtAssert(WN_opcode(orig) == WN_opcode(copy),
02638 ("lnoutils detects PREOPT II failure: orig op=%d copy op=%d",
02639 WN_opcode(orig), WN_opcode(copy)));
02640 #else
02641 if (orig == NULL || copy == NULL) {
02642 fprintf(stderr,
02643 "lnoutils detects PREOPT II failure: missing orig or copy\n");
02644 return FALSE;
02645 }
02646 if (WN_opcode(orig) != WN_opcode(copy)) {
02647 fprintf(stderr,
02648 "lnoutils detects PREOPT II failure: orig op=%d copy op=%d\n",
02649 WN_opcode(orig), WN_opcode(copy));
02650 return FALSE;
02651 }
02652 #endif
02653
02654 OPCODE opc = WN_opcode(orig);
02655 OPERATOR opr = OPCODE_operator(opc);
02656
02657 if (opr == OPR_LDID || opr == OPR_STID ||
02658 opr == OPR_DO_LOOP || opr == OPR_FUNC_ENTRY ||
02659 OPCODE_is_call(opc))
02660 ht->Enter(copy, orig);
02661
02662 if (WN_opcode(orig) == OPC_BLOCK) {
02663 WN* o = WN_first(orig);
02664 WN* c = WN_first(copy);
02665 while (o) {
02666 if (!LNO_Check_Du_HT(o, c, ht))
02667 return FALSE;
02668 o = WN_next(o);
02669 c = WN_next(c);
02670 }
02671 }
02672 else {
02673 for (INT k = 0; k < WN_kid_count(orig); k++)
02674 if (!LNO_Check_Du_HT(WN_kid(orig,k),WN_kid(copy,k), ht))
02675 return FALSE;
02676 }
02677
02678 return TRUE;
02679 }
02680
02681 static BOOL LNO_Check_Du_Check(HASH_TABLE<WN*,WN*>* ht)
02682 {
02683 WN* orig;
02684 WN* copy;
02685
02686 BOOL rval = TRUE;
02687
02688 HASH_TABLE_ITER<WN*,WN*> it(ht);
02689 while (it.Step(©, &orig)) {
02690
02691 OPCODE opc = WN_opcode(orig);
02692 OPERATOR opr = OPCODE_operator(opc);
02693
02694 FmtAssert(opc == WN_opcode(copy), ("Flawed hashtable"));
02695
02696 if (opr == OPR_LDID) {
02697
02698
02699 DEF_LIST* dl = Du_Mgr->Ud_Get_Def(copy);
02700 INT dl_len = dl == NULL ? 0 : dl->Len();
02701 #if 0
02702
02703 FmtAssert(dl_len, ("Missing def list in copy"));
02704 #else
02705 if (dl_len == 0) {
02706 WN *cp;
02707 for (cp = LWN_Get_Parent(copy); cp; cp = LWN_Get_Parent(cp))
02708 if (WN_opcode(cp) == OPC_IO)
02709 break;
02710 FmtAssert(cp, ("Missing def list in copy"));
02711 }
02712 #endif
02713
02714 DEF_LIST* dl2 = Du_Mgr->Ud_Get_Def(orig);
02715 INT dl2_len = dl2 == NULL ? 0 : dl2->Len();
02716
02717
02718 if (dl_len && dl2_len &&
02719 ((dl2->Loop_stmt() == NULL &&
02720 dl->Loop_stmt() != NULL) ||
02721 (dl2->Loop_stmt() != NULL &&
02722 dl2->Loop_stmt() != ht->Find(dl->Loop_stmt())))) {
02723 rval = FALSE;
02724 printf("DU check: Bad deflist do: use=0x%p[0x%p] do=0x%p[0x%p]\n",
02725 orig, copy, dl2->Loop_stmt(), dl->Loop_stmt());
02726 }
02727
02728 DEF_LIST_ITER iter(dl);
02729 for (DU_NODE* du = iter.First(); !iter.Is_Empty(); du = iter.Next()) {
02730 BOOL ok = FALSE;
02731 DEF_LIST_ITER iter2(dl2);
02732 WN* duorig = ht->Find(du->Wn());
02733 for (DU_NODE* du2 = iter2.First(); !iter2.Is_Empty(); du2 = iter2.Next()) {
02734 if (du2->Wn() == duorig) {
02735 ok = TRUE;
02736 break;
02737 }
02738 }
02739 if (ok == FALSE) {
02740 rval = FALSE;
02741 printf("DU check: Inadequate defs: use=0x%p[0x%p] def=0x%p[0x%p]\n",
02742 orig, copy, duorig, du->Wn());
02743 }
02744 }
02745 }
02746 else if (opr == OPR_STID || OPCODE_is_call(opc)) {
02747
02748
02749 USE_LIST* ul = Du_Mgr->Du_Get_Use(copy);
02750 INT ul_len = ul == NULL ? 0 : ul->Len();
02751 if (!OPCODE_is_call(opc) && !ul_len &&
02752 !((ST_class(WN_st(orig))==CLASS_PREG) &&
02753 Preg_Is_Dedicated((WN_offset(orig))))) {
02754 fprintf(stderr,"Missing use list in copy \n");
02755 }
02756
02757
02758 USE_LIST* ul2 = Du_Mgr->Du_Get_Use(orig);
02759
02760
02761 USE_LIST_ITER iter(ul);
02762 for (DU_NODE* du = iter.First(); !iter.Is_Empty(); du = iter.Next()) {
02763 BOOL ok = FALSE;
02764 USE_LIST_ITER iter2(ul2);
02765 WN* duorig = ht->Find(du->Wn());
02766 for (DU_NODE* du2 = iter2.First(); !iter2.Is_Empty(); du2 = iter2.Next()) {
02767 if (du2->Wn() == duorig) {
02768 ok = TRUE;
02769 break;
02770 }
02771 }
02772 if (ok == FALSE) {
02773 rval = FALSE;
02774 printf("DU check: Inadequate uses: def=0x%p[0x%p] use=0x%p[0x%p]\n",
02775 orig, copy, duorig, du->Wn());
02776 }
02777 }
02778 }
02779 else {
02780 FmtAssert(opr == OPR_DO_LOOP || opr == OPR_FUNC_ENTRY,
02781 ("Bad opcode in hash table"));
02782 }
02783 }
02784
02785 return rval;
02786 }
02787
02788 void LNO_Check_Du(WN* orig)
02789 {
02790 WN* copy = LWN_Copy_Tree(orig);
02791 Set_Error_Phase ( "Pre-Optimizer DU" );
02792 copy = Pre_Optimizer(PREOPT_DUONLY_PHASE, copy, Du_Mgr, Alias_Mgr);
02793 Set_Error_Phase ( "Loop nest optimizer Post-DU" );
02794 LWN_Parentize(copy);
02795 Mark_Code(copy, FALSE, TRUE);
02796 LNO_Build_Access(copy, &LNO_default_pool);
02797
02798 MEM_POOL_Push(&LNO_local_pool);
02799 HASH_TABLE<WN*,WN*> ht1(307, &LNO_local_pool);
02800 if (!LNO_Check_Du_HT(orig, copy, &ht1)) {
02801 fprintf(stderr, "LNO_Check_Du() failed to check DU chains because of preopt error\n");
02802 }
02803 else if (!LNO_Check_Du_Check(&ht1)) {
02804
02805 printf("*** ORIG\n");
02806 Dump_WN(orig, stdout, 3);
02807 printf("*** COPY\n");
02808 Dump_WN(copy, stdout, 3);
02809 }
02810 MEM_POOL_Pop(&LNO_local_pool);
02811 }
02812
02813 #endif
02814
02815 WN* WN_prev_executable(WN* wn)
02816 {
02817 wn = WN_prev(wn);
02818 if (wn && OPCODE_is_not_executable(WN_opcode(wn)))
02819 wn = WN_prev(wn);
02820 return wn;
02821 }
02822
02823 WN* WN_next_executable(WN* wn)
02824 {
02825 wn = WN_next(wn);
02826 if (wn && OPCODE_is_not_executable(WN_opcode(wn)))
02827 wn = WN_next(wn);
02828 return wn;
02829 }
02830
02831 static void LNO_Erase_Vertices_In_Loop_Rec(WN *wn, ARRAY_DIRECTED_GRAPH16 *dg)
02832 {
02833 OPCODE opcode = WN_opcode(wn);
02834 if (WN_opcode(wn) == OPC_BLOCK) {
02835 for (WN* w = WN_first(wn); w; w = WN_next(w)) {
02836 LNO_Erase_Vertices_In_Loop_Rec(w, dg);
02837 }
02838 } else if (WN_opcode(wn) != OPC_DO_LOOP) {
02839 for (INT k = 0; k < WN_kid_count(wn); k++) {
02840 LNO_Erase_Vertices_In_Loop_Rec(WN_kid(wn,k), dg);
02841 }
02842 }
02843 if (OPCODE_is_load(opcode) || OPCODE_is_store(opcode) ||
02844 OPCODE_is_call(opcode) || (OPCODE_operator(opcode) == OPR_INTRINSIC_OP)
02845 #ifdef KEY
02846 || (OPCODE_operator(opcode) == OPR_PURE_CALL_OP)
02847 #endif
02848 ) {
02849 VINDEX16 v = dg->Get_Vertex(wn);
02850 if (v) {
02851 dg->Delete_Vertex(v);
02852 }
02853 }
02854 }
02855
02856 void LNO_Erase_Vertices_In_Loop(WN *wn, ARRAY_DIRECTED_GRAPH16 *dg)
02857 {
02858 while (wn && (WN_opcode(wn) != OPC_DO_LOOP)) wn = LWN_Get_Parent(wn);
02859 if (!wn) return;
02860 for (INT k = 0; k < WN_kid_count(wn); k++) {
02861 LNO_Erase_Vertices_In_Loop_Rec(WN_kid(wn,k),dg);
02862 }
02863 }
02864
02865 void Du_Sanity_Check_Matching_Du(STACK<WN*>* read_stack,
02866 STACK<WN*>* write_stack, FILE* fp, UINT fancy)
02867 {
02868 MEM_POOL_Push(&LNO_local_pool);
02869
02870 {
02871
02872 UINT write_count=write_stack->Elements();
02873 UINT read_count=read_stack->Elements();
02874 HASH_TABLE<WN*,INT> bit_pos(2*read_count, &LNO_local_pool);
02875 HASH_TABLE<WN*,INT> write_index(2*write_count, &LNO_local_pool);
02876
02877 INT si;
02878 for (si=0; si<read_stack->Elements(); si++) {
02879 WN *read = read_stack->Bottom_nth(si);
02880 bit_pos.Enter(read,si+1);
02881 }
02882
02883 BIT_VECTOR* write_vector=
02884 CXX_NEW_ARRAY(BIT_VECTOR, write_count+1, &LNO_local_pool);
02885
02886 UINT* Use_Count=CXX_NEW_ARRAY(UINT, write_count+1, &LNO_local_pool);
02887
02888 for (si=0; si<write_stack->Elements(); si++) {
02889 Use_Count[si+1]=0;
02890 write_vector[si+1].Init(read_count+1, &LNO_local_pool);
02891 WN *write = write_stack->Bottom_nth(si);
02892 write_index.Enter(write, si+1);
02893 USE_LIST* use_list=Du_Mgr->Du_Get_Use(write);
02894 USE_LIST_ITER u_iter(use_list);
02895 for (DU_NODE* u_node=u_iter.First(); !u_iter.Is_Empty();
02896 u_node=u_iter.Next()) {
02897 WN* use=u_node->Wn();
02898 Use_Count[si+1]++;
02899 UINT bit=bit_pos.Find(use);
02900 if (bit!=0)
02901 write_vector[si+1].Set(bit);
02902 else if (WN_operator(use)!=OPR_IO) {
02903 OPERATOR opr=WN_operator(write);
02904 fprintf(fp,"WARNING: %s %d [0x%p]",
02905 OPERATOR_name(opr), WN_map_id(write), write);
02906 #ifdef KEY
02907 if (getenv("PATHSCALE_LNO_DEBUG"))
02908 #endif
02909 Dump_WN(write,fp,fancy,2,2,NULL,NULL,NULL,FALSE);
02910 fprintf(fp,"has a non-matching DU relation with node: %d [0x%p]\n",
02911 WN_map_id(use), use);
02912 #ifdef KEY
02913 if (getenv("PATHSCALE_LNO_DEBUG"))
02914 #endif
02915 Dump_WN(use,fp,fancy,2,2,NULL,NULL,NULL,FALSE);
02916 }
02917 }
02918 }
02919
02920 for (si=0; si<read_stack->Elements(); si++) {
02921 WN *read = read_stack->Bottom_nth(si);
02922 UINT bit=si+1;
02923 DEF_LIST* def_list=Du_Mgr->Ud_Get_Def(read);
02924 DEF_LIST_ITER d_iter(def_list);
02925 for (DU_NODE* d_node=d_iter.First(); !d_iter.Is_Empty();
02926 d_node=d_iter.Next()) {
02927 WN* def=d_node->Wn();
02928 UINT index=write_index.Find(def);
02929 if (index!=0 && write_vector[index].Test(bit)) {
02930
02931
02932 Use_Count[index]--;
02933 } else if (WN_operator(def)!=OPR_IO) {
02934 OPERATOR opr=WN_operator(read);
02935 fprintf(fp,"WARNING: %s %d [0x%p]",
02936 OPERATOR_name(opr), WN_map_id(read), read);
02937 #ifdef KEY
02938 if (getenv("PATHSCALE_LNO_DEBUG"))
02939 #endif
02940 Dump_WN(read,fp,fancy,2,2,NULL,NULL,NULL,FALSE);
02941 fprintf(fp,"has a non-matching DU relation with node: %d [0x%p]\n",
02942 WN_map_id(def), def);
02943 #ifdef KEY
02944 if (getenv("PATHSCALE_LNO_DEBUG"))
02945 #endif
02946 if (WN_opcode(def)==OPC_FUNC_ENTRY)
02947 fprintf(fp,"FUNC_ENTRY\n");
02948 else
02949 Dump_WN(def,fp,fancy,2,2,NULL,NULL,NULL,FALSE);
02950 }
02951 }
02952 }
02953
02954
02955 for (si=0; si<read_stack->Elements(); si++) {
02956 WN *read = read_stack->Bottom_nth(si);
02957 UINT bit=si+1;
02958 DEF_LIST* def_list=Du_Mgr->Ud_Get_Def(read);
02959 DEF_LIST_ITER d_iter(def_list);
02960 for (DU_NODE* d_node=d_iter.First(); !d_iter.Is_Empty();
02961 d_node=d_iter.Next()) {
02962 WN* def=d_node->Wn();
02963 UINT index=write_index.Find(def);
02964 if (index!=0 && write_vector[index].Test(bit)) {
02965 write_vector[index].Reset(bit);
02966 }
02967 }
02968 }
02969
02970 for (si=0; si<write_stack->Elements(); si++) {
02971 WN *write = write_stack->Bottom_nth(si);
02972 if (Use_Count[si+1]!=0) {
02973 INT i;
02974 UINT index=si+1;
02975 while ((i=write_vector[si+1].Least_Non_Zero()) != -1) {
02976 WN* use=read_stack->Bottom_nth(i-1);
02977 if (WN_operator(use)!=OPR_IO) {
02978 OPERATOR opr=WN_operator(write);
02979 fprintf(fp,"WARNING: %s %d 0x%p",
02980 OPERATOR_name(opr), WN_map_id(write), write);
02981 #ifdef KEY
02982 if (getenv("PATHSCALE_LNO_DEBUG"))
02983 #endif
02984 Dump_WN(write,fp,fancy,2,2,NULL,NULL,NULL,FALSE);
02985 fprintf(fp,"has a non-matching DU relation with node: %d [0x%p]\n",
02986 WN_map_id(use), use);
02987 #ifdef KEY
02988 if (getenv("PATHSCALE_LNO_DEBUG"))
02989 #endif
02990 Dump_WN(use,fp,fancy,2,2,NULL,NULL,NULL,FALSE);
02991 }
02992 write_vector[index].Reset(i);
02993 }
02994 }
02995 }
02996
02997 }
02998
02999 MEM_POOL_Pop(&LNO_local_pool);
03000
03001 }
03002
03003
03004 static void Du_Sanity_Check_r(
03005 WN* wn, HASH_TABLE<WN*,INT>* h_table, UINT pass, FILE* fp, UINT fancy,
03006 STACK<WN*> *reads, STACK<WN*> *writes)
03007 {
03008 OPCODE opc=WN_opcode(wn);
03009 OPERATOR opr=OPCODE_operator(opc);
03010
03011 if (pass==0) {
03012 if (OPCODE_is_load(opc) || OPCODE_is_store(opc) || opr == OPR_ALTENTRY ||
03013 opr==OPR_FUNC_ENTRY || opr==OPR_RETURN || OPCODE_has_barrier(opc) ||
03014 opr==OPR_PARM || (opr==OPR_LABEL && WN_Label_Is_Handler_Begin(wn)) ||
03015 opr==OPR_IO || OPCODE_is_call(opc) || opr==OPR_INTRINSIC_OP
03016 #ifdef KEY
03017 || opr==OPR_PURE_CALL_OP
03018 || opr==OPR_GOTO_OUTER_BLOCK
03019 #endif
03020 )
03021 h_table->Enter(wn,1);
03022 } else {
03023 if (OPCODE_is_load(opc) || OPCODE_is_store(opc)) {
03024 if (Aliased(Alias_Mgr,wn,wn)==NOT_ALIASED) {
03025 fprintf(fp,"WARNING: %s %d [0x%p]",
03026 OPERATOR_name(opr), WN_map_id(wn), wn);
03027 #ifdef KEY
03028 if (getenv("PATHSCALE_LNO_DEBUG"))
03029 #endif
03030 Dump_WN(wn,fp,fancy,2,2,NULL,NULL,NULL,FALSE);
03031 fprintf(fp,"is not aliased to itself\n");
03032 }
03033 }
03034 if (Du_Mgr->Ud_Get_Def(wn)) {
03035 reads->Push(wn);
03036 DEF_LIST* def_list=Du_Mgr->Ud_Get_Def(wn);
03037 WN* loop=def_list->Loop_stmt();
03038
03039 #ifdef KEY //bug 12856: don't check Loop_stmt for iloads since
03040
03041 if (loop && WN_operator(wn)!=OPR_ILOAD) {
03042 #else
03043 if (loop) {
03044 #endif
03045 if (WN_opcode(loop)!=OPC_DO_LOOP) {
03046 fprintf(fp,"WARNING: %s %d [0x%p]",
03047 OPERATOR_name(opr), WN_map_id(wn), wn);
03048 #ifdef KEY
03049 if (getenv("PATHSCALE_LNO_DEBUG"))
03050 #endif
03051 Dump_WN(wn,fp,fancy,2,2,NULL,NULL,NULL,FALSE);
03052 fprintf(fp,"has a non-loop node as loop_stmt: %d (0x%p 0x%p)\n",
03053 WN_map_id(loop), wn, loop);
03054 #ifdef KEY
03055 if (getenv("PATHSCALE_LNO_DEBUG"))
03056 #endif
03057 Dump_WN(loop,fp,fancy,2,2,NULL,NULL,NULL,FALSE);
03058 }
03059 WN* wn1=wn;
03060 while (WN_opcode(wn1)!=OPC_FUNC_ENTRY) {
03061 if (wn1==loop)
03062 break;
03063 else
03064 wn1=LWN_Get_Parent(wn1);
03065 }
03066 if (wn1!=loop) {
03067 fprintf(fp,"WARNING: %s %d [0x%p]",
03068 OPERATOR_name(opr), WN_map_id(wn), wn);
03069 #ifdef KEY
03070 if (getenv("PATHSCALE_LNO_DEBUG"))
03071 #endif
03072 Dump_WN(wn,fp,fancy,2,2,NULL,NULL,NULL,FALSE);
03073 fprintf(fp,"has a non-ancestor node as loop_stmt: %d\n",
03074 WN_map_id(loop));
03075 #ifdef KEY
03076 if (getenv("PATHSCALE_LNO_DEBUG"))
03077 #endif
03078 Dump_WN(loop,fp,fancy,2,2,NULL,NULL,NULL,FALSE);
03079 }
03080 }
03081 BOOL ldid_in_do_loop_head=FALSE;
03082 WN* parent_loop;
03083 if (WN_operator(wn)==OPR_LDID) {
03084 parent_loop=LWN_Get_Parent(wn);
03085 while (!OPCODE_is_scf(WN_opcode(parent_loop)))
03086 parent_loop=LWN_Get_Parent(parent_loop);
03087 if (WN_opcode(parent_loop)==OPC_DO_LOOP && parent_loop==loop
03088 && SYMBOL(wn) == SYMBOL(WN_index(parent_loop)))
03089 ldid_in_do_loop_head=TRUE;
03090 }
03091 DEF_LIST_ITER d_iter(def_list);
03092 for (DU_NODE *def_node=(DU_NODE *)d_iter.First();
03093 !d_iter.Is_Empty(); def_node=(DU_NODE *)d_iter.Next()) {
03094 WN* def1=def_node->Wn();
03095 if (ldid_in_do_loop_head) {
03096 if (LWN_Get_Parent(def1)!=parent_loop) {
03097 fprintf(fp,"WARNING: %s %d [0x%p]",
03098 OPERATOR_name(opr), WN_map_id(wn), wn);
03099 #ifdef KEY
03100 if (getenv("PATHSCALE_LNO_DEBUG"))
03101 #endif
03102 Dump_WN(wn,fp,fancy,2,2,NULL,NULL,NULL,FALSE);
03103 fprintf(fp,
03104 "is ldid in loop head but has def out of loop head: %d [0x%p]\n",
03105 WN_map_id(def1), def1);
03106 }
03107 }
03108 if (!h_table->Find(def1)) {
03109 fprintf(fp,"WARNING: %s %d [0x%p]",
03110 OPERATOR_name(opr), WN_map_id(wn), wn);
03111 #ifdef KEY
03112 if (getenv("PATHSCALE_LNO_DEBUG"))
03113 #endif
03114 Dump_WN(wn,fp,fancy,2,2,NULL,NULL,NULL,FALSE);
03115 fprintf(fp,"has a def outside the tree: %d\n",
03116 WN_map_id(def1));
03117 #ifdef KEY
03118 if (getenv("PATHSCALE_LNO_DEBUG"))
03119 #endif
03120 if (WN_opcode(def1)==OPC_FUNC_ENTRY)
03121 fprintf(fp,"FUNC_ENTRY\n");
03122 else
03123 Dump_WN(def1,fp,fancy,2,2,NULL,NULL,NULL,FALSE);
03124 }
03125 }
03126 } else if (opr == OPR_LDID) {
03127 fprintf(fp,"WARNING: %s %d [0x%p]",
03128 OPERATOR_name(opr), WN_map_id(wn), wn);
03129 #ifdef KEY
03130 if (getenv("PATHSCALE_LNO_DEBUG"))
03131 #endif
03132 Dump_WN(wn,fp,fancy,2,2,NULL,NULL,NULL,FALSE);
03133 fprintf(fp,"is missing def_list\n");
03134 }
03135 if (Du_Mgr->Du_Get_Use(wn)) {
03136 writes->Push(wn);
03137 USE_LIST* use_list=Du_Mgr->Du_Get_Use(wn);
03138 USE_LIST_ITER u_iter(use_list);
03139 for (DU_NODE *use_node=(DU_NODE *)u_iter.First();
03140 !u_iter.Is_Empty(); use_node=(DU_NODE *)u_iter.Next()) {
03141 WN* use1=use_node->Wn();
03142 if (!h_table->Find(use1)) {
03143 fprintf(fp,"WARNING: Def %d [0x%p]", WN_map_id(wn), wn);
03144 #ifdef KEY
03145 if (getenv("PATHSCALE_LNO_DEBUG"))
03146 #endif
03147 Dump_WN(wn,fp,fancy,2,2,NULL,NULL,NULL,FALSE);
03148 fprintf(fp,"has a use outside the tree: %d [0x%p]\n",
03149 WN_map_id(use1), use1);
03150 #ifdef KEY
03151 if (getenv("PATHSCALE_LNO_DEBUG"))
03152 #endif
03153 Dump_WN(use1,fp,fancy,2,2,NULL,NULL,NULL,FALSE);
03154 }
03155 }
03156 } else if ((opr == OPR_STID) && !TY_is_volatile(WN_ty(wn)) &&
03157 !((ST_class(WN_st(wn)) == CLASS_PREG) &&
03158 Preg_Is_Dedicated(WN_offset(wn)))) {
03159 fprintf(fp,"WARNING: %s %d [0x%p]", OPERATOR_name(opr),
03160 WN_map_id(wn), wn);
03161 #ifdef KEY
03162 if (getenv("PATHSCALE_LNO_DEBUG"))
03163 #endif
03164 Dump_WN(wn,fp,fancy,2,2,NULL,NULL,NULL,FALSE);
03165 fprintf(fp,"is missing use_list\n");
03166 }
03167 }
03168
03169 if (opr==OPR_BLOCK)
03170 for (WN* stmt=WN_first(wn); stmt; stmt=WN_next(stmt))
03171 Du_Sanity_Check_r(stmt,h_table,pass,fp,fancy,reads,writes);
03172 else if ((pass == 0) || (opr != OPR_IO))
03173
03174 for (INT i=0; i<WN_kid_count(wn); i++)
03175 Du_Sanity_Check_r(WN_kid(wn,i),h_table,pass,fp,fancy,reads,writes);
03176 }
03177
03178 static void IV_Loop_Stmt_Check_X(STACK<SYMBOL>& symbols,
03179 STACK<WN*>& loops,
03180 WN* wn)
03181 {
03182 OPERATOR opr = WN_operator(wn);
03183
03184 if (opr == OPR_BLOCK) {
03185 for (WN* w = WN_first(wn); w; w = WN_next(w))
03186 IV_Loop_Stmt_Check_X(symbols, loops, w);
03187 }
03188 else if (opr == OPR_IO)
03189 ;
03190 else if (opr == OPR_DO_LOOP) {
03191 IV_Loop_Stmt_Check_X(symbols, loops, WN_start(wn));
03192 symbols.Push(SYMBOL(WN_index(wn)));
03193 loops.Push(wn);
03194 IV_Loop_Stmt_Check_X(symbols, loops, WN_end(wn));
03195 IV_Loop_Stmt_Check_X(symbols, loops, WN_step(wn));
03196 IV_Loop_Stmt_Check_X(symbols, loops, WN_do_body(wn));
03197 void(symbols.Pop());
03198 void(loops.Pop());
03199 }
03200 else {
03201 for (INT k = 0; k < WN_kid_count(wn); k++)
03202 IV_Loop_Stmt_Check_X(symbols, loops, WN_kid(wn,k));
03203
03204 if (opr == OPR_LDID) {
03205 SYMBOL ldsym = SYMBOL(wn);
03206 for (INT i = symbols.Elements()-1; i >= 0; i--) {
03207 if (symbols.Bottom_nth(i) == ldsym) {
03208 DEF_LIST* dl = Du_Mgr->Ud_Get_Def(wn);
03209 if (dl == NULL) {
03210 DevWarn("Missing def_list for induction variable %s",
03211 ldsym.Name());
03212 }
03213 else if (dl->Loop_stmt() != loops.Bottom_nth(i)) {
03214 if (!dl->Incomplete()) {
03215 DevWarn("Bad loop stmt 0x%p for induction variable %s <fixed>",
03216 dl->Loop_stmt(), ldsym.Name());
03217 dl->Set_loop_stmt(loops.Bottom_nth(i));
03218 }
03219 }
03220 break;
03221 }
03222 }
03223 }
03224 }
03225 }
03226
03227 static void Initialize_Symbols(STACK<SYMBOL>& symbols,
03228 STACK<WN*>& loops,
03229 WN* wn)
03230 {
03231 if (wn) {
03232 Initialize_Symbols(symbols, loops, LWN_Get_Parent(wn));
03233 if (WN_opcode(wn) == OPC_DO_LOOP) {
03234 symbols.Push(SYMBOL(WN_index(wn)));
03235 loops.Push(wn);
03236 }
03237 }
03238 }
03239
03240 void IV_Loop_Stmt_Check(WN* wn, MEM_POOL* pool)
03241 {
03242 STACK<SYMBOL> symbols(pool);
03243 STACK<WN*> loops(pool);
03244 Initialize_Symbols(symbols, loops, LWN_Get_Parent(wn));
03245 IV_Loop_Stmt_Check_X(symbols, loops, wn);
03246 }
03247
03248 void Du_Sanity_Check(WN* wn, FILE* fp, UINT fancy)
03249 {
03250 if (LNO_Verbose)
03251 fprintf(fp, "Begin Du_Sanity_Check ..\n");
03252
03253 MEM_POOL_Push(&LNO_local_pool);
03254 {
03255 IV_Loop_Stmt_Check(wn, &LNO_local_pool);
03256
03257 STACK<WN*> reads(&LNO_local_pool);
03258 STACK<WN*> writes(&LNO_local_pool);
03259
03260 HASH_TABLE<WN*,INT> h_table(256, &LNO_local_pool);
03261 Du_Sanity_Check_r(wn,&h_table,0,fp,fancy,&reads,&writes);
03262 Du_Sanity_Check_r(wn,&h_table,1,fp,fancy,&reads,&writes);
03263 Du_Sanity_Check_Matching_Du(&reads,&writes,fp,fancy);
03264 }
03265 MEM_POOL_Pop(&LNO_local_pool);
03266
03267 if (LNO_Verbose)
03268 fprintf(fp, "End Du_Sanity_Check ..\n");
03269 }
03270
03271 void FB_Sanity_Check(WN *wn)
03272 {
03273 if (Cur_PU_Feedback && LNO_Test_Dump) {
03274 INT32 freq = 0;
03275 LWN_ITER *wniter = LWN_WALK_TreeIter(wn);
03276
03277 while (wniter) {
03278 WN *cur = wniter->wn;
03279 wniter = LWN_WALK_TreeNext(wniter);
03280 freq = WN_MAP32_Get(WN_MAP_FEEDBACK, cur);
03281 if (freq == 0) {
03282 DevWarn("? Missing frequency count for wn=0x%p (opr=%s)",
03283 wn, OPERATOR_name(WN_operator(wn)));
03284 }
03285 }
03286 }
03287 }
03288
03289 BOOL Wn_Is_Inside(WN* inner, const WN* outer)
03290 {
03291 for (WN* wn = inner; wn; wn = LWN_Get_Parent(wn)) {
03292 if (wn == outer)
03293 return TRUE;
03294 }
03295
03296 return FALSE;
03297 }
03298
03299 INT64 LWN_Get_Linenum(const WN *wn)
03300 {
03301 while (wn) {
03302 INT64 line = WN_Get_Linenum(wn);
03303 if (line != 0)
03304 return line;
03305 wn = LWN_Get_Parent(wn);
03306 }
03307
03308 DevWarn("LWN_Get_Linenum() could not find a reasonable line number");
03309 return 0;
03310 }
03311
03312 BOOL Is_Permutation_Vector(const INT order[], INT nloops)
03313 {
03314 INT* save = (INT*) alloca(sizeof(INT)*nloops);
03315 INT i;
03316 for (i = 0; i < nloops; i++)
03317 save[i] = 0;
03318 for (i = 0; i < nloops; i++) {
03319 if (order[i] >= nloops || order[i] < 0)
03320 return FALSE;
03321 if (save[order[i]] != 0)
03322 return FALSE;
03323 save[order[i]] = 1;
03324 }
03325 return TRUE;
03326 }
03327
03328 extern BOOL Are_Permutations(const INT* order1, const INT* order2, INT count)
03329 {
03330
03331
03332 INT i;
03333 for (i = 0; i < count; i++) {
03334 for (INT j = i+1; j < count; j++) {
03335 if (order1[i] == order1[j])
03336 return FALSE;
03337 }
03338 }
03339
03340
03341 for (i = 0; i < count; i++) {
03342 INT j;
03343 for (j = 0; j < count; j++) {
03344 if (order1[i] == order2[j])
03345 break;
03346 }
03347 if (j >= count)
03348 return FALSE;
03349 }
03350
03351 return TRUE;
03352 }
03353
03354
03355
03356
03357
03358
03359
03360 BOOL Is_Loop_Invariant_Use(WN* wn,
03361 WN* outerloop)
03362 {
03363 switch (WN_operator(wn)) {
03364 case OPR_LDID:
03365 case OPR_ILOAD:
03366 case OPR_ISTORE:
03367 case OPR_IO:
03368 case OPR_RETURN:
03369 #ifdef KEY
03370 case OPR_GOTO_OUTER_BLOCK:
03371 #endif
03372 case OPR_CALL:
03373 case OPR_ICALL:
03374 case OPR_INTRINSIC_CALL:
03375 break;
03376 default:
03377 FmtAssert(0, ("Is_Loop_Invariant_Use called with improper node type."));
03378 }
03379
03380 DEF_LIST *def_list = Du_Mgr->Ud_Get_Def(wn);
03381 DEF_LIST_ITER iter(def_list);
03382 const DU_NODE* node = NULL;
03383 for (node = iter.First(); !iter.Is_Empty(); node = iter.Next()) {
03384 WN* def = node->Wn();
03385 if (Wn_Is_Inside(def, outerloop))
03386 return FALSE;
03387 }
03388 return TRUE;
03389 }
03390
03391
03392
03393
03394
03395
03396
03397
03398 BOOL Is_Loop_Invariant_Exp(WN* wn,
03399 WN* outerloop)
03400 {
03401 ARRAY_DIRECTED_GRAPH16* dg = Array_Dependence_Graph;
03402 OPERATOR opr = WN_operator(wn);
03403 if (OPCODE_is_call(WN_opcode(wn)) || opr == OPR_ILOAD) {
03404 if (dg == NULL)
03405 return FALSE;
03406 VINDEX16 v = dg->Get_Vertex(wn);
03407 if (v == 0)
03408 return FALSE;
03409 EINDEX16 e = 0;
03410 for (e = dg->Get_In_Edge(v); e; e = dg->Get_Next_In_Edge(e)) {
03411 VINDEX16 v_source = dg->Get_Source(e);
03412 WN* wn_source = dg->Get_Wn(v_source);
03413 if (Wn_Is_Inside(wn_source, outerloop))
03414 return FALSE;
03415 }
03416 for (INT kid = 0; kid < WN_kid_count(wn); kid++)
03417 if (!Is_Loop_Invariant_Exp(WN_kid(wn, kid), outerloop))
03418 return FALSE;
03419 return TRUE;
03420 } else if (opr == OPR_INTRINSIC_OP
03421 #ifdef KEY
03422 || opr == OPR_PURE_CALL_OP
03423 #endif
03424 ) {
03425 for (INT i = 0; i < WN_kid_count(wn); i++) {
03426 WN* wn_parm_node = WN_kid(wn, i);
03427 if (WN_Parm_By_Reference(wn_parm_node))
03428 return FALSE;
03429 WN* wn_parameter = WN_kid0(wn_parm_node);
03430 if (!Is_Loop_Invariant_Exp(wn_parameter, outerloop))
03431 return FALSE;
03432 }
03433 return TRUE;
03434 } else if (opr == OPR_LDID) {
03435 return Is_Loop_Invariant_Use(wn, outerloop);
03436 } else {
03437 if (!Statically_Safe_Node(wn))
03438 return FALSE;
03439 for (INT kid = 0; kid < WN_kid_count(wn); kid++)
03440 if (!Is_Loop_Invariant_Exp(WN_kid(wn, kid), outerloop))
03441 return FALSE;
03442 return TRUE;
03443 }
03444 }
03445
03446 typedef HASH_TABLE<WN*,WN*> LOOP_MAPPING;
03447
03448
03449
03450
03451
03452 static void SNL_Make_Loop_Mapping_Inside(WN* orig,
03453 WN* copy,
03454 LOOP_MAPPING* ht)
03455 {
03456 Is_True(WN_opcode(orig) == OPC_BLOCK && WN_opcode(copy) == OPC_BLOCK,
03457 ("bad params to SNL_Make_Loop_Mapping_Inside"));
03458
03459 WN* wo = WN_first(orig);
03460 WN* wc = WN_first(copy);
03461
03462 for (;;) {
03463 OPCODE opo;
03464 OPCODE opc;
03465 while (wo && (opo = WN_opcode(wo)) != OPC_DO_LOOP && opo != OPC_IF)
03466 wo = WN_next(wo);
03467 while (wc && (opc = WN_opcode(wc)) != OPC_DO_LOOP && opc != OPC_IF)
03468 wc = WN_next(wc);
03469 if (wo == NULL || wc == NULL) {
03470 FmtAssert(wo == wc, ("Non-identical orig/copy structure"));
03471 break;
03472 }
03473 FmtAssert(opo == opc, ("Bad wo/wc"));
03474 switch (opo) {
03475 case OPC_DO_LOOP:
03476 ht->Enter(wo, wc);
03477 SNL_Make_Loop_Mapping_Inside(WN_do_body(wo), WN_do_body(wc), ht);
03478 break;
03479 case OPC_IF:
03480 SNL_Make_Loop_Mapping_Inside(WN_then(wo), WN_then(wc), ht);
03481 SNL_Make_Loop_Mapping_Inside(WN_else(wo), WN_else(wc), ht);
03482 break;
03483 }
03484 wo = WN_next(wo);
03485 wc = WN_next(wc);
03486 }
03487 }
03488
03489 LOOP_MAPPING* Make_Loop_Mapping(WN* orig,
03490 WN* copy,
03491 MEM_POOL* pool)
03492 {
03493 LOOP_MAPPING* ht = CXX_NEW(LOOP_MAPPING(13, pool), pool);
03494
03495
03496
03497 ht->Enter(orig, copy);
03498 SNL_Make_Loop_Mapping_Inside(WN_do_body(orig), WN_do_body(copy), ht);
03499
03500 return ht;
03501 }
03502
03503 typedef HASH_TABLE<WN*,BOOL> LOOPS_ONLY;
03504
03505 static void Find_Loops_Within_Walk(WN* wn, HASH_TABLE<WN*,BOOL>* ht)
03506 {
03507 switch (WN_operator(wn)) {
03508 case OPR_IF:
03509 Find_Loops_Within_Walk(WN_then(wn), ht);
03510 Find_Loops_Within_Walk(WN_else(wn), ht);
03511 break;
03512 case OPR_DO_LOOP:
03513 ht->Enter(wn, TRUE);
03514 Find_Loops_Within_Walk(WN_do_body(wn), ht);
03515 break;
03516 case OPR_DO_WHILE:
03517 case OPR_WHILE_DO:
03518 Find_Loops_Within_Walk(WN_while_body(wn), ht);
03519 break;
03520 case OPR_BLOCK:
03521 {
03522 for (WN* w = WN_first(wn); w; w = WN_next(w))
03523 Find_Loops_Within_Walk(w, ht);
03524 }
03525 break;
03526 }
03527 }
03528
03529 HASH_TABLE<WN*,BOOL>* Find_Loops_Within(WN* orig, MEM_POOL* pool)
03530 {
03531 LOOPS_ONLY* ht = CXX_NEW(LOOPS_ONLY(13, pool), pool);
03532 Find_Loops_Within_Walk(orig, ht);
03533 return ht;
03534 }
03535
03536
03537 void LS_IN_LOOP::Lexorder(WN* wn, ARRAY_DIRECTED_GRAPH16* dg, INT* lex,
03538 BOOL use_scalars)
03539 {
03540 OPCODE op = WN_opcode(wn);
03541 OPERATOR opr = OPCODE_operator(op);
03542 if (opr == OPR_BLOCK) {
03543 for (WN* w = WN_first(wn); w; w = WN_next(w))
03544 Lexorder(w, dg, lex, use_scalars);
03545 }
03546 else {
03547 for (INT k = 0; k < WN_kid_count(wn); k++)
03548 Lexorder(WN_kid(wn,k), dg, lex, use_scalars);
03549 }
03550
03551 if (OPCODE_is_load(op)
03552 && (opr != OPR_LDID || dg->Get_Vertex(wn) || use_scalars)
03553 || OPCODE_is_store(op)
03554 && (opr != OPR_STID || dg->Get_Vertex(wn) || use_scalars)
03555 || OPCODE_is_call(op)) {
03556 ++(*lex);
03557 _ht.Enter(wn, *lex);
03558 }
03559 }
03560
03561 LS_IN_LOOP::LS_IN_LOOP(WN* loop, ARRAY_DIRECTED_GRAPH16* dg, MEM_POOL* pool,
03562 BOOL use_scalars)
03563 : Loop(loop), _ht(HT_ELTS, pool),
03564 Depth(Do_Depth(loop)), Good_Depth(Good_Do_Depth(loop))
03565 {
03566 INT lexcount = 0;
03567 Lexorder(loop, dg, &lexcount, use_scalars);
03568 }
03569
03570
03571
03572
03573
03574
03575
03576 INT Num_Common_Loops(WN *wn1, WN *wn2)
03577 {
03578 WN* wn = LNO_Common_Loop(wn1, wn2);
03579 return Do_Depth(wn)+1;
03580 }
03581
03582
03583
03584 WN* LNO_Common_Loop(WN *wn1, WN *wn2)
03585 {
03586 WN* l1[LNO_MAX_DO_LOOP_DEPTH];
03587 WN* l2[LNO_MAX_DO_LOOP_DEPTH];
03588 WN *parent;
03589 INT i1 = 0;
03590 INT i2 = 0;
03591
03592 if (WN_opcode(wn1) == OPC_DO_LOOP) {
03593 l1[i1++] = wn1;
03594 }
03595 while ((parent = LWN_Get_Parent(wn1)) != 0) {
03596 if (WN_opcode(parent) == OPC_DO_LOOP) {
03597 if (WN_do_body(parent) == wn1) {
03598 l1[i1++] = parent;
03599 }
03600 }
03601 wn1 = parent;
03602 }
03603
03604 if (WN_opcode(wn2) == OPC_DO_LOOP) {
03605 l2[i2++] = wn2;
03606 }
03607 while ((parent = LWN_Get_Parent(wn2)) != 0) {
03608 if (WN_opcode(parent) == OPC_DO_LOOP) {
03609 if (WN_do_body(parent) == wn2) {
03610 l2[i2++] = parent;
03611 }
03612 }
03613 wn2 = parent;
03614 }
03615
03616 WN* answer = NULL;
03617 while (i1 >= 1 && i2 >= 1 && l1[i1-1] == l2[i2-1]) {
03618 answer = l1[i1-1];
03619 i1--, i2--;
03620 }
03621
03622 return answer;
03623 }
03624
03625
03626
03627
03628
03629
03630
03631
03632 BOOL Equivalent_Access_Arrays(ACCESS_ARRAY *array1,
03633 ACCESS_ARRAY *array2, WN *wn1, WN *wn2)
03634 {
03635 FmtAssert(array1 != NULL && array2 != NULL,
03636 ("Equivalent_Access_Arrays: NULL access array"));
03637
03638 if (!(*array1 == *array2)) {
03639 return FALSE;
03640 }
03641
03642 if ((array1->Non_Const_Loops() == 0) && (array2->Non_Const_Loops() == 0)) {
03643 return (TRUE);
03644 } else {
03645 INT common_loops = Num_Common_Loops(wn1,wn2);
03646 if ((array1->Non_Const_Loops() >= common_loops) ||
03647 (array2->Non_Const_Loops() >= common_loops)) {
03648 return FALSE;
03649 }
03650 }
03651 return TRUE;
03652 }
03653
03654
03655
03656
03657
03658
03659
03660 extern WN* Enclosing_Do_Loop(WN* wn)
03661 {
03662 for (WN* wn_temp = wn; wn_temp != NULL; wn_temp= LWN_Get_Parent(wn_temp))
03663 switch (WN_operator(wn_temp)) {
03664 case OPR_DO_LOOP:
03665 return wn_temp;
03666 }
03667 return NULL;
03668 }
03669
03670
03671
03672
03673
03674
03675
03676 extern WN* Enclosing_Loop(WN* wn)
03677 {
03678 for (WN* wn_temp = wn; wn_temp != NULL; wn_temp= LWN_Get_Parent(wn_temp))
03679 switch (WN_operator(wn_temp)) {
03680 case OPR_DO_LOOP:
03681 case OPR_DO_WHILE:
03682 case OPR_WHILE_DO:
03683 return wn_temp;
03684 }
03685 return NULL;
03686 }
03687
03688
03689
03690
03691
03692
03693
03694 WN* Enclosing_Loop_Body(WN* wn)
03695 {
03696 BOOL saw_block = FALSE;
03697 for (WN* wn_temp = wn; wn_temp != NULL; wn_temp= LWN_Get_Parent(wn_temp)) {
03698 switch (WN_operator(wn_temp)) {
03699 case OPR_DO_LOOP:
03700 case OPR_DO_WHILE:
03701 case OPR_WHILE_DO:
03702 if (saw_block)
03703 return wn_temp;
03704 break;
03705 case OPR_BLOCK:
03706 saw_block = TRUE;
03707 break;
03708 }
03709 }
03710 return NULL;
03711 }
03712
03713
03714
03715
03716
03717
03718
03719 extern WN* Enclosing_Proper_Do_Loop(WN* wn_ref)
03720 {
03721 BOOL found_block = FALSE;
03722 for (WN* wn = wn_ref; wn != NULL; wn = LWN_Get_Parent(wn)) {
03723 if (WN_opcode(wn) == OPC_BLOCK)
03724 found_block = TRUE;
03725 if (WN_opcode(wn) == OPC_DO_LOOP && found_block)
03726 return wn;
03727 }
03728 return NULL;
03729 }
03730
03731
03732
03733
03734
03735
03736
03737 static BOOL Exp_Depends_On_Outer_Loop(WN* wn_exp, SYMBOL index_var,
03738 ARRAY_DIRECTED_GRAPH16* dg, DU_MANAGER* du)
03739 {
03740 if (OPCODE_is_load(WN_opcode(wn_exp)) && SYMBOL(wn_exp) != index_var) {
03741 if (WN_operator(wn_exp) == OPR_LDID) {
03742 DEF_LIST *def_list = du->Ud_Get_Def(wn_exp);
03743 DEF_LIST_ITER iter(def_list);
03744 DU_NODE* dnode = NULL;
03745 for (dnode = iter.First(); !iter.Is_Empty(); dnode = iter.Next()) {
03746 WN* def = dnode->Wn();
03747 if (Enclosing_Loop(def) != NULL)
03748 return TRUE;
03749 }
03750 } else if (WN_operator(wn_exp) == OPR_ILOAD) {
03751 EINDEX16 e = 0;
03752 VINDEX16 v = dg->Get_Vertex(wn_exp);
03753 for (e = dg->Get_Out_Edge(v); e != 0; e = dg->Get_Next_Out_Edge(e)) {
03754 WN* def = dg->Get_Wn(dg->Get_Sink(e));
03755 if (Enclosing_Loop(def) != NULL)
03756 return TRUE;
03757 }
03758 }
03759 } else {
03760 for (INT i = 0; i < WN_kid_count(wn_exp); i++) {
03761 if (Exp_Depends_On_Outer_Loop(WN_kid(wn_exp, i), index_var, dg, du))
03762 return TRUE;
03763 }
03764 }
03765 return FALSE;
03766 }
03767
03768
03769
03770
03771
03772
03773 BOOL Loop_Is_Trapezoidal(WN* wn_loop,
03774 ARRAY_DIRECTED_GRAPH16* dg,
03775 DU_MANAGER* du)
03776 {
03777 SYMBOL index_var(WN_start(wn_loop));
03778
03779 if (Exp_Depends_On_Outer_Loop(WN_start(wn_loop), index_var, dg, du))
03780 return TRUE;
03781 if (Exp_Depends_On_Outer_Loop(WN_end(wn_loop), index_var, dg, du))
03782 return TRUE;
03783 if (Exp_Depends_On_Outer_Loop(WN_step(wn_loop), index_var, dg, du))
03784 return TRUE;
03785 return FALSE;
03786 }
03787
03788
03789
03790
03791
03792
03793
03794 void Remove_Redundant_Stids(WN* wn_start,
03795 DU_MANAGER* du)
03796 {
03797 if (WN_operator(wn_start) == OPR_STID) {
03798 USE_LIST *use_list = du->Du_Get_Use(wn_start);
03799 if (use_list == NULL) {
03800 LWN_Delete_Tree(LWN_Extract_From_Block(wn_start));
03801 } else if (!use_list->Incomplete()) {
03802 USE_LIST_ITER iter(use_list);
03803 if (iter.First() == NULL) {
03804 LWN_Delete_Tree(LWN_Extract_From_Block(wn_start));
03805 }
03806 }
03807 return;
03808 }
03809
03810 if (WN_opcode(wn_start) == OPC_BLOCK) {
03811 WN* wn_next = NULL;
03812 for (WN* wn = WN_first(wn_start); wn != NULL; wn = wn_next) {
03813 wn_next = WN_next(wn);
03814 Remove_Redundant_Stids(wn, du);
03815 }
03816 } else {
03817 for (INT i = 0; i < WN_kid_count(wn_start); i++)
03818 Remove_Redundant_Stids(WN_kid(wn_start, i), du);
03819 }
03820 }
03821
03822
03823
03824
03825
03826
03827
03828 extern OPCODE Matching_Load_Opcode(OPCODE store_op)
03829 {
03830 FmtAssert(OPCODE_is_store(store_op), ("Bad opcode: Matching_Load_Opcode"));
03831 OPERATOR store_opr = OPCODE_operator(store_op);
03832 OPERATOR load_opr = OPERATOR_FIRST;
03833 switch (store_opr) {
03834 case OPR_STID:
03835 load_opr = OPR_LDID;
03836 break;
03837 case OPR_ISTORE:
03838 load_opr = OPR_ILOAD;
03839 break;
03840 case OPR_ISTOREX:
03841 load_opr = OPR_ILOADX;
03842 break;
03843 case OPR_MSTORE:
03844 load_opr = OPR_MLOAD;
03845 break;
03846 default:
03847 FmtAssert(0, ("Bad opcode: Matching_Load_Opcode"));
03848 }
03849 OPCODE load_op = OPCODE_make_op(load_opr, Promote_Type(OPCODE_desc(store_op)), OPCODE_desc(store_op));
03850 FmtAssert(OPCODE_is_load(load_op), ("Bad opcode: Matching_Load_Opcode"));
03851 return load_op;
03852 }
03853
03854
03855
03856
03857
03858
03859
03860
03861 extern WN* Create_ILoad_From_IStore(WN* wn_store,
03862 DU_MANAGER* du,
03863 ARRAY_DIRECTED_GRAPH16* dg)
03864 {
03865 WN* wn_array = LWN_Copy_Tree(WN_kid1(wn_store));
03866 if (du != NULL)
03867 LWN_Copy_Def_Use(WN_kid1(wn_store), wn_array, du);
03868 dg->Add_Deps_To_Copy_Block(WN_kid1(wn_store), wn_array);
03869 OPCODE loadop = Matching_Load_Opcode(WN_opcode(wn_store));
03870 WN* wn_load = LWN_CreateIload(loadop, WN_offset(wn_store),
03871 TY_pointed(WN_ty(wn_store)), WN_ty(wn_store), wn_array);
03872 Duplicate_alias_info(Alias_Mgr, wn_store, wn_load);
03873 return wn_load;
03874 }
03875
03876 BOOL Is_Local_Array_Reference(WN* array)
03877 {
03878 if (WN_operator(array) != OPR_ARRAY)
03879 return FALSE;
03880
03881 WN* base = WN_array_base(array);
03882 OPERATOR base_oper = WN_operator(base);
03883 if ((base_oper == OPR_LDID) || (base_oper == OPR_LDA)) {
03884 ST *st = WN_st(base);
03885 #ifdef _NEW_SYMTAB
03886 if (ST_level(st) == CURRENT_SYMTAB &&
03887 ST_base_idx(st) == ST_st_idx(st))
03888 #else
03889 if (ST_symtab_id(st) == SYMTAB_id(Current_Symtab) &&
03890 ST_sclass(st) != SCLASS_BASED)
03891 #endif
03892 return TRUE;
03893 }
03894 return FALSE;
03895 }
03896
03897 #ifdef Is_True_On
03898 void LNO_Check_Graph(ARRAY_DIRECTED_GRAPH16* dg)
03899 {
03900 dg->Check_Graph();
03901
03902 for (EINDEX16 e = dg->Get_Edge(); e; e = dg->Get_Next_Edge(e)) {
03903 VINDEX16 v1 = dg->Get_Source(e);
03904 VINDEX16 v2 = dg->Get_Sink(e);
03905 FmtAssert(v1 != 0 && v2 != 0, ("missing source or sink for edge=%d", e));
03906 WN* wn1 = dg->Get_Wn(v1);
03907 WN* wn2 = dg->Get_Wn(v2);
03908 FmtAssert(wn1 && wn2, ("missing Get_Wn() mapping"));
03909 OPCODE o1 = WN_opcode(wn1);
03910 OPCODE o2 = WN_opcode(wn2);
03911 WN* common = LNO_Common_Loop(wn1, wn2);
03912 INT dgood = Good_Do_Depth(common);
03913 DEPV_ARRAY* dv_array = dg->Depv_Array(e);
03914
03915 FmtAssert(OPCODE_is_load(o1) || OPCODE_is_store(o1) || OPCODE_is_call(o1),
03916 ("Bad opcode for vertex"));
03917 FmtAssert(OPCODE_is_load(o2) || OPCODE_is_store(o2) || OPCODE_is_call(o2),
03918 ("Bad opcode for vertex"));
03919 FmtAssert(dgood + 1 == dv_array->Num_Dim(),
03920 ("LNO dep graph check fails: e=%d good=%d components=%d",
03921 e, dgood, dv_array->Num_Dim()));
03922 }
03923 }
03924
03925 extern void MP_Sanity_Check_Func(WN *wn)
03926 {
03927 OPCODE opcode = WN_opcode(wn);
03928 if (opcode == OPC_BLOCK) {
03929 for (WN* tmp = WN_first(wn); tmp != NULL; tmp = WN_next(tmp)) {
03930 MP_Sanity_Check_Func(tmp);
03931 }
03932 } else {
03933 if ((opcode == OPC_DO_LOOP) && Do_Loop_Is_Mp(wn)) {
03934 FmtAssert(WN_opcode(LWN_Get_Parent(LWN_Get_Parent(wn))) == OPC_REGION,
03935 ("MP Do loop with a non-region grandparent 0x%p",wn));
03936 }
03937 for (INT i = 0; i < WN_kid_count(wn); i++) {
03938 MP_Sanity_Check_Func(WN_kid(wn,i));
03939 }
03940 }
03941 }
03942
03943 #endif
03944
03945 extern BOOL Is_Mp_Region(WN *wn)
03946 {
03947 if (WN_opcode(wn) == OPC_REGION) {
03948 RID *rid = REGION_get_rid(wn);
03949 FmtAssert(rid != NULL, ("Is_Mp_Region(): Missing rid"));
03950 if (RID_TYPE_mp(rid)) return TRUE;
03951 }
03952 return FALSE;
03953 }
03954
03955 #ifdef KEY
03956 extern BOOL Is_Eh_Or_Try_Region(WN *wn)
03957 {
03958 if (WN_opcode(wn) == OPC_REGION) {
03959 RID *rid = REGION_get_rid(wn);
03960 FmtAssert(rid != NULL, ("Is_Eh_Or_Try_Region(): Missing rid"));
03961 if (RID_TYPE_eh(rid) || RID_TYPE_try(rid)) return TRUE;
03962 }
03963 return FALSE;
03964 }
03965 #endif
03966
03967 extern BOOL Do_Loop_Is_Mp(WN *wn)
03968 {
03969 if (LWN_Get_Parent(wn) == NULL)
03970 return FALSE;
03971 WN* wn_region = LWN_Get_Parent(LWN_Get_Parent(wn));
03972 #ifdef KEY
03973 if (PU_cxx_lang(Get_Current_PU()) && Is_Eh_Or_Try_Region(wn_region))
03974 wn_region = LWN_Get_Parent(LWN_Get_Parent(wn_region));
03975 #endif
03976 if (!Is_Mp_Region(wn_region))
03977 return FALSE;
03978 WN* wn_pragma = WN_first(WN_region_pragmas(wn_region));
03979 if (wn_pragma == NULL)
03980 return FALSE;
03981 if (WN_opcode(wn_pragma) == OPC_PRAGMA
03982 && (WN_pragma(wn_pragma) == WN_PRAGMA_DOACROSS
03983 || WN_pragma(wn_pragma) == WN_PRAGMA_PDO_BEGIN
03984 || WN_pragma(wn_pragma) == WN_PRAGMA_PARALLEL_DO))
03985 return TRUE;
03986 DO_LOOP_INFO* dli = Get_Do_Loop_Info(wn);
03987 if (dli != NULL && dli->Mp_Info != NULL)
03988 return TRUE;
03989 return FALSE;
03990 }
03991
03992 extern RID * Get_Enclosing_Region_ID(WN *wn)
03993 {
03994 Is_True(wn!=NULL,("Get_Enclosing_Region_ID: Null wn pointer"));
03995 WN *pwn = LWN_Get_Parent(wn);
03996 while (pwn && WN_operator(pwn) != OPR_REGION &&
03997 WN_operator(pwn) != OPR_FUNC_ENTRY)
03998 pwn = LWN_Get_Parent(pwn);
03999 return REGION_get_rid(pwn);
04000 }
04001
04002 extern BOOL Is_Nested_Doacross(WN* wn_loop)
04003 {
04004 DO_LOOP_INFO* dli = Get_Do_Loop_Info(wn_loop);
04005 return dli->Mp_Info != NULL && dli->Mp_Info->Nest_Total() > 1;
04006 }
04007
04008
04009
04010 extern void Remark_Depth(WN *wn, mUINT8 depth)
04011 {
04012 WN *kid;
04013 DO_LOOP_INFO *dli;
04014
04015 Is_True(wn,("Null wn in Remark_Depth"));
04016
04017 OPCODE opcode = WN_opcode(wn);
04018
04019 if (opcode == OPC_BLOCK) {
04020 kid = WN_first (wn);
04021 while (kid) {
04022 Remark_Depth(kid,depth);
04023 kid = WN_next(kid);
04024 }
04025 return;
04026 }
04027
04028 if (opcode == OPC_DO_LOOP) {
04029 dli = (DO_LOOP_INFO *) WN_MAP_Get(LNO_Info_Map,wn);
04030 Is_True(dli,("no mapping in Remark_Depth"));
04031 dli->Depth = depth;
04032 depth++;
04033 }
04034
04035 for (INT kidno=0; kidno<WN_kid_count(wn); kidno++) {
04036 kid = WN_kid(wn,kidno);
04037 Remark_Depth(kid,depth);
04038 }
04039
04040 }
04041
04042 WN* UBexp(WN* end, BOOL* ne)
04043 {
04044 OPERATOR opr = WN_operator(end);
04045
04046 switch (opr) {
04047 case OPR_GE:
04048 if (ne) *ne = FALSE;
04049 return WN_kid0(end);
04050 case OPR_GT:
04051 if (ne) *ne = TRUE;
04052 return WN_kid0(end);
04053 case OPR_LE:
04054 if (ne) *ne = FALSE;
04055 return WN_kid1(end);
04056 case OPR_LT:
04057 if (ne) *ne = TRUE;
04058 return WN_kid1(end);
04059 default:
04060 return NULL;
04061 }
04062 }
04063
04064 WN* UBvar(WN* end)
04065 {
04066 WN* wn_index = NULL;
04067 OPERATOR opr = WN_operator(end);
04068 switch (opr) {
04069 case OPR_LE:
04070 case OPR_LT:
04071 wn_index = WN_kid0(end);
04072 break;
04073 case OPR_GE:
04074 case OPR_GT:
04075 wn_index = WN_kid1(end);
04076 break;
04077 default:
04078 return NULL;
04079 }
04080 if (WN_operator(wn_index) != OPR_LDID)
04081 return NULL;
04082 WN *wn;
04083 for (wn = end; wn != NULL; wn = LWN_Get_Parent(wn))
04084 if (WN_opcode(wn) == OPC_DO_LOOP)
04085 break;
04086 if (wn == NULL)
04087 return NULL;
04088 if (SYMBOL(WN_index(wn)) != SYMBOL(wn_index))
04089 return NULL;
04090 return wn_index;
04091 }
04092
04093 INT Loop_Depth(WN* stat)
04094 {
04095 for (WN* wn = stat; wn != NULL; wn = LWN_Get_Parent(wn))
04096 if (WN_opcode(wn) == OPC_DO_LOOP)
04097 return Do_Loop_Depth(wn);
04098 return -1;
04099 }
04100
04101 INT Block_Loop_Depth(WN* stat)
04102 {
04103 BOOL found_block = FALSE;
04104 for (WN* wn = stat; wn != NULL; wn = LWN_Get_Parent(wn)) {
04105 if (WN_opcode(wn) == OPC_BLOCK)
04106 found_block = TRUE;
04107 if (found_block && WN_opcode(wn) == OPC_DO_LOOP)
04108 return Do_Loop_Depth(wn);
04109 }
04110 return -1;
04111 }
04112
04113
04114
04115
04116
04117
04118
04119
04120 void Add_Pragma_To_MP_Region (const WN* cwn,
04121 ST* st,
04122 WN_OFFSET offset,
04123 WN_PRAGMA_ID pragma_id,
04124 BOOL make_compiler_generated) {
04125 Is_True (pragma_id == WN_PRAGMA_LOCAL ||
04126 pragma_id == WN_PRAGMA_SHARED ||
04127 pragma_id == WN_PRAGMA_LASTLOCAL ||
04128 pragma_id == WN_PRAGMA_FIRSTPRIVATE ||
04129 pragma_id == WN_PRAGMA_LASTTHREAD,
04130 ("Add_Pragma_To_MP_Region: Unknown pragma_id"));
04131
04132 WN* wn = (WN*) cwn;
04133 while (wn) {
04134 if (Is_Mp_Region(wn)) break;
04135 wn = LWN_Get_Parent (wn);
04136 }
04137 if (wn == NULL) return;
04138 #ifdef Is_True_On
04139 {
04140
04141 BOOL new_is_local = (pragma_id == WN_PRAGMA_LOCAL ||
04142 pragma_id == WN_PRAGMA_FIRSTPRIVATE ||
04143 pragma_id == WN_PRAGMA_LASTLOCAL);
04144 BOOL new_is_shared = (pragma_id == WN_PRAGMA_SHARED);
04145 if (new_is_local || new_is_shared) {
04146 WN* orig_wn = WN_first(WN_region_pragmas(wn));
04147 while (orig_wn) {
04148 Is_True (WN_operator(orig_wn) == OPR_PRAGMA ||
04149 WN_operator(orig_wn) == OPR_XPRAGMA,
04150 ("Node in MP-region pragma list not pragma or xpragma"));
04151
04152 WN_PRAGMA_ID orig_pragma_id = (WN_PRAGMA_ID) WN_pragma(orig_wn);
04153 BOOL orig_is_local = (orig_pragma_id == WN_PRAGMA_LOCAL ||
04154 orig_pragma_id == WN_PRAGMA_FIRSTPRIVATE ||
04155 orig_pragma_id == WN_PRAGMA_LASTLOCAL);
04156 BOOL orig_is_shared = (orig_pragma_id == WN_PRAGMA_SHARED);
04157 if ((orig_is_local || orig_is_shared) &&
04158 (WN_st(orig_wn) == st) && (WN_pragma_arg1(orig_wn) == offset)) {
04159
04160
04161 Is_True ((new_is_local && orig_is_local) ||
04162 (new_is_shared && orig_is_shared),
04163 ("Add_Pragma_To_MP_Region: adding %s (%s,%s), already in %s list\n",
04164 WN_pragmas[pragma_id].name,
04165 ST_name(st),
04166 (ST_class(st) == CLASS_PREG ? Preg_Name(offset) : ""),
04167 WN_pragmas[orig_pragma_id].name));
04168 }
04169 orig_wn = WN_next(orig_wn);
04170 }
04171 }
04172 }
04173 #endif
04174
04175 if (pragma_id == WN_PRAGMA_LOCAL) {
04176
04177
04178
04179
04180
04181 WN_VECTOR wnv(Malloc_Mem_Pool);
04182
04183 WN *tmp = wn;
04184 while (tmp) {
04185 if (WN_opcode(tmp) == OPC_REGION &&
04186 RID_TYPE_mp(REGION_get_rid(tmp))) {
04187 wnv.push_back (tmp);
04188 }
04189 tmp = LWN_Get_Parent(tmp);
04190 }
04191
04192 Add_Pragma_To_MP_Regions (&wnv, WN_PRAGMA_LOCAL,
04193 st, offset, Parent_Map,
04194 make_compiler_generated);
04195 return;
04196 }
04197
04198
04199
04200
04201 {
04202 WN* curr_wn = WN_first(WN_region_pragmas(wn));
04203 while (curr_wn) {
04204 WN_PRAGMA_ID curr_pragma_id = (WN_PRAGMA_ID) WN_pragma(curr_wn);
04205 if (WN_operator(curr_wn) == OPR_PRAGMA &&
04206 curr_pragma_id == pragma_id &&
04207 WN_st(curr_wn) == st &&
04208 WN_pragma_arg1(curr_wn) == offset) {
04209
04210 if (make_compiler_generated) {
04211 WN_set_pragma_compiler_generated(curr_wn);
04212 }
04213 return;
04214 }
04215 curr_wn = WN_next(curr_wn);
04216 }
04217 }
04218
04219 WN* pwn = WN_CreatePragma (pragma_id, st, offset, 0);
04220 WN_Set_Linenum(pwn, WN_Get_Linenum(wn));
04221 LWN_Insert_Block_Before (WN_region_pragmas(wn), NULL, pwn);
04222 if (make_compiler_generated) {
04223 WN_set_pragma_compiler_generated(pwn);
04224 }
04225 }
04226
04227 extern void Update_MP_Local_Var(ST* st, WN_OFFSET offset, WN *wn)
04228 {
04229
04230
04231
04232
04233 WN_VECTOR wnv(Malloc_Mem_Pool);
04234
04235 WN *tmp = wn;
04236 while (tmp) {
04237 if (WN_opcode(tmp) == OPC_REGION &&
04238 RID_TYPE_mp(REGION_get_rid(tmp))) {
04239 wnv.push_back (tmp);
04240 }
04241 tmp = LWN_Get_Parent(tmp);
04242 }
04243
04244 Add_Pragma_To_MP_Regions (&wnv, WN_PRAGMA_LOCAL,
04245 st, offset, Parent_Map,
04246 FALSE);
04247 }
04248
04249
04250
04251
04252
04253
04254
04255
04256 static WN* Unique_Stid_Definition(WN* wn_ldid,
04257 DU_MANAGER* du)
04258 {
04259 FmtAssert(WN_operator(wn_ldid) == OPR_LDID,
04260 ("Unique_Stid_Definition() should be called with LDID"));
04261 DEF_LIST *def_list = du->Ud_Get_Def(wn_ldid);
04262 DEF_LIST_ITER iter(def_list);
04263 if (def_list == NULL || def_list->Incomplete())
04264 return NULL;
04265 WN* unique_def = NULL;
04266 DU_NODE* node = NULL;
04267 for (node = iter.First(); !iter.Is_Empty(); node = iter.Next()) {
04268 WN* def = node->Wn();
04269 if (unique_def == NULL)
04270 unique_def = def;
04271 else
04272 return NULL;
04273 }
04274 return WN_operator(unique_def) == OPR_STID
04275 ? unique_def : NULL;
04276 }
04277
04278
04279
04280
04281
04282
04283
04284
04285
04286 static BOOL Symbol_In_Expression(WN* wn_exp,
04287 SYMBOL sym,
04288 DU_MANAGER* du)
04289 {
04290 if (WN_operator(wn_exp) == OPR_LDID) {
04291 if (SYMBOL(wn_exp) == sym)
04292 return TRUE;
04293 WN* wn_stid = Unique_Stid_Definition(wn_exp, du);
04294 if (wn_stid != NULL)
04295 return Symbol_In_Expression(WN_kid0(wn_stid), sym, du);
04296 }
04297 for (INT i = 0; i < WN_kid_count(wn_exp); i++)
04298 if (Symbol_In_Expression(WN_kid(wn_exp, i), sym, du))
04299 return TRUE;
04300 return FALSE;
04301 }
04302
04303
04304
04305
04306
04307
04308
04309
04310
04311 static WN* Unique_Ldid_Symbol(WN* wn_exp,
04312 DU_MANAGER* du)
04313 {
04314 if (WN_operator(wn_exp) == OPR_LDID) {
04315 WN* wn_stid = Unique_Stid_Definition(wn_exp, du);
04316 FmtAssert(!Wn_Is_Inside(wn_exp, wn_stid), ("Exp inside def"));
04317 if (wn_stid != NULL)
04318 return Unique_Ldid_Symbol(WN_kid0(wn_stid), du);
04319 return wn_exp;
04320 }
04321 WN* wn_unique = NULL;
04322 for (INT i = 0; i < WN_kid_count(wn_exp); i++) {
04323 WN* wn = Unique_Ldid_Symbol(WN_kid(wn_exp, i), du);
04324 if (wn_unique == NULL)
04325 wn_unique = wn;
04326 else if (wn != NULL)
04327 return NULL;
04328 }
04329 return wn_unique;
04330 }
04331
04332
04333
04334
04335
04336
04337
04338
04339 static WN* Wind_Down_Parent(WN* wn_loop,
04340 DU_MANAGER* du)
04341 {
04342 WN* wn_ldid = WN_kid0(WN_start(wn_loop));
04343 if (WN_operator(wn_ldid) != OPR_LDID)
04344 return NULL;
04345 DEF_LIST *def_list = du->Ud_Get_Def(wn_ldid);
04346 DEF_LIST_ITER iter(def_list);
04347 if (def_list->Incomplete())
04348 return NULL;
04349 INT def_count = 0;
04350 DU_NODE* node = NULL;
04351 WN* wn_loop_parent = NULL;
04352 for (node = iter.First(); !iter.Is_Empty(); node = iter.Next()) {
04353 WN* def = node->Wn();
04354 if (++def_count > 2)
04355 return NULL;
04356 if (LWN_Get_Parent(def) == NULL)
04357 return NULL;
04358 if (WN_opcode(LWN_Get_Parent(def)) != OPC_DO_LOOP)
04359 return NULL;
04360 if (Do_Loop_Depth(LWN_Get_Parent(def)) != Do_Loop_Depth(wn_loop))
04361 return NULL;
04362 if (wn_loop_parent == NULL)
04363 wn_loop_parent = LWN_Get_Parent(def);
04364 else if (wn_loop_parent != LWN_Get_Parent(def))
04365 return NULL;
04366 }
04367 return wn_loop_parent;
04368 }
04369
04370
04371
04372
04373
04374
04375
04376
04377
04378
04379
04380
04381 static WN* Normal_Outer_Tile(WN* wn_loop,
04382 DU_MANAGER* du)
04383 {
04384 WN* wn_original = Wind_Down_Parent(wn_loop, du);
04385 if (wn_original != NULL)
04386 return Outer_Tile(wn_original, du);
04387 WN* wn_ldid = Unique_Ldid_Symbol(WN_start(wn_loop), du);
04388 if (wn_ldid == NULL)
04389 return NULL;
04390 if (!Symbol_In_Expression(WN_end(wn_loop), SYMBOL(wn_ldid), du))
04391 return NULL;
04392 for (WN* wn = LWN_Get_Parent(wn_loop); wn != NULL; wn = LWN_Get_Parent(wn))
04393 if (WN_opcode(wn) == OPC_DO_LOOP && SYMBOL(WN_index(wn)) == SYMBOL(wn_ldid))
04394 return wn;
04395 return NULL;
04396 }
04397
04398
04399
04400
04401
04402
04403
04404
04405
04406
04407 extern WN* Outer_Tile(WN* wn_loop,
04408 DU_MANAGER* du)
04409 {
04410 WN* wn_normal_loop = Normal_Outer_Tile(wn_loop, du);
04411 DO_LOOP_INFO *dli_loop = Get_Do_Loop_Info(wn_loop);
04412 if (dli_loop->Lego_Mp_Key_Lower == 0)
04413 return wn_normal_loop;
04414 if (dli_loop->Lego_Mp_Key_Lower < dli_loop->Lego_Mp_Key_Upper)
04415 return wn_normal_loop;
04416 WN *wn;
04417 for (wn = LWN_Get_Parent(wn_loop); wn != NULL; wn = LWN_Get_Parent(wn)) {
04418 if (WN_opcode(wn) != OPC_DO_LOOP)
04419 continue;
04420 DO_LOOP_INFO* dli = Get_Do_Loop_Info(wn);
04421 if (dli->Lego_Mp_Key_Lower == 0)
04422 continue;
04423 if (dli_loop->Lego_Mp_Key_Lower < dli->Lego_Mp_Key_Lower
04424 || dli_loop->Lego_Mp_Key_Lower > dli->Lego_Mp_Key_Upper)
04425 continue;
04426 break;
04427 }
04428 if (wn == NULL)
04429 return wn_normal_loop;
04430 return Do_Depth(wn) < Do_Depth(wn_normal_loop)
04431 ? wn_normal_loop : wn;
04432 }
04433
04434
04435
04436
04437
04438
04439 extern WN* Return_Node(WN* wn_func_nd)
04440 {
04441 WN* wn_first = WN_first(WN_func_body(wn_func_nd));
04442 WN* wn_return = NULL;
04443 WN* wnn = NULL;
04444 for (WN* wn = wn_first; wn != NULL; wnn = wn, wn = WN_next(wn))
04445 if (WN_opcode(wn) == OPC_RETURN)
04446 wn_return = wn;
04447 if (wn_return == NULL) {
04448 wn_return = LWN_CreateReturn();
04449 LWN_Insert_Block_After(LWN_Get_Parent(wnn), wnn, wn_return);
04450 }
04451 return wn_return;
04452 }
04453
04454
04455
04456
04457
04458
04459 extern WN* Loop_Step(WN* wn_loop)
04460 {
04461 FmtAssert(WN_opcode(wn_loop) == OPC_DO_LOOP,
04462 ("Must be a do loop to find the step"));
04463 WN* wn_add = WN_kid0(WN_step(wn_loop));
04464 FmtAssert(WN_operator(wn_add) == OPR_ADD,
04465 ("Step must be incremented with OPR_ADD node."));
04466 return (WN_operator(WN_kid0(wn_add)) == OPR_LDID
04467 && SYMBOL(WN_kid0(wn_add)) == SYMBOL(WN_step(wn_loop)))
04468 ? WN_kid1(wn_add) : WN_kid0(wn_add);
04469 }
04470
04471
04472
04473
04474
04475
04476
04477
04478 extern WN* Common_Loop_Ancestor(WN* wn1, WN* wn2)
04479 {
04480 DOLOOP_STACK stack1(&LNO_local_pool);
04481 DOLOOP_STACK stack2(&LNO_local_pool);
04482 Build_Doloop_Stack(wn1, &stack1);
04483 Build_Doloop_Stack(wn2, &stack2);
04484 if (stack1.Elements() == 0 || stack2.Elements() == 0)
04485 return NULL;
04486 WN* wn_deepest = NULL;
04487 for (INT i = 0; i < stack1.Elements(); i++) {
04488 if (i == stack2.Elements())
04489 return wn_deepest;
04490 WN* wn1 = stack1.Bottom_nth(i);
04491 WN* wn2 = stack2.Bottom_nth(i);
04492 FmtAssert(Do_Depth(wn1) == i && Do_Depth(wn2) == i,
04493 ("Build_Loop_Stack() returned unexpected do depths"));
04494 if (wn1 != wn2)
04495 return wn_deepest;
04496 wn_deepest = wn1;
04497 }
04498 return wn_deepest;
04499 }
04500
04501
04502
04503
04504
04505
04506
04507 extern void Build_Parent_Stack(WN* wn, STACK<WN*>* stack)
04508 {
04509 if (!wn)
04510 return;
04511 Build_Parent_Stack(LWN_Get_Parent(wn), stack);
04512 stack->Push(wn);
04513 }
04514
04515
04516
04517
04518
04519
04520
04521
04522 extern WN* Common_Ancestor(WN* wn1, WN* wn2)
04523 {
04524 STACK<WN*> stack1(&LNO_local_pool);
04525 STACK<WN*> stack2(&LNO_local_pool);
04526 Build_Parent_Stack(wn1, &stack1);
04527 Build_Parent_Stack(wn2, &stack2);
04528 if (stack1.Elements() == 0 || stack2.Elements() == 0)
04529 return NULL;
04530 WN* wn_deepest = NULL;
04531 for (INT i = 0; i < stack1.Elements(); i++) {
04532 if (i == stack2.Elements())
04533 return wn_deepest;
04534 WN* wn1 = stack1.Bottom_nth(i);
04535 WN* wn2 = stack2.Bottom_nth(i);
04536 if (wn1 != wn2)
04537 return wn_deepest;
04538 wn_deepest = wn1;
04539 }
04540 return wn_deepest;
04541 }
04542
04543
04544
04545
04546
04547
04548
04549 extern BOOL Is_Lex_Before(WN* wn1, WN* wn2)
04550 {
04551 WN* wn_common = Common_Ancestor(wn1, wn2);
04552 if (wn_common == wn1)
04553 return FALSE;
04554 if (wn_common == wn2)
04555 return TRUE;
04556 WN* wn1_before = NULL;
04557 for (WN* wnn1 = wn1; wnn1 != wn_common; wnn1 = LWN_Get_Parent(wnn1))
04558 wn1_before = wnn1;
04559 WN* wn2_before = NULL;
04560 for (WN* wnn2 = wn2; wnn2 != wn_common; wnn2 = LWN_Get_Parent(wnn2))
04561 wn2_before = wnn2;
04562 if (WN_opcode(wn_common) == OPC_BLOCK) {
04563 for (WN* wn = WN_first(wn_common); wn != NULL; wn = WN_next(wn)) {
04564 if (wn == wn1_before)
04565 return TRUE;
04566 if (wn == wn2_before)
04567 return FALSE;
04568 }
04569 } else {
04570 for (INT i = 0; i < WN_kid_count(wn_common); i++) {
04571 if (WN_kid(wn_common, i) == wn1_before)
04572 return TRUE;
04573 if (WN_kid(wn_common, i) == wn2_before)
04574 return FALSE;
04575 }
04576 }
04577 FmtAssert(FALSE, ("Is_Lex_Before: Should have found answer by now"));
04578 return FALSE;
04579 }
04580
04581
04582
04583
04584
04585
04586
04587 extern WN* Find_Node(SYMBOL sym,
04588 WN* wn_tree)
04589 {
04590 if (OPCODE_has_sym(WN_opcode(wn_tree)) && SYMBOL(wn_tree) == sym)
04591 return wn_tree;
04592 if (WN_opcode(wn_tree) == OPC_BLOCK) {
04593 for (WN* wn = WN_first(wn_tree); wn != NULL; wn = WN_next(wn)) {
04594 WN* wn_result = Find_Node(sym, wn);
04595 if (wn_result != NULL)
04596 return wn_result;
04597 }
04598 } else {
04599 for (INT i = 0; i < WN_kid_count(wn_tree); i++) {
04600 WN* wn_result = Find_Node(sym, WN_kid(wn_tree, i));
04601 if (wn_result != NULL)
04602 return wn_result;
04603 }
04604 }
04605 return NULL;
04606 }
04607
04608
04609
04610
04611
04612
04613
04614 extern BOOL Identity_Permutation(INT permutation[],
04615 INT nloops)
04616 {
04617 for (INT i = 0; i < nloops; i++)
04618 if (permutation[i] != i)
04619 return FALSE;
04620 return TRUE;
04621 }
04622
04623 extern WN* Trip_Count(WN* wn_loop)
04624 {
04625 DU_MANAGER* du = Du_Mgr;
04626 ARRAY_DIRECTED_GRAPH16* dg = Array_Dependence_Graph;
04627
04628 Upper_Bound_Standardize(WN_end(wn_loop), FALSE);
04629 TYPE_ID index_type = Promote_Type(Do_Wtype((WN *) wn_loop));
04630 WN* wn_kid0 = WN_kid0(WN_end(wn_loop));
04631 BOOL was_kid0 = WN_operator(wn_kid0) == OPR_LDID
04632 && SYMBOL(wn_kid0) == SYMBOL(WN_index(wn_loop));
04633
04634 WN* wn_trip = NULL;
04635 WN* wn_init = WN_kid0(WN_start(wn_loop));
04636 WN* wn_limit = was_kid0 ? WN_kid1(WN_end(wn_loop))
04637 : WN_kid0(WN_end(wn_loop));
04638 WN* wn_stride = Loop_Step(wn_loop);
04639
04640 WN* wn_cp_init = LWN_Copy_Tree(wn_init);
04641 LWN_Copy_Def_Use(wn_init, wn_cp_init, du);
04642 dg->Add_Deps_To_Copy_Block(wn_init, wn_cp_init, FALSE);
04643
04644 WN* wn_cp_limit = LWN_Copy_Tree(wn_limit);
04645 LWN_Copy_Def_Use(wn_limit, wn_cp_limit, du);
04646 dg->Add_Deps_To_Copy_Block(wn_limit, wn_cp_limit, FALSE);
04647
04648 WN* wn_cp_stride = LWN_Copy_Tree(wn_stride);
04649 LWN_Copy_Def_Use(wn_stride, wn_cp_stride, du);
04650 dg->Add_Deps_To_Copy_Block(wn_stride, wn_cp_stride, FALSE);
04651
04652 WN* wn_cp_stride2 = LWN_Copy_Tree(wn_stride);
04653 LWN_Copy_Def_Use(wn_stride, wn_cp_stride2, du);
04654 dg->Add_Deps_To_Copy_Block(wn_stride, wn_cp_stride2, FALSE);
04655
04656 BOOL unity_stride
04657 = WN_operator(wn_cp_stride2) == OPR_INTCONST
04658 && (WN_const_val(wn_cp_stride2) == 1 || WN_const_val(wn_cp_stride2) == -1);
04659
04660 if (((WN_operator(WN_end(wn_loop)) == OPR_LT) && was_kid0) ||
04661 ((WN_operator(WN_end(wn_loop)) == OPR_GT) && !was_kid0)) {
04662 WN* wn_sub = AWN_Sub(index_type, wn_cp_limit, wn_cp_init);
04663 WN* wn_add = AWN_Add(index_type, wn_sub, wn_cp_stride);
04664 WN* wn_sub2 = AWN_Sub(index_type, wn_add, LWN_Make_Icon(index_type, 1));
04665 wn_trip = unity_stride
04666 ? AWN_Mpy(index_type, wn_sub2, wn_cp_stride2)
04667 : AWN_Div(index_type, wn_sub2, wn_cp_stride2);
04668 } else if (((WN_operator(WN_end(wn_loop)) == OPR_GT)
04669 && was_kid0) || ((WN_operator(WN_end(wn_loop)) == OPR_LT)
04670 && !was_kid0)) {
04671 WN* wn_sub = AWN_Sub(index_type, wn_cp_limit, wn_cp_init);
04672 WN* wn_add = AWN_Add(index_type, wn_sub, wn_cp_stride);
04673 WN* wn_add2 = AWN_Add(index_type, wn_add, LWN_Make_Icon(index_type, 1));
04674 wn_trip = unity_stride
04675 ? AWN_Mpy(index_type, wn_add2, wn_cp_stride2)
04676 : AWN_Div(index_type, wn_add2, wn_cp_stride2);
04677 } else {
04678 WN* wn_sub = AWN_Sub(index_type, wn_cp_limit, wn_cp_init);
04679 WN* wn_add = AWN_Add(index_type, wn_sub, wn_cp_stride);
04680 wn_trip = unity_stride
04681 ? AWN_Mpy(index_type, wn_add, wn_cp_stride2)
04682 : AWN_Div(index_type, wn_add, wn_cp_stride2);
04683 }
04684 return wn_trip;
04685 }
04686
04687
04688
04689
04690
04691
04692
04693
04694
04695
04696
04697
04698 extern INT Reduce_Permutation(INT permutation[],
04699 INT nloops,
04700 INT spermutation[],
04701 INT max_reduction)
04702 {
04703 INT i;
04704 for (i = 0; i < max_reduction; i++)
04705 if (permutation[i] != i)
04706 break;
04707 for (INT j = i; j < nloops; j++)
04708 spermutation[j - i] = permutation[j] - i;
04709 return nloops - i;
04710 }
04711
04712
04713
04714
04715
04716
04717
04718 extern BOOL Index_Variable(WN* wn_index)
04719 {
04720 OPERATOR opr = WN_operator(wn_index);
04721 if (opr != OPR_LDID && opr != OPR_STID)
04722 return FALSE;
04723 SYMBOL sym_index(wn_index);
04724 for (WN* wn = wn_index; wn != NULL; wn = LWN_Get_Parent(wn))
04725 if (WN_opcode(wn) == OPC_DO_LOOP && SYMBOL(WN_index(wn)) == sym_index)
04726 return TRUE;
04727 return FALSE;
04728 }
04729
04730
04731
04732
04733
04734
04735
04736 extern BOOL Contains_Dedicated_Preg(WN* wn_tree)
04737 {
04738 if (OPCODE_has_sym(WN_opcode(wn_tree)) && WN_st(wn_tree) != NULL
04739 && ST_class(WN_st(wn_tree)) == CLASS_PREG
04740 && WN_offset(wn_tree) <= Last_Dedicated_Preg_Offset)
04741 return TRUE;
04742
04743 if (WN_opcode(wn_tree) == OPC_BLOCK) {
04744 for (WN* wn = WN_first(wn_tree); wn != NULL; wn = WN_next(wn))
04745 if (Contains_Dedicated_Preg(wn))
04746 return TRUE;
04747 } else {
04748 for (INT i = 0; i < WN_kid_count(wn_tree); i++)
04749 if (Contains_Dedicated_Preg(WN_kid(wn_tree, i)))
04750 return TRUE;
04751 }
04752 return FALSE;
04753 }
04754
04755
04756
04757
04758
04759
04760
04761 extern INT Factorial(INT n)
04762 {
04763 FmtAssert(n >= 0, ("Factorial() takes a non-negative argument"));
04764 INT factorial = 1;
04765 for (INT i = 2; i <= n; i++)
04766 factorial = factorial * i;
04767 return factorial;
04768 }
04769
04770
04771
04772
04773
04774
04775
04776 extern void Permutation(INT order,
04777 INT nloops,
04778 INT permutation[])
04779 {
04780 if (nloops == 0)
04781 return;
04782 INT* factorials = CXX_NEW_ARRAY(INT, nloops, &LNO_local_pool);
04783 factorials[0] = 1;
04784 INT i;
04785 for (i = 1; i < nloops; i++)
04786 factorials[i] = factorials[i-1] * i;
04787 for (i = 0; i < nloops; i++)
04788 permutation[i] = i;
04789 INT current_base = order;
04790 for (INT search_index = 0; search_index < nloops; search_index++) {
04791 INT current_index = current_base / factorials[nloops - 1 - search_index];
04792 INT next_index = permutation[search_index + current_index];
04793 for (i = search_index + current_index; i > search_index; i--)
04794 permutation[i] = permutation[i-1];
04795 permutation[search_index] = next_index;
04796 current_base -= current_index * factorials[nloops - 1 - search_index];
04797 }
04798 Is_True(Is_Permutation_Vector(permutation, nloops),
04799 ("Permutation: Not a permutation vector"));
04800 }
04801
04802
04803
04804
04805
04806
04807
04808
04809
04810 extern INT WN_Whirl_Linenum(WN* wn_ref)
04811 {
04812 WN *wn;
04813 for (wn = wn_ref; wn != NULL; wn = LWN_Get_Parent(wn))
04814 if (LWN_Get_Linenum(wn) != 0)
04815 break;
04816 return wn == NULL ? 0 : LWN_Get_Linenum(wn);
04817 }
04818
04819
04820
04821 extern void Constant_Propogate(WN *stid, INT64 const_val)
04822 {
04823 MEM_POOL_Push(&LNO_local_pool);
04824 typedef STACK<WN *> STACK_OF_WN;
04825 STACK_OF_WN *new_statement_stack = CXX_NEW(STACK_OF_WN(&LNO_local_pool),&LNO_local_pool);
04826 STACK_OF_WN *use_stack =
04827 CXX_NEW(STACK_OF_WN(&LNO_local_pool),&LNO_local_pool);
04828 USE_LIST *uses = Du_Mgr->Du_Get_Use(stid);
04829 if (!uses) return;
04830 if (uses->Incomplete()) return;
04831
04832 USE_LIST_ITER iter(uses);
04833
04834
04835 for(const DU_NODE *node=iter.First();!iter.Is_Empty();node=iter.Next()){
04836 use_stack->Push((WN *)node->Wn());
04837 }
04838 INT i;
04839 for (i=0; i<use_stack->Elements(); i++) {
04840 WN *use = use_stack->Bottom_nth(i);
04841 if (WN_operator(use) == OPR_LDID &&
04842 WN_st(use) == WN_st(stid) && WN_offset(use) == WN_offset(stid)) {
04843
04844 DEF_LIST *defs = Du_Mgr->Ud_Get_Def(use);
04845 if (defs && !defs->Incomplete()) {
04846 DEF_LIST_ITER iter2(defs);
04847 const DU_NODE *node2 = iter2.First();
04848 iter2.Next();
04849 if (iter2.Is_Empty() && ((WN *)node2->Wn() == stid)) {
04850
04851 WN *parent = LWN_Get_Parent(use);
04852 INT kidno=0;
04853 while (WN_kid(parent,kidno) != use) kidno++;
04854 TYPE_ID type = WN_rtype(use);
04855 LWN_Delete_Tree(use);
04856 WN_kid(parent,kidno) = LWN_Make_Icon(type,const_val);
04857 LWN_Set_Parent(WN_kid(parent,kidno),parent);
04858
04859
04860 WN *statement = parent;
04861 while (OPCODE_is_expression(WN_opcode(statement))) {
04862 statement = LWN_Get_Parent(statement);
04863 }
04864 if (WN_opcode(statement) == OPC_BLOCK) {
04865 statement = LWN_Get_Parent(statement);
04866 }
04867 new_statement_stack->Push(statement);
04868 }
04869 }
04870 }
04871 }
04872 for (i=0; i<new_statement_stack->Elements(); i++) {
04873 WN *statement = new_statement_stack->Bottom_nth(i);
04874 WN_Simplify_Tree(statement);
04875
04876
04877
04878
04879 WN *tmp=statement;
04880 WN *parent = LWN_Get_Parent(tmp);
04881 if (WN_opcode(parent) == OPC_DO_LOOP) {
04882 tmp = parent;
04883 parent = LWN_Get_Parent(tmp);
04884 }
04885
04886 DOLOOP_STACK *loop_stack=CXX_NEW(DOLOOP_STACK(&LNO_local_pool),
04887 &LNO_local_pool);
04888 Build_Doloop_Stack(parent, loop_stack);
04889 LNO_Build_Access(tmp, loop_stack, &LNO_default_pool);
04890
04891 if (WN_opcode(tmp) == OPC_DO_LOOP) {
04892 INT64 iter = Iterations(tmp,&LNO_local_pool);
04893 if (iter > 0) {
04894 DO_LOOP_INFO *dli = Get_Do_Loop_Info(tmp);
04895 dli->Est_Num_Iterations = iter;
04896 dli->Num_Iterations_Symbolic = FALSE;
04897 dli->Num_Iterations_Profile = FALSE;
04898 }
04899 }
04900
04901
04902 if (WN_operator(statement) == OPR_STID) {
04903 if (WN_operator(WN_kid0(statement))==OPR_INTCONST){
04904 Constant_Propogate(statement, WN_const_val(WN_kid0(statement)));
04905 }
04906 }
04907
04908 }
04909 MEM_POOL_Pop(&LNO_local_pool);
04910 }
04911
04912
04913
04914
04915
04916
04917
04918 extern WN* Messy_Subscript(WN* wn_array)
04919 {
04920 for (WN* wn = wn_array; wn != NULL; wn = LWN_Get_Parent(wn)) {
04921 if (WN_operator(wn) == OPR_ARRAY) {
04922 ACCESS_ARRAY* aa = (ACCESS_ARRAY*) WN_MAP_Get(LNO_Info_Map, wn);
04923 if (aa == NULL || aa->Too_Messy)
04924 return wn;
04925 for (INT i = 0; i < aa->Num_Vec(); i++)
04926 if (aa->Dim(i)->Too_Messy)
04927 return wn;
04928 }
04929 }
04930 return NULL;
04931 }
04932
04933
04934
04935
04936
04937
04938
04939
04940 extern void Replace_Index_Variable(WN* loop,
04941 WN* cp_loop,
04942 const char prefix[])
04943 {
04944 const INT bufsz=128;
04945 char buf[bufsz];
04946 INT bufcnt;
04947
04948 ST* st = WN_st(WN_index(loop));
04949 WN_OFFSET offset = WN_offset(WN_index(loop));
04950 TYPE_ID wtype = WN_desc(WN_start(loop));
04951 bufcnt = sprintf(buf, prefix);
04952 (SYMBOL(WN_index(loop))).Name(buf+bufcnt, bufsz-bufcnt);
04953 Replace_Symbol(cp_loop, SYMBOL(st, offset, wtype),
04954 Create_Preg_Symbol(buf, wtype), NULL, cp_loop);
04955
04956 Fix_Do_Du_Info(cp_loop, NULL, TRUE, NULL, 1);
04957 }
04958