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 #define __STDC_LIMIT_MACROS
00037 #include <stdint.h>
00038 #ifdef USE_PCH
00039 #include "lno_pch.h"
00040 #endif // USE_PCH
00041 #pragma hdrstop
00042
00043 #ifdef _KEEP_RCS_ID
00044
00045 static char *rcs_id = "$Source: /home/bos/bk/kpro64-pending/be/lno/SCCS/s.forward.cxx $ $Revision: 1.5 $";
00046 #endif
00047
00048 #include <sys/types.h>
00049
00050 #include "lnoutils.h"
00051 #include "lnopt_main.h"
00052 #include "stab.h"
00053 #include "targ_const.h"
00054 #include "wn_simp.h"
00055 #include "stdlib.h"
00056 #include "lwn_util.h"
00057 #include "strtab.h"
00058 #include "config.h"
00059 #include "optimizer.h"
00060 #include "opt_du.h"
00061 #include "name.h"
00062 #include "wintrinsic.h"
00063 #include "lno_bv.h"
00064 #include "dep_graph.h"
00065 #include "debug.h"
00066 #include "scalar_expand.h"
00067 #include "cxx_memory.h"
00068 #include "reduc.h"
00069 #include "move.h"
00070 #include "dead.h"
00071 #include "targ_sim.h"
00072 #include "ipl_lno_util.h"
00073
00074 static ARRAY_DIRECTED_GRAPH16* dg;
00075 static DU_MANAGER* du;
00076 static REDUCTION_MANAGER* rm;
00077
00078 const INT FS_LOAD_AND_LEAF_LIMIT = 1;
00079 const INT FS_ARRAY_EXP_LIMIT = 80;
00080 const INT FS_NODE_HASH_SIZE = 247;
00081 const INT FS_SIBLING_HASH_SIZE = 247;
00082 const INT FS_MAX_STRING_LENGTH = 80;
00083
00084 static WN *Find_MP(WN *wn);
00085
00086
00087
00088
00089
00090
00091 static INT Count_Loads_And_Leafs(WN* wn)
00092 {
00093 INT load_count = 0;
00094 if (OPCODE_is_load(WN_opcode(wn)) || WN_kid_count(wn) == 0)
00095 return 1;
00096
00097 for (INT i = 0; i < WN_kid_count(wn); i++)
00098 load_count += Count_Loads_And_Leafs(WN_kid(wn, i));
00099 return load_count;
00100 }
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112 static void Fix_Deps_For_Load_Or_Store(WN* wn_orig,
00113 WN* wn_copy,
00114 LS_IN_LOOP* loop_ls,
00115 INT position)
00116 {
00117 dg->Add_Vertex(wn_copy);
00118 EINDEX16 e = 0;
00119 HASH_TABLE<WN*,INT> old_nodes(MIN(dg->Get_Edge_Count(), 512),
00120 &LNO_local_pool);
00121 DOLOOP_STACK source_stack(&LNO_local_pool);
00122 VINDEX16 v_orig = dg->Get_Vertex(wn_orig);
00123 DOLOOP_STACK copy_stack(&LNO_local_pool);
00124 Build_Doloop_Stack(wn_copy, ©_stack);
00125 for (e = dg->Get_In_Edge(v_orig); e != 0; e = dg->Get_Next_In_Edge(e)) {
00126 WN* wn_source = dg->Get_Wn(dg->Get_Source(e));
00127 old_nodes.Enter(wn_source, 1);
00128 Build_Doloop_Stack(wn_source, &source_stack);
00129 if (!dg->Add_Edge(wn_source, &source_stack, wn_copy,
00130 ©_stack, loop_ls->In(wn_source) < position)) {
00131 LNO_Erase_Dg_From_Here_In(wn_copy, dg);
00132 return;
00133 }
00134 source_stack.Clear();
00135 }
00136 DOLOOP_STACK sink_stack(&LNO_local_pool);
00137 for (e = dg->Get_Out_Edge(v_orig); e != 0; e = dg->Get_Next_Out_Edge(e)) {
00138 WN* wn_sink = dg->Get_Wn(dg->Get_Sink(e));
00139 if (old_nodes.Find(wn_sink) != 0)
00140 continue;
00141 Build_Doloop_Stack(wn_sink, &sink_stack);
00142 if (!dg->Add_Edge(wn_copy, ©_stack, wn_sink,
00143 &sink_stack, position < loop_ls->In(wn_sink))) {
00144 LNO_Erase_Dg_From_Here_In(wn_copy, dg);
00145 return;
00146 }
00147 sink_stack.Clear();
00148 }
00149 }
00150
00151
00152
00153
00154
00155
00156
00157 static void Fix_Access_Arrays_In_Copy_Block(WN* wn_tree)
00158 {
00159 if (WN_operator(wn_tree) == OPR_ARRAY) {
00160 DOLOOP_STACK copy_stack(&LNO_local_pool);
00161 Build_Doloop_Stack(wn_tree, ©_stack);
00162 LNO_Build_Access_Array(wn_tree, ©_stack, &LNO_default_pool);
00163 }
00164 for (INT i = 0; i < WN_kid_count(wn_tree); i++)
00165 Fix_Access_Arrays_In_Copy_Block(WN_kid(wn_tree, i));
00166 }
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178 static void Fix_Deps_In_Copy_Block(LS_IN_LOOP* loop_ls,
00179 WN* wn_orig,
00180 WN* wn_copy,
00181 INT position)
00182 {
00183 if (OPCODE_is_load(WN_opcode(wn_orig)) && dg->Get_Vertex(wn_orig))
00184 Fix_Deps_For_Load_Or_Store(wn_orig, wn_copy, loop_ls, position);
00185 for (INT i = 0; i < WN_kid_count(wn_orig); i++)
00186 Fix_Deps_In_Copy_Block(loop_ls, WN_kid(wn_orig, i), WN_kid(wn_copy, i),
00187 position);
00188 }
00189
00190
00191
00192
00193
00194
00195
00196 static BOOL FS_Is_Inside_If(WN* wn_use,
00197 WN* wn_stop)
00198 {
00199 WN *wn;
00200 for (wn = wn_use; wn != NULL && wn != wn_stop;
00201 wn = LWN_Get_Parent(wn))
00202 if (WN_opcode(wn) == OPC_IF)
00203 return TRUE;
00204 FmtAssert(wn == wn_stop, ("wn_use was not originally inside wn_stop"));
00205 return FALSE;
00206 }
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216 static void FS_Substitute(WN* wn_orig,
00217 LS_IN_LOOP* loop_ls)
00218 {
00219 REDUCTION_MANAGER* rm = red_manager;
00220 USE_LIST *use_list = du->Du_Get_Use(wn_orig);
00221 USE_LIST_ITER iter(use_list);
00222 DU_NODE* unode = NULL;
00223 DU_NODE* unnode_next = NULL;
00224 INT sub_count = 0;
00225 for (unode = iter.First(); !iter.Is_Empty(); unode = unnode_next) {
00226 WN* use = unode->Wn();
00227 unnode_next = iter.Next();
00228 if (WN_operator(use) != OPR_LDID)
00229 continue;
00230 if (FS_Is_Inside_If(use, LWN_Get_Parent(wn_orig)))
00231 continue;
00232 sub_count++;
00233 INT position = loop_ls->In(use);
00234 INT32 count = 0;
00235 if (Cur_PU_Feedback) {
00236 count = WN_MAP32_Get(WN_MAP_FEEDBACK,use);
00237 }
00238 if (rm != NULL) {
00239 REDUCTION_TYPE red_type = rm->Which_Reduction(use);
00240 if (red_type != RED_NONE) {
00241 WN *wn;
00242 for (wn = use; wn != NULL; wn = LWN_Get_Parent(wn))
00243 if (OPCODE_is_store(WN_opcode(wn))
00244 && rm->Which_Reduction(wn) == red_type)
00245 break;
00246 FmtAssert(wn != NULL,
00247 ("Could not find store to match reduction load."));
00248 rm->Erase(wn);
00249 }
00250 }
00251 BOOL added_convert = FALSE;
00252 WN* wn_copy = Replace_Wnexp_With_Exp_Copy(use, WN_kid0(wn_orig), du,
00253 &added_convert);
00254 #ifdef KEY
00255
00256
00257
00258
00259
00260
00261 if(added_convert && WN_operator(wn_copy) == OPR_CVT &&
00262 WN_operator(WN_kid0(wn_orig)) == OPR_ILOAD &&
00263 MTYPE_bit_size(WN_desc(wn_orig))<MTYPE_bit_size(WN_rtype(WN_kid0(wn_orig)))){
00264 WN_set_operator(wn_copy, OPR_CVTL);
00265 WN_set_desc(wn_copy, MTYPE_V);
00266 WN_cvtl_bits(wn_copy) = MTYPE_bit_size(WN_desc(wn_orig));
00267 }
00268 #endif
00269 LWN_Set_Frequency_Tree(wn_copy,count);
00270 WN* wn_true_copy = added_convert ? WN_kid0(wn_copy) : wn_copy;
00271 Fix_Access_Arrays_In_Copy_Block(wn_true_copy);
00272 Fix_Deps_In_Copy_Block(loop_ls, WN_kid0(wn_orig), wn_true_copy, position);
00273 }
00274 if (LNO_Verbose) {
00275 fprintf(stdout, " Forward Substituting %d occurences of %s in loop %s\n",
00276 sub_count, WB_Whirl_Symbol(wn_orig),
00277 WB_Whirl_Symbol(Enclosing_Loop(wn_orig)));
00278 fprintf(TFile, " Forward Substituting %d occurences of %s in loop %s\n",
00279 sub_count, WB_Whirl_Symbol(wn_orig),
00280 WB_Whirl_Symbol(Enclosing_Loop(wn_orig)));
00281 }
00282 LWN_Extract_From_Block(wn_orig);
00283 LWN_Delete_Tree(wn_orig);
00284 }
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295 static void BS_Collect_Array(WN* wn_copy,
00296 DOLOOP_STACK* copy_stack,
00297 STACK<WN*>* array_stack,
00298 STACK<INT>* position_stack,
00299 INT position)
00300 {
00301 dg->Add_Vertex(wn_copy);
00302 OPERATOR opr = WN_operator(wn_copy);
00303 FmtAssert(opr == OPR_ILOAD || opr == OPR_ISTORE || opr == OPR_LDID
00304 || opr == OPR_STID,
00305 ("BS_Collect_Array() not called on OPR_ILOAD(LDID) or OPR_ISTORE(STID)"));
00306 INT kid_number = opr == OPR_ILOAD ? 0 : 1;
00307 #ifdef KEY //bug 11113: LNO_Build_Access_Array applies only to arrays
00308 if((opr == OPR_ILOAD || opr == OPR_ISTORE)
00309 && WN_operator(WN_kid(wn_copy, kid_number))==OPR_ARRAY)
00310 #endif
00311 LNO_Build_Access_Array(WN_kid(wn_copy, kid_number), copy_stack,
00312 &LNO_default_pool);
00313 array_stack->Push(wn_copy);
00314 position_stack->Push(position);
00315 }
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326 static void BS_Collect_Arrays(WN* wn_orig,
00327 WN* wn_copy,
00328 DOLOOP_STACK* copy_stack,
00329 STACK<WN*>* array_stack,
00330 STACK<INT>* position_stack,
00331 INT position)
00332 {
00333 if (dg->Get_Vertex(wn_orig))
00334 BS_Collect_Array(wn_copy, copy_stack, array_stack, position_stack,
00335 position);
00336 if (WN_opcode(wn_copy) == OPC_BLOCK) {
00337 WN* wn_old = WN_first(wn_orig);
00338 for (WN* wn = WN_first(wn_copy); wn != NULL; wn = WN_next(wn)) {
00339 BS_Collect_Arrays(wn_old, wn, copy_stack, array_stack, position_stack,
00340 position);
00341 wn_old = WN_next(wn_old);
00342 }
00343 } else {
00344 for (INT i = 0; i < WN_kid_count(wn_copy); i++)
00345 BS_Collect_Arrays(WN_kid(wn_orig, i), WN_kid(wn_copy, i), copy_stack,
00346 array_stack, position_stack, position);
00347 }
00348 }
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361 static void BS_Replace_Load(WN* wn_scalar,
00362 WN* wn_load,
00363 LS_IN_LOOP* loop_ls,
00364 STACK<WN*>* array_stack,
00365 STACK<INT>* position_stack)
00366 {
00367 INT position = loop_ls->In(wn_scalar);
00368 REDUCTION_TYPE red_type = RED_NONE;
00369 if (rm != NULL && rm->Which_Reduction(wn_scalar))
00370 red_type = rm->Which_Reduction(wn_scalar);
00371 INT32 count = 0;
00372 if (Cur_PU_Feedback) {
00373 count = WN_MAP32_Get(WN_MAP_FEEDBACK,wn_scalar);
00374 }
00375 BOOL added_cvt = FALSE;
00376 WN* wn_copy = Replace_Wnexp_With_Exp_Copy(wn_scalar,wn_load,du,&added_cvt);
00377 LWN_Set_Frequency_Tree(wn_copy,count);
00378 DOLOOP_STACK copy_stack(&LNO_local_pool);
00379 WN* wn_true_copy = added_cvt ? WN_kid0(wn_copy) : wn_copy;
00380 Build_Doloop_Stack(wn_true_copy, ©_stack);
00381 BS_Collect_Array(wn_true_copy, ©_stack, array_stack, position_stack,
00382 position);
00383 BS_Collect_Arrays(WN_kid0(wn_load), WN_kid0(wn_true_copy), ©_stack,
00384 array_stack, position_stack, position);
00385 if (rm != NULL && red_type != RED_NONE)
00386 rm->Add_Reduction(wn_true_copy, red_type);
00387 }
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400 static void BS_Replace_Store(WN* wn_scalar,
00401 WN* wn_store,
00402 LS_IN_LOOP* loop_ls,
00403 STACK<WN*>* array_stack,
00404 STACK<INT>* position_stack)
00405 {
00406 INT position = loop_ls->In(wn_scalar);
00407 REDUCTION_TYPE red_type = RED_NONE;
00408 if (rm != NULL && rm->Which_Reduction(wn_scalar))
00409 red_type = rm->Which_Reduction(wn_scalar);
00410 INT32 count = 0;
00411 if (Cur_PU_Feedback) {
00412 count = WN_MAP32_Get(WN_MAP_FEEDBACK,wn_scalar);
00413 }
00414 WN* wn_copy = Replace_Scalar_Store_With_Array_Store(wn_scalar, wn_store, du);
00415 LWN_Set_Frequency_Tree(wn_copy, count);
00416 DOLOOP_STACK copy_stack(&LNO_local_pool);
00417 Build_Doloop_Stack(wn_copy, ©_stack);
00418 BS_Collect_Array(wn_copy, ©_stack, array_stack, position_stack,
00419 position);
00420 BS_Collect_Arrays(WN_kid1(wn_store), WN_kid1(wn_copy), ©_stack,
00421 array_stack, position_stack, position);
00422 if (rm != NULL && red_type != RED_NONE)
00423 rm->Add_Reduction(wn_copy, red_type);
00424 }
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436 static BOOL FS_Load_Assigned_on_Loop_Iteration(WN* wn_load,
00437 WN* wn_loop, LS_IN_LOOP *loop_ls,
00438 INT32 min_lex, INT32 max_lex)
00439 {
00440 if (WN_operator(wn_load) == OPR_LDID) {
00441 if (SYMBOL(wn_load) == SYMBOL(WN_start(wn_loop)))
00442 return FALSE;
00443 if (dg->Get_Vertex(wn_load))
00444 return TRUE;
00445 DEF_LIST *def_list = du->Ud_Get_Def(wn_load);
00446 if (def_list != NULL) {
00447 if (def_list->Incomplete())
00448 return TRUE;
00449 DEF_LIST_ITER iter(def_list);
00450 DU_NODE* dnode = NULL;
00451 for (dnode = iter.First(); !iter.Is_Empty(); dnode = iter.Next()) {
00452 WN* def = dnode->Wn();
00453 if (Wn_Is_Inside(def,wn_loop))
00454 return TRUE;
00455 }
00456 }
00457 return FALSE;
00458 }
00459 if (WN_operator(wn_load) == OPR_ILOAD) {
00460 EINDEX16 e = 0;
00461 VINDEX16 v = dg->Get_Vertex(wn_load);
00462 INT depth = Get_Do_Loop_Info(wn_loop)->Depth;
00463 for (e = dg->Get_Out_Edge(v); e != 0; e = dg->Get_Next_Out_Edge(e)) {
00464 WN* def = dg->Get_Wn(dg->Get_Sink(e));
00465 INT def_lex_number = loop_ls->In(def);
00466 if ((def_lex_number >= min_lex) && (def_lex_number <= max_lex)) {
00467 if (Wn_Is_Inside(def, wn_loop)
00468 && dg->Depv_Array(e)->One_Equal_Through_Depth(depth))
00469 return TRUE;
00470 }
00471 }
00472 return FALSE;
00473 }
00474 FmtAssert(0, ("Found a LOAD which was not LDID or ILOAD"));
00475 return TRUE;
00476 }
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486 static BOOL FS_Exp_Assigned_on_Loop_Iteration(WN* wn_exp,
00487 WN* wn_loop,
00488 LS_IN_LOOP *loop_ls,
00489 INT32 min_lex=INT32_MIN, INT32 max_lex=INT32_MAX)
00490 {
00491 if (OPCODE_is_load(WN_opcode(wn_exp)))
00492 if (FS_Load_Assigned_on_Loop_Iteration(wn_exp, wn_loop,
00493 loop_ls,min_lex,max_lex))
00494 return TRUE;
00495 for (INT i = 0; i < WN_kid_count(wn_exp); i++)
00496 if (FS_Exp_Assigned_on_Loop_Iteration(WN_kid(wn_exp, i),
00497 wn_loop,loop_ls,min_lex,max_lex))
00498 return TRUE;
00499 return FALSE;
00500 }
00501
00502
00503
00504
00505
00506
00507
00508 static BOOL FS_Is_In_Do_Loop_Expression(WN* wn)
00509 {
00510 for (WN* wnt = wn; wnt != NULL; wnt = LWN_Get_Parent(wnt)) {
00511 if (WN_opcode(wnt) == OPC_BLOCK)
00512 return FALSE;
00513 if (WN_opcode(wnt) == OPC_DO_LOOP)
00514 return TRUE;
00515 }
00516 FmtAssert(0, ("Should have found BLOCK or DO_LOOP"));
00517 return FALSE;
00518 }
00519
00520
00521
00522
00523
00524
00525
00526 static BOOL Contains_Intrinsic_Op(WN* wn_tree)
00527 {
00528 if (WN_operator(wn_tree) == OPR_INTRINSIC_OP)
00529 return TRUE;
00530
00531 if (WN_opcode(wn_tree) == OPC_BLOCK) {
00532 for (WN* wn = WN_first(wn_tree); wn != NULL; wn = WN_next(wn))
00533 if (Contains_Intrinsic_Op(wn))
00534 return TRUE;
00535 } else {
00536 for (INT i = 0; i < WN_kid_count(wn_tree); i++)
00537 if (Contains_Intrinsic_Op(WN_kid(wn_tree, i)))
00538 return TRUE;
00539 }
00540 return FALSE;
00541 }
00542
00543
00544
00545
00546
00547
00548
00549
00550 static BOOL FS_Worthwhile(WN* wn_orig,
00551 WN* wn_loop,
00552 LS_IN_LOOP* loop_ls)
00553 {
00554 WN *surrounding_mp=NULL;
00555 if (Contains_MP) {
00556 surrounding_mp = Find_MP(wn_orig);
00557 }
00558 if (Contains_Dedicated_Preg(wn_orig))
00559 return FALSE;
00560 if (Contains_Intrinsic_Op(wn_orig))
00561 return FALSE;
00562 WN *def_loop = Enclosing_Loop(wn_orig);
00563 BOOL all_uses_in_same_def_loop = TRUE;
00564 INT max_lex_use = 0;
00565 INT count = Count_Loads_And_Leafs(WN_kid0(wn_orig));
00566 if (count > FS_LOAD_AND_LEAF_LIMIT && !Do_Loop_Is_Inner(wn_loop))
00567 return FALSE;
00568 USE_LIST *use_list = du->Du_Get_Use(wn_orig);
00569 if (use_list == NULL || use_list->Incomplete() || dg->Get_Vertex(wn_orig))
00570 return FALSE;
00571 USE_LIST_ITER iter(use_list);
00572 DU_NODE* unode = NULL;
00573 BOOL found_inner_use = FALSE;
00574 INT use_count = 0;
00575 #ifdef KEY //bug 11786 count total number of uses
00576 INT total_use_count = 0;
00577 #endif
00578 for (unode = iter.First(); !iter.Is_Empty(); unode = iter.Next()) {
00579 WN *use = unode->Wn();
00580 if (WN_operator(use) != OPR_LDID)
00581 return FALSE;
00582 if (Contains_MP) {
00583 WN *mp = Find_MP(use);
00584 if (mp != surrounding_mp) {
00585 return FALSE;
00586 }
00587 }
00588 if (!Wn_Is_Inside(use, wn_loop))
00589 return FALSE;
00590 WN* use_loop = Enclosing_Loop(use);
00591 if (use_loop != def_loop) {
00592 all_uses_in_same_def_loop = FALSE;
00593 } else {
00594 max_lex_use = MAX(max_lex_use,loop_ls->In(use));
00595 }
00596 if (Wn_Is_Inside(use_loop, wn_loop) && use_loop != wn_loop)
00597 found_inner_use = TRUE;
00598 DEF_LIST *def_list = du->Ud_Get_Def(use);
00599 if (def_list == NULL || def_list->Incomplete() || dg->Get_Vertex(use))
00600 return FALSE;
00601 if (FS_Is_In_Do_Loop_Expression(use))
00602 return FALSE;
00603 DEF_LIST_ITER iter(def_list);
00604 DU_NODE* dnode = NULL;
00605 INT def_count = 0;
00606 BOOL substitution_candidate = TRUE;
00607 for (dnode = iter.First(); !iter.Is_Empty(); dnode = iter.Next()) {
00608 WN* def = dnode->Wn();
00609 if (++def_count > 1 || def != wn_orig) {
00610 substitution_candidate = FALSE;
00611 break;
00612 }
00613 }
00614 if (!substitution_candidate)
00615 return FALSE;
00616
00617 #ifdef KEY
00618
00619
00620
00621 WN *tmp=NULL;
00622 for(tmp = use; tmp!=NULL; tmp=LWN_Get_Parent(tmp))
00623 if(tmp == LWN_Get_Parent(wn_orig))
00624 break;
00625 if(!tmp) return FALSE;
00626 #endif
00627
00628 if (FS_Is_Inside_If(use, LWN_Get_Parent(wn_orig)))
00629 return FALSE;
00630 WN *wn;
00631 for (wn = use; wn != NULL; wn = LWN_Get_Parent(wn))
00632 if (WN_operator(wn) == OPR_ARRAY)
00633 break;
00634 #ifdef KEY //bug 11786: count total number of uses
00635 total_use_count++;
00636 #endif
00637 if (wn != NULL)
00638 continue;
00639 use_count++;
00640 }
00641 if (use_count == 0)
00642 return FALSE;
00643 if (count > FS_LOAD_AND_LEAF_LIMIT && found_inner_use)
00644 return FALSE;
00645 #ifdef KEY //bug 11786: let total uses to control code expansion
00646 if (count > FS_LOAD_AND_LEAF_LIMIT && total_use_count > 1)
00647 #else
00648 if (count > FS_LOAD_AND_LEAF_LIMIT && use_count > 1)
00649 #endif
00650 return FALSE;
00651 if (all_uses_in_same_def_loop) {
00652 if (FS_Exp_Assigned_on_Loop_Iteration(wn_orig, wn_loop,
00653 loop_ls,loop_ls->In(wn_orig),max_lex_use))
00654 return FALSE;
00655 } else {
00656 if (FS_Exp_Assigned_on_Loop_Iteration(wn_orig, wn_loop,loop_ls))
00657 return FALSE;
00658 }
00659
00660 return TRUE;
00661 }
00662
00663
00664
00665
00666
00667
00668
00669
00670 static BOOL BS_Loop_Within_Equivalence_Class(WN* wn_orig,
00671 STACK<WN*>* scalar_stack)
00672 {
00673 WN* wn_orig_loop = Enclosing_Loop(wn_orig);
00674 for (INT i = 0; i < scalar_stack->Elements(); i++) {
00675 WN* wn = scalar_stack->Bottom_nth(i);
00676 WN* wn_loop = Enclosing_Loop(wn);
00677 if (wn_loop != wn_orig_loop && Wn_Is_Inside(wn_loop, wn_orig_loop))
00678 return TRUE;
00679 }
00680 return FALSE;
00681 }
00682
00683
00684
00685
00686
00687
00688
00689 static WN* BS_Find_Sibling(WN* wn_try,
00690 HASH_TABLE<WN*,INT>* region)
00691 {
00692 for (WN* wn = wn_try; wn != NULL; wn = LWN_Get_Parent(wn))
00693 if (region->Find(wn) != 0)
00694 return wn;
00695 return NULL;
00696 }
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706 static BOOL BS_Find_Region(WN* wn_orig,
00707 STACK<WN*>* scalar_stack,
00708 HASH_TABLE<WN*,INT>* region)
00709 {
00710 WN* wn_first = LWN_Get_Parent(wn_orig);
00711 WN* wn_last = LWN_Get_Parent(wn_orig);
00712 WN *wn;
00713 for (wn = wn_last; wn != NULL; wn = WN_prev(wn))
00714 region->Enter(wn, 1);
00715 for (INT i = 0; i < scalar_stack->Elements(); i++) {
00716 WN* wn_scalar = scalar_stack->Bottom_nth(i);
00717 WN* wn_sibling = BS_Find_Sibling(wn_scalar, region);
00718 if (wn_sibling == NULL)
00719 return FALSE;
00720 for (wn = WN_prev(wn_first); wn != NULL; wn = WN_prev(wn))
00721 if (wn == wn_sibling)
00722 break;
00723 if (wn == wn_sibling)
00724 wn_first = wn_sibling;
00725 }
00726 for (wn = WN_prev(wn_first); wn != NULL; wn = WN_prev(wn))
00727 region->Remove(wn);
00728 return TRUE;
00729 }
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739 static BOOL BS_Range_Check(WN* wn_orig,
00740 HASH_TABLE<WN*,INT>* region)
00741 {
00742 EINDEX16 e = 0;
00743 WN* wn_store = LWN_Get_Parent(wn_orig);
00744 VINDEX16 v = dg->Get_Vertex(wn_store);
00745 for (e = dg->Get_In_Edge(v); e != 0; e = dg->Get_Next_In_Edge(e)) {
00746 WN* wn = dg->Get_Wn(dg->Get_Source(e));
00747 if (wn != wn_store && BS_Find_Sibling(wn, region))
00748 return FALSE;
00749 }
00750 for (e = dg->Get_Out_Edge(v); e != 0; e = dg->Get_Next_Out_Edge(e)) {
00751 WN* wn = dg->Get_Wn(dg->Get_Sink(e));
00752 if (wn != wn_store && BS_Find_Sibling(wn, region))
00753 return FALSE;
00754 }
00755 return TRUE;
00756 }
00757
00758
00759
00760
00761
00762
00763
00764
00765 static BOOL BS_Crosses_MP_Region(WN* wn_orig,
00766 STACK<WN*>* scalar_stack)
00767 {
00768 if (!Contains_MP)
00769 return FALSE;
00770 WN* surrounding_mp = Find_MP(wn_orig);
00771 for (INT i = 0; i < scalar_stack->Elements(); i++)
00772 if (Find_MP(scalar_stack->Bottom_nth(i)) != surrounding_mp)
00773 return TRUE;
00774 return FALSE;
00775 }
00776
00777
00778
00779
00780
00781
00782
00783 static BOOL BS_Is_Index_Variable(STACK<WN*>* scalar_stack)
00784 {
00785 for (INT i = 0; i < scalar_stack->Elements(); i++) {
00786 WN* wn_scalar = scalar_stack->Bottom_nth(i);
00787 for (WN* wn = wn_scalar; wn != NULL; wn = LWN_Get_Parent(wn)) {
00788 if (WN_opcode(wn) == OPC_DO_LOOP
00789 && SYMBOL(WN_index(wn)) == SYMBOL(wn_scalar))
00790 return TRUE;
00791 }
00792 }
00793 return FALSE;
00794 }
00795
00796
00797
00798
00799
00800
00801
00802
00803 static BOOL BS_Has_If_In_Region(STACK<WN*>* scalar_stack,
00804 HASH_TABLE<WN*,INT>* region)
00805 {
00806 for (INT i = 0; i < scalar_stack->Elements(); i++) {
00807 WN* wn_scalar = scalar_stack->Bottom_nth(i);
00808 WN* wn_final = BS_Find_Sibling(wn_scalar, region);
00809 FmtAssert(wn_final != NULL, ("wn_scalar was not in region"));
00810 WN *wn;
00811 for (wn = wn_scalar; wn != NULL; wn = LWN_Get_Parent(wn)) {
00812 if (WN_opcode(wn) == OPC_IF)
00813 return TRUE;
00814 if (wn == wn_final)
00815 break;
00816 }
00817 FmtAssert(wn == wn_final, ("wn_scalar was not in region"));
00818 }
00819 return FALSE;
00820 }
00821
00822
00823
00824
00825
00826
00827
00828 static BOOL BS_Has_Varying_Access_Array_In_Region(WN* wn_store)
00829 {
00830 WN* wn_enclosing_loop = Enclosing_Loop(wn_store);
00831 if (wn_enclosing_loop == NULL)
00832 return FALSE;
00833 WN* wn_array = WN_kid1(wn_store);
00834 ACCESS_ARRAY *array = (ACCESS_ARRAY *) WN_MAP_Get(LNO_Info_Map, wn_array);
00835 INT varying_depth = array->Non_Const_Loops() - 1;
00836 return (varying_depth >= Do_Depth(wn_enclosing_loop));
00837 }
00838
00839
00840
00841
00842
00843
00844
00845 static BOOL BS_Has_Use_In_Subscript(WN* wn_sub,
00846 STACK<WN*>* scalar_stack)
00847 {
00848 for (INT i = 0; i < scalar_stack->Elements(); i++) {
00849 WN* wn_store = scalar_stack->Bottom_nth(i);
00850 if (OPCODE_is_store(WN_opcode(wn_store))) {
00851 LWN_ITER* itr = LWN_WALK_TreeIter(wn_sub);
00852 for (; itr != NULL; itr = LWN_WALK_TreeNext(itr)) {
00853 WN* wn = itr->wn;
00854 OPCODE op = WN_opcode(wn);
00855 OPERATOR opr = WN_operator(wn);
00856 if (!OPCODE_is_load(op) && !OPCODE_is_store(op) && opr != OPR_PARM)
00857 continue;
00858 ALIAS_RESULT result = Aliased(Alias_Mgr, wn, wn_store);
00859 if (result != NOT_ALIASED)
00860 return TRUE;
00861 }
00862 }
00863 }
00864 return FALSE;
00865 }
00866
00867 #define MAX_COEFF 20 // same as in cache_model.cxx
00868
00869
00870
00871
00872
00873
00874
00875
00876 static BOOL
00877 BS_Is_Linearized(WN* wn_array)
00878 {
00879 ACCESS_ARRAY* array = (ACCESS_ARRAY*) WN_MAP_Get(LNO_Info_Map, wn_array);
00880 INT num_dims = array->Num_Vec();
00881 for (INT i = 0; i < num_dims; i++) {
00882 ACCESS_VECTOR* dim = array->Dim(i);
00883 INT num_loops = dim->Nest_Depth();
00884 for (INT j = 0; j < num_loops; j++) {
00885 if (abs(dim->Loop_Coeff(j)) > MAX_COEFF) {
00886 return TRUE;
00887 }
00888 }
00889 }
00890 return FALSE;
00891 }
00892
00893
00894
00895
00896
00897
00898
00899
00900 static STACK<WN*>* BS_Worthwhile(WN* wn_store)
00901 {
00902 WN* wn_orig = WN_kid0(wn_store);
00903 if (!OPCODE_is_load(WN_opcode(wn_orig)) || WN_kid_count(wn_orig) != 0)
00904 return NULL;
00905 DEF_LIST *def_list = du->Ud_Get_Def(wn_orig);
00906 if (def_list == NULL || def_list->Incomplete() || dg->Get_Vertex(wn_orig))
00907 return NULL;
00908 STACK<WN*>* scalar_stack = NULL;
00909 scalar_stack = Scalar_Equivalence_Class(wn_orig, du, &LNO_default_pool);
00910 if (scalar_stack == NULL)
00911 return NULL;
00912 if (BS_Crosses_MP_Region(wn_orig, scalar_stack)) {
00913 CXX_DELETE(scalar_stack, &LNO_default_pool);
00914 return NULL;
00915 }
00916 if (BS_Is_Index_Variable(scalar_stack)) {
00917 CXX_DELETE(scalar_stack, &LNO_default_pool);
00918 return NULL;
00919 }
00920 if (!BS_Loop_Within_Equivalence_Class(wn_orig, scalar_stack)) {
00921 CXX_DELETE(scalar_stack, &LNO_default_pool);
00922 return NULL;
00923 }
00924 HASH_TABLE<WN*,INT> region(FS_SIBLING_HASH_SIZE, &LNO_local_pool);
00925 if (!BS_Find_Region(wn_orig, scalar_stack, ®ion)) {
00926 CXX_DELETE(scalar_stack, &LNO_default_pool);
00927 return NULL;
00928 }
00929 if (!BS_Range_Check(wn_orig, ®ion)) {
00930 CXX_DELETE(scalar_stack, &LNO_default_pool);
00931 return NULL;
00932 }
00933 if (BS_Has_If_In_Region(scalar_stack, ®ion)) {
00934 CXX_DELETE(scalar_stack, &LNO_default_pool);
00935 return NULL;
00936 }
00937 if (BS_Has_Varying_Access_Array_In_Region(wn_store)) {
00938 CXX_DELETE(scalar_stack, &LNO_default_pool);
00939 return NULL;
00940 }
00941 if (BS_Has_Use_In_Subscript(WN_kid1(wn_store), scalar_stack)) {
00942 CXX_DELETE(scalar_stack, &LNO_default_pool);
00943 return NULL;
00944 }
00945 if (BS_Is_Linearized(WN_kid1(wn_store))) {
00946 CXX_DELETE(scalar_stack, &LNO_default_pool);
00947 return NULL;
00948 }
00949 return scalar_stack;
00950 }
00951
00952
00953
00954
00955
00956
00957
00958 static BOOL BS_Matching_Load(WN* wn_load,
00959 WN* wn_store)
00960 {
00961 if (!OPCODE_is_load(WN_opcode(wn_load)))
00962 return FALSE;
00963 if (WN_kid_count(wn_load) == 0)
00964 return FALSE;
00965 ACCESS_ARRAY *ac_load = (ACCESS_ARRAY *)
00966 WN_MAP_Get(LNO_Info_Map, WN_kid0(wn_load));
00967 ACCESS_ARRAY *ac_store = (ACCESS_ARRAY *)
00968 WN_MAP_Get(LNO_Info_Map, WN_kid1(wn_store));
00969 if (DEPV_COMPUTE::Base_Test(wn_load, NULL,wn_store,NULL)
00970 != DEP_CONTINUE)
00971 return FALSE;
00972 if (WN_desc(wn_load) != WN_desc(wn_store))
00973 return FALSE;
00974 if (!Equivalent_Access_Arrays(ac_load, ac_store, wn_load, wn_store))
00975 return FALSE;
00976 return TRUE;
00977 }
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990 static void BS_Substitute(WN* wn_store,
00991 WN* wn_loop,
00992 STACK<WN*>* scalar_stack,
00993 LS_IN_LOOP* loop_ls)
00994 {
00995 WN* wn_orig = WN_kid0(wn_store);
00996 if (LNO_Verbose) {
00997 INT sub_count = scalar_stack->Elements();
00998 FmtAssert(sub_count > 0,
00999 ("Backward substituting less than one occurrence."));
01000 fprintf(stdout, " Backward Substituting %d occurences of %s in loop %s\n",
01001 sub_count, WB_Whirl_Symbol(wn_orig), WB_Whirl_Symbol(wn_loop));
01002 fprintf(TFile, " Backward Substituting %d occurences of %s in loop %s\n",
01003 sub_count, WB_Whirl_Symbol(wn_orig), WB_Whirl_Symbol(wn_loop));
01004 }
01005 WN* wn_load = Create_ILoad_From_IStore(wn_store, du, dg);
01006 STACK<WN*>* array_stack = CXX_NEW(STACK<WN*> (&LNO_local_pool),
01007 &LNO_local_pool);
01008 STACK<INT>* position_stack = CXX_NEW(STACK<INT> (&LNO_local_pool),
01009 &LNO_local_pool);
01010 WN* wn_red_load = NULL;
01011 INT i;
01012 for (i = 0; i < scalar_stack->Elements(); i++) {
01013 WN* wn = scalar_stack->Bottom_nth(i);
01014 if (wn == wn_orig)
01015 continue;
01016 if (wn_red_load == NULL
01017 && WN_operator(wn) == OPR_STID
01018 && BS_Matching_Load(WN_kid0(wn), wn_store)) {
01019 wn_red_load = wn;
01020 continue;
01021 }
01022 OPCODE op = WN_opcode(wn);
01023 if (OPCODE_is_store(op) && WN_kid0(wn) != wn_load)
01024 BS_Replace_Store(wn, wn_store, loop_ls, array_stack, position_stack);
01025 else if (OPCODE_is_load(op) && LWN_Get_Parent(wn) != wn_store)
01026 BS_Replace_Load(wn, wn_load, loop_ls, array_stack, position_stack);
01027 }
01028 if (wn_red_load != NULL) {
01029 LWN_Extract_From_Block(wn_red_load);
01030 LWN_Delete_Tree(wn_red_load);
01031 }
01032 EINDEX16 e = 0;
01033 for (i = 0; i < array_stack->Elements(); i++) {
01034 WN* wn_one = array_stack->Bottom_nth(i);
01035 VINDEX16 v = dg->Get_Vertex(wn_store);
01036 for (e = dg->Get_In_Edge(v); e != 0; e = dg->Get_Next_In_Edge(e)) {
01037 WN* wn_source = dg->Get_Wn(dg->Get_Source(e));
01038 if (wn_source == wn_store)
01039 continue;
01040 if (!OPCODE_is_store(WN_opcode(wn_one))
01041 && !OPCODE_is_store(WN_opcode(wn_source)))
01042 continue;
01043 if (!dg->Add_Edge(dg->Get_Vertex(wn_source), dg->Get_Vertex(wn_one),
01044 Create_DEPV_ARRAY(dg->Depv_Array(e), &LNO_default_pool))) {
01045 LNO_Erase_Dg_From_Here_In(wn_store, dg);
01046 return;
01047 }
01048 }
01049 for (e = dg->Get_Out_Edge(v); e != 0; e = dg->Get_Next_Out_Edge(e)) {
01050 WN* wn_sink = dg->Get_Wn(dg->Get_Sink(e));
01051 if (wn_sink == wn_store)
01052 continue;
01053 if (!OPCODE_is_store(WN_opcode(wn_one))
01054 && !OPCODE_is_store(WN_opcode(wn_sink)))
01055 continue;
01056 if (!dg->Add_Edge(dg->Get_Vertex(wn_one), dg->Get_Vertex(wn_sink),
01057 Create_DEPV_ARRAY(dg->Depv_Array(e), &LNO_default_pool))) {
01058 LNO_Erase_Dg_From_Here_In(wn_store, dg);
01059 return;
01060 }
01061 }
01062 if (OPCODE_is_store(WN_opcode(wn_one))) {
01063 USE_LIST *use_list = du->Du_Get_Use(wn_store);
01064 USE_LIST_ITER iter(use_list);
01065 const DU_NODE* node = NULL;
01066 for (node = iter.First(); !iter.Is_Empty(); i++, node = iter.Next())
01067 du->Add_Def_Use(wn_one, node->Wn());
01068 }
01069 }
01070 LWN_Extract_From_Block(wn_store);
01071 LWN_Delete_Tree(wn_store);
01072 LWN_Delete_Tree(wn_load);
01073 for (i = 0; i < array_stack->Elements(); i++) {
01074 WN* wn_one = array_stack->Bottom_nth(i);
01075 INT position_one = position_stack->Bottom_nth(i);
01076 DOLOOP_STACK first_stack(&LNO_local_pool);
01077 Build_Doloop_Stack(wn_one, &first_stack);
01078 for (INT j = i; j < array_stack->Elements(); j++) {
01079 WN* wn_two = array_stack->Bottom_nth(j);
01080 INT position_two = position_stack->Bottom_nth(j);
01081 DOLOOP_STACK second_stack(&LNO_local_pool);
01082 Build_Doloop_Stack(wn_two, &second_stack);
01083 if (!OPCODE_is_store(WN_opcode(wn_one))
01084 && !OPCODE_is_store(WN_opcode(wn_two)))
01085 continue;
01086 if (!dg->Add_Edge(wn_one, &first_stack, wn_two,
01087 &second_stack, position_one < position_two)) {
01088 LNO_Erase_Dg_From_Here_In(wn_two, dg);
01089 return;
01090 }
01091 }
01092 }
01093 }
01094
01095
01096
01097
01098
01099
01100
01101 static BOOL FS_Array_Single_Def_Use(WN* wn_def,
01102 WN* wn_use)
01103 {
01104 EINDEX16 e = 0;
01105 VINDEX16 v = dg->Get_Vertex(wn_use);
01106 BOOL found_def = FALSE;
01107 WN* wn_loop_def = Enclosing_Loop(wn_def);
01108 WN* wn_loop_use = Enclosing_Loop(wn_use);
01109 if (wn_loop_def == NULL || wn_loop_def != wn_loop_use)
01110 return FALSE;
01111 for (e = dg->Get_In_Edge(v); e != 0; e = dg->Get_Next_In_Edge(e)) {
01112 WN* wn_source = dg->Get_Wn(dg->Get_Source(e));
01113 DEPV_ARRAY* dva = dg->Depv_Array(e);
01114 INT num_dim = dva->Num_Dim();
01115 for (INT i = 0; i < dva->Num_Vec(); i++) {
01116 DEPV* depv = dva->Depv(i);
01117 INT j;
01118 for (j = 0; j < num_dim; j++)
01119 if (DEP_Direction(DEPV_Dep(depv, j)) == DIR_POS)
01120 break;
01121 if (j < num_dim)
01122 continue;
01123 if (wn_source == wn_def) {
01124 found_def = TRUE;
01125 continue;
01126 }
01127 return FALSE;
01128 }
01129 }
01130 return found_def;
01131 }
01132
01133
01134
01135
01136
01137
01138
01139
01140
01141
01142
01143 static WN* FS_Condition(WN* wn_node,
01144 INT* which_branch)
01145 {
01146 WN* wnn = NULL;
01147 *which_branch = 0;
01148 WN *wn;
01149 for (wn = wn_node; wn != NULL; wn = LWN_Get_Parent(wn)) {
01150 switch (WN_opcode(wn)) {
01151 case OPC_IF:
01152 if (wnn == WN_then(wn))
01153 *which_branch = 1;
01154 else if (wnn == WN_else(wn))
01155 *which_branch = 2;
01156 return wn;
01157 case OPC_DO_LOOP:
01158 case OPC_DO_WHILE:
01159 case OPC_WHILE_DO:
01160 return wn;
01161 }
01162 wnn = wn;
01163 }
01164 return wn;
01165 }
01166
01167
01168
01169
01170
01171
01172
01173
01174 static BOOL FS_Array_Worthwhile(WN* wn_def,
01175 STACK<WN*>* st_use,
01176 LS_IN_LOOP* loop_ls)
01177 {
01178 WN* wn_loop = Enclosing_Do_Loop(wn_def);
01179 if (wn_loop == NULL)
01180 return FALSE;
01181 if (Do_Loop_Has_Gotos(wn_loop)) {
01182 return FALSE;
01183 }
01184 WN* wn_surrounding_mp = NULL;
01185 if (Contains_MP)
01186 wn_surrounding_mp = Find_MP(wn_def);
01187 if (Contains_Dedicated_Preg(wn_def))
01188 return FALSE;
01189 if (Contains_Intrinsic_Op(wn_def))
01190 return FALSE;
01191 INT count = Node_Count(WN_kid0(wn_def));
01192 if (count > FS_ARRAY_EXP_LIMIT)
01193 return FALSE;
01194 EINDEX16 e = 0;
01195 VINDEX16 v_def = dg->Get_Vertex(wn_def);
01196 if (v_def == 0)
01197 return FALSE;
01198 STACK<WN*> fs_stack(&LNO_local_pool);
01199 INT loop_depth = Do_Loop_Depth(wn_loop);
01200 INT max_lex_use = 0;
01201 for (e = dg->Get_Out_Edge(v_def); e != 0; e = dg->Get_Next_Out_Edge(e)) {
01202 WN* wn_use = dg->Get_Wn(dg->Get_Sink(e));
01203 max_lex_use = MAX(max_lex_use,loop_ls->In(wn_use));
01204 }
01205 for (e = dg->Get_Out_Edge(v_def); e != 0; e = dg->Get_Next_Out_Edge(e)) {
01206 WN* wn_use = dg->Get_Wn(dg->Get_Sink(e));
01207 if (Contains_MP && Find_MP(wn_use) != wn_surrounding_mp)
01208 return FALSE;
01209 if (Wn_Is_Inside(wn_use, wn_def))
01210 continue;
01211 if (!BS_Matching_Load(wn_use, wn_def))
01212 continue;
01213 if (!FS_Array_Single_Def_Use(wn_def, wn_use))
01214 continue;
01215 INT which_branch_def = -1;
01216 INT which_branch_use = -1;
01217 if (FS_Condition(wn_def, &which_branch_def)
01218 != FS_Condition(wn_use, &which_branch_use))
01219 continue;
01220 if (which_branch_def != which_branch_use)
01221 continue;
01222 if (FS_Exp_Assigned_on_Loop_Iteration(wn_def, wn_loop, loop_ls,
01223 loop_ls->In(wn_def), max_lex_use))
01224 continue;
01225 st_use->Push(wn_use);
01226 }
01227 return st_use->Elements() >= 1;
01228 }
01229
01230
01231
01232
01233
01234
01235
01236 static void FS_Array_Substitute(WN* wn_def,
01237 WN* wn_use,
01238 LS_IN_LOOP* loop_ls)
01239 {
01240 DU_MANAGER* du = Du_Mgr;
01241 REDUCTION_MANAGER* rm = red_manager;
01242 INT32 count = 0;
01243 if (LNO_Verbose) {
01244 char buffer[FS_MAX_STRING_LENGTH];
01245 WB_Dep_Symbol(wn_def, buffer, FS_MAX_STRING_LENGTH - 1);
01246 fprintf(stdout, " Forward Substituting Array %s in loop %s\n",
01247 buffer, WB_Whirl_Symbol(Enclosing_Loop(wn_def)));
01248 fprintf(TFile, " Forward Substituting Array %s in loop %s\n",
01249 buffer, WB_Whirl_Symbol(Enclosing_Loop(wn_def)));
01250 }
01251 if (Cur_PU_Feedback)
01252 count = WN_MAP32_Get(WN_MAP_FEEDBACK, wn_use);
01253 INT position = loop_ls->In(wn_use);
01254 if (rm != NULL) {
01255 REDUCTION_TYPE red_type = rm->Which_Reduction(wn_use);
01256 if (red_type != RED_NONE) {
01257 WN *wn;
01258 for (wn = wn_use; wn != NULL; wn = LWN_Get_Parent(wn))
01259 if (OPCODE_is_store(WN_opcode(wn))
01260 && rm->Which_Reduction(wn) == red_type)
01261 break;
01262 FmtAssert(wn != NULL,
01263 ("Could not find store to match reduction load."));
01264 rm->Erase(wn);
01265 }
01266 }
01267 BOOL added_convert = FALSE;
01268 WN* wn_copy = Replace_Wnexp_With_Exp_Copy(wn_use, WN_kid0(wn_def), du,
01269 &added_convert);
01270 LWN_Set_Frequency_Tree(wn_copy, count);
01271 WN* wn_true_copy = added_convert ? WN_kid0(wn_copy) : wn_copy;
01272 INT count1 = Node_Count(WN_kid0(wn_def));
01273 INT count2 = Node_Count(wn_true_copy);
01274 FmtAssert(count1 == count2,
01275 ("FS_Array_Substitute: Counts do not match"));
01276 Fix_Access_Arrays_In_Copy_Block(wn_true_copy);
01277 Fix_Deps_In_Copy_Block(loop_ls, WN_kid0(wn_def), wn_true_copy, position);
01278 }
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289 static BOOL AS_Traverse(WN *wn,
01290 LS_IN_LOOP* loop_ls)
01291 {
01292 BOOL substituted = FALSE;
01293 switch (WN_operator(wn)) {
01294 case OPR_BLOCK:
01295 {
01296 WN* wn_tpp = NULL;
01297 for (WN* wn_tp = WN_first(wn); wn_tp != NULL; wn_tp = wn_tpp) {
01298 wn_tpp = WN_next(wn_tp);
01299 if (AS_Traverse(wn_tp, loop_ls))
01300 substituted = TRUE;
01301 }
01302 }
01303 break;
01304 case OPR_DO_LOOP:
01305 {
01306 if (loop_ls == NULL)
01307 loop_ls = CXX_NEW(LS_IN_LOOP(wn, dg, &LNO_local_pool, TRUE),
01308 &LNO_local_pool);
01309 substituted = AS_Traverse(WN_do_body(wn), loop_ls);
01310 loop_ls = NULL;
01311 }
01312 break;
01313 case OPR_FUNC_ENTRY:
01314 substituted = AS_Traverse(WN_func_body(wn), loop_ls);
01315 break;
01316 case OPR_IF:
01317 {
01318 BOOL sub1 = AS_Traverse(WN_then(wn), loop_ls);
01319 BOOL sub2 = AS_Traverse(WN_else(wn), loop_ls);
01320 substituted = sub1 || sub2;
01321 }
01322 break;
01323 case OPR_DO_WHILE:
01324 case OPR_WHILE_DO:
01325 substituted = AS_Traverse(WN_while_body(wn), loop_ls);
01326 break;
01327 case OPR_STID:
01328 if (LNO_Forward_Substitution) {
01329 WN* wn_loop = Enclosing_Loop(wn);
01330 if (!(wn_loop != NULL
01331 && WN_operator(wn_loop) == OPR_DO_LOOP
01332 && Do_Loop_Is_Good(wn_loop) &&
01333 !Do_Loop_Has_Gotos(wn_loop)))
01334 break;
01335 if (FS_Worthwhile(wn, wn_loop, loop_ls)) {
01336 FS_Substitute(wn, loop_ls);
01337 substituted = TRUE;
01338 }
01339 }
01340 break;
01341 case OPR_ISTORE:
01342 if (LNO_Backward_Substitution) {
01343 WN* wn_loop = Enclosing_Loop(wn);
01344 if (wn_loop != NULL
01345 && WN_operator(wn_loop) == OPR_DO_LOOP
01346 && Do_Loop_Is_Good(wn_loop) &&
01347 !Do_Loop_Has_Gotos(wn_loop)) {
01348 STACK<WN*>* scalar_stack = BS_Worthwhile(wn);
01349 if (scalar_stack != NULL) {
01350 BS_Substitute(wn, wn_loop, scalar_stack, loop_ls);
01351 substituted = TRUE;
01352 break;
01353 }
01354 }
01355 }
01356 if (LNO_Forward_Substitution) {
01357 STACK<WN*> st_use(&LNO_local_pool);
01358 if (FS_Array_Worthwhile(wn, &st_use, loop_ls)) {
01359 if (st_use.Elements() == 1) {
01360 for (INT i = 0; i < st_use.Elements(); i++)
01361 FS_Array_Substitute(wn, st_use.Bottom_nth(i), loop_ls);
01362 substituted = TRUE;
01363 VINDEX16 v = dg->Get_Vertex(wn);
01364 if (v != 0)
01365 Process_Store(wn, v, dg);
01366 }
01367 }
01368 }
01369 }
01370 return substituted;
01371 }
01372
01373
01374
01375
01376
01377
01378 extern void Array_Substitution(WN* func_nd)
01379 {
01380 LS_IN_LOOP* loop_ls = NULL;
01381 if (!LNO_Forward_Substitution && !LNO_Backward_Substitution)
01382 return;
01383 if (LNO_Verbose) {
01384 fprintf(stdout, "Applying Array Substitution\n");
01385 fprintf(TFile, "Applying Array Substitution\n");
01386 }
01387 dg = Array_Dependence_Graph;
01388 du = Du_Mgr;
01389 rm = red_manager;
01390 (void) AS_Traverse(func_nd, loop_ls);
01391 if (LNO_Verbose) {
01392 fprintf(stdout, "Array Substitution Complete\n");
01393 fprintf(TFile, "Array Substitution Complete\n");
01394 }
01395 }
01396
01397
01398
01399
01400
01401
01402
01403 static BOOL Crosses_Regions(WN* wn1, WN* wn2)
01404 {
01405 INT region_count1 = 0;
01406 WN *wn;
01407 for (wn = wn1; wn != NULL; wn = LWN_Get_Parent(wn))
01408 if (WN_opcode(wn) == OPC_REGION)
01409 region_count1++;
01410 INT region_count2 = 0;
01411 for (wn = wn2; wn != NULL; wn = LWN_Get_Parent(wn))
01412 if (WN_opcode(wn) == OPC_REGION)
01413 region_count2++;
01414 return region_count1 != region_count2;
01415 }
01416
01417
01418
01419
01420
01421
01422
01423 static BOOL Contains_ILoad_Without_Vertex(WN* wn_tree)
01424 {
01425 ARRAY_DIRECTED_GRAPH16* dg = Array_Dependence_Graph;
01426 if (WN_operator(wn_tree) == OPR_ILOAD && !dg->Get_Vertex(wn_tree))
01427 return TRUE;
01428 for (INT i = 0; i < WN_kid_count(wn_tree); i++)
01429 if (Contains_ILoad_Without_Vertex(WN_kid(wn_tree, i)))
01430 return TRUE;
01431 return FALSE;
01432 }
01433
01434
01435
01436
01437
01438
01439
01440 static BOOL Exceeds_FS_Limit(WN* wn_node)
01441 {
01442 const INT FS_NODE_COUNT = 100;
01443 const INT FS_SYMBOL_COUNT = 10;
01444 if (Node_Count(wn_node, FS_NODE_COUNT, FALSE) > FS_NODE_COUNT)
01445 return TRUE;
01446 if (Node_Count(wn_node, FS_SYMBOL_COUNT, TRUE) > FS_SYMBOL_COUNT)
01447 return TRUE;
01448 return FALSE;
01449 }
01450
01451
01452
01453
01454
01455
01456
01457
01458 extern WN* Forward_Substitutable(WN* wn_ldid,
01459 DU_MANAGER* du)
01460 {
01461 if (WN_operator(wn_ldid) != OPR_LDID)
01462 return NULL;
01463 if (ST_class(WN_st(wn_ldid)) == CLASS_PREG
01464 && WN_offset(wn_ldid) <= Last_Dedicated_Preg_Offset)
01465 return NULL;
01466 DEF_LIST *def_list = du->Ud_Get_Def(wn_ldid);
01467 if (def_list == NULL || def_list->Incomplete())
01468 return NULL;
01469 DEF_LIST_ITER iter(def_list);
01470 WN* wn_def = NULL;
01471 const DU_NODE* node = NULL;
01472 for (node = iter.First(); !iter.Is_Empty(); node = iter.Next()) {
01473 WN* wn = node->Wn();
01474 if (wn_def != NULL)
01475 return NULL;
01476 wn_def = wn;
01477 }
01478 if (WN_operator(wn_def) != OPR_STID
01479 || SYMBOL(wn_ldid) != SYMBOL(wn_def))
01480 return NULL;
01481 if (Contains_Dedicated_Preg(wn_def))
01482 return NULL;
01483 WN* wn_first = wn_def;
01484 WN* wn_last = Find_Sibling_Containing(wn_first, wn_ldid);
01485 if (wn_last == NULL)
01486 return NULL;
01487 if (Exceeds_FS_Limit(WN_kid0(wn_def)))
01488 return NULL;
01489 if (Maybe_Assigned_Exp(WN_kid0(wn_def), wn_first, wn_last))
01490 return NULL;
01491 if (Crosses_Regions(wn_def, wn_ldid))
01492 return NULL;
01493 WN* wn_enclosing_loop = Enclosing_Proper_Do_Loop(wn_ldid);
01494 if (wn_enclosing_loop != NULL && Do_Loop_Is_Good(wn_enclosing_loop)
01495 && Contains_ILoad_Without_Vertex(wn_def))
01496 return NULL;
01497 return wn_def;
01498 }
01499
01500
01501
01502
01503
01504
01505
01506 static void Fix_Deps_For_Load(WN* wn_orig,
01507 WN* wn_copy)
01508 {
01509 DU_MANAGER* du = Du_Mgr;
01510 ARRAY_DIRECTED_GRAPH16* dg = Array_Dependence_Graph;
01511 OPERATOR op_orig = WN_operator(wn_orig);
01512 OPERATOR op_copy = WN_operator(wn_copy);
01513 FmtAssert(op_orig == op_copy
01514 && (op_orig == OPR_LDID || op_orig == OPR_ILOAD),
01515 ("Fix_Deps_For_Load: Call with improper arguments"));
01516 DOLOOP_STACK copy_stack(&LNO_local_pool);
01517 Build_Doloop_Stack(wn_copy, ©_stack);
01518 dg->Add_Vertex(wn_copy);
01519 HASH_TABLE<WN*,INT> old_nodes(MIN(dg->Get_Edge_Count(), 512),
01520 &LNO_local_pool);
01521 EINDEX16 e = 0;
01522 DOLOOP_STACK source_stack(&LNO_local_pool);
01523 VINDEX16 v_orig = dg->Get_Vertex(wn_orig);
01524 for (e = dg->Get_In_Edge(v_orig); e != 0; e = dg->Get_Next_In_Edge(e)) {
01525 WN* wn_source = dg->Get_Wn(dg->Get_Source(e));
01526 old_nodes.Enter(wn_source, 1);
01527 Build_Doloop_Stack(wn_source, &source_stack);
01528 if (!dg->Add_Edge(wn_source, &source_stack, wn_copy,
01529 ©_stack, Is_Lex_Before(wn_source, wn_orig))) {
01530 LNO_Erase_Dg_From_Here_In(wn_copy, dg);
01531 return;
01532 }
01533 source_stack.Clear();
01534 }
01535 DOLOOP_STACK sink_stack(&LNO_local_pool);
01536 for (e = dg->Get_Out_Edge(v_orig); e != 0; e = dg->Get_Next_Out_Edge(e)) {
01537 WN* wn_sink = dg->Get_Wn(dg->Get_Sink(e));
01538 if (old_nodes.Find(wn_sink) != 0)
01539 continue;
01540 Build_Doloop_Stack(wn_sink, &sink_stack);
01541 if (!dg->Add_Edge(wn_copy, ©_stack, wn_sink,
01542 &sink_stack, Is_Lex_Before(wn_orig, wn_sink))) {
01543 LNO_Erase_Dg_From_Here_In(wn_copy, dg);
01544 return;
01545 }
01546 sink_stack.Clear();
01547 }
01548 }
01549
01550
01551
01552
01553
01554
01555
01556
01557
01558 static void Fix_Exp_Deps(WN* wn_orig,
01559 WN* wn_copy)
01560 {
01561 DU_MANAGER* du = Du_Mgr;
01562 ARRAY_DIRECTED_GRAPH16* dg = Array_Dependence_Graph;
01563 OPCODE op_orig = WN_opcode(wn_orig);
01564 OPCODE op_copy = WN_opcode(wn_copy);
01565 FmtAssert(op_orig == op_copy && OPCODE_is_expression(op_orig),
01566 ("Fix_Exp_Deps: Opcodes do not match or not an expression"));
01567
01568 if (dg->Get_Vertex(wn_orig)) {
01569 Fix_Deps_For_Load(wn_orig, wn_copy);
01570 } else if (WN_operator(wn_copy) == OPR_ILOAD) {
01571 WN* wn_loop = Enclosing_Proper_Do_Loop(wn_copy);
01572 if (wn_loop != NULL && Do_Loop_Is_Good(wn_loop) &&
01573 !Do_Loop_Has_Gotos(wn_loop))
01574 dg->Add_Vertex(wn_copy);
01575 }
01576 for (INT i = 0; i < WN_kid_count(wn_orig); i++) {
01577 WN* wn_new_orig = WN_kid(wn_orig, i);
01578 WN* wn_new_copy = WN_kid(wn_copy, i);
01579 Fix_Exp_Deps(wn_new_orig, wn_new_copy);
01580 }
01581 }
01582
01583
01584
01585
01586
01587
01588
01589 static BOOL Dead_Stid(WN* wn_def)
01590 {
01591 DU_MANAGER* du = Du_Mgr;
01592 OPERATOR opr = WN_operator(wn_def);
01593 if (opr != OPR_STID)
01594 return FALSE;
01595 USE_LIST* use_list = du->Du_Get_Use(wn_def);
01596 if (use_list == NULL)
01597 return TRUE;
01598 if (use_list->Incomplete())
01599 return FALSE;
01600 USE_LIST_ITER iter(use_list);
01601 const DU_NODE* node = iter.First();
01602 if (node == NULL)
01603 return TRUE;
01604 return FALSE;
01605 }
01606
01607
01608
01609
01610
01611
01612
01613
01614 extern void Forward_Substitute_Ldids(WN* wn_exp,
01615 DU_MANAGER* du)
01616 {
01617 FmtAssert(OPCODE_is_expression(WN_opcode(wn_exp)),
01618 ("wn_exp must be expression"));
01619
01620 if (WN_operator(wn_exp) == OPR_LDID) {
01621 WN* wn_def = Forward_Substitutable(wn_exp, du);
01622 if (wn_def != NULL) {
01623 if (LNO_Verbose) {
01624 fprintf(stdout, "FS: Forward substituting %s at 0x%p\n",
01625 WB_Whirl_Symbol(wn_def), wn_def);
01626 fprintf(TFile, "FS: Forward substituting %s at 0x%p\n",
01627 WB_Whirl_Symbol(wn_def), wn_def);
01628 }
01629 WN* wn_orig = WN_kid0(wn_def);
01630 WN* wn_copy = LWN_Copy_Tree(wn_orig);
01631 LWN_Copy_Def_Use(wn_orig, wn_copy, du);
01632 WN* wn_parent = LWN_Get_Parent(wn_exp);
01633 INT k;
01634 for (k = 0; k < WN_kid_count(wn_parent); k++)
01635 if (WN_kid(wn_parent, k) == wn_exp)
01636 break;
01637 WN_kid(wn_parent, k) = wn_copy;
01638 LWN_Set_Parent(wn_copy, wn_parent);
01639 Fix_Access_Arrays_In_Copy_Block(wn_copy);
01640 Fix_Exp_Deps(wn_orig, wn_copy);
01641 LWN_Delete_Tree(wn_exp);
01642 if (Dead_Stid(wn_def)) {
01643 LWN_Extract_From_Block(wn_def);
01644 LWN_Delete_Tree(wn_def);
01645 }
01646 WN *wn;
01647 for (wn = wn_copy; wn != NULL; wn = LWN_Get_Parent(wn))
01648 if (WN_opcode(wn) == OPC_DO_LOOP || WN_opcode(wn) == OPC_IF)
01649 break;
01650 DOLOOP_STACK dostack(&LNO_local_pool);
01651 Build_Doloop_Stack(LWN_Get_Parent(wn), &dostack);
01652 LNO_Build_Access(wn, &dostack, &LNO_default_pool);
01653 return;
01654 }
01655 }
01656
01657 for (INT i = 0; i < WN_kid_count(wn_exp); i++)
01658 Forward_Substitute_Ldids(WN_kid(wn_exp, i), du);
01659 }
01660
01661
01662 static WN *Find_MP(WN *wn)
01663 {
01664 while (wn && !Is_Mp_Region(wn) &&
01665 ((WN_opcode(wn) != OPC_DO_LOOP) || !Do_Loop_Is_Mp(wn))) {
01666 wn = LWN_Get_Parent(wn);
01667 }
01668 return wn;
01669 }