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 #ifdef USE_PCH
00037 #include "lno_pch.h"
00038 #endif // USE_PCH
00039 #pragma hdrstop
00040
00041 #include <sys/types.h>
00042
00043 #include "lnopt_main.h"
00044 #include "config.h"
00045 #include "config_lno.h"
00046 #include "strtab.h"
00047 #include "stab.h"
00048 #include "targ_const.h"
00049
00050 #include "lnoutils.h"
00051 #include "wn_simp.h"
00052 #include "stdlib.h"
00053 #include "lwn_util.h"
00054 #include "optimizer.h"
00055 #include "opt_du.h"
00056 #include "name.h"
00057 #include "wintrinsic.h"
00058 #include "lno_bv.h"
00059 #include "dep_graph.h"
00060 #include "debug.h"
00061 #include "scalar_expand.h"
00062 #include "cxx_memory.h"
00063 #include "reduc.h"
00064 #include "fiz_fuse.h"
00065 #include "snl_utils.h"
00066 #include "forward.h"
00067 #include "prompf.h"
00068 #include "anl_driver.h"
00069 #include "minvariant.h"
00070 #include "cond.h"
00071 #include "move.h"
00072 #include "ipl_lno_util.h"
00073
00074 #pragma weak New_Construct_Id
00075
00076 #define MAX_NAME_SIZE 75
00077 #define HMB_ABS_CODE_EXPANSION 1000
00078 #define HMB_REL_CODE_EXPANSION 3
00079
00080 static INT preg_counter = 0;
00081
00082 enum HMB_BOUND {HMB_LEFT, HMB_RIGHT, HMB_NONE};
00083
00084
00085
00086
00087
00088
00089
00090 static BOOL HMB_Invariant_In_Loop(WN* wn_exp,
00091 WN* wn_loop)
00092 {
00093 DU_MANAGER* du = Du_Mgr;
00094 ARRAY_DIRECTED_GRAPH16* dg = Array_Dependence_Graph;
00095 LWN_ITER* itr = LWN_WALK_TreeIter(wn_exp);
00096 for (; itr != NULL; itr = LWN_WALK_TreeNext(itr)) {
00097 WN* wn = itr->wn;
00098 if (WN_operator(wn) == OPR_ILOAD) {
00099 VINDEX16 v = dg->Get_Vertex(wn);
00100 if (v == 0)
00101 continue;
00102 EINDEX16 e = 0;
00103 for (e = dg->Get_In_Edge(v); e != 0; e = dg->Get_Next_In_Edge(e)) {
00104 WN* wn_source = dg->Get_Wn(dg->Get_Source(e));
00105 if (Wn_Is_Inside(wn_source, wn_loop))
00106 return FALSE;
00107 }
00108 for (e = dg->Get_Out_Edge(v); e != 0; e = dg->Get_Next_Out_Edge(e)) {
00109 WN* wn_sink = dg->Get_Wn(dg->Get_Sink(e));
00110 if (Wn_Is_Inside(wn_sink, wn_loop))
00111 return FALSE;
00112 }
00113 } else if (WN_operator(wn) == OPR_LDID
00114 || WN_operator(wn) == OPR_PARM) {
00115 DEF_LIST* def_list = du->Ud_Get_Def(wn);
00116 DEF_LIST_ITER iter(def_list);
00117 const DU_NODE* node = NULL;
00118 for (node = iter.First(); !iter.Is_Empty(); node = iter.Next()) {
00119 WN* wn_def = node->Wn();
00120 if (Wn_Is_Inside(wn_def, wn_loop))
00121 return FALSE;
00122 }
00123 }
00124 }
00125 return TRUE;
00126 }
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136 static void HMB_Copy_Array_Deps(WN* wn_orig,
00137 WN* wn_copy,
00138 BOOL inside_loop,
00139 LS_IN_LOOP* loop_ls)
00140 {
00141 ARRAY_DIRECTED_GRAPH16* dg = Array_Dependence_Graph;
00142 DOLOOP_STACK copy_stack(&LNO_local_pool);
00143 Build_Doloop_Stack(wn_copy, ©_stack);
00144 LNO_Build_Access(WN_kid0(wn_copy), ©_stack, &LNO_default_pool);
00145 if (!inside_loop)
00146 return;
00147 VINDEX16 v = dg->Get_Vertex(wn_orig);
00148 if (v == 0)
00149 return;
00150 STACK<WN*> wn_stack(&LNO_local_pool);
00151 EINDEX16 e = 0;
00152 INT node_position = loop_ls->In(wn_orig);
00153 for (e = dg->Get_In_Edge(v); e != 0; e = dg->Get_Next_In_Edge(e)) {
00154 WN* wn_source = dg->Get_Wn(dg->Get_Source(e));
00155 INT i;
00156 for (i = 0; i < wn_stack.Elements(); i++)
00157 if (wn_stack.Bottom_nth(i) == wn_source)
00158 break;
00159 if (i == wn_stack.Elements())
00160 wn_stack.Push(wn_source);
00161 }
00162 for (e = dg->Get_Out_Edge(v); e != 0; e = dg->Get_Next_Out_Edge(e)) {
00163 WN* wn_sink = dg->Get_Wn(dg->Get_Sink(e));
00164 INT i;
00165 for (i = 0; i < wn_stack.Elements(); i++)
00166 if (wn_stack.Bottom_nth(i) == wn_sink)
00167 break;
00168 if (i == wn_stack.Elements())
00169 wn_stack.Push(wn_sink);
00170 }
00171 dg->Add_Vertex(wn_copy);
00172 DOLOOP_STACK other_stack(&LNO_local_pool);
00173 INT i;
00174 for (i = 0; i < wn_stack.Elements(); i++) {
00175 WN* wn_other = wn_stack.Bottom_nth(i);
00176 Build_Doloop_Stack(wn_other, &other_stack);
00177 if (!dg->Add_Edge(wn_copy, ©_stack, wn_other, &other_stack,
00178 node_position < loop_ls->In(wn_other))) {
00179 LNO_Erase_Dg_From_Here_In(wn_other, dg);
00180 }
00181 other_stack.Clear();
00182 }
00183 }
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194 static void HMB_Copy_Array_Deps_Exp(WN* wn_orig,
00195 WN* wn_copy,
00196 BOOL inside_loop,
00197 LS_IN_LOOP* loop_ls)
00198 {
00199 ARRAY_DIRECTED_GRAPH16* dg = Array_Dependence_Graph;
00200 if (WN_operator(wn_orig) == OPR_ILOAD)
00201 HMB_Copy_Array_Deps(wn_orig, wn_copy, inside_loop, loop_ls);
00202 for (INT i = 0; i < WN_kid_count(wn_orig); i++) {
00203 WN* wn_orig_kid = WN_kid(wn_orig, i);
00204 WN* wn_copy_kid = WN_kid(wn_copy, i);
00205 HMB_Copy_Array_Deps_Exp(wn_orig_kid, wn_copy_kid, inside_loop, loop_ls);
00206 }
00207 }
00208
00209
00210
00211
00212
00213
00214
00215 static void HMB_Replace_Messy_Bounds(WN* wn_exp,
00216 WN* wn_hoist_loop,
00217 HMB_BOUND bnd_type,
00218 WN* wn_guard,
00219 LS_IN_LOOP* loop_ls,
00220 char name[],
00221 WN* wn_bound)
00222 {
00223 if (LNO_Verbose) {
00224 fprintf(stdout, " HMB: Replacing Messy Bound for Loop 0x%p\n",
00225 wn_hoist_loop);
00226 fprintf(TFile, " HMB: Replacing Messy Bound for Loop 0x%p\n",
00227 wn_hoist_loop);
00228 }
00229 DU_MANAGER* du = Du_Mgr;
00230 ARRAY_DIRECTED_GRAPH16* dg = Array_Dependence_Graph;
00231 TYPE_ID type = WN_rtype(wn_exp);
00232 #ifdef KEY //Bug 11381: retain the original type for messy loop bounds
00233
00234 if(WN_opcode(wn_exp)==OPC_U4U8CVT || WN_opcode(wn_exp)==OPC_U4I8CVT){
00235 TYPE_ID dtype = WN_desc(WN_kid0(wn_exp));
00236 if(WN_operator(WN_kid0(wn_exp)) == OPR_ILOAD && dtype == MTYPE_I4)
00237 type = MTYPE_I4;
00238 }
00239 #endif
00240 OPCODE preg_s_opcode = OPCODE_make_op(OPR_STID, MTYPE_V, type);
00241 OPCODE preg_l_opcode = OPCODE_make_op(OPR_LDID,
00242 Promote_Type(OPCODE_desc(preg_s_opcode)), OPCODE_desc(preg_s_opcode));
00243 if (wn_bound != NULL) {
00244 WN* wn_ldid = LWN_CreateLdid(preg_l_opcode, wn_bound);
00245 du->Add_Def_Use(wn_bound, wn_ldid);
00246 WN* wn_parent = LWN_Get_Parent(wn_exp);
00247 INT i;
00248 for (i = 0; i < WN_kid_count(wn_parent); i++)
00249 if (WN_kid(wn_parent, i) == wn_exp)
00250 break;
00251 LWN_Set_Parent(wn_ldid, wn_parent);
00252 WN_kid(wn_parent, i) = wn_ldid;
00253 LWN_Delete_Tree(wn_exp);
00254 } else {
00255 WN* wn_exp_copy = LWN_Copy_Tree(wn_exp);
00256 LWN_Copy_Def_Use(wn_exp, wn_exp_copy, du);
00257 #ifdef _NEW_SYMTAB
00258 WN_OFFSET preg_num = Create_Preg(type, name);
00259 #else
00260 WN_OFFSET preg_num = Create_Preg(type, name, NULL);
00261 #endif
00262 ST* preg_st = MTYPE_To_PREG(type);
00263 WN* wn_stid = LWN_CreateStid(preg_s_opcode, preg_num, preg_st,
00264 Be_Type_Tbl(type), wn_exp_copy);
00265 INT inside_loop = Do_Loop_Depth(wn_hoist_loop) > 0;
00266 WN* wn_loop = wn_hoist_loop;
00267 DO_LOOP_INFO* dli = Get_Do_Loop_Info(wn_loop);
00268 WN* wn_insert = (bnd_type != HMB_NONE && wn_guard != NULL)
00269 ? wn_guard : wn_loop;
00270 LWN_Insert_Block_Before(LWN_Get_Parent(wn_insert), wn_insert, wn_stid);
00271 HMB_Copy_Array_Deps_Exp(wn_exp, wn_exp_copy, inside_loop, loop_ls);
00272 WN* wn_ldid_copy = LWN_CreateLdid(preg_l_opcode, wn_stid);
00273 WN* wn_ldid = Replace_Wnexp_With_Exp_Copy(wn_exp, wn_ldid_copy, du);
00274 du->Add_Def_Use(wn_stid, wn_ldid);
00275 if (bnd_type != HMB_NONE && wn_guard != NULL) {
00276 WN* wn_guard_exp = bnd_type == HMB_LEFT
00277 ? WN_kid0(WN_if_test(wn_guard)) : WN_kid1(WN_if_test(wn_guard));
00278 WN* wn_ldid = Replace_Wnexp_With_Exp_Copy(wn_guard_exp, wn_ldid_copy, du);
00279 du->Add_Def_Use(wn_stid, wn_ldid);
00280 }
00281 LWN_Delete_Tree(wn_ldid_copy);
00282 }
00283 }
00284
00285
00286
00287
00288
00289
00290
00291 static BOOL HMB_Has_Messy_Left_Bound(WN* wn_loop)
00292 {
00293 DO_LOOP_INFO* dli = Get_Do_Loop_Info(wn_loop);
00294 return (dli->Step->Const_Offset > 0)
00295 ? Bound_Is_Too_Messy(dli->LB) : Bound_Is_Too_Messy(dli->UB);
00296 }
00297
00298
00299
00300
00301
00302
00303
00304 static BOOL HMB_Has_Messy_Right_Bound(WN* wn_loop)
00305 {
00306 DO_LOOP_INFO* dli = Get_Do_Loop_Info(wn_loop);
00307 return (dli->Step->Const_Offset > 0)
00308 ? Bound_Is_Too_Messy(dli->UB) : Bound_Is_Too_Messy(dli->LB);
00309 }
00310
00311
00312
00313
00314
00315
00316
00317 static INT Bound_Exists(STACK<WN*>* stk_bounds,
00318 WN* wn_bound)
00319 {
00320 for (INT i = 0; i < stk_bounds->Elements(); i++)
00321 if (WN_Simp_Compare_Trees(WN_kid0(stk_bounds->Bottom_nth(i)),
00322 wn_bound) == 0)
00323 return i;
00324 return -1;
00325 }
00326
00327
00328
00329
00330
00331
00332
00333 static WN* Unique_Definition(WN* wn_ldid)
00334 {
00335 DU_MANAGER* du = Du_Mgr;
00336 DEF_LIST *def_list = du->Ud_Get_Def(wn_ldid);
00337 DEF_LIST_ITER iter(def_list);
00338 INT count = 0;
00339 WN* wn_stid = NULL;
00340 const DU_NODE* node = NULL;
00341 for (node = iter.First(); !iter.Is_Empty(); node = iter.Next()) {
00342 wn_stid = node->Wn();
00343 count++;
00344 }
00345 FmtAssert(count == 1, ("Unique_Definition: Def not Unique"));
00346 return wn_stid;
00347 }
00348
00349
00350
00351
00352
00353
00354
00355 static void HMB_Replace_Messy_Bounds_Loop(WN* wn_loop,
00356 WN* wn_hoist_loop,
00357 WN* wn_guard,
00358 STACK<WN*>* stk_bounds,
00359 LS_IN_LOOP* loop_ls)
00360 {
00361 FmtAssert(WN_opcode(wn_loop) == OPC_DO_LOOP,
00362 ("HMB_Replace_Messy_Bounds_Loop: First arg must be do loop"));
00363 FmtAssert(WN_opcode(wn_hoist_loop) == OPC_DO_LOOP,
00364 ("HMB_Replace_Messy_Bounds_Loop: Second arg must be do loop"));
00365 FmtAssert(Do_Loop_Depth(wn_loop) >= Do_Loop_Depth(wn_hoist_loop),
00366 ("HMB_Replace_Messy_Bounds_Loop: Loop must be inside hoist loop"));
00367 char buffer[MAX_NAME_SIZE];
00368 DOLOOP_STACK stack(&LNO_local_pool);
00369 if (HMB_Has_Messy_Left_Bound(wn_loop)) {
00370 INT stk_number = Bound_Exists(stk_bounds, WN_kid0(WN_start(wn_loop)));
00371 if (stk_number >= 0) {
00372 sprintf(buffer, "_ab%d", stk_number);
00373 HMB_Replace_Messy_Bounds(WN_kid0(WN_start(wn_loop)), wn_hoist_loop,
00374 HMB_RIGHT, wn_guard, loop_ls, buffer,
00375 stk_bounds->Bottom_nth(stk_number));
00376 } else {
00377 sprintf(buffer, "_ab%d", preg_counter++);
00378 HMB_Replace_Messy_Bounds(WN_kid0(WN_start(wn_loop)), wn_hoist_loop,
00379 HMB_RIGHT, wn_guard, loop_ls, buffer, NULL);
00380 stk_bounds->Push(Unique_Definition(WN_kid0(WN_start(wn_loop))));
00381 }
00382 Build_Doloop_Stack(LWN_Get_Parent(wn_loop), &stack);
00383 LNO_Build_Do_Access(wn_loop, &stack);
00384 stack.Clear();
00385 }
00386 if (HMB_Has_Messy_Right_Bound(wn_loop)) {
00387 INT stk_number = Bound_Exists(stk_bounds, UBexp(WN_end(wn_loop)));
00388 if (stk_number >= 0) {
00389 sprintf(buffer, "_ab%d", stk_number);
00390 HMB_Replace_Messy_Bounds(UBexp(WN_end(wn_loop)), wn_hoist_loop,
00391 HMB_LEFT, wn_guard, loop_ls, buffer,
00392 stk_bounds->Bottom_nth(stk_number));
00393 } else {
00394 sprintf(buffer, "_ab%d", preg_counter++);
00395 HMB_Replace_Messy_Bounds(UBexp(WN_end(wn_loop)), wn_hoist_loop,
00396 HMB_LEFT, wn_guard, loop_ls, buffer, NULL);
00397 stk_bounds->Push(Unique_Definition(WN_kid1(WN_end(wn_loop))));
00398 }
00399 Build_Doloop_Stack(LWN_Get_Parent(wn_loop), &stack);
00400 LNO_Build_Do_Access(wn_loop, &stack);
00401 stack.Clear();
00402 }
00403 }
00404
00405
00406
00407
00408
00409
00410
00411
00412 static WN* Code_Expansion_Limit_Loop(WN* wn_outer)
00413
00414 {
00415 INT nloops = SNL_Loop_Count(wn_outer);
00416 WN* wn_inner = SNL_Get_Inner_Snl_Loop(wn_outer, nloops);
00417 INT outer_depth = Do_Loop_Depth(wn_outer);
00418 INT inner_depth = Do_Loop_Depth(wn_inner);
00419 INT* node_counts = CXX_NEW_ARRAY(INT, inner_depth + 1, &LNO_local_pool);
00420 WN* wn_loop = wn_outer;
00421 INT i;
00422 for (i = outer_depth; i <= inner_depth; i++) {
00423 node_counts[i] = 1;
00424 node_counts[i] += Node_Count(WN_index(wn_loop));
00425 node_counts[i] += Node_Count(WN_start(wn_loop));
00426 node_counts[i] += Node_Count(WN_end(wn_loop));
00427 node_counts[i] += Node_Count(WN_step(wn_loop));
00428 node_counts[i]++;
00429 WN* wn_first = WN_first(WN_do_body(wn_loop));
00430 for (WN* wn = wn_first; wn != NULL; wn = WN_next(wn)) {
00431 if (WN_opcode(wn) == OPC_DO_LOOP)
00432 continue;
00433 node_counts[i] += Node_Count(wn);
00434 }
00435 wn_loop = Find_Next_Innermost_Do(wn_loop);
00436 }
00437 WN* wn_result = NULL;
00438 wn_loop = wn_inner;
00439 for (i = inner_depth; i >= outer_depth; i--) {
00440 INT old_count = 0;
00441 INT new_count = 0;
00442 INT factor = inner_depth - i + 1;
00443 old_count += node_counts[i];
00444 new_count += factor * node_counts[i];
00445 FmtAssert(new_count >= old_count,
00446 ("Code_Expansion_Limit_Loop: Code Expansion must be >= 1"));
00447 if (new_count > HMB_REL_CODE_EXPANSION * old_count
00448 && new_count > HMB_ABS_CODE_EXPANSION)
00449 break;
00450 wn_result = wn_loop;
00451 if (wn_result == wn_outer)
00452 break;
00453 wn_loop = Enclosing_Do_Loop(LWN_Get_Parent(wn_loop));
00454 }
00455 return wn_result;
00456 }
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472 static WN* HMB_Maximum_Point(WN* wn_snl)
00473 {
00474 WN* wn_last = NULL;
00475
00476
00477 WN* wnn = NULL;
00478 WN* wn = 0;
00479 for (wn = wn_snl; wn != NULL; wnn = wn, wn = Find_Next_Innermost_Do(wn));
00480 WN* wn_inner = wnn;
00481
00482
00483 for (wn = wn_inner; wn != LWN_Get_Parent(wn_snl); wn = LWN_Get_Parent(wn)) {
00484 if (WN_opcode(wn) != OPC_DO_LOOP)
00485 continue;
00486 DO_LOOP_INFO* dli = Get_Do_Loop_Info(wn);
00487 if (dli->Has_Gotos)
00488 break;
00489 wn_last = wn;
00490 }
00491 if (wn_last == NULL)
00492 return NULL;
00493
00494
00495 WN* wn_max = wn_last;
00496 wn_last = NULL;
00497 WN* wn_final = LWN_Get_Parent(wn_max);
00498 for (wn = wn_inner; wn != wn_final; wn = LWN_Get_Parent(wn)) {
00499 if (WN_opcode(wn) != OPC_DO_LOOP)
00500 continue;
00501 if (!Upper_Bound_Standardize(WN_end(wn), TRUE))
00502 break;
00503 wn_last = wn;
00504 }
00505 if (wn_last == NULL)
00506 return NULL;
00507
00508
00509 wn_max = wn_last;
00510 wn_last = NULL;
00511 wn_final = LWN_Get_Parent(wn_max);
00512 for (wn = wn_inner; wn != wn_final; wn = LWN_Get_Parent(wn)) {
00513 if (WN_opcode(wn) != OPC_DO_LOOP)
00514 continue;
00515 DO_LOOP_INFO* dli = Get_Do_Loop_Info(wn);
00516 if (!dli->Step->Is_Const())
00517 break;
00518 wn_last = wn;
00519 }
00520 if (wn_last == NULL)
00521 return NULL;
00522
00523
00524
00525 wn_max = wn_last;
00526 wn_last = NULL;
00527 DOLOOP_STACK stk_loop(&LNO_local_pool);
00528 Build_Doloop_Stack(wn_inner, &stk_loop);
00529 for (WN* wn_try = wn_inner; wn_try != LWN_Get_Parent(wn_max);
00530 wn_try = LWN_Get_Parent(wn_try)) {
00531 if (WN_opcode(wn_try) != OPC_DO_LOOP)
00532 continue;
00533 for (wn = wn_inner; wn != wn_try; wn = LWN_Get_Parent(wn)) {
00534 if (WN_opcode(wn) != OPC_DO_LOOP)
00535 continue;
00536 if (!HMB_Invariant_In_Loop(WN_kid0(WN_start(wn)), wn_try))
00537 break;
00538 if (!HMB_Invariant_In_Loop(UBexp(WN_end(wn)), wn_try))
00539 break;
00540 }
00541 if (wn != wn_try)
00542 return wn_last;
00543 wn_last = wn_try;
00544 }
00545
00546 return wn_last;
00547 }
00548
00549
00550
00551
00552
00553
00554
00555 extern BOOL Tree_Has_Regions(WN* wn_tree)
00556 {
00557 if (WN_opcode(wn_tree) == OPC_REGION)
00558 return TRUE;
00559 if (WN_opcode(wn_tree) == OPC_BLOCK) {
00560 for (WN* wn = WN_first(wn_tree); wn != NULL; wn = WN_next(wn))
00561 if (Tree_Has_Regions(wn))
00562 return TRUE;
00563 } else {
00564 for (INT i = 0; i < WN_kid_count(wn_tree); i++)
00565 if (Tree_Has_Regions(WN_kid(wn_tree, i)))
00566 return TRUE;
00567 }
00568 return FALSE;
00569 }
00570
00571
00572
00573
00574
00575
00576
00577 static BOOL Guard_Test_Redundant(WN* wn_loop,
00578 WN* wn_guards[],
00579 INT depth)
00580 {
00581 DU_MANAGER* du = Du_Mgr;
00582 BOOL return_value = FALSE;
00583 WN* wn_parent = LWN_Get_Parent(wn_loop);
00584 COND_BOUNDS_INFO *info =
00585 CXX_NEW(COND_BOUNDS_INFO(&LNO_local_pool), &LNO_local_pool);
00586 info->Collect_Outer_Info(wn_parent);
00587 WN* wn_test = LWN_Copy_Tree(WN_end(wn_loop));
00588 LWN_Copy_Def_Use(WN_end(wn_loop), wn_test, du);
00589 Replace_Ldid_With_Exp_Copy(SYMBOL(WN_start(wn_loop)), wn_test,
00590 WN_kid0(WN_start(wn_loop)), du);
00591 WN* wn_if = LWN_CreateIf(wn_test, WN_CreateBlock(), WN_CreateBlock());
00592 LWN_Insert_Block_Before(LWN_Get_Parent(wn_loop), wn_loop, wn_if);
00593 LWN_Extract_From_Block(wn_loop);
00594 LWN_Insert_Block_After(WN_then(wn_if), NULL, wn_loop);
00595 IF_INFO *ii = CXX_NEW(IF_INFO(&LNO_default_pool, TRUE,
00596 Tree_Has_Regions(wn_loop)), &LNO_default_pool);
00597 WN_MAP_Set(LNO_Info_Map, wn_if, (void *) ii);
00598 return_value = Redundant_Condition(info, wn_test, wn_if);
00599 Forward_Substitute_Ldids(wn_test, du);
00600 wn_guards[depth] = LWN_Copy_Tree(wn_test);
00601 LWN_Copy_Def_Use(wn_test, wn_guards[depth], du);
00602 LWN_Extract_From_Block(wn_loop);
00603 LWN_Insert_Block_Before(LWN_Get_Parent(wn_if), wn_if, wn_loop);
00604 LWN_Extract_From_Block(wn_if);
00605 LWN_Delete_Tree(wn_if);
00606 if (return_value == FALSE) {
00607 for (INT i = 0; i < depth; i++) {
00608 if (wn_guards[i] != NULL
00609 && WN_Simp_Compare_Trees(wn_guards[i], wn_guards[depth]) == 0) {
00610 return_value = TRUE;
00611 break;
00612 }
00613 }
00614 }
00615 return return_value;
00616 }
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626 static void HMB_Add_Guard_Condition(WN* wn_loop,
00627 WN* wn_snl,
00628 WN* wn_if,
00629 LS_IN_LOOP* loop_ls)
00630 {
00631 DU_MANAGER* du = Du_Mgr;
00632 OPCODE op_cand = OPCODE_make_op(OPR_CAND, Boolean_type, MTYPE_V);
00633 WN* wn_upper_bound = LWN_Copy_Tree(UBexp(WN_end(wn_loop)));
00634 LWN_Copy_Def_Use(UBexp(WN_end(wn_loop)), wn_upper_bound, du);
00635 WN* wn_lower_bound = LWN_Copy_Tree(WN_kid0(WN_start(wn_loop)));
00636 LWN_Copy_Def_Use(WN_kid0(WN_start(wn_loop)), wn_lower_bound, du);
00637 BOOL saved_fold_enable = WN_Simplifier_Enable(FALSE);
00638 OPCODE op_cond = OPCODE_make_op(OPR_GE, Boolean_type,
00639 WN_rtype(wn_upper_bound));
00640 WN* wn_cond = LWN_CreateExp2(op_cond, wn_upper_bound, wn_lower_bound);
00641 if (WN_if_test(wn_if) == NULL)
00642 WN_if_test(wn_if) = wn_cond;
00643 else
00644 WN_if_test(wn_if) = LWN_CreateExp2(op_cand, WN_if_test(wn_if), wn_cond); LWN_Set_Parent(WN_if_test(wn_if), wn_if);
00645 BOOL inside_loop = Do_Loop_Depth(wn_snl) > 0;
00646 HMB_Copy_Array_Deps_Exp(UBexp(WN_end(wn_loop)), wn_upper_bound,
00647 inside_loop, loop_ls);
00648 HMB_Copy_Array_Deps_Exp(WN_kid0(WN_start(wn_loop)), wn_lower_bound,
00649 inside_loop, loop_ls);
00650 WN_Simplifier_Enable(saved_fold_enable);
00651 }
00652
00653
00654
00655
00656
00657
00658
00659
00660 static WN* HMB_Simple_Guard_Test(WN* wn_loop,
00661 WN* wn_snl,
00662 LS_IN_LOOP* loop_ls)
00663 {
00664 WN* wn_if = LWN_CreateIf(NULL, WN_CreateBlock(), WN_CreateBlock());
00665 WN_Set_Linenum(wn_if, WN_Get_Linenum(wn_snl));
00666 LWN_Insert_Block_After(LWN_Get_Parent(wn_snl), wn_snl, wn_if);
00667 LWN_Extract_From_Block(wn_snl);
00668 LWN_Insert_Block_After(WN_then(wn_if), NULL, wn_snl);
00669 HMB_Add_Guard_Condition(wn_loop, wn_snl, wn_if, loop_ls);
00670 IF_INFO *ii = CXX_NEW(IF_INFO(&LNO_default_pool, TRUE,
00671 Tree_Has_Regions(wn_snl)), &LNO_default_pool);
00672 WN_MAP_Set(LNO_Info_Map, wn_if, (void *) ii);
00673 DOLOOP_STACK stack(&LNO_local_pool);
00674 Build_Doloop_Stack(wn_if, &stack);
00675 LNO_Build_If_Access(wn_if, &stack);
00676 return wn_if;
00677 }
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687 static WN* HMB_Compound_Guard_Test(WN* wn_snl,
00688 INT guard_mask,
00689 LS_IN_LOOP* loop_ls)
00690 {
00691 if (guard_mask == 0)
00692 return NULL;
00693 INT nloops = SNL_Loop_Count(wn_snl);
00694 INT outer_depth = Do_Loop_Depth(wn_snl);
00695 INT inner_depth = outer_depth + nloops - 1;
00696 INT test_guard_mask = guard_mask;
00697 WN* wn_if = LWN_CreateIf(NULL, WN_CreateBlock(), WN_CreateBlock());
00698 WN_Set_Linenum(wn_if, WN_Get_Linenum(wn_snl));
00699 LWN_Insert_Block_After(LWN_Get_Parent(wn_snl), wn_snl, wn_if);
00700 LWN_Extract_From_Block(wn_snl);
00701 LWN_Insert_Block_After(WN_then(wn_if), NULL, wn_snl);
00702 OPCODE op_cand = OPCODE_make_op(OPR_CAND, Boolean_type, MTYPE_V);
00703 WN* wn_loop = wn_snl;
00704 for (INT i = outer_depth; i <= inner_depth; i++) {
00705 if (guard_mask & (1 << i))
00706 HMB_Add_Guard_Condition(wn_loop, wn_snl, wn_if, loop_ls);
00707 wn_loop = Find_Next_Innermost_Do(wn_loop);
00708 }
00709 IF_INFO *ii = CXX_NEW(IF_INFO(&LNO_default_pool, TRUE,
00710 Tree_Has_Regions(wn_snl)), &LNO_default_pool);
00711 WN_MAP_Set(LNO_Info_Map, wn_if, (void *) ii);
00712 DOLOOP_STACK stack(&LNO_local_pool);
00713 Build_Doloop_Stack(wn_if, &stack);
00714 LNO_Build_If_Access(wn_if, &stack);
00715 return wn_if;
00716 }
00717
00718
00719
00720
00721
00722
00723
00724 static BOOL Has_Code_At_Depth(WN* wn_snl,
00725 INT nloops,
00726 INT depth)
00727 {
00728 INT outer_depth = Do_Loop_Depth(wn_snl);
00729 INT inner_depth = outer_depth + nloops - 1;
00730 FmtAssert(depth >= outer_depth && depth <= inner_depth,
00731 ("Has_Code_At_Depth: Illegal depth"));
00732 if (depth == inner_depth)
00733 return TRUE;
00734 WN* wn_inner = SNL_Get_Inner_Snl_Loop(wn_snl, depth - outer_depth + 2);
00735 WN* wn = 0;
00736 for (wn = WN_prev(wn_inner); wn != NULL; wn = WN_prev(wn))
00737 if (!OPCODE_is_not_executable(WN_opcode(wn)))
00738 return TRUE;
00739 for (wn = WN_next(wn_inner); wn != NULL; wn = WN_next(wn))
00740 if (!OPCODE_is_not_executable(WN_opcode(wn)))
00741 return TRUE;
00742 return FALSE;
00743 }
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754 static void Prompf_Hoist_Messy_Bounds(WN* wn_snl,
00755 WN* wn_version[],
00756 INT version_count,
00757 INT outer_depth,
00758 INT inner_depth)
00759 {
00760 INT nloops = inner_depth - outer_depth + 1;
00761 INT* old_ids = CXX_NEW_ARRAY(INT, nloops, &LNO_local_pool);
00762 INT old_count = 0;
00763 WN* wn = 0;
00764 for (wn = wn_snl; wn != NULL; wn = Next_SNL_Loop(wn))
00765 if (WN_opcode(wn) == OPC_DO_LOOP)
00766 old_ids[old_count++] = WN_MAP32_Get(Prompf_Id_Map, wn);
00767 INT i = 0;
00768 for (wn = wn_version[0]; wn != NULL; wn = Next_SNL_Loop(wn))
00769 if (WN_opcode(wn) == OPC_DO_LOOP)
00770 WN_MAP32_Set(Prompf_Id_Map, wn, old_ids[i++]);
00771 for (i = 1; i < version_count; i++) {
00772 INT new_count = 0;
00773 for (wn = wn_version[i]; wn != NULL; wn = Next_SNL_Loop(wn))
00774 if (WN_opcode(wn) == OPC_DO_LOOP)
00775 new_count++;
00776 if (new_count == 0)
00777 continue;
00778 INT* new_ids = CXX_NEW_ARRAY(INT, new_count, &LNO_local_pool);
00779 INT j = 0;
00780 for (wn = wn_version[i]; wn != NULL; wn = Next_SNL_Loop(wn)) {
00781 if (WN_opcode(wn) == OPC_DO_LOOP) {
00782 INT new_id = New_Construct_Id();
00783 WN_MAP32_Set(Prompf_Id_Map, wn, new_id);
00784 new_ids[j++] = new_id;
00785 }
00786 }
00787 Prompf_Info->Hoist_Messy_Bounds(old_ids, new_ids, new_count);
00788 }
00789 for (wn = wn_snl; wn != NULL; wn = Next_SNL_Loop(wn))
00790 if (WN_opcode(wn) == OPC_DO_LOOP)
00791 WN_MAP32_Set(Prompf_Id_Map, wn, 0);
00792 }
00793
00794
00795
00796
00797
00798
00799
00800 static BOOL Contains_Index_Variable(WN* wn_tree)
00801 {
00802 if (WN_operator(wn_tree) == OPR_LDID) {
00803 WN* wn = 0;
00804 for (wn = wn_tree; wn != NULL; wn = LWN_Get_Parent(wn))
00805 if (WN_opcode(wn) == OPC_DO_LOOP
00806 && SYMBOL(WN_index(wn)) == SYMBOL(wn_tree))
00807 break;
00808 if (wn != NULL)
00809 return TRUE;
00810 }
00811 for (INT i = 0; i < WN_kid_count(wn_tree); i++)
00812 if (Contains_Index_Variable(WN_kid(wn_tree, i)))
00813 return TRUE;
00814 return FALSE;
00815 }
00816
00817
00818
00819
00820
00821
00822
00823 static BOOL Contains_Vertex(WN* wn_exp)
00824 {
00825 ARRAY_DIRECTED_GRAPH16* dg = Array_Dependence_Graph;
00826 LWN_ITER* itr = LWN_WALK_TreeIter(wn_exp);
00827 for (; itr != NULL; itr = LWN_WALK_TreeNext(itr))
00828 if (OPCODE_is_load(WN_opcode(itr->wn))
00829 && (WN_operator(itr->wn) == OPR_ILOAD
00830 || dg->Get_Vertex(itr->wn)))
00831 return TRUE;
00832 return FALSE;
00833 }
00834
00835
00836
00837
00838
00839
00840
00841
00842 static BOOL Is_Messy_Expression(WN* wn_tree,
00843 BOOL need_safe)
00844 {
00845 OPERATOR opr = WN_operator(wn_tree);
00846 return WN_kid_count(wn_tree) > 0 && (opr != OPR_ADD && opr != OPR_SUB
00847 && opr != OPR_MPY && opr != OPR_NEG)
00848 && (!need_safe || Statically_Safe_Exp(wn_tree))
00849 && !Contains_Index_Variable(wn_tree) && !Contains_Vertex(wn_tree);
00850 }
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860 static void HMB_Push_Messy_Expressions(WN* wn_tree,
00861 BOOL need_safe,
00862 STACK<WN*>* stk_messy)
00863 {
00864 DU_MANAGER* du = Du_Mgr;
00865 INT i;
00866 for (i = 0; i < WN_kid_count(wn_tree); i++)
00867 HMB_Push_Messy_Expressions(WN_kid(wn_tree, i), need_safe, stk_messy);
00868
00869 if (Is_Messy_Expression(wn_tree, need_safe)
00870 && Hoistable_Statement(wn_tree, du) < Loop_Depth(wn_tree)) {
00871 INT i;
00872 for (i = 0; i < stk_messy->Elements(); i++)
00873 if (stk_messy->Bottom_nth(i) == wn_tree)
00874 break;
00875 if (i == stk_messy->Elements())
00876 stk_messy->Push(wn_tree);
00877 }
00878 }
00879
00880
00881
00882
00883
00884
00885
00886
00887 static void HMB_Find_Messy_Subscripts(WN* wn_loop,
00888 BOOL need_safe,
00889 STACK<WN*>* stk_messy)
00890 {
00891 DU_MANAGER* du = Du_Mgr;
00892 STACK<WN*>* stk_subs = CXX_NEW(STACK<WN*>(&LNO_local_pool), &LNO_local_pool);
00893 LWN_ITER* itr = LWN_WALK_TreeIter(wn_loop);
00894 for (; itr != NULL; itr = LWN_WALK_TreeNext(itr)) {
00895 WN* wn_array = itr->wn;
00896 if (WN_operator(wn_array) == OPR_ARRAY) {
00897 ACCESS_ARRAY* aa = (ACCESS_ARRAY*) WN_MAP_Get(LNO_Info_Map, wn_array);
00898 FmtAssert(aa != NULL,
00899 ("HMB_Find_Messy_Subscripts: Missing access array on OPR_ARRAY node"));
00900 if (Bound_Is_Too_Messy(aa))
00901 HMB_Push_Messy_Expressions(wn_array, need_safe, stk_messy);
00902 }
00903 }
00904 }
00905
00906
00907
00908
00909
00910
00911
00912 static void HMB_Hoist_Messy_Subscripts(WN* wn_loop,
00913 STACK<WN*>* stk_messy,
00914 STACK<WN*>* stk_bounds,
00915 LS_IN_LOOP* loop_ls)
00916 {
00917 DU_MANAGER* du = Du_Mgr;
00918 ARRAY_DIRECTED_GRAPH16* dg = Array_Dependence_Graph;
00919 char buffer[MAX_NAME_SIZE];
00920 DYN_ARRAY<WN*> new_uses(&LNO_local_pool);
00921 DYN_ARRAY<WN*> parent_uses(&LNO_local_pool);
00922 for (INT j = 0; j < stk_messy->Elements(); j++) {
00923 WN* wn_messy_kid = stk_messy->Bottom_nth(j);
00924 WN* wn_messy = LWN_Get_Parent(wn_messy_kid);
00925
00926
00927 for (INT k = new_uses.Elements() - 1; k >= 0; k--) {
00928 WN* wn_use = new_uses[k];
00929 for (WN* wn = wn_use; wn != NULL; wn = LWN_Get_Parent(wn)) {
00930 if (wn == wn_messy) {
00931 parent_uses.AddElement(wn_use);
00932 for (INT m = k + 1; m < new_uses.Elements(); m++)
00933 new_uses[m-1] = new_uses[m];
00934 new_uses.Decidx();
00935 }
00936 }
00937 }
00938 if (parent_uses.Elements() > 0) {
00939 MIR_Update_Dependences(wn_loop, &parent_uses);
00940 parent_uses.Resetidx();
00941 }
00942 INT hoist_level = Hoistable_Statement(wn_messy_kid, du);
00943 WN* wn = 0;
00944 for (wn = wn_messy_kid; wn != NULL; wn = LWN_Get_Parent(wn))
00945 if (WN_opcode(wn) == OPC_DO_LOOP
00946 && Do_Loop_Depth(wn) == hoist_level + 1)
00947 break;
00948 WN* wn_hoist_loop = wn;
00949 FmtAssert(wn_hoist_loop != NULL,
00950 ("HMB_Hoist_Messy_Subscripts: Could not find hoist loop"));
00951 INT stk_number = Bound_Exists(stk_bounds, wn_messy_kid);
00952 if (stk_number >= 0) {
00953 sprintf(buffer, "_ab%d", stk_number);
00954 HMB_Replace_Messy_Bounds(wn_messy_kid, wn_hoist_loop, HMB_NONE,
00955 NULL, loop_ls, buffer, stk_bounds->Bottom_nth(stk_number));
00956 } else {
00957 sprintf(buffer, "_ab%d", preg_counter++);
00958 WN* wn_parent = LWN_Get_Parent(wn_messy_kid);
00959 INT i;
00960 for (i = 0; i < WN_kid_count(wn_parent); i++)
00961 if (WN_kid(wn_parent, i) == wn_messy_kid)
00962 break;
00963 INT kid = i;
00964 HMB_Replace_Messy_Bounds(wn_messy_kid, wn_hoist_loop, HMB_NONE,
00965 NULL, loop_ls, buffer, NULL);
00966 stk_bounds->Push(Unique_Definition(WN_kid(wn_parent, kid)));
00967 }
00968 for (wn = wn_messy; wn != NULL; wn = LWN_Get_Parent(wn))
00969 if (WN_operator(wn) == OPR_ARRAY)
00970 break;
00971 WN* wn_rebuild = wn;
00972 DOLOOP_STACK do_stack(&LNO_local_pool);
00973 Build_Doloop_Stack(LWN_Get_Parent(wn_rebuild), &do_stack);
00974 LNO_Build_Access(wn_rebuild, &do_stack, &LNO_default_pool);
00975 INT i;
00976 for (i = 0; i < new_uses.Elements(); i++)
00977 if (new_uses[i] == wn_messy)
00978 break;
00979 if (i == new_uses.Elements())
00980 new_uses.AddElement(wn_messy);
00981 }
00982 MIR_Update_Dependences(wn_loop, &new_uses);
00983 }
00984
00985
00986
00987
00988
00989
00990
00991
00992 static void HMB_Find_and_Hoist_Messy_Subscripts(WN* wn_loop,
00993 STACK<WN*>* stk_bounds,
00994 BOOL need_safe,
00995 LS_IN_LOOP* loop_ls)
00996 {
00997 STACK<WN*>* stk_messy = CXX_NEW(STACK<WN*>(&LNO_local_pool),
00998 &LNO_local_pool);
00999 while (TRUE) {
01000 stk_messy->Clear();
01001 HMB_Find_Messy_Subscripts(wn_loop, need_safe, stk_messy);
01002 if (stk_messy->Elements() == 0)
01003 return;
01004 HMB_Hoist_Messy_Subscripts(wn_loop, stk_messy, stk_bounds, loop_ls);
01005 }
01006 }
01007
01008
01009
01010
01011
01012
01013
01014
01015 static void HMB_Similar_Group(STACK<WN*>* stk_messy,
01016 STACK<WN*>* stk_group)
01017 {
01018 STACK<WN*> local_stack(&LNO_local_pool);
01019 WN* wn_pattern = stk_messy->Pop();
01020 stk_group->Push(wn_pattern);
01021 while (stk_messy->Elements() > 0) {
01022 WN* wn_trial = stk_messy->Pop();
01023 if (WN_Simp_Compare_Trees(wn_pattern, wn_trial) == 0)
01024 stk_group->Push(wn_trial);
01025 else
01026 local_stack.Push(wn_trial);
01027 }
01028 while (local_stack.Elements() > 0)
01029 stk_messy->Push(local_stack.Pop());
01030 }
01031
01032
01033
01034
01035
01036
01037 static void HMB_Hoist_Expressions(WN* wn_loop,
01038 STACK<WN*>* stk_messy)
01039 {
01040 DU_MANAGER* du = Du_Mgr;
01041 char buffer[MAX_NAME_SIZE];
01042 STACK<WN*> stk_group(&LNO_local_pool);
01043 while (stk_messy->Elements() > 0) {
01044 sprintf(buffer, "_mb%d", preg_counter++);
01045 HMB_Similar_Group(stk_messy, &stk_group);
01046 WN* wn_pattern = stk_group.Bottom_nth(0);
01047 TYPE_ID type = WN_rtype(wn_pattern);
01048 OPCODE preg_l_opcode = OPCODE_make_op(OPR_LDID, Promote_Type(type), type);
01049 OPCODE preg_s_opcode = OPCODE_make_op(OPR_STID, MTYPE_V, type);
01050 #ifdef _NEW_SYMTAB
01051 WN_OFFSET preg_num = Create_Preg(type, buffer);
01052 #else
01053 WN_OFFSET preg_num = Create_Preg(type, buffer, NULL);
01054 #endif
01055 ST* preg_st = MTYPE_To_PREG(type);
01056 WN* wn_hoist_place = Hoistable_Place(wn_pattern, du);
01057 WN* wn_parent = LWN_Get_Parent(wn_pattern);
01058 WN* wn_stid = LWN_CreateStid(preg_s_opcode, preg_num, preg_st,
01059 Be_Type_Tbl(type), wn_pattern);
01060 WN* wn_ldid = LWN_CreateLdid(preg_l_opcode, wn_stid);
01061 INT j;
01062 for (j = 0; j < WN_kid_count(wn_parent); j++)
01063 if (WN_kid(wn_parent, j) == wn_pattern)
01064 break;
01065 FmtAssert(j < WN_kid_count(wn_parent),
01066 ("Could not find kid for parent."));
01067 INT kid = j;
01068 WN_kid(wn_parent, kid) = wn_ldid;
01069 LWN_Set_Parent(wn_ldid, wn_parent);
01070 du->Add_Def_Use(wn_stid, wn_ldid);
01071 LWN_Insert_Block_Before(LWN_Get_Parent(wn_hoist_place),
01072 wn_hoist_place, wn_stid);
01073 INT i;
01074 for (i = 1; i < stk_group.Elements(); i++) {
01075 WN* wn_div_exp = stk_group.Bottom_nth(i);
01076 WN* wn_parent = LWN_Get_Parent(wn_div_exp);
01077 WN* wn_ldid = LWN_CreateLdid(preg_l_opcode, wn_stid);
01078 INT j;
01079 for (j = 0; j < WN_kid_count(wn_parent); j++)
01080 if (WN_kid(wn_parent, j) == wn_div_exp)
01081 break;
01082 FmtAssert(j < WN_kid_count(wn_parent),
01083 ("Could not find kid for parent."));
01084 INT kid = j;
01085 WN_kid(wn_parent, kid) = wn_ldid;
01086 LWN_Set_Parent(wn_ldid, wn_parent);
01087 du->Add_Def_Use(wn_stid, wn_ldid);
01088 LWN_Delete_Tree(wn_div_exp);
01089 }
01090 }
01091 DOLOOP_STACK rebuild_stack(&LNO_local_pool);
01092 Build_Doloop_Stack(LWN_Get_Parent(wn_loop), &rebuild_stack);
01093 LNO_Build_Access(wn_loop, &rebuild_stack, &LNO_default_pool);
01094 }
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107 static void HMB_Compound_Guard_And_Hoist(WN* wn_version[],
01108 INT guard_mask[],
01109 INT version_count,
01110 STACK<WN*>* stk_bounds,
01111 LS_IN_LOOP* loop_ls,
01112 BOOL no_messy_hoist)
01113 {
01114
01115 WN* wn_nest = NULL;
01116 WN* wn_last_nest = NULL;
01117 INT i;
01118 for (i = 0; i < version_count; i++) {
01119 WN* wn_guard = HMB_Compound_Guard_Test(wn_version[i], guard_mask[i],
01120 loop_ls);
01121 wn_nest = wn_guard != NULL ? wn_guard : wn_version[i];
01122 if (wn_last_nest != NULL) {
01123 LWN_Extract_From_Block(wn_nest);
01124 LWN_Insert_Block_After(WN_else(wn_last_nest), NULL, wn_nest);
01125 }
01126 wn_last_nest = wn_nest;
01127 }
01128
01129
01130
01131 for (i = 0; i < version_count; i++) {
01132 INT stack_count = stk_bounds->Elements();
01133 INT version_nloops = SNL_Loop_Count(wn_version[i]);
01134 for (INT j = 1; j <= version_nloops; j++) {
01135 WN* wn_loop = SNL_Get_Inner_Snl_Loop(wn_version[i], j);
01136 HMB_Replace_Messy_Bounds_Loop(wn_loop, wn_version[i], NULL,
01137 stk_bounds, loop_ls);
01138 if (!no_messy_hoist)
01139 MIR_Hoist_Messy_Subscripts(wn_version[i]);
01140 }
01141 HMB_Find_and_Hoist_Messy_Subscripts(wn_version[i], stk_bounds,
01142 TRUE, loop_ls);
01143 while (stk_bounds->Elements() > stack_count)
01144 (void) stk_bounds->Pop();
01145 }
01146 }
01147
01148
01149
01150
01151
01152
01153
01154
01155
01156 static void HAB_Copy_Array_Deps(WN* wn_orig,
01157 WN* wn_copy,
01158 BOOL inside_loop,
01159 LS_IN_LOOP* loop_ls)
01160 {
01161 if (!inside_loop)
01162 return;
01163 ARRAY_DIRECTED_GRAPH16* dg = Array_Dependence_Graph;
01164 DOLOOP_STACK copy_stack(&LNO_local_pool);
01165 Build_Doloop_Stack(wn_copy, ©_stack);
01166 LNO_Build_Access(WN_kid0(wn_copy), ©_stack, &LNO_default_pool);
01167 VINDEX16 v = dg->Get_Vertex(wn_orig);
01168 if (v == 0)
01169 return;
01170 STACK<WN*> wn_stack(&LNO_local_pool);
01171 EINDEX16 e = 0;
01172 INT node_position = loop_ls->In(wn_orig);
01173 for (e = dg->Get_In_Edge(v); e != 0; e = dg->Get_Next_In_Edge(e)) {
01174 WN* wn_source = dg->Get_Wn(dg->Get_Source(e));
01175 INT i;
01176 for (i = 0; i < wn_stack.Elements(); i++)
01177 if (wn_stack.Bottom_nth(i) == wn_source)
01178 break;
01179 if (i == wn_stack.Elements())
01180 wn_stack.Push(wn_source);
01181 }
01182 for (e = dg->Get_Out_Edge(v); e != 0; e = dg->Get_Next_Out_Edge(e)) {
01183 WN* wn_sink = dg->Get_Wn(dg->Get_Sink(e));
01184 INT i;
01185 for (i = 0; i < wn_stack.Elements(); i++)
01186 if (wn_stack.Bottom_nth(i) == wn_sink)
01187 break;
01188 if (i == wn_stack.Elements())
01189 wn_stack.Push(wn_sink);
01190 }
01191 dg->Add_Vertex(wn_copy);
01192 DOLOOP_STACK other_stack(&LNO_local_pool);
01193 for (INT i = 0; i < wn_stack.Elements(); i++) {
01194 WN* wn_other = wn_stack.Bottom_nth(i);
01195 Build_Doloop_Stack(wn_other, &other_stack);
01196 if (!dg->Add_Edge(wn_copy, ©_stack, wn_other, &other_stack,
01197 node_position < loop_ls->In(wn_other))) {
01198 LNO_Erase_Dg_From_Here_In(wn_other, dg);
01199 }
01200 other_stack.Clear();
01201 }
01202 }
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212
01213 static void HAB_Copy_Array_Deps_Exp(WN* wn_orig,
01214 WN* wn_copy,
01215 BOOL inside_loop,
01216 LS_IN_LOOP* loop_ls)
01217 {
01218 if (WN_operator(wn_orig) == OPR_ILOAD)
01219 HAB_Copy_Array_Deps(wn_orig, wn_copy, inside_loop, loop_ls);
01220 for (INT i = 0; i < WN_kid_count(wn_orig); i++) {
01221 WN* wn_orig_kid = WN_kid(wn_orig, i);
01222 WN* wn_copy_kid = WN_kid(wn_copy, i);
01223 HAB_Copy_Array_Deps_Exp(wn_orig_kid, wn_copy_kid, inside_loop, loop_ls);
01224 }
01225 }
01226
01227
01228
01229
01230
01231
01232
01233
01234
01235
01236 static void HMB_Simple_Guard_And_Hoist(WN* wn_version,
01237 INT guard_mask,
01238 STACK<WN*>* stk_bounds,
01239 LS_IN_LOOP* loop_ls,
01240 BOOL no_messy_hoist)
01241 {
01242 INT nloops = SNL_Loop_Count(wn_version);
01243 INT outer_depth = Do_Loop_Depth(wn_version);
01244 INT inner_depth = outer_depth + nloops - 1;
01245 WN** wn_guard = CXX_NEW_ARRAY(WN*, inner_depth + 1, &LNO_local_pool);
01246 INT i;
01247 for (i = 0; i < inner_depth + 1; i++)
01248 wn_guard[i] = NULL;
01249 WN* wn = 0;
01250 for (wn = wn_version; wn != NULL; wn = Find_Next_Innermost_Do(wn)) {
01251 INT current_depth = Do_Loop_Depth(wn);
01252 if (guard_mask & (1 << current_depth)) {
01253 WN* wn_guard_test = HMB_Simple_Guard_Test(wn, wn_version, loop_ls);
01254 wn_guard[current_depth] = wn_guard_test;
01255 }
01256 }
01257 for (wn = wn_version; wn != NULL; wn = Find_Next_Innermost_Do(wn)) {
01258 INT current_depth = Do_Loop_Depth(wn);
01259 HMB_Replace_Messy_Bounds_Loop(wn, wn_version, wn_guard[current_depth],
01260 stk_bounds, loop_ls);
01261 if (wn_guard[current_depth] != NULL)
01262 LWN_Simplify_Tree(WN_if_test(wn_guard[current_depth]));
01263 }
01264 HMB_Find_and_Hoist_Messy_Subscripts(wn_version, stk_bounds, TRUE, loop_ls);
01265 if (!no_messy_hoist)
01266 MIR_Hoist_Messy_Subscripts(wn_version);
01267 }
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277
01278
01279
01280 static void HMB_Has_Messy_Subscript(WN* wn_loop,
01281 STACK<WN*>* stk_messy,
01282 INT can_hoist[],
01283 INT lowest_depth[],
01284 BOOL initialize)
01285 {
01286 DU_MANAGER* du = Du_Mgr;
01287 STACK<WN*> local_stack(&LNO_local_pool);
01288 if (initialize) {
01289 INT count = SNL_Loop_Count(wn_loop);
01290 WN* wn_inner = SNL_Get_Inner_Snl_Loop(wn_loop, count);
01291 INT inner_depth = Do_Loop_Depth(wn_inner);
01292 for (INT i = 0; i <= inner_depth; i++) {
01293 can_hoist[i] = 0;
01294 lowest_depth[i] = i;
01295 }
01296 }
01297 for (INT i = 0; i < stk_messy->Elements(); i++) {
01298 WN* wn = stk_messy->Bottom_nth(i);
01299 INT depth = Loop_Depth(wn);
01300 WN* wn_hoist = Hoistable_Place(wn, du);
01301 INT hoist_depth = Loop_Depth(wn_hoist);
01302 if (hoist_depth < depth) {
01303 local_stack.Push(wn);
01304 can_hoist[depth]++;
01305 if (hoist_depth < lowest_depth[depth])
01306 lowest_depth[depth] = hoist_depth;
01307 }
01308 }
01309 stk_messy->Clear();
01310 while (local_stack.Elements() > 0)
01311 stk_messy->Push(local_stack.Pop());
01312 }
01313
01314
01315
01316
01317
01318
01319
01320 static void HMB_Hoist_Messy_Bounds(WN* wn_snl,
01321 STACK<WN*>* stk_bounds,
01322 LS_IN_LOOP* loop_ls)
01323 {
01324 ARRAY_DIRECTED_GRAPH16* dg = Array_Dependence_Graph;
01325 REDUCTION_MANAGER* rm = red_manager;
01326
01327 WN* wn_inner = NULL;
01328 WN* wn = 0;
01329 for (wn = wn_snl; wn != NULL; wn = Find_Next_Innermost_Do(wn))
01330 wn_inner = wn;
01331 INT outer_depth = Do_Loop_Depth(wn_snl);
01332 INT inner_depth = Do_Loop_Depth(wn_inner);
01333 INT nloops = inner_depth - outer_depth + 1;
01334
01335
01336 INT* has_code = CXX_NEW_ARRAY(INT, inner_depth + 1, &LNO_local_pool);
01337 INT* has_messy_bound = CXX_NEW_ARRAY(INT, inner_depth + 1, &LNO_local_pool);
01338 INT* guard_test_true = CXX_NEW_ARRAY(INT, inner_depth + 1, &LNO_local_pool);
01339 INT* can_hoist = CXX_NEW_ARRAY(INT, inner_depth + 1, &LNO_local_pool);
01340 INT* lowest_depth = CXX_NEW_ARRAY(INT, inner_depth + 1, &LNO_local_pool);
01341 WN** wn_guards = CXX_NEW_ARRAY(WN*, inner_depth + 1, &LNO_local_pool);
01342 INT i;
01343 for (i = 0; i <= inner_depth; i++) {
01344 has_code[i] = 0;
01345 has_messy_bound[i] = 0;
01346 guard_test_true[i] = 0;
01347 wn_guards[i] = NULL;
01348 }
01349 for (i = outer_depth; i <= inner_depth; i++)
01350 has_code[i] = Has_Code_At_Depth(wn_snl, nloops, i);
01351 for (i = outer_depth; i <= inner_depth; i++) {
01352 WN* wn = SNL_Get_Inner_Snl_Loop(wn_snl, i - outer_depth + 1);
01353 if (HMB_Has_Messy_Left_Bound(wn) || HMB_Has_Messy_Right_Bound(wn))
01354 has_messy_bound[i] = TRUE;
01355 guard_test_true[i] = Guard_Test_Redundant(wn, wn_guards, i);
01356 }
01357 for (i = outer_depth; i <= inner_depth; i++)
01358 LWN_Delete_Tree(wn_guards[i]);
01359
01360 STACK<WN*> stk_safe_messy(&LNO_local_pool);
01361 HMB_Find_Messy_Subscripts(wn_snl, TRUE, &stk_safe_messy);
01362 STACK<WN*> stk_unsafe_messy(&LNO_local_pool);
01363 MIR_Has_Messy_Subscript(wn_snl, can_hoist, lowest_depth, TRUE);
01364
01365
01366
01367 BOOL no_messy_hoist = FALSE;
01368 DOLOOP_STACK stk_loop(&LNO_local_pool);
01369 Build_Doloop_Stack(wn_inner, &stk_loop);
01370 for (i = outer_depth; !no_messy_hoist && i <= inner_depth; i++)
01371 if (can_hoist[i])
01372 for (INT j = lowest_depth[i]; !no_messy_hoist && j < inner_depth; j++)
01373 for (INT k = j + 1; !no_messy_hoist && k <= inner_depth; k++)
01374 if (!SNL_Is_Invariant(&stk_loop, j, k))
01375 no_messy_hoist = TRUE;
01376 if (no_messy_hoist)
01377 for (i = outer_depth; i <= inner_depth; i++)
01378 can_hoist[i] = 0;
01379
01380
01381 for (i = outer_depth; i <= inner_depth; i++)
01382 if (has_messy_bound[i] || can_hoist[i])
01383 break;
01384 if (i > inner_depth && stk_safe_messy.Elements() == 0)
01385 return;
01386
01387
01388 if (LNO_Verbose) {
01389 fprintf(stdout, "HMB: Transforming SNL %s at 0x%p\n",
01390 WB_Whirl_Symbol(wn_snl), wn_snl);
01391 fprintf(TFile, "HMB: Transforming SNL %s at 0x%p\n",
01392 WB_Whirl_Symbol(wn_snl), wn_snl);
01393 }
01394
01395
01396 INT* guard_mask = CXX_NEW_ARRAY(INT, inner_depth + 1, &LNO_local_pool);
01397 INT* last_loop = CXX_NEW_ARRAY(INT, inner_depth + 1, &LNO_local_pool);
01398 for (i = 0; i <= inner_depth; i++) {
01399 last_loop[i] = 0;
01400 guard_mask[i] = 0;
01401 }
01402 INT inside_depth = inner_depth;
01403 INT version_count;
01404 for (version_count = 0; inside_depth >= outer_depth; version_count++) {
01405 last_loop[version_count] = inside_depth;
01406 for (INT i = inside_depth; i >= outer_depth; i--) {
01407 if (i > outer_depth && has_messy_bound[i]) {
01408 for (INT j = outer_depth; j < i; j++)
01409 if (!guard_test_true[j])
01410 guard_mask[version_count] |= 1 << j;
01411 }
01412 if (can_hoist[i]) {
01413 for (INT j = lowest_depth[i]; j <= i; j++)
01414 if (!guard_test_true[j])
01415 guard_mask[version_count] |= 1 << j;
01416 }
01417 }
01418 if (guard_mask[version_count] == 0) {
01419 version_count++;
01420 break;
01421 }
01422 for (inside_depth--; inside_depth >= outer_depth
01423 && !has_code[inside_depth]; inside_depth--);
01424 }
01425
01426
01427 WN* wn_array[2];
01428 wn_array[0] = wn_snl;
01429 WN* wn_insert = wn_snl;
01430 WN** wn_version = CXX_NEW_ARRAY(WN*, version_count, &LNO_local_pool);
01431 for (i = 0; i < version_count; i++)
01432 wn_version[i] = NULL;
01433 for (i = 0; i < version_count; i++) {
01434 WN_MAP version_map = WN_MAP_Create(&LNO_local_pool);
01435 wn_version[i] = LWN_Copy_Tree(wn_snl, TRUE, LNO_Info_Map, TRUE,
01436 version_map);
01437 BOOL all_internal = WN_Rename_Duplicate_Labels(wn_snl, wn_version[i],
01438 Current_Func_Node, &LNO_local_pool);
01439 Is_True(all_internal, ("external labels renamed"));
01440 wn_array[1] = wn_version[i];
01441 Unrolled_DU_Update(wn_array, 2, Do_Loop_Depth(wn_snl) - 1, TRUE, FALSE);
01442 dg->Versioned_Dependences_Update(wn_snl, wn_version[i],
01443 outer_depth, version_map);
01444 WN_MAP_Delete(version_map);
01445 if (rm != NULL)
01446 rm->Unroll_Update(wn_array, 2);
01447 LWN_Insert_Block_After(LWN_Get_Parent(wn_insert), wn_insert,
01448 wn_version[i]);
01449 if (i > 0) {
01450 WN* wn_new_inner = SNL_Get_Inner_Snl_Loop(wn_version[i],
01451 last_loop[i] - outer_depth + 1);
01452 DO_LOOP_INFO* dli_new_inner = Get_Do_Loop_Info(wn_new_inner);
01453 dli_new_inner->Is_Inner = TRUE;
01454 WN* wn_tree = SNL_Get_Inner_Snl_Loop(wn_version[i],
01455 last_loop[i] - outer_depth + 2);
01456 LWN_Extract_From_Block(wn_tree);
01457 LWN_Delete_Tree(wn_tree);
01458 }
01459 wn_insert = wn_version[i];
01460 }
01461
01462
01463 if (Prompf_Info != NULL && Prompf_Info->Is_Enabled())
01464 Prompf_Hoist_Messy_Bounds(wn_snl, wn_version, version_count,
01465 outer_depth, inner_depth);
01466
01467 if (version_count > 1 || Get_Trace(TP_LNOPT2, TT_HMB_FORCE_VERSIONS))
01468 HMB_Compound_Guard_And_Hoist(wn_version, guard_mask, version_count,
01469 stk_bounds, loop_ls, no_messy_hoist);
01470 else
01471 HMB_Simple_Guard_And_Hoist(wn_version[0], guard_mask[0], stk_bounds,
01472 loop_ls, no_messy_hoist);
01473
01474
01475 LWN_Extract_From_Block(wn_snl);
01476 LWN_Delete_Tree(wn_snl);
01477 }
01478
01479
01480
01481
01482
01483
01484 static void Forward_Substitute_SNL_Bounds(WN* wn_loop)
01485 {
01486 DU_MANAGER* du = Du_Mgr;
01487 INT nloops = SNL_Loop_Count(wn_loop);
01488 WN* wn_inner = SNL_Get_Inner_Snl_Loop(wn_loop, nloops);
01489 for (WN* wn = wn_inner; wn != NULL; wn = LWN_Get_Parent(wn)) {
01490 if (WN_opcode(wn) != OPC_DO_LOOP)
01491 continue;
01492 Forward_Substitute_Ldids(WN_kid0(WN_start(wn)), du);
01493 Forward_Substitute_Ldids(WN_end(wn), du);
01494 if (wn == wn_loop)
01495 break;
01496 }
01497 }
01498
01499
01500
01501
01502
01503
01504
01505 static void SNL_Finalize_Index_Variables(WN* wn_loop)
01506 {
01507 for (WN* wn = wn_loop; wn != NULL; wn = Find_Next_Innermost_Do(wn))
01508 if (Index_Variable_Live_At_Exit(wn))
01509 Finalize_Index_Variable(wn, TRUE, TRUE);
01510 }
01511
01512
01513
01514
01515
01516
01517
01518
01519 static BOOL Has_Statically_Safe_Messy_Bounds(WN* wn_loop)
01520 {
01521 BOOL found_messy_bound = FALSE;
01522 if (HMB_Has_Messy_Left_Bound(wn_loop)) {
01523 found_messy_bound = TRUE;
01524 if (!Statically_Safe_Exp(WN_kid0(WN_start(wn_loop))))
01525 return FALSE;
01526 }
01527 if (HMB_Has_Messy_Right_Bound(wn_loop)) {
01528 found_messy_bound = TRUE;
01529 if (!Statically_Safe_Exp(UBexp(WN_end(wn_loop))))
01530 return FALSE;
01531 }
01532 return found_messy_bound;
01533 }
01534
01535
01536
01537
01538
01539
01540
01541
01542 static void HMB_Hoist_Easy_Messy_Bounds(WN* wn_loop,
01543 STACK<WN*>* stk_bounds,
01544 LS_IN_LOOP* loop_ls)
01545 {
01546 DU_MANAGER* du = Du_Mgr;
01547 ARRAY_DIRECTED_GRAPH16* dg = Array_Dependence_Graph;
01548 INT nloops = SNL_Loop_Count(wn_loop);
01549 WN* wn_inner = SNL_Get_Inner_Snl_Loop(wn_loop, nloops);
01550 WN* wn_final = LWN_Get_Parent(wn_loop);
01551 for (WN* wn = wn_inner; wn != wn_final; wn = LWN_Get_Parent(wn))
01552 if (WN_opcode(wn) == OPC_DO_LOOP
01553 && Has_Statically_Safe_Messy_Bounds(wn))
01554 HMB_Replace_Messy_Bounds_Loop(wn, wn_loop, NULL, stk_bounds,
01555 loop_ls);
01556 }
01557
01558
01559
01560
01561
01562
01563
01564 static void HMB_Hoist_Easy_Messy_Subscripts(WN* wn_loop)
01565 {
01566 INT messy_count = 0;
01567 LWN_ITER* itr = LWN_WALK_TreeIter(wn_loop);
01568 for (; itr != NULL; itr = LWN_WALK_TreeNext(itr)) {
01569 WN* wn_array = itr->wn;
01570 WN* wn_messy = Messy_Subscript(wn_array);
01571 if (wn_messy != NULL) {
01572 messy_count++;
01573 if (!Statically_Safe_Exp(wn_messy))
01574 return;
01575 }
01576 }
01577 if (messy_count > 0)
01578 MIR_Hoist_Messy_Subscripts(wn_loop);
01579 }
01580
01581
01582
01583
01584
01585
01586
01587 static void SNL_Hoist_Messy_Bounds(WN* wn_snl)
01588 {
01589 DU_MANAGER* du = Du_Mgr;
01590 ARRAY_DIRECTED_GRAPH16* dg = Array_Dependence_Graph;
01591 REDUCTION_MANAGER* rm = red_manager;
01592
01593 if (!LNO_Hoist_Messy_Bounds)
01594 return;
01595
01596 WN* wn_outer = wn_snl;
01597 Forward_Substitute_SNL_Bounds(wn_snl);
01598 for (WN* wn = wn_outer; wn != NULL; wn = LWN_Get_Parent(wn))
01599 if (WN_opcode(wn) == OPC_DO_LOOP)
01600 wn_outer = wn;
01601 WN* wn_max = HMB_Maximum_Point(wn_snl);
01602 if (wn_max == NULL)
01603 return;
01604
01605 STACK<WN*>* stk_bounds = CXX_NEW(STACK<WN*>(&LNO_local_pool),
01606 &LNO_local_pool);
01607 LS_IN_LOOP* loop_ls = CXX_NEW(LS_IN_LOOP(wn_outer, dg, &LNO_local_pool,
01608 TRUE), &LNO_local_pool);
01609 HMB_Hoist_Easy_Messy_Bounds(wn_max, stk_bounds, loop_ls);
01610 HMB_Hoist_Easy_Messy_Subscripts(wn_max);
01611 wn_max = Code_Expansion_Limit_Loop(wn_max);
01612 HMB_Replace_Messy_Bounds_Loop(wn_max, wn_max, NULL, stk_bounds, loop_ls);
01613 SNL_Finalize_Index_Variables(wn_max);
01614 HMB_Hoist_Messy_Bounds(wn_max, stk_bounds, loop_ls);
01615 }
01616
01617
01618
01619
01620
01621
01622
01623
01624 extern void Hoist_Messy_Bounds(WN* func_nd)
01625 {
01626 if (!LNO_Hoist_Messy_Bounds)
01627 return;
01628
01629 FIZ_FUSE_INFO* ffi=
01630 CXX_NEW(FIZ_FUSE_INFO(&LNO_local_pool), &LNO_local_pool);
01631 ffi->Build(func_nd);
01632
01633 for (INT i = 0; i < ffi->Num_Snl(); i++) {
01634 if (ffi->Get_Depth(i) < 1 || ffi->Get_Type(i) != Inner)
01635 continue;
01636 SNL_Hoist_Messy_Bounds(ffi->Get_Wn(i));
01637 }
01638 }
01639