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 #include "defs.h"
00066 #include "glob.h"
00067 #include "wn.h"
00068 #include "wn_map.h"
00069 #include "lwn_util.h"
00070 #include "ff_utils.h"
00071 #include "lnoutils.h"
00072 #include "lnopt_main.h"
00073 #include "opt_du.h"
00074 #include "dep_graph.h"
00075 #include "ir_reader.h"
00076
00077 static MEM_POOL HoistIf_default_pool;
00078
00079 typedef STACK<WN*> STACK_OF_WN;
00080
00081 static BOOL debug_hoistif;
00082
00083 static void
00084 HoistIf_Update_Use_List (WN* stmt, WN* tmp, WN* innerloop)
00085 {
00086
00087
00088 USE_LIST* use_list=Du_Mgr->Du_Get_Use(stmt);
00089 USE_LIST_ITER iter(use_list);
00090 const DU_NODE* node;
00091 for (node = iter.First(); !iter.Is_Empty(); node = iter.Next()) {
00092 WN* wn_use = node->Wn();
00093 if (!Wn_Is_Inside(wn_use, innerloop))
00094 Du_Mgr->Add_Def_Use(tmp, wn_use);
00095 else
00096 Du_Mgr->Add_Def_Use(tmp, tmp);
00097 }
00098 }
00099
00100 static void
00101 HoistIf_Copy_Def_Use (WN* stmt, WN* tmp, SYMBOL sym, WN* innerloop)
00102 {
00103 if (WN_operator(stmt) == OPR_LDID) {
00104 SYMBOL currentsym = SYMBOL(stmt);
00105 if (currentsym != sym) {
00106 LWN_Copy_Def_Use(stmt, tmp, Du_Mgr);
00107 DEF_LIST* def_list=Du_Mgr->Ud_Get_Def(tmp);
00108 if (def_list->Loop_stmt() == innerloop)
00109 def_list->Set_loop_stmt(NULL);
00110 }
00111 } else if (WN_operator(stmt) == OPR_BLOCK) {
00112 WN* kid_stmt = WN_first(stmt);
00113 WN* kid_tmp = WN_first(tmp);
00114 while(kid_stmt) {
00115 HoistIf_Copy_Def_Use(kid_stmt, kid_tmp, sym, innerloop);
00116 kid_stmt = WN_next(kid_stmt);
00117 kid_tmp = WN_next(kid_tmp);
00118 }
00119 } else {
00120 if (WN_operator(stmt) == OPR_STID) {
00121 SYMBOL currentsym = SYMBOL(stmt);
00122 if (currentsym != sym)
00123 HoistIf_Update_Use_List(stmt, tmp, innerloop);
00124 }
00125
00126 for (INT kid = 0; kid < WN_kid_count(stmt); kid ++)
00127 HoistIf_Copy_Def_Use(WN_kid(stmt, kid), WN_kid(tmp, kid), sym,
00128 innerloop);
00129 }
00130 }
00131
00132 static BOOL
00133 Is_Cmp_Eq_IV (WN* cmp, SYMBOL symindex)
00134 {
00135 if (WN_operator(cmp) == OPR_CAND) {
00136 WN* kid0 = WN_kid0(cmp);
00137 WN* kid1 = WN_kid1(cmp);
00138
00139 if (Is_Cmp_Eq_IV(kid0, symindex) ||
00140 Is_Cmp_Eq_IV(kid1, symindex))
00141 return TRUE;
00142
00143 return FALSE;
00144 } else if (WN_operator(cmp) == OPR_EQ) {
00145 WN* opnd0 = WN_kid0(cmp);
00146 WN* opnd1 = WN_kid1(cmp);
00147
00148 if (WN_operator(opnd0) == OPR_LDID && WN_operator(opnd1) == OPR_LDID) {
00149 SYMBOL sym0 = SYMBOL(opnd0);
00150 SYMBOL sym1 = SYMBOL(opnd1);
00151 if (symindex == sym0 || symindex == sym1)
00152 return TRUE;
00153 } else if ((WN_operator(opnd0) == OPR_SUB ||
00154 WN_operator(opnd0) == OPR_ADD) &&
00155 WN_operator(opnd1) == OPR_LDID) {
00156 WN* tmp_opnd0 = WN_kid0(opnd0);
00157 WN* tmp_opnd1 = WN_kid1(opnd0);
00158 SYMBOL sym0, sym1;
00159 BOOL found_index = FALSE;
00160
00161 if (WN_operator(tmp_opnd0) != OPR_LDID &&
00162 WN_operator(tmp_opnd1) != OPR_LDID)
00163 return FALSE;
00164 if (WN_operator(tmp_opnd0) == OPR_LDID) {
00165 sym0 = SYMBOL(tmp_opnd0);
00166 if (sym0 == symindex)
00167 found_index = TRUE;
00168 }
00169 if (WN_operator(tmp_opnd1) == OPR_LDID) {
00170 sym1 = SYMBOL(tmp_opnd1);
00171 if (sym1 == symindex)
00172 found_index = TRUE;
00173 }
00174 if (!found_index)
00175 return FALSE;
00176 else
00177 return TRUE;
00178 } else if ((WN_operator(opnd1) == OPR_SUB ||
00179 WN_operator(opnd1) == OPR_ADD) &&
00180 WN_operator(opnd0) == OPR_LDID) {
00181 WN* tmp_opnd0 = WN_kid0(opnd1);
00182 WN* tmp_opnd1 = WN_kid1(opnd1);
00183 SYMBOL sym0, sym1;
00184 BOOL found_index = FALSE;
00185
00186 if (WN_operator(tmp_opnd0) != OPR_LDID &&
00187 WN_operator(tmp_opnd1) != OPR_LDID)
00188 return FALSE;
00189 if (WN_operator(tmp_opnd0) == OPR_LDID) {
00190 sym0 = SYMBOL(tmp_opnd0);
00191 if (sym0 == symindex)
00192 found_index = TRUE;
00193 }
00194 if (WN_operator(tmp_opnd1) == OPR_LDID) {
00195 sym1 = SYMBOL(tmp_opnd1);
00196 if (sym1 == symindex)
00197 found_index = TRUE;
00198 }
00199 if (!found_index)
00200 return FALSE;
00201 else
00202 return TRUE;
00203 } else {
00204 BOOL found_index = FALSE;
00205 if (WN_operator(opnd0) == OPR_LDID) {
00206 SYMBOL sym0 = SYMBOL(opnd0);
00207 if (sym0 == symindex)
00208 found_index = TRUE;
00209 }
00210 if (WN_operator(opnd1) == OPR_LDID) {
00211 SYMBOL sym1 = SYMBOL(opnd1);
00212 if (sym1 == symindex)
00213 found_index = TRUE;
00214 }
00215 if (!found_index)
00216 return FALSE;
00217 else
00218 return TRUE;
00219 }
00220 }
00221 return FALSE;
00222 }
00223
00224 static BOOL
00225 compared_operand_has_index (WN *opnd, SYMBOL symindex)
00226 {
00227 if (WN_operator(opnd) == OPR_LDID) {
00228 SYMBOL sym = SYMBOL(opnd);
00229 if (sym == symindex)
00230 return TRUE;
00231
00232 } else
00233 for (INT kid = 0; kid < WN_kid_count(opnd); kid ++)
00234 if (compared_operand_has_index (WN_kid(opnd, kid), symindex))
00235 return TRUE;
00236
00237 return FALSE;
00238 }
00239
00240 static BOOL
00241 Is_HoistIf_Amenable (WN* stmt, WN* innerloop)
00242 {
00243 if (WN_operator(stmt) != OPR_IF)
00244 return FALSE;
00245
00246 if (WN_first(WN_kid2(stmt)) != NULL)
00247 return FALSE;
00248
00249 WN* kid0 = WN_kid0(stmt);
00250 if (WN_operator(kid0) != OPR_EQ &&
00251 WN_operator(kid0) != OPR_CAND)
00252 return FALSE;
00253
00254 SYMBOL symindex = SYMBOL(WN_index(innerloop));
00255 if (WN_operator(kid0) == OPR_EQ) {
00256 WN* opnd0 = WN_kid0(kid0);
00257 WN* opnd1 = WN_kid1(kid0);
00258
00259 if (WN_operator(opnd0) == OPR_LDID && WN_operator(opnd1) == OPR_LDID) {
00260 SYMBOL sym0 = SYMBOL(opnd0);
00261 SYMBOL sym1 = SYMBOL(opnd1);
00262 if (symindex != sym0 && symindex != sym1)
00263 return FALSE;
00264 } else if ((WN_operator(opnd0) == OPR_SUB ||
00265 WN_operator(opnd0) == OPR_ADD) &&
00266 WN_operator(opnd1) == OPR_LDID) {
00267 WN* tmp_opnd0 = WN_kid0(opnd0);
00268 WN* tmp_opnd1 = WN_kid1(opnd0);
00269 SYMBOL sym0, sym1;
00270 BOOL found_index = FALSE;
00271
00272 if (WN_operator(tmp_opnd0) != OPR_LDID &&
00273 WN_operator(tmp_opnd1) != OPR_LDID)
00274 return FALSE;
00275 if (WN_operator(tmp_opnd0) == OPR_LDID) {
00276 sym0 = SYMBOL(tmp_opnd0);
00277 if (sym0 == symindex)
00278 found_index = TRUE;
00279 if (found_index && compared_operand_has_index(tmp_opnd1, symindex))
00280 return FALSE;
00281 }
00282 if (WN_operator(tmp_opnd1) == OPR_LDID) {
00283 sym1 = SYMBOL(tmp_opnd1);
00284 if (sym1 == symindex)
00285 found_index = TRUE;
00286 if (found_index && compared_operand_has_index(tmp_opnd0, symindex))
00287 return FALSE;
00288 }
00289 if (!found_index)
00290 return FALSE;
00291 } else if ((WN_operator(opnd1) == OPR_SUB ||
00292 WN_operator(opnd1) == OPR_ADD) &&
00293 WN_operator(opnd0) == OPR_LDID) {
00294 WN* tmp_opnd0 = WN_kid0(opnd1);
00295 WN* tmp_opnd1 = WN_kid1(opnd1);
00296 SYMBOL sym0, sym1;
00297 BOOL found_index = FALSE;
00298
00299 if (WN_operator(tmp_opnd0) != OPR_LDID &&
00300 WN_operator(tmp_opnd1) != OPR_LDID)
00301 return FALSE;
00302 if (WN_operator(tmp_opnd0) == OPR_LDID) {
00303 sym0 = SYMBOL(tmp_opnd0);
00304 if (sym0 == symindex)
00305 found_index = TRUE;
00306 if (found_index && compared_operand_has_index(tmp_opnd1, symindex))
00307 return FALSE;
00308 }
00309 if (WN_operator(tmp_opnd1) == OPR_LDID) {
00310 sym1 = SYMBOL(tmp_opnd1);
00311 if (sym1 == symindex)
00312 found_index = TRUE;
00313 if (found_index && compared_operand_has_index(tmp_opnd0, symindex))
00314 return FALSE;
00315 }
00316 if (!found_index)
00317 return FALSE;
00318 } else {
00319 BOOL found_index = FALSE;
00320 if (WN_operator(opnd0) == OPR_LDID) {
00321 SYMBOL sym0 = SYMBOL(opnd0);
00322 if (sym0 == symindex)
00323 found_index = TRUE;
00324 if (found_index && compared_operand_has_index(opnd1, symindex))
00325 return FALSE;
00326 }
00327 if (WN_operator(opnd1) == OPR_LDID) {
00328 SYMBOL sym1 = SYMBOL(opnd1);
00329 if (sym1 == symindex)
00330 found_index = TRUE;
00331 if (found_index && compared_operand_has_index(opnd0, symindex))
00332 return FALSE;
00333 }
00334 if (!found_index)
00335 return FALSE;
00336 }
00337 } else {
00338
00339
00340 if (!Is_Cmp_Eq_IV(kid0, symindex))
00341 return FALSE;
00342 }
00343
00344 return TRUE;
00345 }
00346
00347 static void
00348 HoistIf_Delete_Def_Use (WN *wn_tree, SYMBOL sym)
00349 {
00350 if (WN_operator(wn_tree) == OPR_LDID) {
00351 SYMBOL currentsym = SYMBOL(wn_tree);
00352 if (currentsym == sym)
00353 return;
00354 DEF_LIST *def_list = Du_Mgr->Ud_Get_Def(wn_tree);
00355 DEF_LIST_ITER iter(def_list);
00356 const DU_NODE *node = iter.First();
00357 Is_True(!iter.Is_Empty(),("Empty def list in HoistIf_Delete_Def_Use"));
00358 for(; !iter.Is_Empty();node=iter.Next()){
00359 WN *def = (WN *) node->Wn();
00360 Du_Mgr->Delete_Def_Use(def,wn_tree);
00361 }
00362 }
00363 for (INT i = 0; i < WN_kid_count(wn_tree); i++)
00364 HoistIf_Delete_Def_Use(WN_kid(wn_tree, i), sym);
00365 }
00366
00367
00368 static void
00369 Replace_Equality_Check(WN* stmt, WN* cmp, WN* cmp_value, WN* innerloop)
00370 {
00371 WN* parent = LWN_Get_Parent(cmp);
00372 WN* lb = LWN_Copy_Tree(WN_kid0(WN_start(innerloop)), TRUE, LNO_Info_Map);
00373 WN* ub = LWN_Copy_Tree(WN_kid1(WN_end(innerloop)), TRUE, LNO_Info_Map);
00374 WN* copy1 = LWN_Copy_Tree(cmp_value, TRUE, LNO_Info_Map);
00375 WN* copy2 = LWN_Copy_Tree(cmp_value, TRUE, LNO_Info_Map);
00376 INT kid;
00377 OPCODE op_cand = OPCODE_make_op(OPR_CAND, Boolean_type, MTYPE_V);
00378 TYPE_ID index_type = WN_rtype(WN_end(innerloop));
00379 OPCODE op_le = OPCODE_make_op(OPR_LE, index_type, index_type);
00380 OPCODE op_ge = OPCODE_make_op(OPR_GE, index_type, index_type);
00381 WN* opnd0;
00382 WN* opnd1;
00383
00384 LWN_Copy_Def_Use(WN_kid0(WN_start(innerloop)), lb, Du_Mgr);
00385 LWN_Copy_Def_Use(WN_kid1(WN_end(innerloop)), ub, Du_Mgr);
00386 LWN_Copy_Def_Use(cmp_value, copy1, Du_Mgr);
00387 LWN_Copy_Def_Use(cmp_value, copy2, Du_Mgr);
00388 LWN_Copy_Linenumber(WN_kid0(WN_start(innerloop)), lb);
00389 LWN_Copy_Linenumber(WN_kid1(WN_end(innerloop)), ub);
00390 LWN_Copy_Linenumber(cmp_value, copy1);
00391 LWN_Copy_Linenumber(cmp_value, copy2);
00392
00393 opnd0 = LWN_CreateExp2(op_le, copy1, ub);
00394 opnd1 = LWN_CreateExp2(op_ge, copy2, lb);
00395
00396 for (kid = 0; kid < WN_kid_count(parent); kid ++)
00397 if (WN_kid(parent, kid) == cmp)
00398 break;
00399
00400 WN_kid(parent, kid) = LWN_CreateExp2(op_cand, opnd0, opnd1);
00401 LWN_Parentize(WN_kid(parent, kid));
00402 LWN_Set_Parent(WN_kid(parent, kid), parent);
00403
00404 return;
00405 }
00406
00407 static void
00408 HoistIf_Replace_Symbol (WN* node, SYMBOL sym, WN* ldid, WN* innerloop)
00409 {
00410 if (WN_operator(node) == OPR_LDID) {
00411 SYMBOL currsym = SYMBOL(node);
00412 if (currsym == sym) {
00413 WN* parent = LWN_Get_Parent(node);
00414 INT kid;
00415 for (kid = 0; kid < WN_kid_count(parent); kid ++)
00416 if (WN_kid(parent, kid) == node)
00417 break;
00418 WN* copy_ldid = LWN_Copy_Tree(ldid, TRUE, LNO_Info_Map);
00419 LWN_Copy_Def_Use(ldid, copy_ldid, Du_Mgr);
00420 LWN_Copy_Linenumber(ldid, copy_ldid);
00421 {
00422 SYMBOL symindex = SYMBOL(WN_index(innerloop));
00423 HoistIf_Delete_Def_Use(WN_kid(parent, kid), symindex);
00424 }
00425 WN_kid(parent, kid) = copy_ldid;
00426 LWN_Set_Parent(copy_ldid, parent);
00427 }
00428 } else if (WN_operator(node) == OPR_BLOCK) {
00429 WN* kid = WN_first(node);
00430
00431 while(kid) {
00432 HoistIf_Replace_Symbol(kid, sym, ldid, innerloop);
00433 kid = WN_next(kid);
00434 }
00435 }
00436
00437 for (INT i = 0; i < WN_kid_count(node); i ++)
00438 HoistIf_Replace_Symbol(WN_kid(node, i), sym, ldid, innerloop);
00439 }
00440
00441 static void
00442 Replace_IV_Ref (WN* stmt, WN* cmp_value, WN* innerloop)
00443 {
00444
00445
00446 HoistIf_Replace_Symbol(stmt, WN_index(innerloop), cmp_value, innerloop);
00447 }
00448
00449 static WN*
00450 Find_Compare_Value (WN* node, WN* innerloop)
00451 {
00452 SYMBOL symindex = SYMBOL (WN_index(innerloop));
00453 WN* opnd0 = WN_kid0(node);
00454 WN* opnd1 = WN_kid1(node);
00455
00456 if (WN_operator(opnd0) == OPR_LDID &&
00457 WN_operator(opnd1) == OPR_LDID) {
00458 SYMBOL sym0(opnd0);
00459 SYMBOL sym1(opnd1);
00460
00461 if (sym0 == symindex)
00462 return opnd1;
00463 else if (sym1 == symindex)
00464 return opnd0;
00465 else
00466 return NULL;
00467 } else if ((WN_operator(opnd0) == OPR_SUB ||
00468 WN_operator(opnd0) == OPR_ADD) &&
00469 WN_operator(opnd1) == OPR_LDID) {
00470 WN* tmp_opnd0 = WN_kid0(opnd0);
00471 WN* tmp_opnd1 = WN_kid1(opnd0);
00472 SYMBOL sym0, sym1;
00473
00474 FmtAssert(WN_operator(tmp_opnd0) == OPR_LDID ||
00475 WN_operator(tmp_opnd1) == OPR_LDID,
00476 ("Find_Compare_Value: Handle this"));
00477 if (WN_operator(tmp_opnd0) == OPR_LDID) {
00478 sym0 = SYMBOL(tmp_opnd0);
00479 if (sym0 == symindex) {
00480 WN* opnd1_tmp = LWN_Copy_Tree(opnd1, TRUE, LNO_Info_Map);
00481 LWN_Copy_Def_Use(opnd1, opnd1_tmp, Du_Mgr);
00482 LWN_Copy_Linenumber(opnd1, opnd1_tmp);
00483 WN* tmp_opnd1_tmp = LWN_Copy_Tree(tmp_opnd1, TRUE, LNO_Info_Map);
00484 LWN_Copy_Def_Use(tmp_opnd1, tmp_opnd1_tmp, Du_Mgr);
00485 LWN_Copy_Linenumber(tmp_opnd1, tmp_opnd1_tmp);
00486 if (WN_operator(opnd0) == OPR_SUB) {
00487 OPCODE op_add =
00488 OPCODE_make_op(OPR_ADD, WN_rtype(opnd0), WN_desc(opnd0));
00489 return LWN_CreateExp2(op_add, opnd1_tmp, tmp_opnd1_tmp);
00490 }
00491 OPCODE op_sub =
00492 OPCODE_make_op(OPR_SUB, WN_rtype(opnd0), WN_desc(opnd0));
00493 return LWN_CreateExp2(op_sub, opnd1_tmp, tmp_opnd1_tmp);
00494 }
00495 }
00496 if (WN_operator(tmp_opnd1) == OPR_LDID) {
00497 sym1 = SYMBOL(tmp_opnd1);
00498 if (sym1 == symindex) {
00499 WN* opnd1_tmp = LWN_Copy_Tree(opnd1, TRUE, LNO_Info_Map);
00500 LWN_Copy_Def_Use(opnd1, opnd1_tmp, Du_Mgr);
00501 LWN_Copy_Linenumber(opnd1, opnd1_tmp);
00502 WN* tmp_opnd0_tmp = LWN_Copy_Tree(tmp_opnd0, TRUE, LNO_Info_Map);
00503 LWN_Copy_Def_Use(tmp_opnd0, tmp_opnd0_tmp, Du_Mgr);
00504 LWN_Copy_Linenumber(tmp_opnd0, tmp_opnd0_tmp);
00505 if (WN_operator(opnd0) == OPR_SUB) {
00506 OPCODE op_add =
00507 OPCODE_make_op(OPR_ADD, WN_rtype(opnd0), WN_desc(opnd0));
00508 return LWN_CreateExp2(op_add, opnd1_tmp, tmp_opnd0_tmp);
00509 }
00510 OPCODE op_sub =
00511 OPCODE_make_op(OPR_SUB, WN_rtype(opnd0), WN_desc(opnd0));
00512 return LWN_CreateExp2(op_sub, opnd1_tmp, tmp_opnd0_tmp);
00513 }
00514 }
00515 } else if ((WN_operator(opnd1) == OPR_SUB ||
00516 WN_operator(opnd1) == OPR_ADD) &&
00517 WN_operator(opnd0) == OPR_LDID) {
00518 WN* tmp_opnd0 = WN_kid0(opnd1);
00519 WN* tmp_opnd1 = WN_kid1(opnd1);
00520 SYMBOL sym0, sym1;
00521
00522 FmtAssert(WN_operator(tmp_opnd0) == OPR_LDID ||
00523 WN_operator(tmp_opnd1) == OPR_LDID,
00524 ("Find_Compare_Value: Handle this"));
00525 if (WN_operator(tmp_opnd0) == OPR_LDID) {
00526 sym0 = SYMBOL(tmp_opnd0);
00527 if (sym0 == symindex) {
00528 WN* opnd0_tmp = LWN_Copy_Tree(opnd0, TRUE, LNO_Info_Map);
00529 LWN_Copy_Def_Use(opnd0, opnd0_tmp, Du_Mgr);
00530 LWN_Copy_Linenumber(opnd0, opnd0_tmp);
00531 WN* tmp_opnd1_tmp = LWN_Copy_Tree(tmp_opnd1, TRUE, LNO_Info_Map);
00532 LWN_Copy_Def_Use(tmp_opnd1, tmp_opnd1_tmp, Du_Mgr);
00533 LWN_Copy_Linenumber(tmp_opnd1, tmp_opnd1_tmp);
00534 if (WN_operator(opnd1) == OPR_SUB) {
00535 OPCODE op_add =
00536 OPCODE_make_op(OPR_ADD, WN_rtype(opnd1), WN_desc(opnd1));
00537 return LWN_CreateExp2(op_add, opnd0_tmp, tmp_opnd1_tmp);
00538 }
00539 OPCODE op_sub =
00540 OPCODE_make_op(OPR_SUB, WN_rtype(opnd1), WN_desc(opnd1));
00541 return LWN_CreateExp2(op_sub, opnd0_tmp, tmp_opnd1_tmp);
00542 }
00543 }
00544 if (WN_operator(tmp_opnd1) == OPR_LDID) {
00545 sym1 = SYMBOL(tmp_opnd1);
00546 if (sym1 == symindex) {
00547 WN* opnd0_tmp = LWN_Copy_Tree(opnd0, TRUE, LNO_Info_Map);
00548 LWN_Copy_Def_Use(opnd0, opnd0_tmp, Du_Mgr);
00549 LWN_Copy_Linenumber(opnd0, opnd0_tmp);
00550 WN* tmp_opnd0_tmp = LWN_Copy_Tree(tmp_opnd0, TRUE, LNO_Info_Map);
00551 LWN_Copy_Def_Use(tmp_opnd0, tmp_opnd0_tmp, Du_Mgr);
00552 LWN_Copy_Linenumber(tmp_opnd0, tmp_opnd0_tmp);
00553 if (WN_operator(opnd1) == OPR_SUB) {
00554 OPCODE op_add =
00555 OPCODE_make_op(OPR_ADD, WN_rtype(opnd1), WN_desc(opnd1));
00556 return LWN_CreateExp2(op_add, opnd0_tmp, tmp_opnd0_tmp);
00557 }
00558 OPCODE op_sub =
00559 OPCODE_make_op(OPR_SUB, WN_rtype(opnd1), WN_desc(opnd1));
00560 return LWN_CreateExp2(op_sub, opnd0_tmp, tmp_opnd0_tmp);
00561 }
00562 }
00563 } else {
00564 if (WN_operator(opnd0) == OPR_LDID) {
00565 SYMBOL sym0 = SYMBOL(opnd0);
00566 if (sym0 == symindex)
00567 return opnd1;
00568 }
00569 if (WN_operator(opnd1) == OPR_LDID) {
00570 SYMBOL sym1 = SYMBOL(opnd1);
00571 if (sym1 == symindex)
00572 return opnd0;
00573 }
00574 }
00575 return NULL;
00576 }
00577
00578 static WN*
00579 Find_Compare_IV_Recurse (WN* cmp, SYMBOL symindex)
00580 {
00581 if (WN_operator(cmp) == OPR_CAND) {
00582 WN* kid0 = Find_Compare_IV_Recurse(WN_kid0(cmp), symindex);
00583
00584 if (kid0)
00585 return kid0;
00586 else
00587 return Find_Compare_IV_Recurse(WN_kid1(cmp), symindex);
00588 } else if (WN_operator(cmp) == OPR_EQ) {
00589 WN* opnd0 = WN_kid0(cmp);
00590 WN* opnd1 = WN_kid1(cmp);
00591
00592 if (WN_operator(opnd0) == OPR_LDID && WN_operator(opnd1) == OPR_LDID) {
00593 SYMBOL sym0 = SYMBOL(opnd0);
00594 SYMBOL sym1 = SYMBOL(opnd1);
00595 if (symindex == sym0 || symindex == sym1)
00596 return cmp;
00597 } else if ((WN_operator(opnd0) == OPR_SUB ||
00598 WN_operator(opnd0) == OPR_ADD) &&
00599 WN_operator(opnd1) == OPR_LDID) {
00600 WN* tmp_opnd0 = WN_kid0(opnd0);
00601 WN* tmp_opnd1 = WN_kid1(opnd0);
00602 SYMBOL sym0, sym1;
00603 BOOL found_index = FALSE;
00604
00605 if (WN_operator(tmp_opnd0) != OPR_LDID &&
00606 WN_operator(tmp_opnd1) != OPR_LDID)
00607 return NULL;
00608 if (WN_operator(tmp_opnd0) == OPR_LDID) {
00609 sym0 = SYMBOL(tmp_opnd0);
00610 if (sym0 == symindex)
00611 found_index = TRUE;
00612 }
00613 if (WN_operator(tmp_opnd1) == OPR_LDID) {
00614 sym1 = SYMBOL(tmp_opnd1);
00615 if (sym1 == symindex)
00616 found_index = TRUE;
00617 }
00618 if (found_index)
00619 return cmp;
00620 } else if ((WN_operator(opnd1) == OPR_SUB ||
00621 WN_operator(opnd1) == OPR_ADD) &&
00622 WN_operator(opnd0) == OPR_LDID) {
00623 WN* tmp_opnd0 = WN_kid0(opnd1);
00624 WN* tmp_opnd1 = WN_kid1(opnd1);
00625 SYMBOL sym0, sym1;
00626 BOOL found_index = FALSE;
00627
00628 if (WN_operator(tmp_opnd0) != OPR_LDID &&
00629 WN_operator(tmp_opnd1) != OPR_LDID)
00630 return NULL;
00631 if (WN_operator(tmp_opnd0) == OPR_LDID) {
00632 sym0 = SYMBOL(tmp_opnd0);
00633 if (sym0 == symindex)
00634 found_index = TRUE;
00635 }
00636 if (WN_operator(tmp_opnd1) == OPR_LDID) {
00637 sym1 = SYMBOL(tmp_opnd1);
00638 if (sym1 == symindex)
00639 found_index = TRUE;
00640 }
00641 if (found_index)
00642 return cmp;
00643 } else {
00644 BOOL found_index = FALSE;
00645 if (WN_operator(opnd0) == OPR_LDID) {
00646 SYMBOL sym0 = SYMBOL(opnd0);
00647 if (sym0 == symindex)
00648 found_index = TRUE;
00649 }
00650 if (WN_operator(opnd1) == OPR_LDID) {
00651 SYMBOL sym1 = SYMBOL(opnd1);
00652 if (sym1 == symindex)
00653 found_index = TRUE;
00654 }
00655 if (found_index)
00656 return cmp;
00657 }
00658 }
00659 return NULL;
00660 }
00661
00662 static WN*
00663 Find_Compare_IV (WN* node, WN* innerloop)
00664 {
00665 SYMBOL symindex = SYMBOL(WN_index(innerloop));
00666
00667 if (WN_operator(node) == OPR_EQ) {
00668 WN* opnd0 = WN_kid0(node);
00669 WN* opnd1 = WN_kid1(node);
00670
00671 if (WN_operator(opnd0) == OPR_LDID && WN_operator(opnd1) == OPR_LDID) {
00672 SYMBOL sym0 = SYMBOL(opnd0);
00673 SYMBOL sym1 = SYMBOL(opnd1);
00674 if (symindex == sym0 || symindex == sym1)
00675 return node;
00676 } else if ((WN_operator(opnd0) == OPR_SUB ||
00677 WN_operator(opnd0) == OPR_ADD) &&
00678 WN_operator(opnd1) == OPR_LDID) {
00679 WN* tmp_opnd0 = WN_kid0(opnd0);
00680 WN* tmp_opnd1 = WN_kid1(opnd0);
00681 SYMBOL sym0, sym1;
00682 BOOL found_index = FALSE;
00683
00684 if (WN_operator(tmp_opnd0) != OPR_LDID &&
00685 WN_operator(tmp_opnd1) != OPR_LDID)
00686 return NULL;
00687 if (WN_operator(tmp_opnd0) == OPR_LDID) {
00688 sym0 = SYMBOL(tmp_opnd0);
00689 if (sym0 == symindex)
00690 found_index = TRUE;
00691 }
00692 if (WN_operator(tmp_opnd1) == OPR_LDID) {
00693 sym1 = SYMBOL(tmp_opnd1);
00694 if (sym1 == symindex)
00695 found_index = TRUE;
00696 }
00697 if (found_index)
00698 return node;
00699 } else if ((WN_operator(opnd1) == OPR_SUB ||
00700 WN_operator(opnd1) == OPR_ADD) &&
00701 WN_operator(opnd0) == OPR_LDID) {
00702 WN* tmp_opnd0 = WN_kid0(opnd1);
00703 WN* tmp_opnd1 = WN_kid1(opnd1);
00704 SYMBOL sym0, sym1;
00705 BOOL found_index = FALSE;
00706
00707 if (WN_operator(tmp_opnd0) != OPR_LDID &&
00708 WN_operator(tmp_opnd1) != OPR_LDID)
00709 return NULL;
00710 if (WN_operator(tmp_opnd0) == OPR_LDID) {
00711 sym0 = SYMBOL(tmp_opnd0);
00712 if (sym0 == symindex)
00713 found_index = TRUE;
00714 }
00715 if (WN_operator(tmp_opnd1) == OPR_LDID) {
00716 sym1 = SYMBOL(tmp_opnd1);
00717 if (sym1 == symindex)
00718 found_index = TRUE;
00719 }
00720 if (found_index)
00721 return node;
00722 } else {
00723 BOOL found_index = FALSE;
00724 if (WN_operator(opnd0) == OPR_LDID) {
00725 SYMBOL sym0 = SYMBOL(opnd0);
00726 if (sym0 == symindex)
00727 found_index = TRUE;
00728 }
00729 if (WN_operator(opnd1) == OPR_LDID) {
00730 SYMBOL sym1 = SYMBOL(opnd1);
00731 if (sym1 == symindex)
00732 found_index = TRUE;
00733 }
00734 if (found_index)
00735 return node;
00736 }
00737 } else {
00738 FmtAssert(WN_operator(node) == OPR_CAND,
00739 ("LNO_HoistIf: Invalid node passed to Find_Compare_IV"));
00740 return Find_Compare_IV_Recurse(node, symindex);
00741 }
00742 }
00743
00744 static void
00745 HoistIf_Optimize (WN* stmt, STACK_OF_WN *hoistifed_stmts, WN* innerloop)
00746 {
00747 WN* tmp;
00748 WN* stmt_tmp1;
00749 WN* stmt_tmp2;
00750 WN* cmp;
00751 WN* cmp_value;
00752
00753 tmp = LWN_Copy_Tree(stmt, TRUE, LNO_Info_Map);
00754 LWN_Copy_Linenumber(stmt, tmp);
00755 {
00756 SYMBOL sym = SYMBOL(WN_index(innerloop));
00757 HoistIf_Copy_Def_Use(stmt, tmp, sym, innerloop);
00758 }
00759 LWN_Parentize(tmp);
00760
00761 FmtAssert(WN_operator(tmp) == OPR_IF,
00762 ("LNO_HoistIf: Invalid statement passed to HoistIf_Optimize"));
00763
00764
00765
00766 FmtAssert(WN_operator(WN_kid0(tmp)) == OPR_CAND ||
00767 WN_operator(WN_kid0(tmp)) == OPR_EQ,
00768 ("LNO_HoistIf: Invalid condition passed to HoistIf_Optimize"));
00769
00770
00771
00772
00773 cmp = Find_Compare_IV(WN_kid0(tmp), innerloop);
00774 FmtAssert(WN_operator(cmp) == OPR_EQ,
00775 ("LNO_FLOW: Invalid condition passed to HoistIf_Optimize"));
00776 cmp_value = Find_Compare_Value(cmp, innerloop);
00777
00778
00779
00780 Replace_Equality_Check(tmp, cmp, cmp_value, innerloop);
00781
00782
00783
00784 Replace_IV_Ref(tmp, cmp_value, innerloop);
00785
00786 {
00787
00788 SYMBOL sym = SYMBOL(WN_index(innerloop));
00789 if (WN_operator(cmp_value) != OPR_LDID &&
00790 cmp_value != WN_kid0(cmp) && cmp_value != WN_kid1(cmp)) {
00791
00792
00793 HoistIf_Delete_Def_Use(cmp_value, sym);
00794 LWN_Delete_Tree(cmp_value);
00795 }
00796 HoistIf_Delete_Def_Use(cmp, sym);
00797 LWN_Delete_Tree(cmp);
00798 }
00799
00800 LWN_Copy_Linenumber(innerloop, tmp);
00801
00802 hoistifed_stmts->Push(tmp);
00803
00804 return;
00805 }
00806
00807
00808 static INT
00809 HoistIf (WN* innerloop)
00810 {
00811 if (
00812 Do_Loop_Has_Calls(innerloop) || Do_Loop_Has_Gotos(innerloop)) {
00813 if (debug_hoistif) {
00814 printf("(%s:%d) ",
00815 Src_File_Name,
00816 Srcpos_To_Line(WN_Get_Linenum(innerloop)));
00817 printf("Loop has calls or Gotos. Not suitable for hoistif opt.\n");
00818 }
00819 Is_True(0, ("Bad loop passed to HoistIf().\n"));
00820 return 0;
00821 }
00822 if (!Do_Loop_Is_Inner(innerloop)) {
00823 if (debug_hoistif) {
00824 printf("(%s:%d) ",
00825 Src_File_Name,
00826 Srcpos_To_Line(WN_Get_Linenum(innerloop)));
00827 printf("Loop is not innermost. Loop was not vectorized.\n");
00828 }
00829 Is_True(0, ("Non-innermost loop passed to HoistIf().\n"));
00830 return 0;
00831 }
00832
00833 Upper_Bound_Standardize(WN_end(innerloop), TRUE);
00834
00835
00836
00837 if (Index_Variable_Live_At_Exit(innerloop)) {
00838
00839 if (Upper_Bound_Standardize(WN_end(innerloop),TRUE)==FALSE) {
00840 if (debug_hoistif) {
00841 printf("(%s:%d) ",
00842 Src_File_Name,
00843 Srcpos_To_Line(WN_Get_Linenum(innerloop)));
00844 printf("Loop upper bound can not be std. ");
00845 printf("Loop is not hoist if optimized.\n");
00846 }
00847 return 0;
00848 }
00849 Finalize_Index_Variable(innerloop,FALSE);
00850 scalar_rename(WN_start(innerloop));
00851 }
00852
00853 WN* stmt;
00854 UINT stmt_count=0;
00855 WN* body=WN_do_body(innerloop);
00856
00857 for (stmt = WN_first(body); stmt; stmt = WN_next(stmt)) {
00858 if (!Is_HoistIf_Amenable(stmt, innerloop)) {
00859 if (debug_hoistif) {
00860 printf("(%s:%d) ",
00861 Src_File_Name,
00862 Srcpos_To_Line(WN_Get_Linenum(innerloop)));
00863 printf("Loop is not amenable to hoistif optimization.\n");
00864 }
00865 return 0;
00866 }
00867 stmt_count ++;
00868 if (stmt_count > LNO_HoistIf_Threshold) {
00869 if (debug_hoistif) {
00870 printf("(%s:%d) ",
00871 Src_File_Name,
00872 Srcpos_To_Line(WN_Get_Linenum(innerloop)));
00873 printf("Loop has too many stmts for Hoist If opt.\n");
00874 }
00875 return 0;
00876 }
00877 }
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890 STACK_OF_WN *hoistif_stmts =
00891 CXX_NEW(STACK_OF_WN(&HoistIf_default_pool),
00892 &HoistIf_default_pool);
00893 for (stmt = WN_first(body); stmt; stmt = WN_next(stmt)) {
00894 HoistIf_Optimize (stmt, hoistif_stmts, innerloop);
00895 }
00896
00897
00898 if (hoistif_stmts->Elements() == 0) {
00899 if (debug_hoistif) {
00900 printf("(%s:%d) ",
00901 Src_File_Name,
00902 Srcpos_To_Line(WN_Get_Linenum(innerloop)));
00903 printf("Loop has no Hoist If opt stmt.\n");
00904 }
00905 return 0;
00906 }
00907 for (INT i=hoistif_stmts->Elements()-1; i >= 0; i--) {
00908 WN* stmt = hoistif_stmts->Top_nth(i);
00909
00910 LWN_Insert_Block_Before(LWN_Get_Parent(innerloop),
00911 innerloop, stmt);
00912 LWN_Parentize(stmt);
00913 LWN_Set_Parent(stmt, LWN_Get_Parent(innerloop));
00914 }
00915 if (debug_hoistif) {
00916 printf("(%s:%d) ",
00917 Src_File_Name,
00918 Srcpos_To_Line(WN_Get_Linenum(innerloop)));
00919 printf("Hoist If succeeded on loop.\n");
00920 }
00921 return 1;
00922 }
00923
00924 static void HoistIf_Walk(WN* wn) {
00925 OPCODE opc=WN_opcode(wn);
00926
00927 if (!OPCODE_is_scf(opc))
00928 return;
00929 else if (opc==OPC_DO_LOOP) {
00930 if (
00931 Do_Loop_Is_Inner(wn) && !Do_Loop_Has_Calls(wn)
00932 && !Do_Loop_Is_Mp(wn) && !Do_Loop_Has_Gotos(wn)) {
00933 if (HoistIf(wn)) {
00934 WN* parent_loop = LWN_Get_Parent(wn);
00935 if (WN_opcode(parent_loop) == OPC_BLOCK)
00936 parent_loop = LWN_Get_Parent(parent_loop);
00937 if (WN_opcode(parent_loop) == OPC_DO_LOOP) {
00938
00939 BOOL parent_has_another_inner_loop = FALSE;
00940 for (WN* tmp = WN_first(WN_do_body(parent_loop));
00941 tmp; tmp = WN_next(tmp)) {
00942 if (WN_opcode(tmp) == OPC_DO_LOOP && tmp != wn) {
00943 parent_has_another_inner_loop = TRUE;
00944 break;
00945 }
00946 }
00947 if (!parent_has_another_inner_loop) {
00948 DO_LOOP_INFO* dli = Get_Do_Loop_Info(parent_loop);
00949 dli->Is_Inner = TRUE;
00950 }
00951 }
00952 LWN_Delete_Tree(wn);
00953 }
00954 } else
00955 HoistIf_Walk(WN_do_body(wn));
00956 } else if (opc==OPC_BLOCK)
00957 for (WN* stmt=WN_first(wn); stmt;) {
00958 WN* next_stmt=WN_next(stmt);
00959 HoistIf_Walk(stmt);
00960 stmt=next_stmt;
00961 }
00962 else
00963 for (UINT kidno=0; kidno<WN_kid_count(wn); kidno++) {
00964 HoistIf_Walk(WN_kid(wn,kidno));
00965 }
00966 }
00967
00968 void HoistIf_Phase(WN* func_nd) {
00969
00970 MEM_POOL_Initialize(&HoistIf_default_pool,"HoistIf_default_pool",FALSE);
00971 MEM_POOL_Push(&HoistIf_default_pool);
00972
00973 debug_hoistif = Get_Trace(TP_LNOPT, TT_LNO_DEBUG_HOISTIF);
00974 if (debug_hoistif) {
00975 fprintf(TFile, "=======================================================================\n");
00976 fprintf(TFile, "LNO: \"WHIRL tree before hoist if phase\"\n");
00977 fdump_tree (TFile, func_nd);
00978 }
00979 HoistIf_Walk(func_nd);
00980 if (debug_hoistif) {
00981 fprintf(TFile, "=======================================================================\n");
00982 fprintf(TFile, "LNO: \"WHIRL tree after hoist if phase\"\n");
00983 fdump_tree (TFile, func_nd);
00984 }
00985
00986 MEM_POOL_Pop(&HoistIf_default_pool);
00987 MEM_POOL_Delete(&HoistIf_default_pool);
00988
00989 }