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
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077 #ifdef USE_PCH
00078 #include "lno_pch.h"
00079 #endif // USE_PCH
00080 #pragma hdrstop
00081
00082 const static char *source_file = __FILE__;
00083 const static char *rcs_id = "$Source$ $Revision$";
00084
00085 #include <sys/types.h>
00086 #include "lnopt_main.h"
00087 #include "dep_graph.h"
00088 #include "lnoutils.h"
00089 #include "lwn_util.h"
00090 #include "opt_du.h"
00091 #include "lno_bv.h"
00092 #include "whirl2src.h"
00093 #include "fiz_fuse.h"
00094 #include "fission.h"
00095 #include "snl_utils.h"
00096 #include "scalar_expand.h"
00097 #include "small_trips.h"
00098 #include "soe.h"
00099 #include "cond.h"
00100 #include "prompf.h"
00101 #include "anl_driver.h"
00102
00103 #pragma weak New_Construct_Id
00104
00105 static void Transform_Expression(BIT_VECTOR *bv, WN *exp, DOLOOP_STACK *do_stack, INT num_loops,
00106 INT outer_reg_tile, BOOL can_tile);
00107 static BOOL Process_Load(WN *load, BIT_VECTOR *result,DOLOOP_STACK *do_stack,
00108 INT num_elements,HASH_TABLE<WN *,BIT_VECTOR *> *htable, MEM_POOL *pool, BOOL outer_only);
00109 static BOOL Compatible_Expressions(BIT_VECTOR *input, BIT_VECTOR *output, BOOL outer_only);
00110 extern WN *Split_Using_Preg(WN* stmt, WN* op,
00111 ARRAY_DIRECTED_GRAPH16* dep_graph, BOOL recursive);
00112 static WN *Fission_Statement(WN *statement, DOLOOP_STACK *do_stack, INT num_loops);
00113 static BOOL Contains_Work(WN *exp);
00114 static BOOL Contains_Varying_Indirect_Load(WN *exp);
00115 static BOOL Contains_Indirect_Load(WN *exp);
00116 static BOOL Contains_Load(WN *exp);
00117 static void Scalar_Expansion_Tile(DOLOOP_STACK *do_stack,INT num_loops,
00118 BIT_VECTOR *used_loops);
00119 extern INT SNL_INV_Compute_Tile_Size(INT depth);
00120 void Mark_Invar(WN *region, INT num_loops, DOLOOP_STACK *do_stack,
00121 HASH_TABLE<WN *,BIT_VECTOR *> *htable, MEM_POOL *pool, BOOL outer_only);
00122 static BIT_VECTOR *Mark_Expression(WN *wn, INT num_loops, DOLOOP_STACK *do_stack,
00123 HASH_TABLE<WN *,BIT_VECTOR *> *htable, MEM_POOL *pool, BOOL outer_only);
00124 static INT First_Invariant(BIT_VECTOR *bv,INT num_loops);
00125 static void Hoist_Inner_Invar(BIT_VECTOR *bv,WN *exp, DOLOOP_STACK *do_stack, INT num_loops);
00126 static BOOL Sufficient_Iterations(BIT_VECTOR *bv, DOLOOP_STACK *stack,
00127 INT num_loops) ;
00128 typedef STACK<WN *> STACK_OF_WN;
00129
00130
00131
00132 #define MAX_SIZE 50
00133
00134
00135
00136 #define MIN_ITERATIONS 8
00137
00138
00139
00140
00141 class WN_BV
00142 {
00143 public:
00144 WN *wn;
00145 WN *parent;
00146 INT kid_pos;
00147 BIT_VECTOR *bv;
00148 WN_BV(WN *w, BIT_VECTOR *b) {
00149 wn=w;
00150 bv=b;
00151 };
00152 WN_BV(WN *w, BIT_VECTOR *b, WN *par, INT kp) {
00153 wn=w;
00154 bv=b;
00155 parent = par;
00156 kid_pos = kp;
00157 };
00158 WN_BV() {}
00159 } ;
00160
00161 typedef STACK<WN_BV> WN_BV_STACK;
00162
00163 static void Remove_Invar_Duplicates(WN_BV_STACK* invar_stack);
00164 static void Prune_Invar_Memops(WN_BV_STACK* invar_stack, BOOL inner_invar);
00165 static void Sort_Invar_Stack(WN_BV_STACK *invar_stack, INT num_loops);
00166 static void Gather_Invar(WN *inner, INT num_loops, DOLOOP_STACK *do_stack,
00167 HASH_TABLE<WN *,BIT_VECTOR *> *htable, WN_BV_STACK *invar_stack);
00168
00169
00170
00171
00172
00173
00174 void Hoist_Outer_Invar(WN *wn_inner, INT num_loops, INT outer_reg_tile, BOOL can_tile)
00175 {
00176 DO_LOOP_INFO *dli = Get_Do_Loop_Info(wn_inner);
00177 if (!dli->Num_Iterations_Symbolic &&
00178 dli->Est_Num_Iterations < MIN_ITERATIONS) {
00179 return;
00180 }
00181
00182 MEM_POOL_Push(&LNO_local_pool);
00183 if (LNO_Verbose) {
00184 fprintf(stdout,
00185 "# Hoisting outer invariants from loop on line %d (begin)\n",
00186 (INT) WN_linenum(wn_inner));
00187 fprintf(TFile,
00188 "# Hoisting outer invariants from loop on line %d (begin)\n",
00189 (INT) WN_linenum(wn_inner));
00190 }
00191 DOLOOP_STACK *do_stack = CXX_NEW(DOLOOP_STACK(&LNO_local_pool),
00192 &LNO_local_pool);
00193 WN_BV_STACK *invar_stack = CXX_NEW(WN_BV_STACK(&LNO_local_pool),
00194 &LNO_local_pool);
00195 {
00196 HASH_TABLE<WN *,BIT_VECTOR *> htable(500,&LNO_local_pool);
00197 Build_Doloop_Stack(wn_inner,do_stack);
00198 Mark_Invar(WN_do_body(wn_inner),num_loops,do_stack,&htable,
00199 &LNO_local_pool,FALSE);
00200 Gather_Invar(WN_do_body(wn_inner),num_loops,do_stack,&htable,invar_stack);
00201 Remove_Invar_Duplicates(invar_stack);
00202 Prune_Invar_Memops(invar_stack, outer_reg_tile == num_loops);
00203 Sort_Invar_Stack(invar_stack,num_loops);
00204
00205 for (INT i=0; i<invar_stack->Elements(); i++) {
00206 WN *wn = invar_stack->Bottom_nth(i).wn;
00207 BIT_VECTOR *bv = invar_stack->Bottom_nth(i).bv;
00208 if (bv->Test(bv->Size()-1)) {
00209 if (outer_reg_tile == num_loops && Contains_Indirect_Load(wn))
00210 Hoist_Inner_Invar(bv,wn,do_stack,num_loops);
00211 } else {
00212 if (Sufficient_Iterations(bv,do_stack,num_loops)) {
00213 Transform_Expression(bv,wn,do_stack,num_loops,outer_reg_tile,
00214 can_tile);
00215 }
00216 }
00217 }
00218 }
00219 if (LNO_Verbose) {
00220 fprintf(stdout,
00221 "# Hoisting outer invariants from loop on line %d (end)\n",
00222 (INT) WN_linenum(wn_inner));
00223 fprintf(TFile,
00224 "# Hoisting outer invariants from loop on line %d (end)\n",
00225 (INT) WN_linenum(wn_inner));
00226 }
00227 MEM_POOL_Pop(&LNO_local_pool);
00228 }
00229
00230
00231
00232
00233
00234 static void
00235 Remove_Invar_Duplicates(WN_BV_STACK* invar_stack)
00236 {
00237 for (INT i = 0; i < invar_stack->Elements(); ++i) {
00238 WN* wn = invar_stack->Bottom_nth(i).wn;
00239 for (INT j = i+1; j < invar_stack->Elements(); ++j) {
00240 if (Tree_Equiv(wn, invar_stack->Bottom_nth(j).wn)) {
00241 invar_stack->Bottom_nth(j) = invar_stack->Top();
00242 invar_stack->Pop();
00243 --j;
00244 }
00245 }
00246 }
00247 }
00248
00249
00250
00251
00252
00253 static inline BOOL
00254 Is_Very_Expensive_Expression(const WN* wn)
00255 {
00256 OPERATOR opr = WN_operator(wn);
00257
00258 return (opr == OPR_DIV ||
00259 opr == OPR_DIVREM ||
00260 opr == OPR_RECIP ||
00261 opr == OPR_SQRT ||
00262 opr == OPR_RSQRT
00263 #ifdef TARG_X8664
00264 || opr == OPR_ATOMIC_RSQRT
00265 #endif
00266 );
00267 }
00268
00269 #ifdef KEY
00270 static BOOL Operands_All_Invariant(WN *wn)
00271 {
00272 WN *do_loop = Enclosing_Do_Loop(wn);
00273 for (INT i = 0; i < WN_kid_count(wn); i++){
00274 WN *kid = WN_kid(wn,i);
00275 if(!WN_operator(kid)==OPR_LDID ||
00276 !Is_Loop_Invariant_Exp(kid, do_loop))
00277 return FALSE;
00278 }
00279 return TRUE;
00280 }
00281 #endif
00282
00283
00284
00285
00286
00287
00288
00289
00290 static BOOL
00291 Expr_Should_Always_Be_Hoisted(WN* wn,
00292 DYN_ARRAY<WN*>& ld_array,
00293 INT* num_loads,
00294 INT* num_bytes)
00295 {
00296 if (WN_operator(wn) == OPR_ILOAD) {
00297
00298 INT loads = 1;
00299 TYPE_ID rtype = WN_rtype(wn);
00300
00301
00302
00303 if (MTYPE_is_complex(rtype)) {
00304 WN* parent = LWN_Get_Parent(wn);
00305 OPERATOR parent_opr = WN_operator(parent);
00306 if (parent_opr == OPR_REALPART || parent_opr == OPR_IMAGPART) {
00307 wn = parent;
00308 rtype = WN_rtype(wn);
00309 }
00310 else {
00311 loads = 2;
00312 }
00313 }
00314
00315
00316 for (INT i = 0; i < ld_array.Elements(); ++i) {
00317 if (Tree_Equiv(wn, ld_array[i])) {
00318 return FALSE;
00319 }
00320 }
00321
00322
00323 ld_array.AddElement(wn);
00324
00325 INT bytes = MTYPE_byte_size(rtype);
00326
00327 (*num_loads) += loads;
00328 (*num_bytes) += bytes;
00329 }
00330
00331
00332
00333
00334 #ifdef KEY
00335 else if (Is_Very_Expensive_Expression(wn) &&
00336 !Operands_All_Invariant(wn)){
00337 #else
00338 else if (Is_Very_Expensive_Expression(wn)) {
00339 #endif
00340 return TRUE;
00341 }
00342
00343 else {
00344 for (INT i = 0; i < WN_kid_count(wn); ++i) {
00345 if (Expr_Should_Always_Be_Hoisted(WN_kid(wn,i),
00346 ld_array,
00347 num_loads,
00348 num_bytes)) {
00349 return TRUE;
00350 }
00351 }
00352 }
00353
00354 return FALSE;
00355 }
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381 static void
00382 Prune_Invar_Memops(WN_BV_STACK* invar_stack, BOOL inner_invar)
00383 {
00384 for (INT i = 0; i < invar_stack->Elements(); ++i) {
00385
00386 WN* wn = invar_stack->Bottom_nth(i).wn;
00387 BIT_VECTOR* bv = invar_stack->Bottom_nth(i).bv;
00388
00389
00390
00391 if (inner_invar && bv->Test(bv->Size()-1) && Contains_Indirect_Load(wn)) {
00392 continue;
00393 }
00394
00395 INT loads_after_hoisting = (WN_operator(wn) == OPR_COMPLEX ? 2 : 1);
00396 INT bytes_after_hoisting = MTYPE_byte_size(WN_rtype(wn));
00397
00398 DYN_ARRAY<WN*> loads(&LNO_local_pool);
00399 INT loads_before_hoisting = 0;
00400 INT bytes_before_hoisting = 0;
00401
00402
00403
00404 if (!Expr_Should_Always_Be_Hoisted(wn,
00405 loads,
00406 &loads_before_hoisting,
00407 &bytes_before_hoisting)
00408 &&
00409 (loads_after_hoisting > loads_before_hoisting ||
00410 bytes_after_hoisting > bytes_before_hoisting)) {
00411 invar_stack->Bottom_nth(i) = invar_stack->Top();
00412 invar_stack->Pop();
00413 --i;
00414 }
00415 }
00416 }
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426 static void Sort_Invar_Stack(WN_BV_STACK *invar_stack,INT num_loops)
00427 {
00428 for (INT i=0; i<invar_stack->Elements(); i++) {
00429 BIT_VECTOR *bvi = invar_stack->Bottom_nth(i).bv;
00430 INT min_val = First_Invariant(bvi,num_loops);
00431 INT min_pos = i;
00432 for (INT j=i+1; j<invar_stack->Elements(); j++) {
00433 BIT_VECTOR *bvj = invar_stack->Bottom_nth(j).bv;
00434 INT val = First_Invariant(bvj,num_loops);
00435 if (val < min_val) {
00436 min_val = val;
00437 min_pos = j;
00438 }
00439 }
00440 if (min_pos != i) {
00441 WN *tmp_wn = invar_stack->Bottom_nth(i).wn;
00442 invar_stack->Bottom_nth(i).wn = invar_stack->Bottom_nth(min_pos).wn;
00443 invar_stack->Bottom_nth(i).bv = invar_stack->Bottom_nth(min_pos).bv;
00444 invar_stack->Bottom_nth(min_pos).wn = tmp_wn;
00445 invar_stack->Bottom_nth(min_pos).bv = bvi;
00446 }
00447 }
00448 }
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460 void Mark_Invar(WN *wn_inner, INT num_loops, DOLOOP_STACK *do_stack,
00461 HASH_TABLE<WN *,BIT_VECTOR *> *htable, MEM_POOL *pool, BOOL outer_only)
00462 {
00463 OPCODE opcode = WN_opcode(wn_inner);
00464 if (opcode == OPC_BLOCK) {
00465 WN *kid = WN_first(wn_inner);
00466 while (kid) {
00467 WN *next = WN_next(kid);
00468 Mark_Invar(kid,num_loops,do_stack,htable,pool,outer_only);
00469 kid = next;
00470 }
00471 } else if (OPCODE_is_expression(opcode)) {
00472 Mark_Expression(wn_inner,num_loops,do_stack,htable,pool,outer_only);
00473 } else if (OPCODE_is_store(opcode)) {
00474 Mark_Invar(WN_kid0(wn_inner),num_loops,do_stack,htable,pool,outer_only);
00475 if (WN_kid_count(wn_inner) == 2) {
00476 Mark_Invar(WN_kid1(wn_inner),num_loops,do_stack,htable,pool,outer_only);
00477 }
00478 }
00479 }
00480
00481 static BIT_VECTOR *Mark_Expression(WN *wn, INT num_loops, DOLOOP_STACK *do_stack,
00482 HASH_TABLE<WN *,BIT_VECTOR *> *htable, MEM_POOL *pool, BOOL outer_only)
00483 {
00484 OPCODE opcode = WN_opcode(wn);
00485 if (OPCODE_is_load(opcode)) {
00486 BIT_VECTOR *result = CXX_NEW(BIT_VECTOR(num_loops,pool),pool);
00487 for (INT i=0; i<num_loops; i++) result->Set(i);
00488 BOOL is_clean = Process_Load(wn,result,do_stack,num_loops,htable,pool,outer_only);
00489 if (is_clean) {
00490 if (Contains_Work(wn)) {
00491 htable->Enter(wn,result);
00492 }
00493 }
00494 return result;
00495 } else if (OPCODE_operator(opcode) == OPR_INTCONST ||
00496 OPCODE_operator(opcode) == OPR_CONST) {
00497 BIT_VECTOR *result = CXX_NEW(BIT_VECTOR(num_loops,pool),pool);
00498 for (INT i=0; i<num_loops; i++) result->Set(i);
00499 return result;
00500 } else if (WN_kid_count(wn)) {
00501 BIT_VECTOR *result = Mark_Expression(WN_kid0(wn),num_loops,do_stack,htable,pool,outer_only);
00502 if (WN_operator(WN_kid0(wn)) == OPR_PARM &&
00503 !WN_Parm_By_Value(WN_kid0(wn))) {
00504 return NULL;
00505 }
00506
00507 for (INT i=1; i<WN_kid_count(wn); i++) {
00508 BIT_VECTOR *new_bv =
00509 Mark_Expression(WN_kid(wn,i),num_loops,do_stack,htable,pool,outer_only);
00510 if (!Compatible_Expressions(new_bv,result,outer_only) ||
00511 !(WN_operator(WN_kid0(wn)) != OPR_PARM || WN_Parm_By_Value(wn))) {
00512 INT j;
00513 for (j=1; j<i; j++) {
00514 Mark_Expression(WN_kid(wn,j),num_loops,do_stack,htable,pool,outer_only);
00515 }
00516 for (j=i+1; j<WN_kid_count(wn); j++) {
00517 BIT_VECTOR *bv = Mark_Expression(WN_kid(wn,j),num_loops,do_stack,htable,pool,outer_only);
00518 }
00519 return NULL;
00520 }
00521 }
00522 if (Contains_Work(wn)) {
00523 htable->Enter(wn,result);
00524 }
00525 return result;
00526 }
00527 return NULL;
00528 }
00529
00530
00531
00532
00533
00534 static void Gather_Invar(WN *wn_inner, INT num_loops, DOLOOP_STACK *do_stack,
00535 HASH_TABLE<WN *,BIT_VECTOR *> *htable,
00536 WN_BV_STACK *invar_stack)
00537 {
00538
00539 OPCODE opcode = WN_opcode(wn_inner);
00540 if (opcode == OPC_BLOCK) {
00541 WN *kid = WN_first(wn_inner);
00542 while (kid) {
00543 WN *next = WN_next(kid);
00544 Gather_Invar(kid,num_loops,do_stack,htable,invar_stack);
00545 kid = next;
00546 }
00547 } else if (OPCODE_is_expression(opcode)) {
00548 BIT_VECTOR *bv = htable->Find(wn_inner);
00549 if (bv) {
00550 if (bv->Pop_Count()) {
00551 if (invar_stack->Elements() >= MAX_SIZE)
00552 return;
00553 if (OPCODE_operator(opcode) != OPR_PARM) {
00554 invar_stack->Push(WN_BV(wn_inner,bv));
00555 } else {
00556 invar_stack->Push(WN_BV(WN_kid0(wn_inner),bv));
00557 }
00558 }
00559 } else {
00560 for (INT kidno=0; kidno<WN_kid_count(wn_inner); kidno++) {
00561 Gather_Invar(WN_kid(wn_inner,kidno),num_loops,do_stack,htable,
00562 invar_stack);
00563 }
00564 }
00565 } else if (OPCODE_is_store(opcode)) {
00566 Gather_Invar(WN_kid0(wn_inner),num_loops,do_stack,htable,invar_stack);
00567 if (WN_kid_count(wn_inner) == 2) {
00568 Gather_Invar(WN_kid1(wn_inner),num_loops,do_stack,htable,invar_stack);
00569 }
00570 }
00571 }
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582 static BOOL Compatible_Expressions(BIT_VECTOR *input, BIT_VECTOR *output, BOOL outer_only)
00583 {
00584 if (!input || !output) return FALSE;
00585 INT num_match=0;
00586 INT i;
00587 for (i=0; i<input->Size()-1; i++) {
00588 if (input->Test(i) && output->Test(i)) num_match++;
00589 }
00590 if (!outer_only && input->Test(i) && output->Test(i)) num_match++;
00591 if (num_match) {
00592 for (INT i=0; i<input->Size(); i++) {
00593 if (!input->Test(i)) output->Reset(i);
00594 }
00595 return TRUE;
00596 }
00597 return FALSE;
00598 }
00599
00600
00601
00602
00603
00604
00605 static BOOL Process_Load(WN *load, BIT_VECTOR *result,DOLOOP_STACK *do_stack,
00606 INT num_elements,HASH_TABLE<WN *,BIT_VECTOR *> *htable, MEM_POOL *pool, BOOL outer_only)
00607 {
00608 OPCODE opcode = WN_opcode(load);
00609 WN *inner_loop=do_stack->Top_nth(0);
00610
00611
00612 if (OPCODE_operator(opcode) == OPR_LDID) {
00613
00614 SYMBOL load_sym(load);
00615 for (INT i=0; i<num_elements; i++) {
00616 INT offset = do_stack->Elements() - num_elements;
00617 SYMBOL loop_sym(WN_index(do_stack->Bottom_nth(i+offset)));
00618 if (loop_sym == load_sym) {
00619 result->Reset(i);
00620 return TRUE;
00621 }
00622 }
00623 DEF_LIST *defs = Du_Mgr->Ud_Get_Def(load);
00624 if (defs) {
00625 DEF_LIST_ITER iter(defs);
00626 for(DU_NODE *node=iter.First(); !iter.Is_Empty(); node=iter.Next()) {
00627 WN *def = node->Wn();
00628 WN *def_loop = LNO_Common_Loop(def,inner_loop);
00629 INT i=0;
00630 while (i<num_elements && do_stack->Top_nth(i) != def_loop) {
00631 i++;
00632 }
00633 for (INT j=i; j<num_elements; j++) {
00634 result->Reset(num_elements-1-j);
00635 }
00636 }
00637 }
00638 } else {
00639
00640
00641 WN *array = WN_kid0(load);
00642 if (WN_operator(array) == OPR_ADD) {
00643 if (WN_operator(WN_kid0(array)) == OPR_INTCONST) {
00644 array = WN_kid1(array);
00645 } else if (WN_operator(WN_kid1(array)) == OPR_INTCONST) {
00646 array = WN_kid0(array);
00647 }
00648 }
00649 if (WN_operator(array) != OPR_ARRAY) {
00650 for (INT i=0; i<num_elements; i++) result->Reset(i);
00651 return FALSE;
00652
00653 }
00654 ACCESS_ARRAY *aa = (ACCESS_ARRAY *) WN_MAP_Get(LNO_Info_Map,array);
00655 BOOL messy = aa->Too_Messy;
00656 if (!messy) {
00657 for (INT i=0; i<aa->Num_Vec() ; i++) {
00658 ACCESS_VECTOR *av = aa->Dim(i);
00659 if (av->Too_Messy) messy = TRUE;
00660 }
00661 }
00662
00663
00664 if (messy) {
00665 BIT_VECTOR *tmp = Mark_Expression(array,num_elements,do_stack,htable,pool,outer_only);
00666 if (tmp) {
00667 for (INT i=0; i<num_elements; i++) {
00668 if (!tmp->Test(i)) result->Reset(i);
00669 }
00670 } else {
00671 for (INT i=0; i<num_elements; i++) result->Reset(i);
00672 return FALSE;
00673 }
00674 } else {
00675 for (INT j=0; j<aa->Num_Vec() ; j++) {
00676 ACCESS_VECTOR *av = aa->Dim(j);
00677 INT bad_symbolics = av->Non_Const_Loops() + num_elements - av->Nest_Depth();
00678 INT i;
00679 for (i=0; i<bad_symbolics; i++) {
00680 result->Reset(i);
00681 }
00682 INT i0 = av->Nest_Depth()-num_elements;
00683 for (i=MAX(0,bad_symbolics); i<num_elements; i++) {
00684 if (av->Loop_Coeff(i+i0)) {
00685 result->Reset(i);
00686 }
00687 }
00688 }
00689 }
00690
00691
00692 VINDEX16 v = Array_Dependence_Graph->Get_Vertex(load);
00693 if (!v) {
00694 for (INT i=0; i<num_elements; i++) result->Reset(i);
00695 return FALSE;
00696 }
00697 for (EINDEX16 e = Array_Dependence_Graph->Get_In_Edge(v); e;
00698 e=Array_Dependence_Graph->Get_Next_In_Edge(e)) {
00699 DEPV_ARRAY *da = Array_Dependence_Graph->Depv_Array(e);
00700 INT maxlevel = da->Max_Level();
00701 INT i0 = da->Num_Dim() + da->Num_Unused_Dim();
00702 for (INT i=0; i<=MIN(maxlevel-i0+num_elements,num_elements-1); i++) {
00703 result->Reset(i);
00704 }
00705 }
00706 }
00707 return TRUE;
00708 }
00709
00710
00711
00712
00713
00714
00715
00716 static BOOL Varying_Load(WN *load)
00717 {
00718 WN *array = WN_kid0(load);
00719 if (WN_operator(array) == OPR_ADD) {
00720 if (WN_operator(WN_kid0(array)) == OPR_INTCONST) {
00721 array = WN_kid1(array);
00722 } else if (WN_operator(WN_kid1(array)) == OPR_INTCONST) {
00723 array = WN_kid0(array);
00724 }
00725 }
00726 if (WN_operator(array) != OPR_ARRAY) {
00727 return FALSE;
00728 }
00729 ACCESS_ARRAY *aa = (ACCESS_ARRAY *) WN_MAP_Get(LNO_Info_Map,array);
00730 if (!aa->Too_Messy) {
00731 for (INT i=0; i<aa->Num_Vec() ; i++) {
00732 ACCESS_VECTOR *av = aa->Dim(i);
00733 if (av->Too_Messy) return FALSE;
00734 }
00735 }
00736 for (INT i=0; i<aa->Num_Vec() ; i++) {
00737 ACCESS_VECTOR *av = aa->Dim(i);
00738 if (av->Loop_Coeff(av->Nest_Depth()-1)) {
00739 return TRUE;
00740 }
00741 }
00742 return FALSE;
00743 }
00744
00745
00746 static INT First_Invariant(BIT_VECTOR *bv,INT num_loops)
00747 {
00748 INT first_invariant=0;
00749 while (first_invariant<num_loops-1 && !bv->Test(first_invariant)) first_invariant++;
00750 return first_invariant;
00751 }
00752
00753
00754 static BOOL Perfectly_Nested(WN *loop, INT num_outer)
00755 {
00756 if (num_outer == 0) return TRUE;
00757 if (WN_next(loop) || WN_prev(loop)) return FALSE;
00758 WN *new_loop = LWN_Get_Parent(LWN_Get_Parent(loop));
00759 OPCODE opc = WN_opcode(new_loop);
00760 if (opc != OPC_DO_LOOP) return FALSE;
00761 return Perfectly_Nested(new_loop,num_outer-1);
00762 }
00763
00764
00765
00766 static void Transform_Expression(BIT_VECTOR *bv, WN *exp, DOLOOP_STACK *do_stack, INT num_loops,
00767 INT outer_reg_tile, BOOL can_tile)
00768 {
00769 INT first_invariant=First_Invariant(bv,num_loops);
00770 first_invariant = MIN(first_invariant,outer_reg_tile);
00771 num_loops = num_loops-first_invariant;
00772
00773
00774 MEM_POOL_Push(&LNO_local_pool);
00775
00776 BIT_VECTOR *used_loops = CXX_NEW(BIT_VECTOR(num_loops,&LNO_local_pool),
00777 &LNO_local_pool);
00778 INT used_loops_offset = bv->Size()-num_loops;
00779 INT i;
00780 for (i=0; i<num_loops; i++) {
00781 if (bv->Test(i+used_loops_offset)) {
00782 used_loops->Reset(i);
00783 } else {
00784 used_loops->Set(i);
00785 }
00786 }
00787
00788
00789 if (can_tile && Perfectly_Nested(do_stack->Top_nth(0),num_loops-1)) {
00790 Scalar_Expansion_Tile(do_stack,num_loops,used_loops);
00791 }
00792
00793
00794 WN *new_statement = Split_Using_Preg(LWN_Get_Statement(exp),
00795 exp,Array_Dependence_Graph, FALSE);
00796 WN *rhs = WN_kid0(new_statement);
00797
00798
00799 WN **loops = CXX_NEW_ARRAY(WN *,num_loops,&LNO_local_pool);
00800 INT *order = CXX_NEW_ARRAY(INT,num_loops,&LNO_local_pool);
00801 INT *strip_sizes = CXX_NEW_ARRAY(INT,num_loops,&LNO_local_pool);
00802 for (i=0; i<num_loops; i++) {
00803 loops[num_loops-i-1] = do_stack->Top_nth(i);
00804 order[i] = i;
00805 strip_sizes[i] = 0;
00806 }
00807 Scalar_Expand(do_stack->Top_nth(num_loops-1),
00808 do_stack->Top_nth(num_loops-1), new_statement, SYMBOL(new_statement),
00809 loops, order, num_loops, TRUE, FALSE, FALSE, NULL, used_loops);
00810
00811
00812 new_statement = LWN_Get_Parent(rhs);
00813
00814
00815 WN *new_outer_loop = Fission_Statement(new_statement,do_stack,num_loops);
00816
00817
00818 DOLOOP_STACK *stack = CXX_NEW(DOLOOP_STACK(&LNO_local_pool), &LNO_local_pool);
00819 WN *tmp = rhs;
00820 for (i=0; i<num_loops; i++) {
00821 tmp = LWN_Get_Parent(tmp);
00822 while (WN_opcode(tmp) != OPC_DO_LOOP) tmp = LWN_Get_Parent(tmp);
00823 if (!used_loops->Test(num_loops-1-i)) {
00824 stack->Push(tmp);
00825 }
00826 }
00827 Is_True(new_outer_loop == tmp,("Internal error in Transform_Expression"));
00828 SNL_Finalize_Loops(new_outer_loop,stack,Array_Dependence_Graph,Du_Mgr);
00829
00830
00831 MEM_POOL_Pop(&LNO_local_pool);
00832 }
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845 static void Hoist_Inner_Invar(BIT_VECTOR *bv,WN *exp, DOLOOP_STACK *do_stack, INT num_loops)
00846 {
00847 INT i=num_loops-1;
00848 while (i>=0 && bv->Test(i)) i--;
00849 num_loops = num_loops-i-1;
00850 WN *new_statement = Split_Using_Preg(LWN_Get_Statement(exp),
00851 exp,Array_Dependence_Graph, FALSE);
00852 WN *new_outer_loop = Fission_Statement(new_statement,do_stack,num_loops);
00853
00854 MEM_POOL_Push(&LNO_local_pool);
00855 DOLOOP_STACK *stack = CXX_NEW(DOLOOP_STACK(&LNO_local_pool), &LNO_local_pool);
00856 WN *tmp = new_statement;
00857 for (i=0; i<num_loops; i++) {
00858 while (WN_opcode(tmp) != OPC_DO_LOOP) tmp = LWN_Get_Parent(tmp);
00859 stack->Push(tmp);
00860 tmp = LWN_Get_Parent(tmp);
00861 }
00862 SNL_Finalize_Loops(new_outer_loop,stack,Array_Dependence_Graph,Du_Mgr);
00863 MEM_POOL_Pop(&LNO_local_pool);
00864 }
00865
00866
00867
00868
00869
00870
00871
00872
00873 static WN *Fission_Statement(WN *statement, DOLOOP_STACK *do_stack, INT num_loops)
00874 {
00875 WN *fission_loop = do_stack->Top_nth(0);
00876 for (INT i=0; i<num_loops; i++) {
00877 MEM_POOL_Push(&LNO_local_pool);
00878 {
00879 DYN_ARRAY<FF_STMT_LIST> loop_list(&LNO_local_pool);
00880 loop_list.Newidx(); loop_list[0].Init(NULL);
00881 loop_list.Newidx(); loop_list[1].Init(NULL);
00882
00883 WN *tmp = WN_first(WN_do_body(fission_loop));
00884 while (tmp) {
00885 if (tmp == statement) {
00886 loop_list[1].Append(tmp,&LNO_local_pool);
00887 } else {
00888 loop_list[0].Append(tmp,&LNO_local_pool);
00889 }
00890 tmp = WN_next(tmp);
00891 }
00892 Separate_And_Update(fission_loop,loop_list,1,1);
00893 WN* new_loop = WN_next(fission_loop);
00894 if (Prompf_Info != NULL && Prompf_Info->Is_Enabled()) {
00895 INT new_id = New_Construct_Id();
00896 WN_MAP32_Set(Prompf_Id_Map, new_loop, new_id);
00897 INT old_ids[1];
00898 old_ids[0] = WN_MAP32_Get(Prompf_Id_Map, fission_loop);
00899 INT new_ids[1];
00900 new_ids[0] = WN_MAP32_Get(Prompf_Id_Map, new_loop);
00901 PROMPF_LINES** old_lines = CXX_NEW_ARRAY(PROMPF_LINES*, 1,
00902 &PROMPF_pool);
00903 old_lines[0] = CXX_NEW(PROMPF_LINES(fission_loop, &PROMPF_pool),
00904 &PROMPF_pool);
00905 PROMPF_LINES** new_lines = CXX_NEW_ARRAY(PROMPF_LINES*, 1,
00906 &PROMPF_pool);
00907 new_lines[0] = CXX_NEW(PROMPF_LINES(new_loop, &PROMPF_pool),
00908 &PROMPF_pool);
00909 Prompf_Info->Fission(old_ids, old_lines, new_ids, new_lines, 1);
00910 }
00911 }
00912 MEM_POOL_Pop(&LNO_local_pool);
00913
00914 if (i != num_loops -1) {
00915
00916 fission_loop = LWN_Get_Parent(fission_loop);
00917 while (WN_opcode(fission_loop) != OPC_DO_LOOP) fission_loop = LWN_Get_Parent(fission_loop);
00918
00919 }
00920
00921 statement = LWN_Get_Parent(statement);
00922 while (WN_opcode(statement) != OPC_DO_LOOP) statement = LWN_Get_Parent(statement);
00923
00924
00925
00926
00927
00928
00929 WN *other_loop = WN_prev(statement);
00930 Is_True(WN_opcode(other_loop) == OPC_DO_LOOP,("Fissioned loops not adjacent"));
00931 WN *parent = LWN_Get_Parent(statement);
00932 WN *prev = WN_prev(other_loop);
00933 other_loop = LWN_Extract_From_Block(other_loop);
00934 statement = LWN_Extract_From_Block(statement);
00935 LWN_Insert_Block_After(parent,prev,other_loop);
00936 LWN_Insert_Block_After(parent,prev,statement);
00937
00938 }
00939
00940
00941 return statement;
00942 }
00943
00944 static BOOL Contains_FP_Non_Load(WN *exp)
00945 {
00946 OPCODE opc = WN_opcode(exp);
00947 OPERATOR oper = OPCODE_operator(opc);
00948 if (MTYPE_float(OPCODE_rtype(opc))) {
00949 if (!OPCODE_is_load(opc) &&
00950 (oper != OPR_CONST) &&
00951 (oper != OPR_PARM) &&
00952 (oper != OPR_REALPART) &&
00953 (oper != OPR_IMAGPART) &&
00954 (oper != OPR_COMPLEX) &&
00955 (oper != OPR_PAREN)) {
00956 return TRUE;
00957 }
00958 }
00959 for (INT kidno=0; kidno<WN_kid_count(exp); kidno++) {
00960 if (Contains_FP_Non_Load(WN_kid(exp,kidno))) {
00961 return TRUE;
00962 }
00963 }
00964 return FALSE;
00965 }
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978 static BOOL Contains_Work(WN *exp)
00979 {
00980 OPCODE opc = WN_opcode(exp);
00981 OPERATOR oper = OPCODE_operator(opc);
00982 if ( (oper == OPR_CONST) ||
00983 (oper == OPR_LDA)) {
00984 return FALSE;
00985 }
00986 if (oper == OPR_ILOAD) {
00987 return Contains_Work(WN_kid0(exp));
00988 }
00989 if (oper == OPR_PAREN || oper == OPR_PARM ||
00990 oper == OPR_REALPART || oper == OPR_IMAGPART) {
00991 return Contains_Work(WN_kid0(exp));
00992 }
00993 if (!OPCODE_is_load(opc) && MTYPE_float(OPCODE_rtype(opc)) &&
00994 (OPCODE_operator(opc) != OPR_COMPLEX)) return TRUE;
00995 BOOL non_add_non_load = (!OPCODE_is_load(opc) &&
00996 oper != OPR_ADD && oper != OPR_SUB && oper != OPR_NEG);
00997 BOOL contains_indirect=FALSE;
00998 BOOL num_kids_with_loads=0;
00999 for (INT kidno=0; kidno<WN_kid_count(exp); kidno++) {
01000 if (Contains_FP_Non_Load(WN_kid(exp,kidno))) {
01001 return TRUE;
01002 }
01003 if (Contains_Varying_Indirect_Load(WN_kid(exp,kidno))) {
01004 if (non_add_non_load) return TRUE;
01005 contains_indirect=TRUE;
01006 num_kids_with_loads++;
01007 } else if (Contains_Load(WN_kid(exp,kidno))) {
01008 num_kids_with_loads++;
01009 }
01010 }
01011 if (num_kids_with_loads >= 2 && contains_indirect) return TRUE;
01012 return FALSE;
01013 }
01014
01015
01016
01017
01018 static BOOL Contains_Varying_Indirect_Load(WN *exp)
01019 {
01020 OPCODE opc = WN_opcode(exp);
01021 if (OPCODE_is_load(opc) &&
01022 (OPCODE_operator(opc) != OPR_LDID)) {
01023 if (Varying_Load(exp)) {
01024 return TRUE;
01025 }
01026 }
01027 for (INT kidno=0; kidno<WN_kid_count(exp); kidno++) {
01028 if (Contains_Varying_Indirect_Load(WN_kid(exp,kidno))) {
01029 return TRUE;
01030 }
01031 }
01032 return FALSE;
01033 }
01034
01035 static BOOL Contains_Indirect_Load(WN *exp)
01036 {
01037 OPCODE opc = WN_opcode(exp);
01038 if (OPCODE_is_load(opc) &&
01039 (OPCODE_operator(opc) != OPR_LDID)) {
01040 return TRUE;
01041 }
01042 for (INT kidno=0; kidno<WN_kid_count(exp); kidno++) {
01043 if (Contains_Indirect_Load(WN_kid(exp,kidno))) {
01044 return TRUE;
01045 }
01046 }
01047 return FALSE;
01048 }
01049
01050 static BOOL Contains_Load(WN *exp)
01051 {
01052 OPCODE opc = WN_opcode(exp);
01053 if (OPCODE_is_load(opc)) {
01054 return TRUE;
01055 }
01056 for (INT kidno=0; kidno<WN_kid_count(exp); kidno++) {
01057 if (Contains_Load(WN_kid(exp,kidno))) {
01058 return TRUE;
01059 }
01060 }
01061 return FALSE;
01062 }
01063
01064
01065
01066
01067
01068
01069 static void Scalar_Expansion_Tile(DOLOOP_STACK *do_stack,INT num_loops,
01070 BIT_VECTOR *used_loops) {
01071 INT num_used_loops = used_loops->Pop_Count();
01072 INT tile_size = SNL_INV_Compute_Tile_Size(num_used_loops);
01073 WN *outer_loop = do_stack->Top_nth(num_loops-1);
01074 INT *permutation = CXX_NEW_ARRAY(INT,num_loops,&LNO_local_pool);
01075 for (INT i=0; i<num_loops; i++) {
01076 if (used_loops->Test(i)) {
01077 WN *loop = do_stack->Top_nth(num_loops-i-1);
01078 DO_LOOP_INFO *dli = Get_Do_Loop_Info(loop);
01079 if (dli->Num_Iterations_Symbolic || dli->Est_Num_Iterations > tile_size) {
01080 if (!dli->Is_Inner_Tile || dli->Tile_Size > tile_size) {
01081 SYMBOL oldsym(WN_index(loop));
01082 char *Str_Buf =
01083 CXX_NEW_ARRAY(char,18+strlen(oldsym.Name()),&LNO_local_pool);
01084 sprintf(Str_Buf,"oinvar_tile_%s",oldsym.Name());
01085 SYMBOL *sym_pid = CXX_NEW(
01086 SYMBOL(Create_Preg_Symbol(Str_Buf, Do_Wtype(loop))),
01087 &LNO_default_pool);
01088 WN* newloop = Tile_Loop(loop,tile_size,0,SNL_INV_SE_ONLY,sym_pid,
01089 &LNO_local_pool);
01090 if (Prompf_Info != NULL && Prompf_Info->Is_Enabled()) {
01091 INT old_id = WN_MAP32_Get(Prompf_Id_Map, loop);
01092 INT new_id = New_Construct_Id();
01093 WN_MAP32_Set(Prompf_Id_Map, newloop, new_id);
01094 Prompf_Info->Se_Tile(old_id, new_id);
01095 }
01096 permutation[0] = i;
01097 for (INT j=1; j<=i; j++) {
01098 permutation[j] = j-1;
01099 }
01100 SNL_INV_Permute_Loops(outer_loop,permutation,i+1,TRUE);
01101 if (Prompf_Info != NULL && Prompf_Info->Is_Enabled()) {
01102 INT* old_ids = CXX_NEW_ARRAY(INT, i+1, &PROMPF_pool);
01103 INT* new_ids = CXX_NEW_ARRAY(INT, i+1, &PROMPF_pool);
01104 INT k;
01105 for (k = 1; k <= i+1; k++) {
01106 WN* wn_loop = SNL_Get_Inner_Snl_Loop(outer_loop, k);
01107 old_ids[k-1] = WN_MAP32_Get(Prompf_Id_Map, wn_loop);
01108 }
01109 for (k = 0; k < i+1; k++)
01110 new_ids[k] = old_ids[permutation[k]];
01111 Prompf_Info->Interchange(old_ids, new_ids, i+1);
01112 }
01113 }
01114 }
01115 }
01116 }
01117 }
01118
01119
01120
01121
01122
01123
01124
01125 class WNS_BV
01126 {
01127 public:
01128 STACK_OF_WN *stack;
01129 BIT_VECTOR *bv;
01130 WNS_BV(STACK_OF_WN *wns, BIT_VECTOR *b) { stack = wns; bv=b;};
01131 };
01132
01133 typedef STACK<WNS_BV> WNS_BV_STACK;
01134
01135 enum EQUIVALENCE_TYPE { EQ_NONE=0, EQ_ADD, EQ_MPY, EQ_MIN, EQ_MAX };
01136 static EQUIVALENCE_TYPE Sort_Invar_Expression(WN *wn, HASH_TABLE<WN *,BIT_VECTOR *> *htable);
01137 static void Sort_Equivalence_Class(WN *wn, HASH_TABLE<WN *,BIT_VECTOR *> *htable);
01138 static void Sort_Equivalence_Class_Rec(WN *wn, HASH_TABLE<WN *,BIT_VECTOR *> *htable,
01139 WN_BV_STACK *wn_bv_stack);
01140 static void Sort_Invar_Expressions_Rec(WN *wn, HASH_TABLE<WN *,BIT_VECTOR *> *htable);
01141 static BOOL sorted_something;
01142
01143
01144
01145
01146
01147
01148
01149 BOOL Sort_Invar_Expressions(WN *wn, HASH_TABLE<WN *,BIT_VECTOR *> *htable)
01150 {
01151 sorted_something = FALSE;
01152 Sort_Invar_Expressions_Rec(wn,htable);
01153 return sorted_something;
01154 }
01155
01156 static void Sort_Invar_Expressions_Rec(WN *wn, HASH_TABLE<WN *,BIT_VECTOR *> *htable)
01157 {
01158 OPCODE opcode = WN_opcode(wn);
01159 if (opcode == OPC_BLOCK) {
01160 WN *kid = WN_first(wn);
01161 while (kid) {
01162 WN *next = WN_next(kid);
01163 Sort_Invar_Expressions_Rec(kid,htable);
01164 kid = next;
01165 }
01166 } else if (OPCODE_is_expression(opcode)) {
01167 if (Sort_Invar_Expression(wn,htable) != EQ_NONE) {
01168 Sort_Equivalence_Class(wn,htable);
01169 }
01170 } else if (OPCODE_is_store(opcode)) {
01171 if (Sort_Invar_Expression(WN_kid0(wn),htable) != EQ_NONE) {
01172 Sort_Equivalence_Class(WN_kid0(wn),htable);
01173 }
01174 } else if (opcode == OPC_DO_LOOP) {
01175 Sort_Invar_Expressions_Rec(WN_do_body(wn),htable);
01176 }
01177 }
01178
01179
01180
01181
01182
01183 static EQUIVALENCE_TYPE Sort_Invar_Expression(WN *wn, HASH_TABLE<WN *,BIT_VECTOR *> *htable)
01184 {
01185 OPCODE opcode = WN_opcode(wn);
01186 OPERATOR oper = OPCODE_operator(opcode);
01187 if ((oper == OPR_ADD) || (oper == OPR_MPY) ||
01188 (oper == OPR_MIN) || (oper == OPR_MAX)) {
01189 EQUIVALENCE_TYPE eq;
01190 if (oper == OPR_ADD) eq = EQ_ADD;
01191 else if (oper == OPR_MPY) eq = EQ_MPY;
01192 else if (oper == OPR_MAX) eq = EQ_MAX;
01193 else if (oper == OPR_MIN) eq = EQ_MIN;
01194 EQUIVALENCE_TYPE eq0 = Sort_Invar_Expression(WN_kid0(wn),htable);
01195 EQUIVALENCE_TYPE eq1 = Sort_Invar_Expression(WN_kid1(wn),htable);
01196 BOOL match0 = (opcode==WN_opcode(WN_kid0(wn)));
01197 BOOL match1 = (opcode==WN_opcode(WN_kid1(wn)));
01198 if (match0 && match1) return eq;
01199 if (!match0) {
01200 if (eq0 != EQ_NONE) {
01201 Sort_Equivalence_Class(WN_kid0(wn),htable);
01202 }
01203 }
01204 if (!match1) {
01205 if (eq1 != EQ_NONE) {
01206 Sort_Equivalence_Class(WN_kid1(wn),htable);
01207 }
01208 }
01209 if (match0 || match1) {
01210 return eq;
01211 }
01212 return EQ_NONE;
01213 }
01214 return EQ_NONE;
01215 }
01216
01217
01218 static void Left_Justify(WN *wn)
01219 {
01220 OPCODE opcode = WN_opcode(wn);
01221 if (WN_opcode(WN_kid0(wn)) == opcode) {
01222 Left_Justify(WN_kid0(wn));
01223 }
01224 if (WN_opcode(WN_kid1(wn)) == opcode) {
01225 Left_Justify(WN_kid1(wn));
01226 }
01227 if (opcode == WN_opcode(WN_kid1(wn)) &&
01228 opcode != WN_opcode(WN_kid0(wn))) {
01229 WN *tmp = WN_kid0(wn);
01230 WN_kid0(wn) = WN_kid1(wn);
01231 WN_kid1(wn) = tmp;
01232 }
01233 }
01234
01235
01236
01237 static void Sort_Equivalence_Class(WN *wn, HASH_TABLE<WN *,BIT_VECTOR *> *htable)
01238 {
01239 MEM_POOL_Push(&LNO_local_pool);
01240 WN_BV_STACK *wn_bv_stack = CXX_NEW(WN_BV_STACK(&LNO_local_pool),&LNO_local_pool);
01241 Left_Justify(wn);
01242 Sort_Equivalence_Class_Rec(wn,htable,wn_bv_stack);
01243
01244 INT elements = wn_bv_stack->Elements();
01245
01246
01247
01248 if (elements <= 2 || elements >= MAX_SIZE) {
01249 MEM_POOL_Pop(&LNO_local_pool);
01250 return;
01251 }
01252
01253
01254
01255
01256
01257
01258
01259
01260 WNS_BV_STACK *sorted_stack = CXX_NEW(WNS_BV_STACK(&LNO_local_pool),&LNO_local_pool);
01261 INT i;
01262 for (i=0; i<elements; i++) {
01263 BIT_VECTOR *bvi = wn_bv_stack->Bottom_nth(i).bv;
01264 if (bvi && bvi->Pop_Count()) {
01265 WN *wni = wn_bv_stack->Bottom_nth(i).wn;
01266 BOOL found = FALSE;
01267 for (INT j=0; j<sorted_stack->Elements() && !found; j++) {
01268 BIT_VECTOR *bvj = sorted_stack->Bottom_nth(j).bv;
01269 if (bvi->Intersects(bvj)) {
01270 *bvi &= *bvj;
01271 found = TRUE;
01272 sorted_stack->Bottom_nth(j).stack->Push(wni);
01273 }
01274 }
01275 if (!found) {
01276 BIT_VECTOR *new_bv = CXX_NEW(BIT_VECTOR(bvi->Size(),&LNO_local_pool),&LNO_local_pool);
01277 *new_bv = *bvi;
01278 sorted_stack->Push(WNS_BV(CXX_NEW(STACK_OF_WN(&LNO_local_pool),&LNO_local_pool),
01279 new_bv));
01280 sorted_stack->Top_nth(0).stack->Push(wni);
01281 }
01282 }
01283 }
01284
01285
01286
01287
01288 INT sort_elements = sorted_stack->Elements();
01289 if (sort_elements == 0) {
01290 MEM_POOL_Pop(&LNO_local_pool);
01291 return;
01292 }
01293 for (i=0; i<sort_elements; i++) {
01294 INT max = sorted_stack->Bottom_nth(i).stack->Elements();
01295 INT max_pos = i;
01296 for (INT j=i+1; j<sort_elements; j++) {
01297 INT ej = sorted_stack->Bottom_nth(j).stack->Elements();
01298 if (ej > max) {
01299 max = ej;
01300 max_pos = j;
01301 }
01302 }
01303 if (max_pos != i) {
01304 STACK_OF_WN *tmp = sorted_stack->Bottom_nth(i).stack;
01305 sorted_stack->Bottom_nth(i).stack =
01306 sorted_stack->Bottom_nth(max_pos).stack;
01307 sorted_stack->Bottom_nth(max_pos).stack = tmp;
01308 }
01309 }
01310
01311
01312
01313 INT bucket = 0;
01314 INT bucket_pos = 0;
01315 STACK_OF_WN *sorted_wn = sorted_stack->Bottom_nth(bucket).stack;
01316
01317 BOOL done = FALSE;
01318 for (i=0; i<elements && !done; i++) {
01319 WN_BV *wn_bvi = &wn_bv_stack->Bottom_nth(i);
01320 if (bucket_pos == sorted_wn->Elements()) {
01321 bucket++;
01322 if (bucket < sorted_stack->Elements()) {
01323 bucket_pos = 0;
01324 sorted_wn = sorted_stack->Bottom_nth(bucket).stack;
01325 if (sorted_wn->Elements() <= 1) done = TRUE;
01326 } else {
01327 done = TRUE;
01328 }
01329 }
01330 if (!done) {
01331 WN *parenti = wn_bvi->parent;
01332 INT posi = wn_bvi->kid_pos;
01333 WN *wni = WN_kid(parenti,posi);
01334
01335
01336
01337 WN *wnj = sorted_wn->Bottom_nth(bucket_pos);
01338 if (wni != wnj) {
01339 WN *parentj = LWN_Get_Parent(wnj);
01340 INT posj = 0;
01341 if (wnj = WN_kid1(parentj)) posj = 1;
01342
01343 WN_kid(parenti,posi) = wnj;
01344 LWN_Set_Parent(wnj,parenti);
01345 WN_kid(parentj,posj) = wni;
01346 LWN_Set_Parent(wni,parentj);
01347 sorted_something = TRUE;
01348 }
01349 bucket_pos++;
01350 }
01351 }
01352 MEM_POOL_Pop(&LNO_local_pool);
01353 }
01354
01355
01356
01357 static void Sort_Equivalence_Class_Rec(WN *wn, HASH_TABLE<WN *,BIT_VECTOR *> *htable,
01358 WN_BV_STACK *wn_bv_stack)
01359 {
01360 OPCODE opcode = WN_opcode(wn);
01361 OPERATOR oper = OPCODE_operator(opcode);
01362
01363 if (opcode==WN_opcode(WN_kid0(wn))) {
01364 Sort_Equivalence_Class_Rec(WN_kid0(wn),htable,wn_bv_stack);
01365 } else {
01366 BIT_VECTOR *bv = htable->Find(WN_kid0(wn));
01367 wn_bv_stack->Push(WN_BV(WN_kid0(wn),bv,wn,0));
01368 }
01369
01370 if (opcode==WN_opcode(WN_kid1(wn))) {
01371 Sort_Equivalence_Class_Rec(WN_kid1(wn),htable,wn_bv_stack);
01372 } else {
01373 BIT_VECTOR *bv = htable->Find(WN_kid1(wn));
01374 wn_bv_stack->Push(WN_BV(WN_kid1(wn),bv,wn,1));
01375 }
01376
01377 }
01378
01379
01380 static BOOL Sufficient_Iterations(BIT_VECTOR *bv, DOLOOP_STACK *stack,
01381 INT num_loops)
01382 {
01383 INT prod=1;
01384 for (INT i=0; i<num_loops; i++) {
01385 if (bv->Test(bv->Size()-1-i)) {
01386 DO_LOOP_INFO *dli = Get_Do_Loop_Info(stack->Top_nth(i));
01387 if (dli->Num_Iterations_Symbolic) {
01388 return TRUE;
01389 } else {
01390 prod = prod * dli->Est_Num_Iterations;
01391 }
01392 }
01393 }
01394 return prod >= MIN_ITERATIONS;
01395 }
01396