00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048 #define __STDC_LIMIT_MACROS
00049 #include <stdint.h>
00050 #ifdef USE_PCH
00051 #include "lno_pch.h"
00052 #endif // USE_PCH
00053 #pragma hdrstop
00054
00055 #ifdef _KEEP_RCS_ID
00056
00057 static char *rcs_id = "$Source: be/lno/SCCS/s.move.cxx $ $Revision: 1.9 $";
00058 #endif
00059
00060 #include <alloca.h>
00061 #include <sys/types.h>
00062 #include <ctype.h>
00063 #include <limits.h>
00064
00065 #include "pu_info.h"
00066 #include "lnoutils.h"
00067 #include "config.h"
00068 #include "config_cache.h"
00069 #include "config_lno.h"
00070 #include "lnopt_main.h"
00071 #include "stab.h"
00072 #include "targ_const.h"
00073 #include "wn_simp.h"
00074 #include "stdlib.h"
00075 #include "lwn_util.h"
00076 #include "strtab.h"
00077 #include "targ_sim.h"
00078 #include "optimizer.h"
00079 #include "opt_du.h"
00080 #include "name.h"
00081 #include "wintrinsic.h"
00082 #include "lno_bv.h"
00083 #include "region_util.h"
00084 #include "lego_gen.h"
00085 #include "snl_utils.h"
00086 #include "dep_graph.h"
00087 #include "wn_pragmas.h"
00088 #include "ff_utils.h"
00089 #include "move.h"
00090 #include "w2op.h"
00091 #include "prompf.h"
00092 #include "anl_driver.h"
00093 #include "ipa_lno_util.h"
00094 #include "call_info.h"
00095 #include "debug.h"
00096 #include "opt_alias_interface.h"
00097 #include "opt_alias_mgr.h"
00098 #include "ara_utils.h"
00099
00100
00101
00102
00103
00104
00105
00106
00107 extern void Hoist_Statement(WN* wn_stat,
00108 INT hoist_level)
00109 {
00110 if (Loop_Depth(wn_stat) == hoist_level)
00111 return;
00112
00113 WN* place_loop = NULL;
00114 for (WN* wn = wn_stat; wn != NULL; wn = LWN_Get_Parent(wn)) {
00115 if (WN_opcode(wn) == OPC_DO_LOOP) {
00116 DO_LOOP_INFO* dli = Get_Do_Loop_Info(wn);
00117 if (dli->Depth == hoist_level + 1) {
00118 place_loop = wn;
00119 break;
00120 }
00121 }
00122 }
00123 FmtAssert(place_loop != NULL, ("Could not find place loop."));
00124 FmtAssert(WN_opcode(place_loop) == OPC_DO_LOOP,
00125 ("Did not find do loop of correct level"));
00126 wn_stat = LWN_Extract_From_Block(wn_stat);
00127 LWN_Insert_Block_Before(LWN_Get_Parent(place_loop), place_loop, wn_stat);
00128 }
00129
00130
00131
00132
00133
00134
00135
00136
00137 static BOOL Single_Definition_Uses(WN* wn_stid)
00138 {
00139 USE_LIST *use_list = Du_Mgr->Du_Get_Use(wn_stid);
00140 if (use_list == NULL)
00141 return TRUE;
00142 if (use_list->Incomplete())
00143 return FALSE;
00144 USE_LIST_ITER iter(use_list);
00145 const DU_NODE* node1 = NULL;
00146 for (node1 = iter.First(); !iter.Is_Empty(); node1 = iter.Next()) {
00147 WN* wn_use = node1->Wn();
00148 DEF_LIST* def_list = Du_Mgr->Ud_Get_Def(wn_use);
00149 if (def_list->Incomplete())
00150 return FALSE;
00151 DEF_LIST_ITER iter(def_list);
00152 const DU_NODE* node2 = NULL;
00153 for (node2 = iter.First(); !iter.Is_Empty(); node2 = iter.Next()) {
00154 WN* wn_def = node2->Wn();
00155 if (wn_def != wn_stid)
00156 return FALSE;
00157 }
00158 }
00159 return TRUE;
00160 }
00161
00162
00163
00164
00165
00166
00167
00168 static BOOL Possibly_Used_Outside_Program_Unit(WN* wn_stid)
00169 {
00170 USE_LIST *use_list = Du_Mgr->Du_Get_Use(wn_stid);
00171 if (use_list == NULL)
00172 return FALSE;
00173 if (use_list->Incomplete())
00174 return TRUE;
00175 USE_LIST_ITER iter(use_list);
00176 const DU_NODE* node1 = NULL;
00177 for (node1 = iter.First(); !iter.Is_Empty(); node1 = iter.Next()) {
00178 WN* wn_use = node1->Wn();
00179 if (WN_opcode(wn_use) == OPC_RETURN
00180 #ifdef KEY
00181 || WN_opcode(wn_use) == OPC_GOTO_OUTER_BLOCK
00182 #endif
00183 )
00184 return TRUE;
00185 }
00186 return FALSE;
00187 }
00188
00189
00190
00191
00192
00193
00194
00195
00196 static INT Region_Depth(WN* wn_stid)
00197 {
00198 for (WN* wn = wn_stid; wn != NULL; wn = LWN_Get_Parent(wn))
00199 if (WN_opcode(wn) == OPC_REGION)
00200 return Loop_Depth(wn);
00201 return -1;
00202 }
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213 static BOOL May_Be_Same_Memory(WN* wn_stid, WN* wn)
00214 {
00215 if (WN_operator(wn_stid) == OPR_LDA)
00216 return WN_operator(wn) == OPR_STID
00217 && SYMBOL(wn_stid) == SYMBOL(wn);
00218 if (!OPCODE_is_store(WN_opcode(wn)))
00219 return FALSE;
00220 if (!Valid_alias(Alias_Mgr, wn))
00221 return TRUE;
00222 if (Aliased(Alias_Mgr, wn_stid, wn) == NOT_ALIASED)
00223 return FALSE;
00224 return TRUE;
00225 }
00226
00227
00228
00229
00230
00231
00232
00233 extern WN* Initial_Hoist_Place(WN* wn_stat)
00234 {
00235 WN* wn_return = WN_func_body(Current_Func_Node);
00236 WN *wn;
00237 for (wn = wn_stat; wn != wn_return; wn = LWN_Get_Parent(wn))
00238 if (WN_opcode(wn) == OPC_REGION)
00239 break;
00240 if (WN_opcode(wn) == OPC_REGION)
00241 wn_return = wn;
00242 return wn_return;
00243 }
00244
00245
00246
00247
00248
00249
00250
00251
00252 extern WN* Hoist_Merge(WN* wn1, WN* wn2)
00253 {
00254 if (Wn_Is_Inside(wn1, wn2))
00255 return wn1;
00256 if (Wn_Is_Inside(wn2, wn1))
00257 return wn2;
00258 return NULL;
00259 }
00260
00261
00262
00263
00264
00265
00266
00267 static WN* Scalar_Store_Hoist_Place(WN* wn_stid)
00268 {
00269 if (!Single_Definition_Uses(wn_stid))
00270 return NULL;
00271 if (Possibly_Used_Outside_Program_Unit(wn_stid))
00272 return NULL;
00273 WN* wn_return = Initial_Hoist_Place(wn_stid);
00274 WN* wn_outer_loop = NULL;
00275 for (WN* wn = wn_stid; wn != NULL; wn = LWN_Get_Parent(wn))
00276 if (WN_opcode(wn) == OPC_DO_LOOP)
00277 wn_outer_loop = wn;
00278 if (wn_outer_loop == NULL)
00279 return NULL;
00280 LWN_ITER* itr = LWN_WALK_TreeIter(wn_outer_loop);
00281 for (; itr != NULL; itr = LWN_WALK_TreeNext(itr)) {
00282 WN* wn = itr->wn;
00283 if (wn == wn_stid || !May_Be_Same_Memory(wn_stid, wn))
00284 continue;
00285 wn_return = Hoist_Merge(Common_Ancestor(wn, wn_stid), wn_return);
00286 if (wn_return == NULL)
00287 return NULL;
00288 }
00289 return wn_return;
00290 }
00291
00292
00293
00294
00295
00296
00297
00298 extern WN* Hoist_Place(WN* wn_stat,
00299 DU_MANAGER* du)
00300 {
00301 ARRAY_DIRECTED_GRAPH16* dg = Array_Dependence_Graph;
00302 WN* wn_return = NULL;
00303 OPERATOR opr = WN_operator(wn_stat);
00304 switch (opr) {
00305 case OPR_LDID: {
00306 if (dg == NULL || dg->Get_Vertex(wn_stat))
00307 return NULL;
00308 wn_return = Initial_Hoist_Place(wn_stat);
00309 DEF_LIST *def_list = du->Ud_Get_Def(wn_stat);
00310 if (def_list == NULL || def_list->Incomplete())
00311 return NULL;
00312 if (def_list->Loop_stmt() != NULL)
00313 wn_return = Hoist_Merge(def_list->Loop_stmt(), wn_return);
00314 DEF_LIST_ITER iter(def_list);
00315 const DU_NODE* node = NULL;
00316 for (node = iter.First(); !iter.Is_Empty(); node = iter.Next()) {
00317 WN* wn_def = node->Wn();
00318 wn_return = Hoist_Merge(Common_Ancestor(wn_def, wn_stat), wn_return);
00319 if (wn_return == NULL)
00320 return NULL;
00321 }
00322 return wn_return;
00323 }
00324 case OPR_STID:
00325 {
00326 if (dg == NULL || dg->Get_Vertex(wn_stat))
00327 return NULL;
00328 if (ST_class(WN_st(wn_stat)) == CLASS_PREG
00329 && Preg_Is_Dedicated(WN_offset(wn_stat)))
00330 return NULL;
00331 wn_return = Hoist_Place(WN_kid0(wn_stat), du);
00332 if (wn_return == NULL)
00333 return NULL;
00334 WN* wn_store_hoist = Scalar_Store_Hoist_Place(wn_stat);
00335 if (wn_store_hoist == NULL)
00336 return NULL;
00337 wn_return = Hoist_Merge(wn_store_hoist, wn_return);
00338 return wn_return;
00339 }
00340 case OPR_DIV:
00341 case OPR_REM:
00342 case OPR_ADD:
00343 case OPR_SUB:
00344 case OPR_MPY:
00345 case OPR_MIN:
00346 case OPR_MAX:
00347 case OPR_NEG:
00348 case OPR_LAND:
00349 case OPR_LIOR:
00350 case OPR_CAND:
00351 case OPR_CIOR:
00352 case OPR_MOD:
00353 case OPR_EQ:
00354 case OPR_NE:
00355 case OPR_GE:
00356 case OPR_GT:
00357 case OPR_LE:
00358 case OPR_LT:
00359 case OPR_CVT:
00360 case OPR_TRUNC:
00361 case OPR_INTRINSIC_CALL:
00362 case OPR_INTRINSIC_OP:
00363 {
00364 if (!((opr == OPR_DIV || opr == OPR_REM || opr == OPR_MOD)
00365 && Safe_Spec_Map != WN_MAP_UNDEFINED
00366 && WN_MAP_Get(Safe_Spec_Map, (WN*) wn_stat)
00367 || Statically_Safe_Node(wn_stat)))
00368 return NULL;
00369 wn_return = Initial_Hoist_Place(wn_stat);
00370 for (INT i = 0; i < WN_kid_count(wn_stat); i++) {
00371 WN* wn_hoist = Hoist_Place(WN_kid(wn_stat, i), du);
00372 if (wn_hoist == NULL)
00373 return NULL;
00374 wn_return = Hoist_Merge(wn_hoist, wn_return);
00375 Is_True(wn_return != NULL, ("Expected a node in the parent chain"));
00376 if (wn_return == NULL)
00377 return NULL;
00378 }
00379 return wn_return;
00380 }
00381 case OPR_PARM:
00382 if (WN_Parm_By_Value(wn_stat))
00383 return Hoist_Place(WN_kid0(wn_stat), du);
00384 if (WN_Parm_By_Reference(wn_stat))
00385 return Scalar_Store_Hoist_Place(WN_kid0(wn_stat));
00386 FmtAssert(FALSE, ("Parameter must be by value or by reference."));
00387 case OPR_CALL:
00388 #ifdef KEY
00389 case OPR_PURE_CALL_OP:
00390 #endif
00391 {
00392 if (!Special_Lego_Or_Mp_Call(WN_st(wn_stat))
00393 && (WN_Call_Never_Return(wn_stat) || WN_Call_Non_Data_Mod(wn_stat)
00394 || WN_Call_Non_Data_Ref(wn_stat) || WN_Call_Non_Parm_Mod(wn_stat)
00395 || WN_Call_Non_Parm_Ref(wn_stat) || WN_Call_Parm_Mod(wn_stat)))
00396 return wn_stat;
00397 USE_LIST *use_list = du->Du_Get_Use(wn_stat);
00398 if (use_list == NULL || use_list->Incomplete())
00399 return wn_stat;
00400 USE_LIST_ITER iter(use_list);
00401 const DU_NODE* node = NULL;
00402 for (node = iter.First(); !iter.Is_Empty(); node = iter.Next()) {
00403 WN* wn_use = node->Wn();
00404 if (OPCODE_has_sym(WN_opcode(wn_use))
00405 && ST_class(WN_st(wn_use)) == CLASS_PREG
00406 && Preg_Is_Dedicated(WN_offset(wn_use)))
00407 return wn_stat;
00408 }
00409 WN* wn_return = Initial_Hoist_Place(wn_stat);
00410 for (INT i = 0; i < WN_kid_count(wn_stat); i++) {
00411 WN* wn_hoist = Hoist_Place(WN_kid(wn_stat, i), du);
00412 if (wn_hoist == NULL)
00413 return NULL;
00414 wn_return = Hoist_Merge(wn_hoist, wn_return);
00415 Is_True(wn_return != NULL, ("Expected a node in the parent chain"));
00416 if (wn_return == NULL)
00417 return NULL;
00418 }
00419 return wn_return;
00420 }
00421 case OPR_INTCONST:
00422 case OPR_CONST:
00423 return Initial_Hoist_Place(wn_stat);
00424 default:
00425 return NULL;
00426 }
00427 }
00428
00429
00430
00431
00432
00433
00434
00435 extern INT Hoistable_Statement(WN* wn_stat,
00436 DU_MANAGER* du)
00437 {
00438 WN* wn_place = Hoist_Place(wn_stat, du);
00439 if (wn_place == NULL)
00440 return Loop_Depth(wn_stat);
00441 for (WN* wn = wn_place; wn != NULL; wn = LWN_Get_Parent(wn))
00442 if (WN_opcode(wn) == OPC_DO_LOOP)
00443 return Do_Depth(wn);
00444 return -1;
00445 }
00446
00447
00448
00449
00450
00451
00452
00453 extern WN* Hoistable_Place(WN* wn_stat,
00454 DU_MANAGER* du)
00455 {
00456 WN* wn_place = Hoist_Place(wn_stat, du);
00457 if (wn_place == NULL)
00458 return NULL;
00459 WN* wn_return = NULL;
00460 for (WN* wn = wn_stat; wn != wn_place; wn = LWN_Get_Parent(wn))
00461 if (WN_opcode(LWN_Get_Parent(wn)) == OPC_BLOCK)
00462 wn_return = wn;
00463 return wn_return;
00464 }
00465
00466
00467
00468
00469
00470
00471
00472 extern void Hoist_Statements(WN* wn_outer_loop,
00473 DU_MANAGER* du)
00474 {
00475 WN* next_stat = NULL;
00476 WN* first_stat = WN_first(WN_do_body(wn_outer_loop));
00477 INT hoist_level = -1;
00478 for (WN* stat = first_stat; stat != NULL; stat = next_stat) {
00479 next_stat = WN_next(stat);
00480 if (WN_opcode(stat) == OPC_DO_LOOP) {
00481 DO_LOOP_INFO* dli = Get_Do_Loop_Info(stat);
00482 if (!dli->Is_Inner)
00483 Hoist_Statements(stat, du);
00484 } else {
00485 hoist_level = Hoistable_Statement(stat, du);
00486 if (hoist_level < Loop_Depth(stat))
00487 Hoist_Statement(stat, hoist_level);
00488 }
00489 }
00490 }
00491
00492
00493
00494
00495
00496
00497 static WN* Get_Statement(WN* wn_node)
00498 {
00499 if (WN_opcode(wn_node) == OPC_FUNC_ENTRY)
00500 return wn_node;
00501 WN *wn;
00502 for (wn = wn_node; wn != NULL; wn = LWN_Get_Parent(wn))
00503 if (LWN_Get_Parent(wn) != NULL
00504 && WN_opcode(LWN_Get_Parent(wn)) == OPC_BLOCK)
00505 return wn;
00506 FmtAssert(wn != NULL, ("Could not find enclosing block"));
00507 return NULL;
00508 }
00509
00510
00511
00512
00513
00514
00515
00516 static WN* New_Lowest_Statement(WN* wn_one,
00517 WN* wn_two)
00518 {
00519 WN* wn_common = Common_Ancestor(wn_one, wn_two);
00520 if (WN_opcode(wn_common) != OPC_BLOCK)
00521 return wn_common;
00522 for (WN* wn = WN_first(wn_common); wn != NULL; wn = WN_next(wn)) {
00523 if (Wn_Is_Inside(wn_one, wn))
00524 return wn;
00525 if (Wn_Is_Inside(wn_two, wn))
00526 return wn;
00527 }
00528 FmtAssert(TRUE, ("New_Lowest_Statement: Didn't find lowest statement"));
00529 return NULL;
00530 }
00531
00532
00533
00534
00535
00536
00537
00538 static WN* Hoist_Point(WN* wn_stat,
00539 DU_MANAGER* du)
00540 {
00541 WN* wn_lowest_statement = wn_stat;
00542 INT lowest_loop_depth = Loop_Depth(wn_stat);
00543 LWN_ITER* itr = LWN_WALK_TreeIter(wn_stat);
00544 for (; itr != NULL; itr = LWN_WALK_TreeNext(itr)) {
00545 WN* wn_def = itr->wn;
00546 USE_LIST *use_list = du->Du_Get_Use(wn_def);
00547 if (use_list == NULL)
00548 continue;
00549 USE_LIST_ITER iter(use_list);
00550 const DU_NODE* node = NULL;
00551 for (node = iter.First(); !iter.Is_Empty(); node = iter.Next()) {
00552 WN* wn_use = node->Wn();
00553 WN* wn_statement = Get_Statement(wn_use);
00554 if (wn_statement == wn_lowest_statement)
00555 continue;
00556 INT current_loop_depth = Loop_Depth(wn_statement);
00557 if (current_loop_depth < lowest_loop_depth) {
00558 wn_lowest_statement = wn_statement;
00559 lowest_loop_depth = current_loop_depth;
00560 } else if (current_loop_depth == lowest_loop_depth) {
00561 WN* wn_new_statement = New_Lowest_Statement(wn_statement,
00562 wn_lowest_statement);
00563 if (wn_new_statement != wn_lowest_statement) {
00564 wn_lowest_statement = wn_new_statement;
00565 lowest_loop_depth = Loop_Depth(wn_new_statement);
00566 }
00567 }
00568 }
00569 }
00570 return wn_lowest_statement;
00571 }
00572
00573
00574
00575
00576
00577
00578
00579
00580 extern void Hoist_Necessary_Code_Up(WN* wn_sunk,
00581 DU_MANAGER* du)
00582 {
00583 WN* wnn = NULL;
00584 for (WN* wn = wn_sunk; wn != NULL; wn = wnn) {
00585 wnn = WN_prev(wn);
00586 WN* wn_hoist_place = Hoist_Point(wn, du);
00587 if (wn_hoist_place != wn) {
00588 LWN_Extract_From_Block(LWN_Get_Parent(wn), wn);
00589 LWN_Insert_Block_Before(LWN_Get_Parent(wn_hoist_place),
00590 wn_hoist_place, wn);
00591 }
00592 }
00593 }
00594
00595
00596
00597
00598
00599
00600 static BOOL Is_Inside_Store(WN* wn_node)
00601 {
00602 for (WN* wn = wn_node; wn != NULL; wn = LWN_Get_Parent(wn))
00603 if (OPCODE_is_store(WN_opcode(wn)))
00604 return TRUE;
00605 return FALSE;
00606 }
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616 static BOOL Maybe_Assigned(WN* wn_symbol,
00617 WN* wn_first,
00618 WN* wn_last)
00619 {
00620 WN* wn_alias = wn_symbol;
00621 if (WN_operator(wn_symbol) == OPR_PARM)
00622 wn_symbol = WN_kid0(wn_symbol);
00623 BOOL is_preg = ST_class(WN_st(wn_symbol)) == CLASS_PREG;
00624 BOOL is_inside_store = Is_Inside_Store(wn_symbol);
00625 for (WN* wn_stat = wn_first; wn_stat != NULL; wn_stat = WN_next(wn_stat)) {
00626 LWN_ITER* itr = LWN_WALK_TreeIter(wn_stat);
00627 for (; itr != NULL; itr = LWN_WALK_TreeNext(itr)) {
00628 WN* wn = itr->wn;
00629 if (WN_operator(wn) == OPR_LDA
00630 && wn != wn_symbol && SYMBOL(wn) == SYMBOL(wn_symbol)
00631 && (is_inside_store || Is_Inside_Store(wn)))
00632 return TRUE;
00633 if (OPCODE_is_store(WN_opcode(wn))
00634 && (is_preg
00635 || OPCODE_has_sym(WN_opcode(wn)) && ST_class(WN_st(wn)) == CLASS_PREG)
00636 && (!OPCODE_has_sym(WN_opcode(wn)) || SYMBOL(wn) != SYMBOL(wn_symbol)))
00637 continue;
00638 if (OPCODE_is_store(WN_opcode(wn)) && Valid_alias(Alias_Mgr, wn)
00639 && wn != wn_alias && Aliased(Alias_Mgr, wn, wn_alias) != NOT_ALIASED)
00640 return TRUE;
00641 if (OPCODE_is_call(WN_opcode(wn))) {
00642 if (Has_Call_Info(wn)) {
00643 POINTS_TO* pt_symbol = Points_To(wn_symbol, &LNO_local_pool);
00644 ARA_LOOP_INFO* ali_call = Get_Call_Info(wn)->Call_Ara_Info();
00645 INT i;
00646 for (i = 0; i < ali_call->MAY_DEF().Elements(); i++) {
00647 ARA_REF* ara_call = ali_call->MAY_DEF().Bottom_nth(i);
00648 POINTS_TO* pt_call = Points_To(ara_call, &LNO_local_pool);
00649 if (Alias_Mgr->Aliased(pt_call, pt_symbol))
00650 return TRUE;
00651 if (SYMBOL(wn_symbol) == ara_call->Array())
00652 return TRUE;
00653 }
00654 for (i = 0; i < ali_call->SCALAR_MAY_DEF().Elements(); i++) {
00655 SCALAR_STACK& stk = (SCALAR_STACK&) ali_call->SCALAR_MAY_DEF();
00656 SCALAR_NODE* sn = stk.Bottom_nth(i);
00657 POINTS_TO* pt_sn = Points_To(sn, &LNO_local_pool);
00658 if (Alias_Mgr->Aliased(pt_sn, pt_symbol))
00659 return TRUE;
00660 if (SYMBOL(wn_symbol) == stk.Bottom_nth(i)->_scalar)
00661 return TRUE;
00662 }
00663 } else {
00664 if (Aliased_with_region(Alias_Mgr, wn, wn_alias, WRITE)
00665 != NOT_ALIASED)
00666 return TRUE;
00667 }
00668 return FALSE;
00669 }
00670 }
00671 if (wn_stat == wn_last)
00672 return FALSE;
00673 }
00674 FmtAssert(FALSE, ("wn_first and wn_last were not siblings"));
00675 return TRUE;
00676 }
00677
00678
00679
00680
00681
00682
00683
00684 static BOOL Is_In_Range(WN* wn_node,
00685 WN* wn_first,
00686 WN* wn_last)
00687 {
00688 WN *wn;
00689 for (wn = wn_node; wn != NULL; wn = LWN_Get_Parent(wn))
00690 if (LWN_Get_Parent(wn) == LWN_Get_Parent(wn_first))
00691 break;
00692 if (wn == NULL)
00693 return FALSE;
00694 if (wn == wn_first || wn == wn_last)
00695 return TRUE;
00696 WN* wn_sibling = wn;
00697 for (wn = wn_sibling; wn != NULL; wn = WN_next(wn)) {
00698 if (wn == wn_first)
00699 return FALSE;
00700 if (wn == wn_last)
00701 return TRUE;
00702 }
00703 return FALSE;
00704 }
00705
00706
00707
00708
00709
00710
00711
00712 static BOOL Maybe_Assigned_Exp_Traverse(WN* wn_exp,
00713 WN* wn_first,
00714 WN* wn_last)
00715 {
00716 ARRAY_DIRECTED_GRAPH16* dg = Array_Dependence_Graph;
00717 FmtAssert(OPCODE_is_expression(WN_opcode(wn_exp)),
00718 ("wn_exp must be an expression"));
00719
00720 switch (WN_operator(wn_exp)) {
00721 case OPR_LDA:
00722 return FALSE;
00723 case OPR_LDID:
00724 return Maybe_Assigned(wn_exp, wn_first, wn_last);
00725 case OPR_INTCONST:
00726 case OPR_CONST:
00727 return FALSE;
00728 case OPR_ILOAD:
00729 {
00730 EINDEX16 e = 0;
00731 if (dg == NULL)
00732 return TRUE;
00733 VINDEX16 v = dg->Get_Vertex(wn_exp);
00734 if (v == 0) {
00735 for (WN* wnn = wn_first; wnn != NULL; wnn = WN_next(wnn)) {
00736 LWN_ITER* itr = LWN_WALK_TreeIter(wnn);
00737 for (; itr != NULL; itr = LWN_WALK_TreeNext(itr)) {
00738 WN* wn = itr->wn;
00739 #ifdef KEY
00740
00741
00742
00743
00744 if (WN_operator(wn) == OPR_CALL && !Valid_alias(Alias_Mgr, wn))
00745 return TRUE;
00746 #endif
00747 if (Valid_alias(Alias_Mgr, wn)
00748 && !OPCODE_is_load(WN_opcode(wn))
00749 && Aliased(Alias_Mgr, wn, wn_exp) != NOT_ALIASED)
00750 return TRUE;
00751 }
00752 if (wnn == wn_last)
00753 break;
00754 }
00755 } else {
00756 for (e = dg->Get_In_Edge(v); e != 0; e = dg->Get_Next_In_Edge(e)) {
00757 WN* wn_source = dg->Get_Wn(dg->Get_Source(e));
00758 if (Is_In_Range(wn_source, wn_first, wn_last))
00759 return TRUE;
00760 }
00761 for (e = dg->Get_Out_Edge(v); e != 0; e = dg->Get_Next_Out_Edge(e)) {
00762 WN* wn_sink = dg->Get_Wn(dg->Get_Sink(e));
00763 if (Is_In_Range(wn_sink, wn_first, wn_last))
00764 return TRUE;
00765 }
00766 }
00767 for (INT i = 0; i < WN_kid_count(wn_exp); i++)
00768 if (Maybe_Assigned_Exp_Traverse(WN_kid(wn_exp, i), wn_first, wn_last))
00769 return TRUE;
00770 return FALSE;
00771 }
00772 case OPR_PARM:
00773 if (WN_Parm_By_Value(wn_exp))
00774 return Maybe_Assigned_Exp_Traverse(WN_kid0(wn_exp), wn_first, wn_last);
00775 return TRUE;
00776 case OPR_DIV:
00777 case OPR_REM:
00778 case OPR_ADD:
00779 case OPR_SUB:
00780 case OPR_MPY:
00781 case OPR_MIN:
00782 case OPR_MAX:
00783 case OPR_NEG:
00784 case OPR_LAND:
00785 case OPR_LIOR:
00786 case OPR_CAND:
00787 case OPR_CIOR:
00788 case OPR_MOD:
00789 case OPR_EQ:
00790 case OPR_NE:
00791 case OPR_GE:
00792 case OPR_GT:
00793 case OPR_LE:
00794 case OPR_LT:
00795 case OPR_CVT:
00796 case OPR_TRUNC:
00797 case OPR_INTRINSIC_CALL:
00798 case OPR_INTRINSIC_OP:
00799 case OPR_ARRAY:
00800 #ifdef KEY
00801 case OPR_PURE_CALL_OP:
00802 #endif
00803 {
00804 for (INT i = 0; i < WN_kid_count(wn_exp); i++)
00805 if (Maybe_Assigned_Exp_Traverse(WN_kid(wn_exp, i), wn_first, wn_last))
00806 return TRUE;
00807 return FALSE;
00808 }
00809 default:
00810 return TRUE;
00811 }
00812 }
00813
00814
00815
00816
00817
00818
00819
00820 extern BOOL Maybe_Assigned_Exp(WN* wn_exp,
00821 WN* wn_first,
00822 WN* wn_last)
00823 {
00824 return Maybe_Assigned_Exp_Traverse(wn_exp, wn_first, wn_last);
00825 }
00826
00827
00828
00829
00830
00831
00832
00833 static BOOL Trip_One_Loop(WN* wn_loop)
00834 {
00835 DO_LOOP_INFO* dli = Get_Do_Loop_Info(wn_loop);
00836 if (dli->Is_Processor_Tile)
00837 return TRUE;
00838 if (Iterations(wn_loop, &LNO_local_pool) > 0)
00839 return TRUE;
00840 return FALSE;
00841 }
00842
00843
00844
00845
00846
00847
00848
00849 static BOOL Loop_Dominates_Uses(WN* wn_stat,
00850 WN* wn_loop,
00851 DU_MANAGER* du)
00852 {
00853 USE_LIST *use_list = du->Du_Get_Use(wn_stat);
00854 if (use_list == NULL)
00855 return TRUE;
00856 if (use_list->Incomplete())
00857 return FALSE;
00858 USE_LIST_ITER iter(use_list);
00859 const DU_NODE* node = NULL;
00860 for (node = iter.First(); !iter.Is_Empty(); node = iter.Next()) {
00861 WN* wn_use = node->Wn();
00862 WN* wn = NULL;
00863 for (wn = wn_use; wn != NULL; wn = LWN_Get_Parent(wn))
00864 if (wn == WN_do_body(wn_loop))
00865 break;
00866 if (wn == NULL)
00867 return FALSE;
00868 }
00869 return TRUE;
00870 }
00871
00872
00873
00874
00875
00876
00877
00878 extern WN* Find_Sibling_Containing(WN* wn_stat,
00879 WN* wn_contained)
00880 {
00881 for (WN* wn = wn_stat; wn != NULL; wn = WN_next(wn)) {
00882 for (WN* wnn = wn_contained; wnn != NULL; wnn = LWN_Get_Parent(wnn))
00883 if (wnn == wn)
00884 return wn;
00885 }
00886 return NULL;
00887 }
00888
00889
00890
00891
00892
00893
00894
00895
00896 static BOOL Sinkable_Into_Loop(WN* wn_stat,
00897 WN* wn_test,
00898 WN* wn_sink_loop,
00899 DU_MANAGER* du)
00900 {
00901 WN* wn_sibling = Find_Sibling_Containing(wn_stat, wn_sink_loop);
00902 FmtAssert(wn_sibling != NULL, ("Could not find a sink loop sibling."));
00903 switch (WN_operator(wn_test)) {
00904 case OPR_LDID:
00905 return !Maybe_Assigned(wn_test, WN_next(wn_stat), wn_sibling);
00906 case OPR_STID:
00907 if (ST_class(WN_st(wn_test)) != CLASS_PREG) {
00908 WN* wn_enclosing = Enclosing_Loop(wn_stat);
00909 for (WN* wn = wn_sink_loop; wn != wn_enclosing; wn = LWN_Get_Parent(wn))
00910 if (WN_opcode(wn) == OPC_DO_LOOP && !Trip_One_Loop(wn))
00911 return FALSE;
00912 } else if (Preg_Is_Dedicated(WN_offset(wn_test))) {
00913 return FALSE;
00914 }
00915 if (Maybe_Assigned(wn_test, WN_next(wn_stat), wn_sibling))
00916 return FALSE;
00917 if (!Loop_Dominates_Uses(wn_stat, wn_sink_loop, du))
00918 return FALSE;
00919 return TRUE;
00920 case OPR_ADD:
00921 case OPR_SUB:
00922 case OPR_MPY:
00923 case OPR_DIV:
00924 case OPR_MIN:
00925 case OPR_MAX:
00926 case OPR_NEG:
00927 case OPR_EQ:
00928 case OPR_INTRINSIC_CALL:
00929 case OPR_INTRINSIC_OP:
00930 {
00931 for (INT i = 0; i < WN_kid_count(wn_test); i++)
00932 if (!Sinkable_Into_Loop(wn_stat, WN_kid(wn_test, i), wn_sink_loop, du))
00933 return FALSE;
00934 return TRUE;
00935 }
00936 case OPR_PARM:
00937 if (WN_Parm_By_Value(wn_test))
00938 return Sinkable_Into_Loop(wn_stat, WN_kid0(wn_test), wn_sink_loop, du);
00939 else if (WN_Parm_By_Reference(wn_test)) {
00940 if (Maybe_Assigned(wn_test, WN_next(wn_stat), wn_sibling))
00941 return FALSE;
00942 else if (!Loop_Dominates_Uses(wn_stat, wn_sink_loop,du))
00943 return FALSE;
00944 else
00945 return TRUE;
00946 }
00947 FmtAssert(FALSE, ("Parameter must be by value or by reference."));
00948 case OPR_CALL:
00949 #ifdef KEY
00950 case OPR_PURE_CALL_OP:
00951 #endif
00952 {
00953 if (!Special_Lego_Or_Mp_Call(WN_st(wn_test))
00954 && (WN_Call_Never_Return(wn_test) || WN_Call_Non_Data_Mod(wn_test)
00955 || WN_Call_Non_Data_Ref(wn_test) || WN_Call_Non_Parm_Mod(wn_test)
00956 || WN_Call_Non_Parm_Ref(wn_test) || WN_Call_Parm_Mod(wn_test)))
00957 return FALSE;
00958 for (INT i = 0; i < WN_kid_count(wn_test); i++)
00959 if (!Sinkable_Into_Loop(wn_stat, WN_kid(wn_test, i), wn_sibling, du))
00960 return FALSE;
00961 return TRUE;
00962 }
00963 case OPR_INTCONST:
00964 return TRUE;
00965 case OPC_BLOCK:
00966 {
00967 for (WN* wnn = WN_first(wn_test); wnn != NULL; wnn = WN_next(wnn))
00968 if (!Sinkable_Into_Loop(wn_stat, wnn, wn_sink_loop, du))
00969 return FALSE;
00970 return TRUE;
00971 }
00972 case OPC_IF:
00973 if (!Sinkable_Into_Loop(wn_stat, WN_if_test(wn_test), wn_sink_loop, du))
00974 return FALSE;
00975 if (!Sinkable_Into_Loop(wn_stat, WN_then(wn_test), wn_sink_loop, du))
00976 return FALSE;
00977 if (!Sinkable_Into_Loop(wn_stat, WN_else(wn_test), wn_sink_loop, du))
00978 return FALSE;
00979 return TRUE;
00980 default:
00981 return FALSE;
00982 }
00983 }
00984
00985
00986
00987
00988
00989
00990
00991 static BOOL All_Uses_Outside_Of_Loop(WN* wn_stat,
00992 WN* wn_loop,
00993 DU_MANAGER* du)
00994 {
00995 USE_LIST *use_list = du->Du_Get_Use(wn_stat);
00996 USE_LIST_ITER iter(use_list);
00997 const DU_NODE* node = NULL;
00998 for (node = iter.First(); !iter.Is_Empty(); node = iter.Next()) {
00999 WN* wn_use = node->Wn();
01000 WN* wn = NULL;
01001 for (wn = wn_use; wn != NULL; wn = LWN_Get_Parent(wn))
01002 if (wn == wn_loop)
01003 break;
01004 if (wn != NULL)
01005 return FALSE;
01006 }
01007 return TRUE;
01008 }
01009
01010
01011
01012
01013
01014
01015
01016
01017 static BOOL Sinkable_Out_Of_Loop(WN* wn_stat,
01018 WN* wn_test,
01019 WN* wn_sink_loop,
01020 DU_MANAGER* du)
01021 {
01022 ARRAY_DIRECTED_GRAPH16* dg = Array_Dependence_Graph;
01023 switch (WN_operator(wn_test)) {
01024 case OPR_LDID:
01025 return !Maybe_Assigned(wn_test, wn_sink_loop, wn_sink_loop);
01026 case OPR_STID:
01027 {
01028 if (!All_Uses_Outside_Of_Loop(wn_stat, wn_sink_loop, du))
01029 return FALSE;
01030 for (INT i = 0; i < WN_kid_count(wn_test); i++)
01031 if (!Sinkable_Out_Of_Loop(wn_stat, WN_kid(wn_test, i), wn_sink_loop, du))
01032 return FALSE;
01033 return TRUE;
01034 }
01035 case OPR_ILOAD:
01036 {
01037 EINDEX16 e = 0;
01038 if (dg == NULL)
01039 return TRUE;
01040 VINDEX16 v = dg->Get_Vertex(wn_test);
01041 if (v == 0)
01042 return TRUE;
01043 for (e = dg->Get_In_Edge(v); e != 0; e = dg->Get_Next_In_Edge(e)) {
01044 WN* wn_source = dg->Get_Wn(dg->Get_Source(e));
01045 if (Wn_Is_Inside(wn_source, wn_sink_loop))
01046 return FALSE;
01047 }
01048 for (e = dg->Get_Out_Edge(v); e != 0; e = dg->Get_Next_Out_Edge(e)) {
01049 WN* wn_sink = dg->Get_Wn(dg->Get_Sink(e));
01050 if (Wn_Is_Inside(wn_sink, wn_sink_loop))
01051 return FALSE;
01052 }
01053
01054 }
01055 case OPR_ADD:
01056 case OPR_SUB:
01057 case OPR_MPY:
01058 case OPR_DIV:
01059 case OPR_MIN:
01060 case OPR_MAX:
01061 case OPR_NEG:
01062 case OPR_INTRINSIC_CALL:
01063 case OPR_INTRINSIC_OP:
01064 case OPR_ARRAY:
01065 {
01066 for (INT i = 0; i < WN_kid_count(wn_test); i++)
01067 if (!Sinkable_Out_Of_Loop(wn_stat, WN_kid(wn_test, i), wn_sink_loop, du))
01068 return FALSE;
01069 return TRUE;
01070 }
01071 case OPR_PARM:
01072 if (WN_Parm_By_Value(wn_test))
01073 return Sinkable_Out_Of_Loop(wn_stat, WN_kid0(wn_test), wn_sink_loop, du);
01074 if (WN_Parm_By_Reference(wn_test))
01075 #ifdef KEY
01076 return !Maybe_Assigned(WN_kid0(wn_test), wn_sink_loop, wn_sink_loop);
01077 #else
01078 return !Maybe_Assigned(WN_kid0(wn_test), WN_next(wn_stat), wn_sink_loop);
01079 #endif
01080 FmtAssert(FALSE, ("Parameter must be by value or by reference."));
01081 case OPR_CALL:
01082 #ifdef KEY
01083 case OPR_PURE_CALL_OP:
01084 #endif
01085 {
01086 if (!Special_Lego_Or_Mp_Call(WN_st(wn_test))
01087 && (WN_Call_Never_Return(wn_test) || WN_Call_Non_Data_Mod(wn_test)
01088 || WN_Call_Non_Data_Ref(wn_test) || WN_Call_Non_Parm_Mod(wn_test)
01089 || WN_Call_Non_Parm_Ref(wn_test) || WN_Call_Parm_Mod(wn_test)))
01090 return FALSE;
01091 for (INT i = 0; i < WN_kid_count(wn_test); i++)
01092 if (!Sinkable_Out_Of_Loop(wn_stat, WN_kid(wn_test, i), wn_sink_loop, du))
01093 return FALSE;
01094 return TRUE;
01095 }
01096 case OPR_INTCONST:
01097 return TRUE;
01098 default:
01099 return FALSE;
01100 }
01101 }
01102
01103
01104
01105
01106
01107
01108
01109 extern BOOL Statement_Sinkable_Out_Of_Loop(WN* wn_stat,
01110 WN* wn_loop)
01111 {
01112 DU_MANAGER* du = Du_Mgr;
01113 FmtAssert(WN_opcode(LWN_Get_Parent(wn_stat)) == OPC_BLOCK,
01114 ("Sinkable_Out_Of_Loop: First arg must be a statement"));
01115 DOLOOP_STACK stack(&LNO_local_pool);
01116 Build_Doloop_Stack(wn_stat, &stack);
01117 INT outer_depth = Do_Loop_Depth(wn_loop);
01118 WN* wn_inner_loop = stack.Bottom_nth(stack.Elements() - 1);
01119 INT inner_depth = Do_Loop_Depth(wn_inner_loop);
01120 for (INT i = outer_depth; i <= inner_depth; i++) {
01121 WN* wn_loop = stack.Bottom_nth(i);
01122 DO_LOOP_INFO* dli_loop = Get_Do_Loop_Info(wn_loop);
01123 if (dli_loop->Has_Gotos)
01124 return FALSE;
01125 if (!Upper_Bound_Standardize(WN_end(wn_loop), TRUE))
01126 return FALSE;
01127 for (INT j = i + 1; j <= inner_depth; j++)
01128 if (!SNL_Is_Invariant(&stack, i, j))
01129 return FALSE;
01130 }
01131 return Sinkable_Out_Of_Loop(wn_stat, wn_stat, wn_loop, du);
01132 }
01133
01134
01135
01136
01137
01138
01139
01140
01141 extern BOOL Sandwiched_Code_Sinkable_In(WN* wn_outer_loop,
01142 WN* wn_sink_loop,
01143 DU_MANAGER* du)
01144 {
01145 WN* wn_sink_block = WN_do_body(wn_sink_loop);
01146 if (WN_next(wn_sink_loop))
01147 return FALSE;
01148 for (WN* wn_loop = wn_sink_loop; wn_loop != wn_outer_loop;
01149 wn_loop = LWN_Get_Parent(LWN_Get_Parent(wn_loop))) {
01150 WN* wnn = NULL;
01151 for (WN* wn = WN_prev(wn_loop); wn != NULL; wn = wnn) {
01152 wnn = WN_prev(wn);
01153 if (!Sinkable_Into_Loop(wn, wn, wn_sink_loop, du))
01154 return FALSE;
01155 }
01156 }
01157 return TRUE;
01158 }
01159
01160
01161
01162
01163
01164
01165
01166
01167 extern WN* Sink_Sandwiched_Code_In(WN* wn_outer_loop,
01168 WN* wn_sink_loop)
01169 {
01170 WN* wn_first = NULL;
01171 WN* wn_sink_block = WN_do_body(wn_sink_loop);
01172 for (WN* wn_loop = wn_sink_loop; wn_loop != wn_outer_loop;
01173 wn_loop = LWN_Get_Parent(LWN_Get_Parent(wn_loop))) {
01174 WN* wnn = NULL;
01175 for (WN* wn = WN_prev(wn_loop); wn != NULL; wn = wnn) {
01176 wnn = WN_prev(wn);
01177 if (wn_first == NULL)
01178 wn_first = wn;
01179 LWN_Extract_From_Block(LWN_Get_Parent(wn), wn);
01180 LWN_Insert_Block_After(wn_sink_block, NULL, wn);
01181 }
01182 }
01183 return wn_first;
01184 }
01185
01186
01187
01188
01189
01190
01191
01192 static void Hoist_Out_Nested_Statements(WN* wn_loop,
01193 WN* wn_hoist_loop,
01194 DU_MANAGER* du)
01195 {
01196 WN* wnn = NULL;
01197 WN* wn_inner_loop = NULL;
01198 DO_LOOP_INFO* dli = Get_Do_Loop_Info(wn_loop);
01199 if (dli->Is_Inner)
01200 return;
01201 for (WN* wn = WN_first(WN_do_body(wn_loop)); wn != NULL; wn = wnn) {
01202 wnn = WN_next(wn);
01203 FmtAssert(WN_opcode(wn) != OPC_REGION,
01204 ("MP regions should be filtered out by now."));
01205 if (WN_opcode(wn) == OPC_DO_LOOP) {
01206 Hoist_Out_Nested_Statements(wn, wn_hoist_loop, du);
01207 return;
01208 }
01209 INT hoist_level = Hoistable_Statement(wn, du);
01210 if (hoist_level < Loop_Depth(wn))
01211 Hoist_Statement(wn, hoist_level);
01212 }
01213 }
01214
01215
01216
01217
01218
01219
01220
01221 static BOOL Sandwiched_Code_Sinkable_Out(WN* wn_loop,
01222 WN* wn_sink_loop,
01223 DU_MANAGER* du)
01224 {
01225 WN* wn_inner_loop = NULL;
01226 DO_LOOP_INFO* dli = Get_Do_Loop_Info(wn_loop);
01227 if (dli->Is_Inner)
01228 return TRUE;
01229 WN* wnn = NULL;
01230 WN *wn;
01231 for (wn = WN_first(WN_do_body(wn_loop)); wn != NULL; wn = wnn) {
01232 WN* wnn = WN_next(wn);
01233 FmtAssert(WN_opcode(wn) != OPC_REGION,
01234 ("MP regions should be filtered out by now."));
01235 if (WN_opcode(wn) == OPC_DO_LOOP) {
01236 wn_inner_loop = wn;
01237 break;
01238 }
01239 }
01240 for (wn = WN_next(wn_inner_loop); wn != NULL; wn = WN_next(wn))
01241 if (!Statement_Sinkable_Out_Of_Loop(wn, wn_loop))
01242 return FALSE;
01243 return Sandwiched_Code_Sinkable_Out(wn_inner_loop, wn_sink_loop, du);
01244 }
01245
01246
01247
01248
01249
01250
01251
01252
01253 static WN* Generate_Guard_Test(WN* wn_loop,
01254 WN* wn_block,
01255 DU_MANAGER* du)
01256 {
01257 if (Trip_One_Loop(wn_loop))
01258 return wn_block;
01259 INT outer_depth = Do_Loop_Depth(wn_loop) - 1;
01260 ARRAY_DIRECTED_GRAPH16* dg = Array_Dependence_Graph;
01261 FmtAssert(dg != NULL, ("Could not find dependence graph"));
01262 WN_MAP version_map = WN_MAP_Create(&LNO_local_pool);
01263 WN* wn_cp_end = LWN_Copy_Tree(UBexp(WN_end(wn_loop)), TRUE, LNO_Info_Map,
01264 TRUE, version_map);
01265 LWN_Copy_Def_Use(UBexp(WN_end(wn_loop)), wn_cp_end, du);
01266 if (outer_depth >= 0)
01267 dg->Versioned_Dependences_Update(UBexp(WN_end(wn_loop)), wn_cp_end,
01268 outer_depth, version_map);
01269 WN_MAP_Delete(version_map);
01270 version_map = WN_MAP_Create(&LNO_local_pool);
01271 WN* wn_cp_start = LWN_Copy_Tree(WN_kid0(WN_start(wn_loop)), TRUE,
01272 LNO_Info_Map, TRUE, version_map);
01273 LWN_Copy_Def_Use(WN_kid0(WN_start(wn_loop)), wn_cp_start, du);
01274 if (outer_depth >= 0)
01275 dg->Versioned_Dependences_Update(WN_kid0(WN_start(wn_loop)), wn_cp_start,
01276 outer_depth, version_map);
01277 WN_MAP_Delete(version_map);
01278 OPCODE opge = OPCODE_make_op(OPR_GE, Boolean_type,
01279 Promote_Type(Do_Wtype(wn_loop)));
01280 WN* wn_cond = LWN_CreateExp2(opge, wn_cp_end, wn_cp_start);
01281 WN* wn_if_block = WN_CreateBlock();
01282 WN* wn_if = LWN_CreateIf(wn_cond, wn_if_block, WN_CreateBlock());
01283 LWN_Insert_Block_After(wn_block, NULL, wn_if);
01284 return wn_if_block;
01285 }
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295 static void Generate_Sink_Out_Code(WN* wn_loop,
01296 WN* wn_sink_loop,
01297 INT max_depth,
01298 WN* wn_block,
01299 BOOL test_legality,
01300 DU_MANAGER* du)
01301 {
01302 WN* wn_inner_loop = NULL;
01303 DO_LOOP_INFO* dli = Get_Do_Loop_Info(wn_loop);
01304 if (dli->Is_Inner || max_depth >= 0 && Do_Depth(wn_loop) >= max_depth)
01305 return;
01306 WN *wn;
01307 for (wn = WN_first(WN_do_body(wn_loop)); wn != NULL; wn = WN_next(wn)) {
01308 if (WN_opcode(wn) == OPC_DO_LOOP) {
01309 wn_inner_loop = wn;
01310 break;
01311 }
01312 }
01313 WN* wn_insert_block = Generate_Guard_Test(wn_loop, wn_block, du);
01314 if (WN_next(wn_inner_loop) != NULL) {
01315 WN* wn_first = WN_next(wn_inner_loop);
01316 WN *wnn;
01317 for (wnn = wn_first; WN_next(wnn) != NULL; wnn = WN_next(wnn));
01318 for (wn = wnn; wn != wn_inner_loop; wn = wnn) {
01319 wnn = WN_prev(wn);
01320 if (!test_legality || Statement_Sinkable_Out_Of_Loop(wn, wn_sink_loop)) {
01321 LWN_Extract_From_Block(LWN_Get_Parent(wn), wn);
01322 LWN_Insert_Block_After(wn_insert_block, NULL, wn);
01323 }
01324 }
01325 }
01326 Generate_Sink_Out_Code(wn_inner_loop, wn_sink_loop, max_depth,
01327 wn_insert_block, test_legality, du);
01328 }
01329
01330
01331
01332
01333
01334
01335 static void Simplify_Sink_Out_Code(WN* wn_block)
01336 {
01337 WN* wnn = NULL;
01338 if (wn_block == NULL)
01339 return;
01340 for (WN* wn = WN_first(wn_block); wn != NULL; wn = wnn) {
01341 wnn = WN_next(wn);
01342 if (WN_opcode(wn) == OPC_IF) {
01343 Simplify_Sink_Out_Code(WN_then(wn));
01344 Simplify_Sink_Out_Code(WN_else(wn));
01345 if (WN_first(WN_then(wn)) == NULL && WN_first(WN_else(wn)) == NULL) {
01346 LWN_Extract_From_Block(LWN_Get_Parent(wn), wn);
01347 LWN_Delete_Tree(wn);
01348 }
01349 }
01350 }
01351 }
01352
01353
01354
01355
01356
01357
01358
01359 static void Generate_If_Accesses(WN* wn_node)
01360 {
01361 LWN_ITER* itr = LWN_WALK_TreeIter(wn_node);
01362 for (; itr != NULL; itr = LWN_WALK_TreeNext(itr)) {
01363 WN* wn = itr->wn;
01364 if (WN_opcode(wn) == OPC_IF) {
01365 IF_INFO *ii = CXX_NEW(IF_INFO(&LNO_default_pool, FALSE, FALSE),
01366 &LNO_default_pool);
01367 WN_MAP_Set(LNO_Info_Map, wn, (void *) ii);
01368 DOLOOP_STACK *stack = CXX_NEW(DOLOOP_STACK(&LNO_local_pool),
01369 &LNO_local_pool);
01370 Build_Doloop_Stack(wn, stack);
01371 LNO_Build_If_Access(wn, stack);
01372 CXX_DELETE(stack, &LNO_local_pool);
01373 }
01374 }
01375 }
01376
01377
01378
01379
01380
01381
01382 static void Delete_Deps(WN* wn,
01383 ARRAY_DIRECTED_GRAPH16* dg)
01384 {
01385 FmtAssert(dg != NULL, ("Could not find dependence graph"));
01386 VINDEX16 v = dg->Get_Vertex(wn);
01387 EINDEX16 e = 0;
01388 EINDEX16 enext = 0;
01389 for (e = dg->Get_In_Edge(v); e != 0; e = enext) {
01390 enext = dg->Get_Next_In_Edge(e);
01391 dg->Delete_Array_Edge(e);
01392 }
01393 for (e = dg->Get_Out_Edge(v); e != 0; e = enext) {
01394 enext = dg->Get_Next_Out_Edge(e);
01395 dg->Delete_Array_Edge(e);
01396 }
01397 dg->Delete_Vertex(v);
01398 }
01399
01400
01401
01402
01403
01404
01405
01406 static void Recompute_Deps(WN* wn,
01407 LS_IN_LOOP* ls_loop,
01408 ARRAY_DIRECTED_GRAPH16* dg)
01409 {
01410 FmtAssert(dg != NULL, ("Could not find dependence graph"));
01411 DOLOOP_STACK wn_stack(&LNO_local_pool);
01412 Build_Doloop_Stack(wn, &wn_stack);
01413 #ifdef KEY //bug 11113
01414 typedef STACK<WN *> WN_STACK;
01415 WN_STACK *tmp_stack =
01416 CXX_NEW(WN_STACK(&LNO_local_pool),&LNO_local_pool);
01417 #endif
01418 EINDEX16 e = 0;
01419 DOLOOP_STACK source_stack(&LNO_local_pool);
01420 VINDEX16 v = dg->Get_Vertex(wn);
01421 for (e = dg->Get_In_Edge(v); e != 0; e = dg->Get_Next_In_Edge(e)) {
01422 WN* wn_source = dg->Get_Wn(dg->Get_Source(e));
01423 #ifdef KEY
01424 tmp_stack->Push(wn_source);
01425 #else
01426 Build_Doloop_Stack(wn_source, &source_stack);
01427 #endif
01428 dg->Delete_Array_Edge(e);
01429 EINDEX16 ec = 0;
01430 for (ec = dg->Get_Out_Edge(v); ec != 0; ec = dg->Get_Next_Out_Edge(ec)) {
01431 WN* wn_sink = dg->Get_Wn(dg->Get_Sink(ec));
01432 if (wn_sink == wn_source)
01433 break;
01434 }
01435 if (ec != 0)
01436 dg->Delete_Array_Edge(ec);
01437 #ifndef KEY //bug 11113
01438 if (!dg->Add_Edge(wn_source, &source_stack, wn,
01439 &wn_stack, ls_loop->In(wn_source) < ls_loop->In(wn)))
01440 LNO_Erase_Dg_From_Here_In(wn, dg);
01441 source_stack.Clear();
01442 #endif
01443 }
01444
01445 #ifdef KEY //bug 11113: build incoming edges only after all incoming edges removed
01446 while(tmp_stack->Elements() != 0){
01447 WN *wn_source = tmp_stack->Pop();
01448 Build_Doloop_Stack(wn_source, &source_stack);
01449 if (!dg->Add_Edge(wn_source, &source_stack, wn,
01450 &wn_stack, ls_loop->In(wn_source) < ls_loop->In(wn)))
01451 LNO_Erase_Dg_From_Here_In(wn, dg);
01452 source_stack.Clear();
01453 }
01454 #endif
01455 DOLOOP_STACK sink_stack(&LNO_local_pool);
01456 for (e = dg->Get_Out_Edge(v); e != 0; e = dg->Get_Next_Out_Edge(e)) {
01457 WN* wn_sink = dg->Get_Wn(dg->Get_Sink(e));
01458 #ifdef KEY
01459 tmp_stack->Push(wn_sink);
01460 #else
01461 Build_Doloop_Stack(wn_sink, &sink_stack);
01462 #endif
01463 dg->Delete_Array_Edge(e);
01464 EINDEX16 ec = 0;
01465 for (ec = dg->Get_In_Edge(v); ec != 0; ec = dg->Get_Next_In_Edge(ec)) {
01466 WN* wn_source = dg->Get_Wn(dg->Get_Source(ec));
01467 if (wn_source == wn_sink)
01468 break;
01469 }
01470 if (ec != 0)
01471 dg->Delete_Array_Edge(ec);
01472 #ifndef KEY //bug 11113
01473 if (!dg->Add_Edge(wn, &wn_stack, wn_sink,
01474 &sink_stack, ls_loop->In(wn) < ls_loop->In(wn_sink)))
01475 LNO_Erase_Dg_From_Here_In(wn, dg);
01476 sink_stack.Clear();
01477 #endif
01478 }
01479 #ifdef KEY //bug 11113: build outgoing edges only after all outgoing edges deleted
01480 while(tmp_stack->Elements() != 0){
01481 WN *wn_sink = tmp_stack->Pop();
01482 Build_Doloop_Stack(wn_sink, &sink_stack);
01483 if (!dg->Add_Edge(wn, &wn_stack, wn_sink,
01484 &sink_stack, ls_loop->In(wn) < ls_loop->In(wn_sink)))
01485 LNO_Erase_Dg_From_Here_In(wn, dg);
01486 sink_stack.Clear();
01487 }
01488 #endif
01489 }
01490
01491
01492
01493
01494
01495
01496
01497
01498 static void Recompute_Deps_For_Tree(WN* wn_tree,
01499 LS_IN_LOOP* ls_loop,
01500 ARRAY_DIRECTED_GRAPH16* dg)
01501 {
01502 FmtAssert(dg != NULL, ("Could not find dependence graph"));
01503 if (WN_opcode(wn_tree) == OPC_DO_LOOP && Do_Depth(wn_tree) == 0) {
01504 LS_IN_LOOP* ls_loop_new = CXX_NEW(LS_IN_LOOP(wn_tree, dg, &LNO_local_pool,
01505 TRUE), &LNO_local_pool);
01506 if (WN_opcode(wn_tree) == OPC_BLOCK) {
01507 for (WN* wn = WN_first(wn_tree); wn != NULL; wn = WN_next(wn))
01508 Recompute_Deps_For_Tree(wn, ls_loop_new, dg);
01509 } else {
01510 for (INT i = 0; i < WN_kid_count(wn_tree); i++)
01511 Recompute_Deps_For_Tree(WN_kid(wn_tree, i), ls_loop_new, dg);
01512 }
01513 CXX_DELETE(ls_loop_new, &LNO_local_pool);
01514 }
01515 if (dg->Get_Vertex(wn_tree))
01516 if (Enclosing_Do_Loop(wn_tree) == NULL)
01517 Delete_Deps(wn_tree, dg);
01518 else
01519 Recompute_Deps(wn_tree, ls_loop, dg);
01520 if (WN_opcode(wn_tree) == OPC_BLOCK)
01521 for (WN* wn = WN_first(wn_tree); wn != NULL; wn = WN_next(wn))
01522 Recompute_Deps_For_Tree(wn, ls_loop, dg);
01523 else
01524 for (INT i = 0; i < WN_kid_count(wn_tree); i++)
01525 Recompute_Deps_For_Tree(WN_kid(wn_tree, i), ls_loop, dg);
01526 }
01527
01528
01529
01530
01531
01532
01533 static void Insert_Sink_Code(WN* wn_block,
01534 WN* wn_loop)
01535 {
01536 if (WN_first(wn_block) != NULL) {
01537 WN* wn_first = WN_first(wn_block);
01538 WN *wnn;
01539 for (wnn = wn_first; WN_next(wnn) != NULL; wnn = WN_next(wnn));
01540 for (WN* wn = wnn; wn != NULL; wn = wnn) {
01541 wnn = WN_prev(wn);
01542 LWN_Extract_From_Block(LWN_Get_Parent(wn), wn);
01543 LWN_Insert_Block_After(LWN_Get_Parent(wn_loop), wn_loop, wn);
01544 }
01545 }
01546 LWN_Delete_Tree(wn_block);
01547 }
01548
01549
01550
01551
01552
01553
01554
01555 static void Fix_Accesses_And_Deps(WN* wn_loop,
01556 WN* wn_after,
01557 ARRAY_DIRECTED_GRAPH16* dg)
01558 {
01559 FmtAssert(dg != NULL, ("Could not find dependence graph"));
01560 LS_IN_LOOP* ls_loop = NULL;
01561 if (WN_next(wn_loop) != NULL) {
01562 WN* wn_encl_loop = Enclosing_Loop(WN_next(wn_loop));
01563 if (wn_encl_loop != NULL)
01564 ls_loop = CXX_NEW(LS_IN_LOOP(wn_encl_loop, dg, &LNO_local_pool,
01565 TRUE), &LNO_local_pool);
01566 }
01567 for (WN* wn = WN_next(wn_loop); wn != wn_after; wn = WN_next(wn)) {
01568 Generate_If_Accesses(wn);
01569 Recompute_Deps_For_Tree(wn, ls_loop, dg);
01570 }
01571 if (ls_loop != NULL)
01572 CXX_DELETE(ls_loop, &LNO_local_pool);
01573 }
01574
01575
01576
01577
01578
01579
01580
01581 extern void Sink_Out_Sandwiched_Statement(WN* wn_stat,
01582 WN* wn_sink_loop)
01583 {
01584 DU_MANAGER* du = Du_Mgr;
01585 ARRAY_DIRECTED_GRAPH16* dg = Array_Dependence_Graph;
01586 FmtAssert(dg != NULL, ("Could not find dependence graph"));
01587 FmtAssert(WN_opcode(LWN_Get_Parent(wn_stat)) == OPC_BLOCK,
01588 ("Sink_Out_Sandwiched_Statement: First arg must be a statement"));
01589 DOLOOP_STACK do_stack(&LNO_local_pool);
01590 Build_Doloop_Stack(wn_stat, &do_stack);
01591 INT i;
01592 for (i = 0; i < do_stack.Elements(); i++)
01593 if (do_stack.Bottom_nth(i) == wn_sink_loop)
01594 break;
01595 WN* wn_block = WN_CreateBlock();
01596 WN* wn_new_block = wn_block;
01597 for (INT j = i; j < do_stack.Elements(); j++) {
01598 WN* wn_loop = do_stack.Bottom_nth(j);
01599 wn_new_block = Generate_Guard_Test(wn_loop, wn_new_block, du);
01600 }
01601 LWN_Extract_From_Block(wn_stat);
01602 WN* wn_after = WN_next(wn_sink_loop);
01603 LWN_Insert_Block_After(wn_new_block, NULL, wn_stat);
01604 LWN_Insert_Block_After(LWN_Get_Parent(wn_sink_loop), wn_sink_loop, wn_block);
01605 Fix_Accesses_And_Deps(wn_sink_loop, wn_after, dg);
01606 }
01607
01608
01609
01610
01611
01612
01613
01614
01615
01616 extern void SNL_Sink_Out_Sandwiched_Statements(WN* wn_loop,
01617 INT nloops,
01618 BOOL test_legality,
01619 ARRAY_DIRECTED_GRAPH16* dg,
01620 DU_MANAGER* du)
01621 {
01622 FmtAssert(dg != NULL, ("Could not find dependence graph"));
01623 if (wn_loop == NULL)
01624 return;
01625 WN* wn_block = WN_CreateBlock();
01626 WN* wn_after = WN_next(wn_loop);
01627 INT outer_depth = Do_Loop_Depth(wn_loop);
01628 INT inner_depth = outer_depth + nloops - 1;
01629 Generate_Sink_Out_Code(wn_loop, wn_loop, inner_depth, wn_block,
01630 test_legality, du);
01631 Simplify_Sink_Out_Code(wn_block);
01632 Insert_Sink_Code(wn_block, wn_loop);
01633 Fix_Accesses_And_Deps(wn_loop, wn_after, dg);
01634 }
01635
01636
01637
01638
01639
01640
01641
01642 extern void Hoist_And_Sink_For_Nested_Doacross(WN* wn_loop,
01643 ARRAY_DIRECTED_GRAPH16* dg,
01644 DU_MANAGER* du)
01645 {
01646 FmtAssert(dg != NULL, ("Could not find dependence graph"));
01647 FmtAssert(WN_opcode(wn_loop) == OPC_DO_LOOP, ("Not a do loop"));
01648 DO_LOOP_INFO* dli = Get_Do_Loop_Info(wn_loop);
01649 FmtAssert(dli->Mp_Info != NULL, ("Not an MP loop"));
01650 FmtAssert(dli->Mp_Info->Nest_Index() == 0,
01651 ("Not an outer nested doacross"));
01652 FmtAssert(dli->Mp_Info->Nest_Total() > 1,
01653 ("Not a nested doacross"));
01654 Hoist_Out_Nested_Statements(wn_loop, wn_loop, du);
01655 INT nloops = dli->Mp_Info->Nest_Total();
01656 SNL_Sink_Out_Sandwiched_Statements(wn_loop, nloops, FALSE, dg, du);
01657 }