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
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114 #define __STDC_LIMIT_MACROS
00115 #include <stdint.h>
00116 #ifdef USE_PCH
00117 #include "lno_pch.h"
00118 #endif // USE_PCH
00119 #pragma hdrstop
00120
00121 static const char *source_file = __FILE__;
00122 static const char *rcs_id = "$Source: be/lno/SCCS/s.cse.cxx $ $Revision: 1.13 $";
00123
00124 #include <sys/types.h>
00125 #include "lnopt_main.h"
00126 #include "dep_graph.h"
00127 #include "lnoutils.h"
00128 #include "lwn_util.h"
00129 #include "opt_du.h"
00130 #include "cse.h"
00131 #include "reduc.h"
00132
00133 enum EQUIVALENCE_TYPE { EQ_NONE=0, EQ_ADD, EQ_MPY, EQ_MIN, EQ_MAX, EQ_RECIP, EQ_DIV,
00134 EQ_RSQRT,EQ_SQRT,EQ_LOAD };
00135
00136 static void Inter_Iteration_Cses_R(WN *wn);
00137 static void Inter_Iteration_Cses_Loop(WN *loop);
00138 static EQUIVALENCE_TYPE Set_Up_Equivalence_Classes(WN *wn, WN *loop);
00139 static void Set_Up_Equivalence_Class(WN *wn, OPERATOR etype, WN *loop,TYPE_ID type);
00140 static void Process_Pair(WN *a1, WN *b1, WN *a2, WN *b2, WN *loop);
00141 static void Transform_Code(STACK<WN_PAIR_EC> *cse_stack, WN *loop, BOOL all_invariant);
00142 static void Add_Invariant_Deps();
00143 static UINT16 equivalence_class_number;
00144 static WN_MAP Equivalence_Class_Map;
00145
00146 static INT name = 0;
00147 static INT debug;
00148
00149 extern void Inter_Iteration_Cses(WN *func_nd)
00150 {
00151 debug = Get_Trace(TP_LNOPT, TT_LNO_DEBUG_CSE);
00152 if (debug) fprintf(TFile,"Begin Inter_Iteration_Cses");
00153 Equivalence_Class_Map = WN_MAP32_Create(&LNO_default_pool);
00154 FmtAssert(Equivalence_Class_Map != -1,
00155 ("Ran out off mappings in Inter_Iterations_Cses"));
00156 Inter_Iteration_Cses_R(func_nd);
00157 WN_MAP_Delete(Equivalence_Class_Map);
00158 }
00159
00160 static void Inter_Iteration_Cses_R(WN *wn)
00161 {
00162 OPCODE opcode = WN_opcode(wn);
00163 if (opcode == OPC_BLOCK) {
00164 WN *kid = WN_first(wn);
00165 while (kid) {
00166 WN *next = WN_next(kid);
00167 Inter_Iteration_Cses_R(kid);
00168 kid = next;
00169 }
00170 } else if ((opcode == OPC_DO_LOOP) && Do_Loop_Is_Inner(wn) &&
00171 !Do_Loop_Is_Mp(wn)) {
00172 if (Do_Loop_Is_Good(wn) && !Do_Loop_Has_Gotos(wn) &&
00173 (WN_kid_count(wn) == 6)) {
00174 WN *loop_info = WN_do_loop_info(wn);
00175 if (WN_Loop_Nz_Trip(loop_info)) {
00176 Inter_Iteration_Cses_Loop(wn);
00177 }
00178 }
00179 } else {
00180 for (INT kidno=0; kidno<WN_kid_count(wn); kidno++) {
00181 Inter_Iteration_Cses_R(WN_kid(wn,kidno));
00182 }
00183 }
00184 }
00185
00186
00187
00188 BOOL Same_Side(WN *child1, WN *parent1, WN *child2, WN *parent2)
00189 {
00190 if (child1 == WN_kid0(parent1)) {
00191 return (child2 == WN_kid0(parent2));
00192 } else {
00193 return (child2 == WN_kid1(parent2));
00194 }
00195 }
00196
00197
00198 typedef STACK<WN *> STACK_OF_WN;
00199 STACK_OF_WN *delete_stack;
00200 STACK_OF_WN *load_stack;
00201 STACK_OF_WN *invariant_ldid_stack;
00202 WN *insertion_point;
00203
00204
00205 static void Inter_Iteration_Cses_Loop(WN *loop)
00206 {
00207 if (debug) fprintf(TFile,"Processing an inner loop.");
00208 MEM_POOL_Push(&LNO_local_pool);
00209
00210
00211
00212 WN *tmp = WN_first(WN_do_body(loop));
00213 insertion_point = NULL;
00214 while (tmp != NULL && OPCODE_is_prefetch(WN_opcode(tmp))) {
00215 insertion_point = tmp;
00216 tmp = WN_next(tmp);
00217 }
00218
00219 load_stack = CXX_NEW(STACK_OF_WN(&LNO_local_pool),&LNO_local_pool);
00220 invariant_ldid_stack = CXX_NEW(STACK_OF_WN(&LNO_local_pool),&LNO_local_pool);
00221 delete_stack = CXX_NEW(STACK_OF_WN(&LNO_local_pool),&LNO_local_pool);
00222 name=-1;
00223
00224
00225
00226 equivalence_class_number = 0;
00227 Set_Up_Equivalence_Classes(WN_do_body(loop),loop);
00228
00229 #ifdef KEY
00230
00231
00232
00233
00234 if (invariant_ldid_stack->Elements() > 1000) {
00235 CXX_DELETE(load_stack,&LNO_local_pool);
00236 CXX_DELETE(invariant_ldid_stack,&LNO_local_pool);
00237 CXX_DELETE(delete_stack,&LNO_local_pool);
00238 MEM_POOL_Pop(&LNO_local_pool);
00239 return;
00240 }
00241 #endif
00242
00243 Add_Invariant_Deps();
00244
00245
00246
00247
00248 EQUIV_WN_HASH *hash_table = CXX_NEW(EQUIV_WN_HASH(200,&LNO_local_pool),
00249 &LNO_local_pool);
00250 INT i;
00251 for (i=0; i<load_stack->Elements(); i++) {
00252 WN *load = load_stack->Bottom_nth(i);
00253 UINT16 eq1 = (UINT16) WN_MAP32_Get(Equivalence_Class_Map,load);
00254 if (eq1) {
00255 VINDEX16 v = Current_Dep_Graph->Get_Vertex(load);
00256 EINDEX16 e = Current_Dep_Graph->Get_In_Edge(v);
00257 WN *parent = LWN_Get_Parent(load);
00258 WN *child = load;
00259 if (WN_operator(parent) == OPR_CVT) {
00260 child = parent;
00261 parent = LWN_Get_Parent(parent);
00262 }
00263 OPCODE parent_opc = WN_opcode(parent);
00264 OPERATOR oper = OPCODE_operator(parent_opc);
00265 while (e && eq1) {
00266 DEP dep = Current_Dep_Graph->Dep(e);
00267 if (Current_Dep_Graph->Is_Must(e) &&
00268 (!DEP_IsDistance(dep) || (DEP_Distance(dep) == 1))) {
00269 VINDEX16 v2 = Current_Dep_Graph->Get_Source(e);
00270 if (v2 != v) {
00271 WN *load2 = Current_Dep_Graph->Get_Wn(v2);
00272 UINT16 eq2 = (UINT16) WN_MAP32_Get(Equivalence_Class_Map,load2);
00273 WN *parent2 = LWN_Get_Parent(load2);
00274 WN *child2 = load2;
00275 if (WN_operator(parent2) == OPR_CVT) {
00276 child2 = parent2;
00277 parent2 = LWN_Get_Parent(parent2);
00278 }
00279 if (eq2 && (parent_opc == WN_opcode(parent2)) &&
00280 ((oper != OPR_DIV) || Same_Side(child,parent,child2,parent2))) {
00281 if ((oper == OPR_RECIP) || (oper == OPR_SQRT) ||
00282 (oper == OPR_RSQRT)
00283 #ifdef TARG_X8664
00284 || (oper == OPR_ATOMIC_RSQRT)
00285 #endif
00286 ) {
00287 Process_Pair(load,NULL,load2,NULL,loop);
00288 eq1 = 0;
00289 } else {
00290 WN_PAIR *wn_pair = hash_table->Find(EQUIV_PAIR(eq1,eq2));
00291 if (wn_pair) {
00292 if (!WN_MAP32_Get(Equivalence_Class_Map,wn_pair->Wn1) ||
00293 !WN_MAP32_Get(Equivalence_Class_Map,wn_pair->Wn2)) {
00294 hash_table->Remove(EQUIV_PAIR(eq1,eq2));
00295 WN_PAIR *wn_pair=CXX_NEW(WN_PAIR(load,load2),&LNO_local_pool);
00296 hash_table->Enter(EQUIV_PAIR(eq1,eq2),wn_pair);
00297 } else if ((load != wn_pair->Wn1) && (load != wn_pair->Wn2) &&
00298 (load2 != wn_pair->Wn1) && (load2 != wn_pair->Wn2)) {
00299 Process_Pair(load,wn_pair->Wn1,load2,wn_pair->Wn2,
00300 loop);
00301 eq1 = 0;
00302 }
00303 } else {
00304 WN_PAIR *wn_pair = CXX_NEW(WN_PAIR(load,load2),&LNO_local_pool);
00305 hash_table->Enter(EQUIV_PAIR(eq1,eq2),wn_pair);
00306 }
00307 }
00308 }
00309 }
00310 }
00311 e = Current_Dep_Graph->Get_Next_In_Edge(e);
00312 }
00313 }
00314 }
00315
00316
00317 for (i=0; i<load_stack->Elements(); i++) {
00318 WN *load = load_stack->Bottom_nth(i);
00319 if (WN_operator(load) == OPR_LDID) {
00320 LWN_Delete_CG_dep_graph(load);
00321 }
00322 }
00323
00324
00325 for (i=0; i<delete_stack->Elements(); i++) {
00326 WN *to_delete = delete_stack->Bottom_nth(i);
00327 LWN_Delete_Tree(to_delete);
00328 }
00329 CXX_DELETE(hash_table,&LNO_local_pool);
00330 CXX_DELETE(load_stack,&LNO_local_pool);
00331 CXX_DELETE(delete_stack,&LNO_local_pool);
00332 MEM_POOL_Pop(&LNO_local_pool);
00333 }
00334
00335 static OPERATOR Norm_Opr(OPERATOR oper)
00336 {
00337 if (oper == OPR_SUB) return OPR_ADD;
00338 return oper;
00339 }
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349 static EQUIVALENCE_TYPE Set_Up_Equivalence_Classes(WN *wn, WN *loop)
00350 {
00351 OPCODE opcode = WN_opcode(wn);
00352 if (opcode == OPC_BLOCK) {
00353 WN *kid = WN_first(wn);
00354 while (kid) {
00355 WN *next = WN_next(kid);
00356 Set_Up_Equivalence_Classes(kid,loop);
00357 kid = next;
00358 }
00359 return EQ_NONE;
00360 }
00361 TYPE_ID type = OPCODE_rtype(opcode);
00362
00363 if (OPCODE_is_store(opcode)) {
00364 if (!OPCODE_is_load(WN_opcode(WN_kid0(wn)))) {
00365 #ifdef TARG_X8664
00366 if (WN_desc(wn) == MTYPE_V16I1 || WN_desc(wn) == MTYPE_V16I2 ||
00367 WN_desc(wn) == MTYPE_V16I4 || WN_desc(wn) == MTYPE_V16I8 ||
00368 WN_desc(wn) == MTYPE_V16F4 || WN_desc(wn) == MTYPE_V16F8)
00369 return EQ_NONE;
00370 #endif
00371 if (Set_Up_Equivalence_Classes(WN_kid0(wn),loop) != EQ_NONE) {
00372 equivalence_class_number++;
00373 Set_Up_Equivalence_Class(WN_kid0(wn),
00374 Norm_Opr(WN_operator(WN_kid0(wn))),loop,WN_rtype(WN_kid0(wn)));
00375 }
00376 }
00377 return EQ_NONE;
00378 } else if (OPCODE_is_leaf(opcode) || OPCODE_is_load(opcode)) {
00379 return EQ_LOAD;
00380 } else if ((OPCODE_operator(opcode) == OPR_CVT) &&
00381 (OPCODE_is_load(WN_opcode(WN_kid0(wn)))) &&
00382 (OPCODE_desc(opcode) == WN_rtype(WN_kid0(wn)))) {
00383 return EQ_LOAD;
00384 } else if (OPCODE_is_expression(opcode)) {
00385 OPERATOR oper = OPCODE_operator(opcode);
00386 if ((oper == OPR_ADD) || (oper == OPR_MPY) || (oper == OPR_MAX) ||
00387 (oper == OPR_MIN) || (oper == OPR_SUB) || (oper == OPR_DIV)) {
00388 EQUIVALENCE_TYPE result0 = Set_Up_Equivalence_Classes(WN_kid0(wn),loop);
00389 EQUIVALENCE_TYPE result1 = Set_Up_Equivalence_Classes(WN_kid1(wn),loop);
00390 EQUIVALENCE_TYPE return_result = EQ_NONE;
00391 TYPE_ID type0 = WN_rtype(WN_kid0(wn));
00392 TYPE_ID type1 = WN_rtype(WN_kid1(wn));
00393
00394 BOOL finished_kid0 = FALSE;
00395 BOOL finished_kid1 = FALSE;
00396 if ((result0 != EQ_NONE) && (result0 != EQ_LOAD) && (type0 != type)) {
00397 finished_kid0 = TRUE;
00398 }
00399 if ((result1 != EQ_NONE) && (result1 != EQ_LOAD) && (type1 != type)) {
00400 finished_kid1 = TRUE;
00401 }
00402
00403 if (oper == OPR_ADD) {
00404 if ((result0 != EQ_NONE)&&(result0 != EQ_LOAD)&&(result0 != EQ_ADD)){
00405 finished_kid0 = TRUE;
00406 }
00407 if ((result1 != EQ_NONE)&&(result1 != EQ_LOAD)&&(result1 != EQ_ADD)){
00408 finished_kid1 = TRUE;
00409 }
00410 if (type0 == type && ((result0 == EQ_ADD) || (result0 == EQ_LOAD))) {
00411 return_result = EQ_ADD;
00412 }
00413 if (type1 == type && ((result1 == EQ_ADD) || (result1 == EQ_LOAD))) {
00414 return_result = EQ_ADD;
00415 }
00416 } else if (oper == OPR_SUB) {
00417 if ((result1 != EQ_NONE) && (result1 != EQ_LOAD)) {
00418 finished_kid1 = TRUE;
00419 }
00420 if (type0 == type && ((result0 == EQ_ADD) || (result0 == EQ_LOAD))) {
00421 return_result = EQ_ADD;
00422 }
00423 } else if (oper == OPR_MPY) {
00424 if ((result0 != EQ_NONE)&&(result0 != EQ_LOAD)&&(result0 != EQ_MPY)){
00425 finished_kid0 = TRUE;
00426 }
00427 if ((result1 != EQ_NONE)&&(result1 != EQ_LOAD)&&(result1 != EQ_MPY)){
00428 finished_kid1 = TRUE;
00429 }
00430 if (type0 == type && ((result0 == EQ_MPY) || (result0 == EQ_LOAD))) {
00431 return_result = EQ_MPY;
00432 }
00433 if (type1 == type && ((result1 == EQ_MPY) || (result1 == EQ_LOAD))) {
00434 return_result = EQ_MPY;
00435 }
00436 } else if (oper == OPR_DIV) {
00437 if ((result0 == EQ_LOAD) && (result1 == EQ_LOAD) && (type0 == type) &&
00438 (type1 == type)) {
00439 return EQ_DIV;
00440 }
00441 if ((result1 != EQ_NONE) && (result1 != EQ_LOAD)) {
00442 finished_kid1 = TRUE;
00443 }
00444 if ((result0 != EQ_NONE) && (result0 != EQ_LOAD)) {
00445 finished_kid0 = TRUE;
00446 }
00447 } else if (oper == OPR_MAX) {
00448 if ((result0 != EQ_NONE)&&(result0 != EQ_LOAD)&&(result0 != EQ_MAX)){
00449 finished_kid0 = TRUE;
00450 }
00451 if ((result1 != EQ_NONE)&&(result1 != EQ_LOAD)&&(result1 != EQ_MAX)) {
00452 finished_kid1 = TRUE;
00453 }
00454 if (type0 == type && ((result0 == EQ_MAX) || (result0 == EQ_LOAD))) {
00455 return_result = EQ_MAX;
00456 }
00457 if (type1 == type && ((result1 == EQ_MAX) || (result1 == EQ_LOAD))) {
00458 return_result = EQ_MAX;
00459 }
00460 } else if (oper == OPR_MIN) {
00461 if ((result0 != EQ_NONE)&&(result0 != EQ_LOAD)&&(result0 != EQ_MIN)){
00462 finished_kid0 = TRUE;
00463 }
00464 if ((result1 != EQ_NONE)&&(result1 != EQ_LOAD)&&(result1 != EQ_MIN)) {
00465 finished_kid1 = TRUE;
00466 }
00467 if (type0 == type && ((result0 == EQ_MIN) || (result0 == EQ_LOAD))) {
00468 return_result = EQ_MIN;
00469 }
00470 if (type1 == type && ((result1 == EQ_MIN) || (result1 == EQ_LOAD))) {
00471 return_result = EQ_MIN;
00472 }
00473 }
00474 if ((result0 != EQ_NONE) && (result0 != EQ_LOAD)) {
00475 finished_kid0 = TRUE;
00476 }
00477 if ((result1 != EQ_NONE) && (result1 != EQ_LOAD)) {
00478 finished_kid1 = TRUE;
00479 }
00480
00481 if (finished_kid0) {
00482 if (equivalence_class_number==UINT16_MAX) return EQ_NONE;
00483 equivalence_class_number++;
00484 Set_Up_Equivalence_Class(WN_kid0(wn),
00485 Norm_Opr(WN_operator(WN_kid0(wn))),loop,type);
00486 }
00487 if (finished_kid1) {
00488 if (equivalence_class_number==UINT16_MAX) return EQ_NONE;
00489 equivalence_class_number++;
00490 Set_Up_Equivalence_Class(WN_kid1(wn),
00491 Norm_Opr(WN_operator(WN_kid1(wn))),loop,type);
00492 }
00493
00494 return return_result;
00495 } else if ((oper == OPR_RECIP) || (oper == OPR_SQRT) ||
00496 (oper == OPR_RSQRT)
00497 #ifdef TARG_X8664
00498 || (oper == OPR_ATOMIC_RSQRT)
00499 #endif
00500 ) {
00501 EQUIVALENCE_TYPE result = Set_Up_Equivalence_Classes(WN_kid0(wn),loop);
00502 if ((result == EQ_LOAD) &&
00503 (WN_rtype(WN_kid0(wn)) == type)) {
00504 if (equivalence_class_number==UINT16_MAX) {
00505 return EQ_NONE;
00506 }
00507 equivalence_class_number++;
00508 Set_Up_Equivalence_Class(wn,oper,loop,type);
00509 }
00510 } else {
00511 for (INT kidno=0; kidno<WN_kid_count(wn); kidno++) {
00512 EQUIVALENCE_TYPE result =
00513 Set_Up_Equivalence_Classes(WN_kid(wn,kidno),loop);
00514 if ((result != EQ_NONE) && (result != EQ_LOAD)) {
00515 if (equivalence_class_number==UINT16_MAX) {
00516 return EQ_NONE;
00517 }
00518 equivalence_class_number++;
00519 Set_Up_Equivalence_Class(WN_kid(wn,kidno),
00520 Norm_Opr(WN_operator(WN_kid(wn,kidno))),loop,type);
00521 }
00522 }
00523 return EQ_NONE;
00524 }
00525 }
00526 return EQ_NONE;
00527 }
00528
00529
00530
00531
00532 static void Set_Up_Equivalence_Class(WN *wn, OPERATOR etype, WN *loop,TYPE_ID type)
00533 {
00534 OPCODE opcode = WN_opcode(wn);
00535 if ((OPCODE_operator(opcode) == OPR_CVT) &&
00536 (OPCODE_rtype(opcode) == type)) {
00537 WN *kid = WN_kid0(wn);
00538 OPCODE kido = WN_opcode(kid);
00539 if (OPCODE_is_load(kido)) {
00540 Set_Up_Equivalence_Class(kid,etype,loop,type);
00541 return;
00542 }
00543 }
00544 if (OPCODE_is_load(opcode)) {
00545 WN *parent = LWN_Get_Parent(wn);
00546 OPCODE parent_opcode = WN_opcode(parent);
00547 if ((OPCODE_operator(parent_opcode) == OPR_CVT)) {
00548 if (OPCODE_desc(parent_opcode) != OPCODE_rtype(opcode)) {
00549 return;
00550 }
00551 } else {
00552 if (OPCODE_rtype(opcode) != type) return;
00553 }
00554 if (OPCODE_operator(opcode) == OPR_LDID) {
00555 DEF_LIST *defs = Du_Mgr->Ud_Get_Def(wn);
00556 BOOL invar = TRUE;
00557 if (defs) {
00558 DEF_LIST_ITER iter(defs);
00559 for(DU_NODE *node=iter.First(); !iter.Is_Empty() && invar; node=iter.Next()) {
00560 WN *def = node->Wn();
00561 WN *parent = def;
00562 while (parent && WN_opcode(parent) != OPC_DO_LOOP) {
00563 parent = LWN_Get_Parent(parent);
00564 }
00565 if (parent == loop) invar = FALSE;
00566 }
00567 }
00568 if (invar) {
00569 WN_MAP32_Set(Equivalence_Class_Map,wn,(INT32) equivalence_class_number);
00570 load_stack->Push(wn);
00571 invariant_ldid_stack->Push(wn);
00572 }
00573 } else {
00574 VINDEX16 v = Current_Dep_Graph->Get_Vertex(wn);
00575 if (v) {
00576 EINDEX16 e = Current_Dep_Graph->Get_In_Edge(v);
00577 while (e) {
00578 VINDEX16 v2 = Current_Dep_Graph->Get_Source(e);
00579 if (OPCODE_is_store(WN_opcode(Current_Dep_Graph->Get_Wn(v2)))) {
00580 return;
00581 }
00582 e = Current_Dep_Graph->Get_Next_In_Edge(e);
00583 }
00584 }
00585 WN_MAP32_Set(Equivalence_Class_Map,wn,(INT32) equivalence_class_number);
00586 load_stack->Push(wn);
00587 }
00588 } else if ((WN_operator(wn) == etype) &&
00589 (WN_rtype(wn) == type)) {
00590 for (INT kidno=0; kidno<WN_kid_count(wn); kidno++) {
00591 Set_Up_Equivalence_Class(WN_kid(wn,kidno),etype,loop,type);
00592 }
00593 } else if ((etype == OPR_ADD) &&
00594 (WN_operator(wn) == OPR_SUB)) {
00595 Set_Up_Equivalence_Class(WN_kid0(wn),etype,loop,type);
00596 }
00597 }
00598
00599
00600 static void Append_Wn_Pair(STACK<WN_PAIR_EC> *cse_stack, WN *a3, WN *b3,
00601 INT32 eclass)
00602 {
00603 cse_stack->Push(WN_PAIR_EC(a3,b3,eclass));
00604 }
00605
00606
00607
00608
00609
00610 static void Prepend_Wn_Pair(STACK<WN_PAIR_EC> *cse_stack, WN *a0, WN *b0,
00611 INT32 eclass)
00612 {
00613 WN_PAIR_EC *top = & cse_stack->Top_nth(0);
00614 cse_stack->Push(WN_PAIR_EC(top->Wn1,top->Wn2,top->EClass));
00615 for (INT i=cse_stack->Elements()-2; i>=1; i--) {
00616 WN_PAIR_EC *in = &cse_stack->Bottom_nth(i);
00617 WN_PAIR_EC *out = &cse_stack->Bottom_nth(i-1);
00618 in->Wn1 = out->Wn1;
00619 in->Wn2 = out->Wn2;
00620 in->EClass = out->EClass;
00621 }
00622 WN_PAIR_EC *bot = &cse_stack->Bottom_nth(0);
00623 bot->Wn1 = a0;
00624 bot->Wn2 = b0;
00625 bot->EClass = eclass;
00626 }
00627
00628
00629
00630
00631
00632 static BOOL Both_Invariant(STACK<WN_PAIR_EC> *cse_stack)
00633 {
00634 WN_PAIR_EC wn_pair0 = cse_stack->Bottom_nth(0);
00635 WN_PAIR_EC wn_pair1 = cse_stack->Bottom_nth(1);
00636 VINDEX16 v0 = Current_Dep_Graph->Get_Vertex(wn_pair0.Wn1);
00637 VINDEX16 v1 = Current_Dep_Graph->Get_Vertex(wn_pair1.Wn1);
00638 EINDEX16 e = Current_Dep_Graph->Get_Edge(v1,v0);
00639 DEP dep = Current_Dep_Graph->Dep(e);
00640 if (DEP_IsDistance(dep)) return FALSE;
00641
00642 if (!wn_pair0.Wn2) return TRUE;
00643 v0 = Current_Dep_Graph->Get_Vertex(wn_pair0.Wn2);
00644 v1 = Current_Dep_Graph->Get_Vertex(wn_pair1.Wn2);
00645 e = Current_Dep_Graph->Get_Edge(v1,v0);
00646 dep = Current_Dep_Graph->Dep(e);
00647 if (DEP_IsDistance(dep)) return FALSE;
00648
00649 return TRUE;
00650 }
00651
00652
00653
00654
00655
00656 static void Process_Pair(WN *a1, WN *b1, WN *a2, WN *b2, WN *loop)
00657 {
00658
00659 INT32 ec1 = WN_MAP32_Get(Equivalence_Class_Map,a1);
00660 INT32 ec2 = WN_MAP32_Get(Equivalence_Class_Map,a2);
00661 WN_MAP32_Set(Equivalence_Class_Map,a1,(INT32) 0);
00662 if (b1) WN_MAP32_Set(Equivalence_Class_Map,b1,(INT32) 0);
00663 WN_MAP32_Set(Equivalence_Class_Map,a2,(INT32) 0);
00664 if (b2) WN_MAP32_Set(Equivalence_Class_Map,b2,(INT32) 0);
00665
00666 WN *parent = LWN_Get_Parent(a1);
00667 WN *child = a1;
00668 if (WN_operator(parent) == OPR_CVT) {
00669 child = parent;
00670 parent = LWN_Get_Parent(parent);
00671 }
00672 if (WN_operator(parent) == OPR_DIV) {
00673 if (child != WN_kid0(parent)) {
00674 WN *tmp = a1;
00675 a1 = b1;
00676 b1 = tmp;
00677
00678 tmp = a2;
00679 a2 = b2;
00680 b2 = tmp;
00681 }
00682 }
00683
00684
00685 STACK<WN_PAIR_EC> cse_stack(&LNO_local_pool);
00686 cse_stack.Push(WN_PAIR_EC(a1,b1,ec1));
00687 cse_stack.Push(WN_PAIR_EC(a2,b2,ec2));
00688
00689
00690
00691 BOOL found_earlier;
00692 do {
00693 found_earlier = FALSE;
00694 VINDEX16 v = Current_Dep_Graph->Get_Vertex(a2);
00695 WN *par_a2 = LWN_Get_Parent(a2);
00696 WN *child_a2 = a2;
00697 if (WN_operator(par_a2) == OPR_CVT) {
00698 child_a2 = par_a2;
00699 par_a2 = LWN_Get_Parent(par_a2);
00700 }
00701 OPCODE parop_a2 = WN_opcode(par_a2);
00702 EINDEX16 e = Current_Dep_Graph->Get_In_Edge(v);
00703 while (e && !found_earlier) {
00704 DEP dep = Current_Dep_Graph->Dep(e);
00705 if (Current_Dep_Graph->Is_Must(e) &&
00706 (!DEP_IsDistance(dep) || (DEP_Distance(dep) == 1))) {
00707 VINDEX16 sourcev = Current_Dep_Graph->Get_Source(e);
00708 WN *a3 = Current_Dep_Graph->Get_Wn(sourcev);
00709 UINT16 eq0 = (UINT16) WN_MAP32_Get(Equivalence_Class_Map,a3);
00710 WN *par_a3 = LWN_Get_Parent(a3);
00711 WN *child_a3 = a3;
00712 if (WN_operator(par_a3) == OPR_CVT) {
00713 child_a3 = par_a3;
00714 par_a3 = LWN_Get_Parent(par_a3);
00715 }
00716 if (eq0 && (WN_opcode(par_a3) == parop_a2) &&
00717 ((OPCODE_operator(parop_a2) != OPR_DIV) ||
00718 Same_Side(child_a2,par_a2,child_a3,par_a3))) {
00719 if (!b1) {
00720 INT32 ec = WN_MAP32_Get(Equivalence_Class_Map,a3);
00721 WN_MAP32_Set(Equivalence_Class_Map,a3,(INT32) 0);
00722 Append_Wn_Pair(&cse_stack,a3,NULL,ec);
00723 found_earlier = TRUE;
00724 } else {
00725 VINDEX16 vb = Current_Dep_Graph->Get_Vertex(b2);
00726 EINDEX16 eb = Current_Dep_Graph->Get_In_Edge(vb);
00727 while (eb && !found_earlier) {
00728 DEP dep = Current_Dep_Graph->Dep(eb);
00729 if (Current_Dep_Graph->Is_Must(eb) &&
00730 (!DEP_IsDistance(dep) || (DEP_Distance(dep) == 1))) {
00731 VINDEX16 sourcev = Current_Dep_Graph->Get_Source(eb);
00732 WN *b3 = Current_Dep_Graph->Get_Wn(sourcev);
00733 if (b3 != a3) {
00734 UINT16 eqb3 = (UINT16) WN_MAP32_Get(Equivalence_Class_Map,b3);
00735 if (eqb3 == eq0) {
00736 INT32 ec = WN_MAP32_Get(Equivalence_Class_Map,a3);
00737 WN_MAP32_Set(Equivalence_Class_Map,a3,(INT32) 0);
00738 WN_MAP32_Set(Equivalence_Class_Map,b3,(INT32) 0);
00739 Append_Wn_Pair(&cse_stack,a3,b3,ec);
00740 found_earlier = TRUE;
00741 }
00742 }
00743 }
00744 eb = Current_Dep_Graph->Get_Next_In_Edge(eb);
00745 }
00746 }
00747 }
00748 }
00749 e = Current_Dep_Graph->Get_Next_In_Edge(e);
00750 }
00751 if (found_earlier) {
00752 a2 = cse_stack.Top_nth(0).Wn1;
00753 b2 = cse_stack.Top_nth(0).Wn2;
00754 }
00755 } while (found_earlier);
00756
00757
00758
00759 BOOL found_later;
00760 do {
00761 found_later = FALSE;
00762 VINDEX16 v = Current_Dep_Graph->Get_Vertex(a1);
00763 WN *par_a1 = LWN_Get_Parent(a1);
00764 WN *child_a1 = a1;
00765 if (WN_operator(par_a1) == OPR_CVT) {
00766 child_a1 = par_a1;
00767 par_a1 = LWN_Get_Parent(par_a1);
00768 }
00769 OPCODE parop_a1 = WN_opcode(par_a1);
00770 EINDEX16 e = Current_Dep_Graph->Get_Out_Edge(v);
00771 while (e && !found_later) {
00772 DEP dep = Current_Dep_Graph->Dep(e);
00773 if (Current_Dep_Graph->Is_Must(e) &&
00774 (!DEP_IsDistance(dep) || (DEP_Distance(dep) == 1))) {
00775 VINDEX16 sinkv = Current_Dep_Graph->Get_Sink(e);
00776 WN *a0 = Current_Dep_Graph->Get_Wn(sinkv);
00777 UINT16 eq3 = (UINT16) WN_MAP32_Get(Equivalence_Class_Map,a0);
00778 WN *par_a0 = LWN_Get_Parent(a0);
00779 WN *child_a0 = a0;
00780 if (WN_operator(par_a0) == OPR_CVT) {
00781 child_a0 = par_a0;
00782 par_a0 = LWN_Get_Parent(par_a0);
00783 }
00784 if (eq3 && (WN_opcode(par_a0) == parop_a1) &&
00785 ((OPCODE_operator(parop_a1) != OPR_DIV) ||
00786 Same_Side(child_a1,par_a1,child_a0,par_a0))) {
00787 if (!b1) {
00788 INT32 ec = WN_MAP32_Get(Equivalence_Class_Map,a0);
00789 WN_MAP32_Set(Equivalence_Class_Map,a0,(INT32) 0);
00790 Prepend_Wn_Pair(&cse_stack,a0,NULL,ec);
00791 found_later = TRUE;
00792 } else {
00793 VINDEX16 vb = Current_Dep_Graph->Get_Vertex(b1);
00794 EINDEX16 eb = Current_Dep_Graph->Get_Out_Edge(vb);
00795 while (eb && !found_later) {
00796 DEP dep = Current_Dep_Graph->Dep(eb);
00797 if (Current_Dep_Graph->Is_Must(eb) &&
00798 (!DEP_IsDistance(dep) || (DEP_Distance(dep) == 1))) {
00799 VINDEX16 sinkv = Current_Dep_Graph->Get_Sink(eb);
00800 WN *b0 = Current_Dep_Graph->Get_Wn(sinkv);
00801 if (a0 != b0) {
00802 UINT16 eqb0 = (UINT16) WN_MAP32_Get(Equivalence_Class_Map,b0);
00803 if (eqb0 == eq3) {
00804 INT32 ec = WN_MAP32_Get(Equivalence_Class_Map,a0);
00805 WN_MAP32_Set(Equivalence_Class_Map,a0,(INT32) 0);
00806 WN_MAP32_Set(Equivalence_Class_Map,b0,(INT32) 0);
00807 Prepend_Wn_Pair(&cse_stack,a0,b0,ec);
00808 found_later = TRUE;
00809 }
00810 }
00811 }
00812 eb = Current_Dep_Graph->Get_Next_Out_Edge(eb);
00813 }
00814 }
00815 }
00816 }
00817 e = Current_Dep_Graph->Get_Next_Out_Edge(e);
00818 }
00819 if (found_later) {
00820 a1 = cse_stack.Bottom_nth(0).Wn1;
00821 b1 = cse_stack.Bottom_nth(0).Wn2;
00822 }
00823 } while (found_later);
00824 if (Both_Invariant(&cse_stack)) {
00825 Transform_Code(&cse_stack,loop,1);
00826 } else {
00827 Transform_Code(&cse_stack,loop,0);
00828 }
00829 }
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847 static void Transform_Code(STACK<WN_PAIR_EC> *cse_stack, WN *loop, BOOL all_invariant)
00848 {
00849 #ifdef KEY
00850 static UINT cse_num = 0;
00851 cse_num ++;
00852 if (cse_num < LNO_Cse_Loop_Skip_Before ||
00853 cse_num > LNO_Cse_Loop_Skip_After ||
00854 cse_num == LNO_Cse_Loop_Skip_Equal)
00855 return;
00856 #endif
00857 DO_LOOP_INFO *dli = Get_Do_Loop_Info(loop);
00858 WN *guard = dli->Guard;
00859 if (guard) {
00860 WN_Reset_If_Guard(guard);
00861 }
00862
00863
00864
00865 name++;
00866
00867 INT number_sums = cse_stack->Elements() ;
00868 WN_OFFSET *preg_array = CXX_NEW_ARRAY(WN_OFFSET,number_sums,
00869 &LNO_local_pool);
00870
00871 if (debug) {
00872 fprintf(TFile,"Cse'ing a sum used across %d iterations.\n",number_sums);
00873 }
00874
00875
00876
00877 TYPE_ID type;
00878 if (WN_operator(LWN_Get_Parent(
00879 cse_stack->Bottom_nth(0).Wn1)) == OPR_CVT) {
00880 type =
00881 WN_rtype(LWN_Get_Parent(cse_stack->Bottom_nth(0).Wn1));
00882 } else {
00883 type = WN_rtype(cse_stack->Bottom_nth(0).Wn1);
00884 }
00885 ST *preg_st = MTYPE_To_PREG(type);
00886 char preg_name[20];
00887 SYMBOL index_symbol(WN_start(loop));
00888 char *index_name = ST_name(index_symbol.St());
00889 INT length = strlen(index_name);
00890 if (length < 10) {
00891 sprintf(preg_name,"tmp%d_%s",name,index_name);
00892 } else {
00893 sprintf(preg_name,"tmp%d_i",name);
00894 }
00895 length = strlen(preg_name);
00896 sprintf(&preg_name[length],"_%d",0);
00897 #ifdef _NEW_SYMTAB
00898 preg_array[0] = Create_Preg(type,preg_name);
00899 #else
00900 preg_array[0] = Create_Preg(type,preg_name,NULL);
00901 #endif
00902 INT i;
00903 for (i=1; i<number_sums; i++) {
00904 if (all_invariant) {
00905 preg_array[i] = preg_array[0];
00906 } else {
00907 sprintf(&preg_name[length],"_%d",i);
00908 #ifdef _NEW_SYMTAB
00909 preg_array[i] = Create_Preg(type,preg_name);
00910 #else
00911 preg_array[i] = Create_Preg(type,preg_name,NULL);
00912 #endif
00913 }
00914 }
00915
00916 BOOL unary = (cse_stack->Bottom_nth(0).Wn2 == NULL);
00917 WN *wn1p = LWN_Get_Parent(cse_stack->Bottom_nth(0).Wn1);
00918 if (WN_operator(wn1p) == OPR_CVT) wn1p = LWN_Get_Parent(wn1p);
00919
00920 OPERATOR oper = Norm_Opr(WN_operator(wn1p));
00921 OPCODE op = OPCODE_make_op(oper,type,MTYPE_V);
00922 OPCODE stid_op = OPCODE_make_op(OPR_STID, MTYPE_V, type);
00923 OPCODE ldid_op = OPCODE_make_op(OPR_LDID, type, type);
00924
00925
00926 WN **init_stids = CXX_NEW_ARRAY(WN *,number_sums,&LNO_local_pool);
00927 WN **loop_stids = CXX_NEW_ARRAY(WN *,number_sums,&LNO_local_pool);
00928 WN **loop_ldids = CXX_NEW_ARRAY(WN *,number_sums,&LNO_local_pool);
00929
00930 DOLOOP_STACK *loop_stack=CXX_NEW(DOLOOP_STACK(&LNO_local_pool),
00931 &LNO_local_pool);
00932 Build_Doloop_Stack(LWN_Get_Parent(loop), loop_stack);
00933
00934
00935
00936 if (!all_invariant) {
00937 for (i=0; i<number_sums-1; i++) {
00938 WN_PAIR_EC *wn_pair = &cse_stack->Bottom_nth(i);
00939 WN *sum1,*sum2=NULL;
00940 if (WN_operator(wn_pair->Wn1) == OPR_LDID) {
00941
00942
00943 WN_PAIR_EC *wn_pair_next = &cse_stack->Bottom_nth(i+1);
00944 if (WN_operator(LWN_Get_Parent(wn_pair_next->Wn1)) ==
00945 OPR_CVT) {
00946 sum1 = LWN_Copy_Tree(LWN_Get_Parent(wn_pair_next->Wn1));
00947 LWN_Copy_Def_Use(wn_pair_next->Wn1,WN_kid0(sum1),Du_Mgr);
00948 } else {
00949 sum1 = LWN_Copy_Tree(wn_pair_next->Wn1);
00950 LWN_Copy_Def_Use(wn_pair_next->Wn1,sum1,Du_Mgr);
00951 }
00952 } else {
00953 if (WN_operator(LWN_Get_Parent(wn_pair->Wn1)) ==
00954 OPR_CVT) {
00955 sum1 = LWN_Copy_Tree(LWN_Get_Parent(wn_pair->Wn1));
00956 LWN_Copy_Def_Use(wn_pair->Wn1,WN_kid0(sum1),Du_Mgr);
00957 } else {
00958 sum1 = LWN_Copy_Tree(wn_pair->Wn1);
00959 LWN_Copy_Def_Use(wn_pair->Wn1,sum1,Du_Mgr);
00960 }
00961 Replace_Ldid_With_Exp_Copy(index_symbol,sum1,
00962 WN_kid0(WN_start(loop)),Du_Mgr);
00963 }
00964 if (wn_pair->Wn2) {
00965 if (WN_operator(wn_pair->Wn2) == OPR_LDID) {
00966 WN_PAIR_EC *wn_pair_next = &cse_stack->Bottom_nth(i+1);
00967 if (WN_operator(LWN_Get_Parent(wn_pair_next->Wn2)) ==
00968 OPR_CVT) {
00969 sum2 = LWN_Copy_Tree(LWN_Get_Parent(wn_pair_next->Wn2));
00970 LWN_Copy_Def_Use(wn_pair_next->Wn2,WN_kid0(sum2),Du_Mgr);
00971 } else {
00972 sum2 = LWN_Copy_Tree(wn_pair_next->Wn2);
00973 LWN_Copy_Def_Use(wn_pair_next->Wn2,sum2,Du_Mgr);
00974 }
00975 } else {
00976 if (WN_operator(LWN_Get_Parent(wn_pair->Wn2)) ==
00977 OPR_CVT) {
00978 sum2 = LWN_Copy_Tree(LWN_Get_Parent(wn_pair->Wn2));
00979 LWN_Copy_Def_Use(wn_pair->Wn2,WN_kid0(sum2),Du_Mgr);
00980 } else {
00981 sum2 = LWN_Copy_Tree(wn_pair->Wn2);
00982 LWN_Copy_Def_Use(wn_pair->Wn2,sum2,Du_Mgr);
00983 }
00984 Replace_Ldid_With_Exp_Copy(index_symbol,sum2,
00985 WN_kid0(WN_start(loop)),Du_Mgr);
00986 }
00987 }
00988 WN *add;
00989 if (sum2) {
00990 add = LWN_CreateExp2(op,sum1,sum2);
00991 } else {
00992 add = LWN_CreateExp1(op,sum1);
00993 }
00994 WN *stid = LWN_CreateStid(stid_op,preg_array[i+1],
00995 preg_st,Be_Type_Tbl(type),add);
00996 LWN_Copy_Frequency(add,sum1);
00997 LWN_Copy_Frequency(stid,add);
00998 init_stids[i+1] = stid;
00999 Create_alias(Alias_Mgr,stid);
01000 LWN_Insert_Block_Before(LWN_Get_Parent(loop),loop,stid);
01001 LWN_Copy_Linenumber(LWN_Get_Statement(wn_pair->Wn1),stid);
01002 LNO_Build_Access(stid, loop_stack, &LNO_default_pool);
01003 }
01004 }
01005
01006
01007
01008
01009
01010 WN_PAIR_EC *wn_pair;
01011 WN *wn1, *wn2;
01012 WN *statement;
01013 statement = LWN_Get_Statement(cse_stack->Top_nth(0).Wn1);
01014 for (i=0; i<number_sums; i++) {
01015 WN *ldid = WN_CreateLdid(ldid_op,preg_array[i],
01016 preg_st,Be_Type_Tbl(type));
01017 loop_ldids[i] = ldid;
01018 Create_alias(Alias_Mgr,ldid);
01019 wn_pair = &cse_stack->Bottom_nth(i);
01020 wn1 = wn_pair->Wn1;
01021 if (WN_operator(LWN_Get_Parent(wn1)) == OPR_CVT) {
01022 wn1 = LWN_Get_Parent(wn1);
01023 }
01024 WN *plus1 = LWN_Get_Parent(wn1);
01025 LWN_Copy_Frequency_Tree(ldid,wn1);
01026 if (unary) {
01027 if (i != number_sums-1) {
01028 delete_stack->Push(WN_kid0(plus1));
01029 }
01030 WN *parent = LWN_Get_Parent(plus1);
01031 INT j=0;
01032 while (WN_kid(parent,j) != plus1) j++;
01033 WN_kid(parent,j) = ldid;
01034 LWN_Set_Parent(ldid,parent);
01035 #ifndef KEY
01036
01037
01038 WN_Delete(plus1);
01039 #endif
01040 } else {
01041 if (wn1 == WN_kid0(plus1)) {
01042
01043 if (i != number_sums-1) {
01044 delete_stack->Push(WN_kid0(plus1));
01045 }
01046 WN_kid0(plus1) = ldid;
01047 LWN_Set_Parent(ldid,plus1);
01048 } else {
01049 if (i != number_sums-1) {
01050 delete_stack->Push(WN_kid1(plus1));
01051 }
01052 WN_kid1(plus1) = ldid;
01053 LWN_Set_Parent(ldid,plus1);
01054 }
01055 }
01056
01057 wn2 = wn_pair->Wn2;
01058 if (wn2) {
01059 if (WN_operator(LWN_Get_Parent(wn2)) == OPR_CVT) {
01060 wn2 = LWN_Get_Parent(wn2);
01061 }
01062 WN *plus2 = LWN_Get_Parent(wn2);
01063 WN *other_kid=NULL;
01064 if (wn2 == WN_kid0(plus2)) {
01065
01066 if (i != number_sums-1) {
01067 delete_stack->Push(WN_kid0(plus2));
01068 }
01069 if (WN_kid_count(plus2) > 1) {
01070 other_kid = WN_kid1(plus2);
01071 }
01072 } else {
01073 if (i != number_sums-1) {
01074 delete_stack->Push(WN_kid1(plus2));
01075 }
01076 other_kid = WN_kid0(plus2);
01077 }
01078 if (WN_operator(plus2) == OPR_SUB) {
01079 other_kid = LWN_CreateExp1(OPCODE_make_op(OPR_NEG,type,MTYPE_V),
01080 other_kid);
01081 }
01082
01083
01084 WN *parent = LWN_Get_Parent(plus2);
01085 INT j=0;
01086 while (WN_kid(parent,j) != plus2) j++;
01087 WN_kid(parent,j) = other_kid;
01088 LWN_Set_Parent(other_kid,parent);
01089 #ifndef KEY
01090
01091
01092 WN_Delete(plus2);
01093 #endif
01094
01095 }
01096 }
01097
01098
01099
01100 WN *add;
01101 if (wn2) {
01102 add = LWN_CreateExp2(op,wn1,wn2);
01103 } else {
01104 add = LWN_CreateExp1(op,wn1);
01105 }
01106 WN *stid = LWN_CreateStid(stid_op,preg_array[number_sums-1],
01107 preg_st,Be_Type_Tbl(type),add);
01108 WN *prev_stid = stid;
01109 loop_stids[number_sums-1] = stid;
01110 Create_alias(Alias_Mgr,stid);
01111 WN* new_insertion_point;
01112 if (all_invariant) {
01113 LWN_Insert_Block_Before(LWN_Get_Parent(loop),loop,stid);
01114 #ifdef KEY // bug 8624
01115
01116
01117
01118 new_insertion_point = insertion_point;
01119 #else
01120 new_insertion_point = NULL;
01121 #endif
01122 } else {
01123 LWN_Insert_Block_After(WN_do_body(loop),insertion_point,stid);
01124 new_insertion_point = stid;
01125 }
01126 LWN_Copy_Linenumber(statement,stid);
01127 LWN_Copy_Frequency_Tree(stid,wn1);
01128
01129
01130 if (!all_invariant) {
01131 for (i=number_sums-2; i>=0; i--) {
01132 WN_PAIR_EC *wn_pair = &cse_stack->Bottom_nth(i);
01133 WN *ldid = WN_CreateLdid(ldid_op,preg_array[i+1],
01134 preg_st,Be_Type_Tbl(type));
01135 Create_alias(Alias_Mgr,ldid);
01136 stid = LWN_CreateStid(stid_op,preg_array[i],
01137 preg_st,Be_Type_Tbl(type),ldid);
01138 loop_stids[i] = stid;
01139 Create_alias(Alias_Mgr,stid);
01140 LWN_Insert_Block_After(WN_do_body(loop),insertion_point,stid);
01141 LWN_Copy_Linenumber(LWN_Get_Statement(wn_pair->Wn1),stid);
01142 LWN_Copy_Frequency_Tree(stid,wn_pair->Wn1);
01143 Du_Mgr->Add_Def_Use(prev_stid,ldid);
01144 Du_Mgr->Add_Def_Use(init_stids[i+1],ldid);
01145 Du_Mgr->Ud_Get_Def(ldid)->Set_loop_stmt(loop);
01146 prev_stid = stid;
01147 }
01148 }
01149 insertion_point = new_insertion_point;
01150
01151
01152 if (!all_invariant) {
01153 for (i=0; i<number_sums; i++) {
01154 Du_Mgr->Add_Def_Use(loop_stids[i],loop_ldids[i]);
01155 }
01156 } else {
01157 for (i=0; i<number_sums; i++) {
01158 Du_Mgr->Add_Def_Use(loop_stids[number_sums-1],loop_ldids[i]);
01159 }
01160 }
01161
01162
01163
01164
01165 if (!unary) {
01166 for (i=0; i<number_sums; i++) {
01167 Current_Dep_Graph->Add_Vertex(loop_ldids[i]);
01168 load_stack->Push(loop_ldids[i]);
01169 WN_MAP32_Set(Equivalence_Class_Map,
01170 loop_ldids[i],cse_stack->Bottom_nth(i).EClass);
01171 }
01172 }
01173
01174 if (!all_invariant) {
01175 for (INT from=1; from<number_sums; from++) {
01176 VINDEX16 vfrom = Current_Dep_Graph->Get_Vertex(loop_ldids[from]);
01177 if (vfrom) {
01178 INT to = from - 1;
01179 VINDEX16 vto = Current_Dep_Graph->Get_Vertex(loop_ldids[to]);
01180 if (vto) {
01181 Current_Dep_Graph->Add_Edge(vfrom,vto,DEP_SetDistance(1),1);
01182 }
01183 }
01184 }
01185 } else {
01186 for (INT from=0; from<number_sums; from++) {
01187 VINDEX16 vfrom = Current_Dep_Graph->Get_Vertex(loop_ldids[from]);
01188 if (vfrom) {
01189 for (INT to=from+1; to<number_sums; to++) {
01190 VINDEX16 vto = Current_Dep_Graph->Get_Vertex(loop_ldids[to]);
01191 if (vto) {
01192 Current_Dep_Graph->Add_Edge(vfrom,vto,DEP_SetDirection(DIR_POSEQ),1);
01193 Current_Dep_Graph->Add_Edge(vto,vfrom,DEP_SetDirection(DIR_POS),1);
01194 }
01195 }
01196 }
01197 }
01198 }
01199
01200 CXX_DELETE_ARRAY(preg_array,&LNO_local_pool);
01201 CXX_DELETE_ARRAY(init_stids,&LNO_local_pool);
01202 CXX_DELETE_ARRAY(loop_stids,&LNO_local_pool);
01203 CXX_DELETE_ARRAY(loop_ldids,&LNO_local_pool);
01204
01205 }
01206
01207
01208 static void Add_Invariant_Deps()
01209 {
01210 MEM_POOL_Push(&LNO_local_pool);
01211 VINDEX16 *vertices =
01212 CXX_NEW_ARRAY(VINDEX16,invariant_ldid_stack->Elements(),&LNO_local_pool);
01213 STACK_OF_WN *tmp_stack;
01214 tmp_stack = CXX_NEW(STACK_OF_WN(&LNO_local_pool),&LNO_local_pool);
01215 INT i2=0;
01216 INT i;
01217 for (i=0; i<invariant_ldid_stack->Elements(); i++) {
01218 WN *tmp = invariant_ldid_stack->Bottom_nth(i);
01219 if (!Current_Dep_Graph->Get_Vertex(tmp)) {
01220 vertices[i2++] = Current_Dep_Graph->Add_Vertex(tmp);
01221 tmp_stack->Push(tmp);
01222 }
01223 }
01224 for (i=0; i<tmp_stack->Elements(); i++) {
01225 ST *st1 = WN_st(tmp_stack->Bottom_nth(i));
01226 WN_OFFSET offset1 = WN_offset(tmp_stack->Bottom_nth(i));
01227 for (INT j=i+1; j<tmp_stack->Elements(); j++) {
01228 ST *st2 = WN_st(tmp_stack->Bottom_nth(j));
01229 WN_OFFSET offset2 = WN_offset(tmp_stack->Bottom_nth(j));
01230 if ((st1 == st2) && (offset1 == offset2)) {
01231 Current_Dep_Graph->Add_Edge(vertices[i],vertices[j],DEP_SetDirection(DIR_POSEQ),1);
01232 Current_Dep_Graph->Add_Edge(vertices[j],vertices[i],DEP_SetDirection(DIR_POS),1);
01233 }
01234 }
01235 }
01236 MEM_POOL_Pop(&LNO_local_pool);
01237 }
01238
01239 #ifdef KEY
01240 #include "const.h"
01241 #include "wn_simp.h"
01242 #include "glob.h"
01243
01244 static REDUCTION_MANAGER *reduc_mgr=NULL;
01245 static MEM_POOL FACT_default_pool;
01246 static INT current_level=0;
01247 static int local_num=0;
01248
01249 extern WN* Find_Stmt_Under(WN* stmt,WN* body);
01250 extern void Fully_Unroll_Short_Loops(WN *);
01251
01252 #define STOP_LEVEL 3
01253 #define GOOD_FACTORS 4
01254
01255 static INT In_Invar_Stack(WN *wn, STACK_OF_WN *invar_stack)
01256 {
01257 for(INT i=0; i<invar_stack->Elements(); i++){
01258 WN *tmp = invar_stack->Top_nth(i);
01259 if(Tree_Equiv(wn,tmp)){
01260 if(wn==tmp) return 2;
01261 else return 1;
01262 }
01263 }
01264 return 0;
01265 }
01266
01267
01268 static void Split_Var_Tree(WN *mult, WN *loop, STACK_OF_WN *invar_stack)
01269 {
01270 TYPE_ID type = WN_rtype(mult);
01271 OPERATOR opr = WN_operator(mult);
01272 switch(opr){
01273 case OPR_ADD: case OPR_MPY:
01274 Split_Var_Tree(WN_kid0(mult),loop,invar_stack);
01275 Split_Var_Tree(WN_kid1(mult),loop,invar_stack);
01276 break;
01277 case OPR_LDID:
01278 {
01279 INT ret_num = In_Invar_Stack(mult, invar_stack);
01280 if(ret_num){
01281 TCON tcon; ST* st;
01282 tcon = Host_To_Targ_Float(type, 1.0);
01283 st = New_Const_Sym (Enter_tcon(tcon), Be_Type_Tbl(type));
01284 WN *const_wn = WN_CreateConst(OPR_CONST, type, MTYPE_V, st);
01285 WN *parent = LWN_Get_Parent(mult);
01286 INT which_kid=1;
01287 if(mult == WN_kid0(parent))
01288 which_kid = 0;
01289 WN_kid(parent, which_kid) = const_wn;
01290 LWN_Set_Parent(const_wn, parent);
01291 LWN_Parentize(parent);
01292
01293
01294
01295
01296 }
01297 break;
01298 }
01299 case OPR_ILOAD:
01300 break;
01301 default:
01302 FmtAssert(FALSE,("Not an vaild term!"));
01303 break;
01304 }
01305 }
01306
01307 static WN *Build_Invar_Tree(STACK_OF_WN *invar_stack)
01308 {
01309 WN *invar_tree = NULL;
01310 OPCODE mpy_opc;
01311 for(INT i=0; i< invar_stack->Elements(); i++){
01312 WN *wn = invar_stack->Top_nth(i);
01313 if(invar_tree==NULL)
01314 invar_tree = wn;
01315 else{
01316 mpy_opc = OPCODE_make_op(OPR_MPY, WN_rtype(wn), MTYPE_V);
01317 invar_tree = LWN_CreateExp2(mpy_opc, invar_tree, wn);
01318 }
01319 }
01320 return invar_tree;
01321 }
01322
01323 static BOOL Well_Formed_Mult(WN *mpy)
01324 {
01325 if(WN_rtype(mpy) != MTYPE_F8 && WN_rtype(mpy) != MTYPE_F4)
01326 return FALSE;
01327
01328 if(WN_operator(mpy)==OPR_MPY){
01329 if(!Well_Formed_Mult(WN_kid0(mpy)) || !Well_Formed_Mult(WN_kid1(mpy)))
01330 return FALSE;
01331 else return TRUE;
01332 }else if(WN_operator(mpy)==OPR_ILOAD || WN_operator(mpy)==OPR_LDID)
01333 return TRUE;
01334 else return FALSE;
01335 }
01336
01337 static BOOL Well_Formed_Terms(WN *reduction_term)
01338 {
01339 if(WN_operator(reduction_term)==OPR_ADD){
01340 if(!Well_Formed_Terms(WN_kid0(reduction_term)) ||
01341 !Well_Formed_Terms(WN_kid1(reduction_term)))
01342 return FALSE;
01343 else
01344 return TRUE;
01345 }else if(WN_operator(reduction_term)==OPR_MPY)
01346 return Well_Formed_Mult(reduction_term);
01347 else
01348 return FALSE;
01349 }
01350
01351 static STACK_OF_WN *Invar_Stack_Intersection(STACK_OF_WN *one, STACK_OF_WN *two)
01352 {
01353 STACK_OF_WN *tmp_stack=CXX_NEW(STACK_OF_WN(&FACT_default_pool),
01354 &FACT_default_pool);
01355 for(INT i=0; i<one->Elements(); i++){
01356 WN *ele1 = one->Top_nth(i);
01357 for(INT j=0; j<two->Elements();j++){
01358 WN *ele2 = two->Top_nth(j);
01359 if(Tree_Equiv(ele1,ele2))
01360 tmp_stack->Push(ele1);
01361 }
01362 }
01363
01364
01365 return tmp_stack;
01366 }
01367
01368
01369 static BOOL Gather_Term_Invars(WN *term, STACK_OF_WN *invar_stack, WN *loop)
01370 {
01371 if((WN_operator(term)==OPR_LDID
01372 && Is_Loop_Invariant_Exp(term, loop))){
01373 for(INT ii=0; ii<invar_stack->Elements(); ii++)
01374 if(Tree_Equiv(invar_stack->Bottom_nth(ii), term))
01375 return FALSE;
01376 invar_stack->Push(term);
01377 }
01378 else if(WN_operator(term)==OPR_MPY){
01379 if(!Gather_Term_Invars(WN_kid0(term), invar_stack, loop))
01380 return FALSE;
01381 if(!Gather_Term_Invars(WN_kid1(term), invar_stack, loop))
01382 return FALSE;
01383 }
01384 return TRUE;
01385 }
01386
01387 static BOOL Build_Term_Stack(WN *term, STACK_OF_WN *term_stack)
01388 {
01389 if(WN_operator(term)==OPR_MPY){
01390 term_stack->Push(term);
01391 }else if(WN_operator(term)==OPR_ADD ||
01392 WN_operator(term)==OPR_SUB){
01393 if(!Build_Term_Stack(WN_kid0(term), term_stack))
01394 return FALSE;
01395 if(!Build_Term_Stack(WN_kid1(term), term_stack))
01396 return FALSE;
01397 }else return FALSE;
01398 return TRUE;
01399 }
01400
01401
01402 static BOOL Gather_Stmt_Common_Invar(WN *stmt, STACK_OF_WN *common_invar, WN *loop)
01403 {
01404
01405 FmtAssert(common_invar && common_invar->Elements()==0,
01406 ("Expect an initialized but empty stack!"));
01407 STACK_OF_WN *term_stack = CXX_NEW(STACK_OF_WN(&FACT_default_pool),
01408 &FACT_default_pool);
01409 if(!Build_Term_Stack(WN_kid1(WN_kid0(stmt)), term_stack))
01410 return FALSE;
01411 if(term_stack->Elements()==0)
01412 return FALSE;
01413 STACK_OF_WN *ret_invar;
01414 for(INT ii=0; ii< term_stack->Elements(); ii++){
01415 WN *term = term_stack->Bottom_nth(ii);
01416 STACK_OF_WN *tmp_invar = CXX_NEW(STACK_OF_WN(&FACT_default_pool),
01417 &FACT_default_pool);
01418 if(!Gather_Term_Invars(term, tmp_invar, loop))
01419 return FALSE;
01420 if(tmp_invar->Elements()==0)
01421 return FALSE;
01422 if(ii==0)
01423 ret_invar = tmp_invar;
01424 else
01425 ret_invar = Invar_Stack_Intersection(ret_invar, tmp_invar);
01426 if(ret_invar->Elements()==0)
01427 return FALSE;
01428 }
01429
01430 while(ret_invar->Elements()>0)
01431 common_invar->Push(ret_invar->Pop());
01432 return TRUE;
01433 }
01434
01435
01436 static WN *Find_Reduction_Variable(WN *add)
01437 {
01438 FmtAssert(WN_operator(add)==OPR_ADD,("Not an addition!"));
01439 if(WN_operator(WN_kid0(add))==OPR_LDID &&
01440 reduc_mgr->Which_Reduction(WN_kid0(add))==RED_ADD)
01441 return WN_kid0(add);
01442 else if(WN_operator(WN_kid1(add))==OPR_LDID &&
01443 reduc_mgr->Which_Reduction(WN_kid1(add))==RED_ADD)
01444 return WN_kid1(add);
01445
01446 if(WN_operator(WN_kid0(add))==OPR_ADD){
01447 WN *reduc = Find_Reduction_Variable(WN_kid0(add));
01448 if(reduc) return reduc;
01449 }
01450
01451 if(WN_operator(WN_kid1(add))==OPR_ADD){
01452 WN *reduc = Find_Reduction_Variable(WN_kid1(add));
01453 if(reduc) return reduc;
01454 }
01455 return NULL;
01456 }
01457
01458
01459 static BOOL Well_Formed_Reduction_Stmt(WN *stmt, WN *loop)
01460 {
01461
01462 if(WN_operator(stmt) != OPR_STID ||
01463 reduc_mgr->Which_Reduction(stmt) != RED_ADD)
01464 return FALSE;
01465
01466 WN *kid0 = WN_kid0(stmt);
01467 WN *terms=NULL;
01468 INT which_kid;
01469
01470 if(WN_operator(kid0)==OPR_ADD){
01471 WN *reduc = Find_Reduction_Variable(kid0);
01472 if(!reduc)
01473 return FALSE;
01474 INT which_path=0;
01475 WN *parent = LWN_Get_Parent(reduc);
01476 if(WN_kid1(parent)==reduc)
01477 which_path=1;
01478 WN *tmp = reduc;
01479 while(LWN_Get_Parent(tmp) != kid0)
01480 tmp = LWN_Get_Parent(tmp);
01481 FmtAssert(tmp, ("Error!"));
01482 if(tmp==WN_kid0(kid0)){
01483 if(tmp!=reduc){
01484 WN *temp = WN_kid1(kid0);
01485 WN_kid(parent, which_path) = temp;
01486 LWN_Set_Parent(temp, parent);
01487 WN_kid1(kid0)=tmp;
01488 LWN_Set_Parent(tmp, kid0);
01489 WN_kid0(kid0)=reduc;
01490 LWN_Set_Parent(reduc, kid0);
01491 LWN_Parentize(kid0);
01492 LWN_Parentize(parent);
01493 }
01494 }else{
01495 WN *temp = WN_kid0(kid0);
01496 WN_kid0(kid0)=reduc;
01497 LWN_Set_Parent(reduc, kid0);
01498 WN_kid(parent, which_path) = temp;
01499 LWN_Set_Parent(temp, parent);
01500 LWN_Parentize(kid0);
01501 LWN_Parentize(parent);
01502 }
01503 terms = WN_kid1(kid0);
01504 which_kid = 1;
01505 }else if(WN_operator(kid0)==OPR_SUB){
01506
01507 return FALSE;
01508 FmtAssert(WN_operator(WN_kid0(kid0))==OPR_LDID &&
01509 reduc_mgr->Which_Reduction(WN_kid0(kid0))==RED_ADD,
01510 ("Wrong reduction!"));
01511 terms = WN_kid1(kid0);
01512 which_kid = 1;
01513 }else
01514 return FALSE;
01515
01516 if(!Well_Formed_Terms(terms))
01517 return FALSE;
01518
01519
01520 if (!Du_Mgr)
01521 return FALSE;
01522 USE_LIST* use_list=Du_Mgr->Du_Get_Use(stmt);
01523 if (!use_list) return FALSE;
01524 WN *body = WN_do_body(loop);
01525 USE_LIST_ITER uiter(use_list);
01526 for (DU_NODE* u = uiter.First(); !uiter.Is_Empty(); u=uiter.Next()){
01527 WN* use=u->Wn();
01528 if (Wn_Is_Inside(use, loop)) {
01529 WN* stmt1 = Find_Stmt_Under(use, body);
01530 if (reduc_mgr->Which_Reduction(stmt1) == RED_NONE ||
01531 (WN_operator(stmt1) == OPR_STID &&
01532 (WN_st(stmt1) != WN_st(stmt) ||
01533 WN_store_offset(stmt1) != WN_store_offset(stmt)))){
01534 return FALSE;
01535 }
01536 }
01537 }
01538 DEF_LIST *def_list = Du_Mgr->Ud_Get_Def(WN_kid(kid0, 1-which_kid));
01539 if (!def_list) return FALSE;
01540 DEF_LIST_ITER diter(def_list);
01541 for (DU_NODE* d = diter.First(); !diter.Is_Empty(); d=diter.Next()){
01542 WN* def=d->Wn();
01543 if (Wn_Is_Inside(def, loop)){
01544 WN* stmt1 = Find_Stmt_Under(def, body);
01545 if (reduc_mgr->Which_Reduction(stmt1) == RED_NONE ||
01546 (WN_operator(stmt1) == OPR_STID &&
01547 (WN_st(stmt1) != WN_st(stmt) ||
01548 WN_store_offset(stmt1) != WN_store_offset(stmt)))){
01549 return FALSE;
01550 }
01551 }
01552 }
01553 return TRUE;
01554 }
01555
01556
01557
01558
01559
01560 static void Handle_Stmt(STACK_OF_WN *group, STACK_OF_WN *common_invar, WN *loop)
01561 {
01562 WN *first = group->Bottom_nth(0);
01563 TYPE_ID type = WN_rtype(WN_kid1(WN_kid0(first)));
01564 WN_OFFSET preg_num=0;
01565 ST *preg_st=0;
01566 char preg_name[20];
01567 preg_st = MTYPE_To_PREG(type);
01568 sprintf(preg_name,"invar_fact%d",local_num++);
01569 preg_num = Create_Preg(type,preg_name);
01570 OPCODE preg_s_opcode = OPCODE_make_op(OPR_STID,MTYPE_V,type);
01571 OPCODE preg_l_opcode = OPCODE_make_op(OPR_LDID,type,type);
01572 OPCODE add_opc= OPCODE_make_op(OPR_ADD,type, MTYPE_V);
01573 OPCODE sub_opc= OPCODE_make_op(OPR_SUB,type, MTYPE_V);
01574 WN *preg_store;
01575 WN *preg_load;
01576 for(INT i=0; i<group->Elements(); i++){
01577 WN *stmt = group->Bottom_nth(i);
01578 if(i==0){
01579 TCON tcon;
01580 ST* st;
01581 tcon = Host_To_Targ_Float(type, 0.0);
01582 st = New_Const_Sym (Enter_tcon(tcon), Be_Type_Tbl(type));
01583 WN *const_wn = WN_CreateConst(OPR_CONST, type, MTYPE_V, st);
01584 preg_store = LWN_CreateStid(preg_s_opcode,preg_num,
01585 preg_st, Be_Type_Tbl(type),const_wn);
01586 LWN_Insert_Block_Before(LWN_Get_Parent(loop),loop,preg_store);
01587 }
01588
01589 WN *terms = WN_kid1(WN_kid0(stmt));
01590
01591 Split_Var_Tree(terms, loop, common_invar);
01592 WN *var_tree = WN_Simplify_Tree(terms);
01593
01594 WN *preg_load = WN_CreateLdid(preg_l_opcode,preg_num, preg_st, Be_Type_Tbl(type));
01595 Du_Mgr->Add_Def_Use(preg_store,preg_load);
01596 WN *add = LWN_CreateExp2(WN_operator(WN_kid0(stmt))==OPR_ADD?add_opc:sub_opc,preg_load,var_tree);
01597 preg_store = LWN_CreateStid(preg_s_opcode,preg_num,
01598 preg_st, Be_Type_Tbl(type),add);
01599 LWN_Insert_Block_Before(LWN_Get_Parent(stmt),stmt,preg_store);
01600 if(i==group->Elements()-1){
01601 WN *invar_tree = Build_Invar_Tree(common_invar);
01602 WN *preg_load = WN_CreateLdid(preg_l_opcode,preg_num, preg_st, Be_Type_Tbl(type));
01603 Du_Mgr->Add_Def_Use(preg_store,preg_load);
01604 OPCODE mpy_opc = OPCODE_make_op(OPR_MPY,WN_rtype(invar_tree),MTYPE_V);
01605 invar_tree = LWN_CreateExp2(mpy_opc, invar_tree, preg_load);
01606 WN_kid1(WN_kid0(stmt))=invar_tree;
01607 LWN_Set_Parent(invar_tree, WN_kid0(stmt));
01608 LWN_Parentize(WN_kid0(stmt));
01609 LWN_Extract_From_Block(LWN_Get_Parent(stmt), stmt);
01610 LWN_Insert_Block_After(LWN_Get_Parent(loop),loop,stmt);
01611 }else{
01612 WN_kid1(WN_kid0(stmt))=NULL;
01613 LWN_Parentize(WN_kid0(stmt));
01614 LWN_Extract_From_Block(LWN_Get_Parent(stmt), stmt);
01615 LWN_Delete_Tree(stmt);
01616 }
01617 }
01618 }
01619
01620
01621 static BOOL Factorize_Statement(STACK_OF_WN *current_stmt_group, WN *loop)
01622 {
01623
01624 STACK_OF_WN *common_invar;
01625 for(INT ii=0; ii<current_stmt_group->Elements(); ii++){
01626 WN * stmt=current_stmt_group->Bottom_nth(ii);
01627 STACK_OF_WN *tmp_invar = CXX_NEW(STACK_OF_WN(&FACT_default_pool),
01628 &FACT_default_pool);
01629 if(!Gather_Stmt_Common_Invar(stmt, tmp_invar, loop))
01630 return FALSE;
01631 if(tmp_invar->Elements()==0)
01632 return FALSE;
01633 if(ii == 0)
01634 common_invar = tmp_invar;
01635 else
01636 common_invar = Invar_Stack_Intersection(common_invar, tmp_invar);
01637 if(common_invar->Elements()==0)
01638 return FALSE;
01639 }
01640 if (LNO_Invar_Factor_Verbose){
01641 printf(" %d statements with %d common_invariants have been factorized.\n",
01642 current_stmt_group->Elements(),
01643 common_invar->Elements());
01644 }
01645 Handle_Stmt(current_stmt_group, common_invar, loop);
01646 return TRUE;
01647 }
01648
01649 static BOOL Under_Same_Level(WN_OFFSET offset, ST *st,
01650 WN *loop, WN* body)
01651 {
01652 for (LWN_ITER* itr = LWN_WALK_TreeIter(loop);
01653 itr;
01654 itr = LWN_WALK_TreeNext(itr)){
01655 WN* wn = itr->wn;
01656 if (WN_operator(wn) == OPR_STID &&
01657 WN_st(wn) == st &&
01658 WN_store_offset(wn)==offset){
01659 if(LWN_Get_Parent(wn) != body)
01660 return FALSE;
01661 }
01662 }
01663 return TRUE;
01664 }
01665
01666 static BOOL Already_Passed_Stid(WN *stid, STACK_OF_WN *stmt_stack)
01667 {
01668 for(INT ii=0; ii<stmt_stack->Elements(); ii++){
01669 WN *wn = stmt_stack->Top_nth(ii);
01670 if(WN_st(stid) == WN_st(wn) &&
01671 WN_store_offset(stid) == WN_store_offset(wn))
01672 return TRUE;
01673 }
01674 return FALSE;
01675 }
01676
01677
01678 static BOOL Factorize_Loop(WN *loop)
01679 {
01680 if(WN_operator(loop) != OPR_DO_LOOP ||
01681 Do_Loop_Has_Calls(loop) ||
01682 Do_Loop_Has_Exits(loop) ||
01683 Do_Loop_Has_Gotos(loop) ||
01684 Do_Loop_Is_Mp(loop) ||
01685 Is_Nested_Doacross(loop) ||
01686 !Do_Loop_Is_Good(loop))
01687 return FALSE;
01688
01689
01690 BOOL has_factorization = FALSE;
01691 WN *body = WN_do_body(loop);
01692 WN *next=WN_first(body);
01693 WN *stmt;
01694 if(current_level >= STOP_LEVEL){
01695 DO_LOOP_INFO *dli = Get_Do_Loop_Info(loop);
01696 if(dli && dli->Delay_Full_Unroll && LNO_Full_Unrolling_Limit != 0)
01697 Fully_Unroll_Short_Loops(loop);
01698 return FALSE;
01699 }
01700
01701 STACK_OF_WN *stid_stmt_list = CXX_NEW
01702 (STACK_OF_WN(&FACT_default_pool),&FACT_default_pool);
01703
01704 for(stmt=WN_first(body); stmt; stmt=WN_next(stmt)){
01705 if(WN_operator(stmt) == OPR_STID){
01706 if(!Already_Passed_Stid(stmt, stid_stmt_list))
01707 stid_stmt_list->Push(stmt);
01708 }
01709 }
01710
01711
01712 for(INT ii=0; ii<stid_stmt_list->Elements(); ii++){
01713 WN *orig_stmt = stid_stmt_list->Bottom_nth(ii);
01714 WN_OFFSET offset = WN_store_offset(orig_stmt);
01715 ST *st = WN_st(orig_stmt);
01716 if(Under_Same_Level(offset, st, loop, body)){
01717 STACK_OF_WN *current_stmt_group=CXX_NEW(STACK_OF_WN(&FACT_default_pool),&FACT_default_pool);
01718 BOOL everything_good = TRUE;
01719 for(stmt=WN_first(body); stmt; stmt=WN_next(stmt)){
01720 if(WN_operator(stmt)==OPR_STID &&
01721 WN_store_offset(stmt)==offset &&
01722 WN_st(stmt)==st) {
01723 if(Well_Formed_Reduction_Stmt(stmt, loop))
01724 current_stmt_group->Push(stmt);
01725 else{
01726 everything_good = FALSE;
01727 break;
01728 }
01729 }
01730 }
01731 if(everything_good){
01732 BOOL factorized = Factorize_Statement(current_stmt_group,loop);
01733 if(factorized)
01734 has_factorization = TRUE;
01735 }
01736 }
01737 }
01738
01739 if(has_factorization){
01740 current_level++;
01741 WN *parent = LWN_Get_Parent(loop);
01742 WN *outer_loop = Enclosing_Do_Loop(parent);
01743 if(outer_loop)
01744 Factorize_Loop(outer_loop);
01745 }
01746 return has_factorization;
01747 }
01748
01749 static INT Factors_In_Mult_Tree(WN *mpy)
01750 {
01751 if(WN_operator(mpy) != OPR_MPY)
01752 return 0;
01753 return (Factors_In_Mult_Tree(WN_kid0(mpy)) +
01754 Factors_In_Mult_Tree(WN_kid1(mpy)) + 1);
01755 }
01756
01757 static INT Factors_In_Terms(WN *terms)
01758 {
01759 if(WN_operator(terms)==OPR_ADD){
01760 INT left = Factors_In_Terms(WN_kid0(terms));
01761 INT right = Factors_In_Terms(WN_kid1(terms));
01762 return (left > right ? right : left);
01763 }else if(WN_operator(terms)==OPR_MPY)
01764 return Factors_In_Mult_Tree(terms);
01765 return 0;
01766 }
01767
01768
01769 static INT Statement_Invariant_Factors(WN *stmt, WN *innerloop)
01770 {
01771 if(WN_operator(stmt)!=OPR_STID && WN_operator(stmt)!=OPR_ISTORE)
01772 return 0;
01773 WN *terms;
01774 WN *kid0 = WN_kid0(stmt);
01775 if(WN_operator(kid0) != OPR_ADD)
01776 return 0;
01777 if(WN_operator(stmt)==OPR_STID){
01778 if(WN_operator(WN_kid0(kid0))==OPR_LDID &&
01779
01780 WN_st(stmt)==WN_st(WN_kid0(kid0)) &&
01781 WN_store_offset(stmt) == WN_load_offset(WN_kid0(kid0)) &&
01782 WN_field_id(stmt) == WN_field_id(WN_kid0(kid0)))
01783 terms = WN_kid1(kid0);
01784 else if(WN_operator(WN_kid1(kid0))==OPR_LDID &&
01785
01786 WN_st(stmt)==WN_st(WN_kid1(kid0)) &&
01787 WN_store_offset(stmt) == WN_load_offset(WN_kid1(kid0)) &&
01788 WN_field_id(stmt) == WN_field_id(WN_kid1(kid0)))
01789 terms = WN_kid0(kid0);
01790 else return 0;
01791 }else if(WN_operator(stmt)==OPR_ISTORE){
01792 WN *array_to = WN_kid1(stmt);
01793 if(WN_operator(array_to) != OPR_ARRAY)
01794 return 0;
01795 WN *array_from;
01796 if(WN_operator(WN_kid0(kid0))==OPR_ILOAD &&
01797 WN_operator(WN_kid0(WN_kid0(kid0))) == OPR_ARRAY){
01798 array_from = WN_kid0(WN_kid0(kid0));
01799 terms = WN_kid1(kid0);
01800 }else if(WN_operator(WN_kid1(kid0))==OPR_ILOAD &&
01801 WN_operator(WN_kid0(WN_kid1(kid0))) == OPR_ARRAY){
01802 array_from = WN_kid0(WN_kid1(kid0));
01803 terms = WN_kid0(kid0);
01804 }else return 0;
01805 if(!Tree_Equiv(array_from, array_to))
01806 return 0;
01807 }
01808 if(!Well_Formed_Terms(terms))
01809 return 0;
01810 return Factors_In_Terms(terms);
01811 }
01812
01813
01814 static BOOL Invar_Factor_Candidate(WN *innerloop)
01815 {
01816 INT invar_factors = 0;
01817 INT stmt_invar_factors;
01818 WN *body = WN_do_body(innerloop);
01819 for(WN *stmt=WN_first(body); stmt; stmt=WN_next(stmt)){
01820 stmt_invar_factors = Statement_Invariant_Factors(stmt, innerloop);
01821 if(stmt_invar_factors > invar_factors)
01822 invar_factors = stmt_invar_factors;
01823 }
01824 return (invar_factors >= GOOD_FACTORS);
01825 }
01826
01827 extern BOOL Is_Invariant_Factorization_Beneficial(WN *loop){
01828
01829 if(!LNO_Invariant_Factorization ||
01830 Roundoff_Level < ROUNDOFF_ASSOC ||
01831 Get_Trace(TP_LNOPT, TT_LNO_GUARD))
01832 return FALSE;
01833
01834
01835 STACK_OF_WN *innerdo_stack = CXX_NEW
01836 (STACK_OF_WN(&LNO_default_pool),&LNO_default_pool);
01837 for (LWN_ITER* itr = LWN_WALK_TreeIter(WN_do_body(loop));
01838 itr;
01839 itr = LWN_WALK_TreeNext(itr)){
01840 WN* wn = itr->wn;
01841 if (WN_operator(wn) == OPR_DO_LOOP){
01842 DO_LOOP_INFO *dli = Get_Do_Loop_Info(wn);
01843 if(dli && dli->Is_Inner)
01844 innerdo_stack->Push(wn);
01845 }
01846 }
01847 for(INT ii=0; ii<innerdo_stack->Elements(); ii++){
01848 WN *innerloop = innerdo_stack->Bottom_nth(ii);
01849 if(Invar_Factor_Candidate(innerloop))
01850 return TRUE;
01851 }
01852 return FALSE;
01853 }
01854
01855 static BOOL pool_initialized = FALSE;
01856
01857 extern void Invariant_Factorization(WN *func_nd)
01858 {
01859 if(!pool_initialized){
01860 MEM_POOL_Initialize(&FACT_default_pool,"FACT_default_pool",FALSE);
01861 MEM_POOL_Push(&FACT_default_pool);
01862 pool_initialized = TRUE;
01863 }
01864 reduc_mgr = CXX_NEW
01865 (REDUCTION_MANAGER(&FACT_default_pool), &FACT_default_pool);
01866 reduc_mgr->Build(func_nd,TRUE,FALSE);
01867
01868 INT factorized_loops = 0;
01869
01870 STACK_OF_WN *inner_do_stack = CXX_NEW
01871 (STACK_OF_WN(&FACT_default_pool),&FACT_default_pool);
01872 for (LWN_ITER* itr = LWN_WALK_TreeIter(func_nd);
01873 itr;
01874 itr = LWN_WALK_TreeNext(itr)){
01875 WN* wn = itr->wn;
01876 if (WN_operator(wn) == OPR_DO_LOOP){
01877 DO_LOOP_INFO *dli = Get_Do_Loop_Info(wn);
01878 if(dli && dli->Is_Inner)
01879 inner_do_stack->Push(wn);
01880 }
01881 }
01882
01883 for(INT ii=0; ii<inner_do_stack->Elements(); ii++){
01884 WN *loop = inner_do_stack->Bottom_nth(ii);
01885 current_level=0;
01886 if(Factorize_Loop(loop)){
01887 if (LNO_Invar_Factor_Verbose){
01888 printf("(%s:%d) Loop invariants were factorized.\n", Src_File_Name,
01889 Srcpos_To_Line(WN_Get_Linenum(loop)));
01890 }
01891 factorized_loops++;
01892 }
01893 }
01894
01895
01896
01897 }
01898 #endif
01899