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 #ifdef USE_PCH
00041 #include "lno_pch.h"
00042 #endif // USE_PCH
00043 #pragma hdrstop
00044
00045 #include <sys/types.h>
00046 #include <assert.h>
00047 #include <stdio.h>
00048 #include "wn.h"
00049 #include "cxx_memory.h"
00050 #include "cxx_queue.h"
00051 #include "if_info.h"
00052 #include "lnopt_main.h"
00053 #include "lwn_util.h"
00054 #include "lnoutils.h"
00055 #include "access_vector.h"
00056 #include "lego_util.h"
00057 #include "soe.h"
00058 #include "wn_simp.h"
00059 #include "opt_du.h"
00060 #include "array_bounds.h"
00061 #include "access_main.h"
00062 #include "shackle.h"
00063 #include "shackle_ifs.h"
00064 #include "prompf.h"
00065 #include "anl_driver.h"
00066
00067 #pragma weak New_Construct_Id
00068
00069 static INT32 shackle_if_debug_level;
00070 static QUEUE<INT32>
00071 *Prompf_Elimination_Queue;
00072 extern MEM_POOL LNO_default_pool;
00073 extern MEM_POOL LNO_local_pool;
00074 static MEM_POOL* shackle_if_pool;
00075 extern MEM_POOL shackle_map_pool;
00076 extern WN_MAP shackle_prompf_id_map;
00077 static WN_MAP shackle_if_copy_map1;
00078 static WN_MAP shackle_if_if_map;
00079 static BOOL hoist_mins_from_loop_bounds = TRUE;
00080 static INT32 shackle_debug_exec_count;
00081 static BOOL Has_Sibling_In_Block(WN *);
00082 static WN* Shackle_Unseen_Highest_Enclosing_If(WN *stmt);
00083 static void Maybe_Handle_Sink_Promotion_Case (WN *,
00084 WN *,
00085 INT32,
00086 ACCESS_VECTOR *);
00087 static void Deferred_Shackle_Prompf_Eliminate(INT32);
00088
00089 #define SHACKLE_IF_HAS_BEEN_SEEN 1
00090 #define SHACKLE_IF_YET_UNSEEN 0
00091
00092 #define Shackle_If_Seen(wn) \
00093 (WN_MAP32_Get (shackle_if_if_map, (wn)) == SHACKLE_IF_HAS_BEEN_SEEN)
00094 #define Shackle_If_Unseen(wn) \
00095 (WN_MAP32_Get (shackle_if_if_map, (wn)) == SHACKLE_IF_YET_UNSEEN)
00096 #define Shackle_If_Seen_Set(wn) \
00097 (WN_MAP32_Set (shackle_if_if_map, (wn), SHACKLE_IF_HAS_BEEN_SEEN))
00098 #define Shackle_If_Unseen_Set(wn) \
00099 (WN_MAP32_Set (shackle_if_if_map, (wn), SHACKLE_IF_YET_UNSEEN))
00100
00101
00102 static void
00103 Delete_Shackle_Prompf_Info(WN *wn)
00104 {
00105 if (Prompf_Info != NULL && Prompf_Info->Is_Enabled()) {
00106 INT32 map_id = WN_MAP32_Get (Prompf_Id_Map, wn);
00107 if (0 != map_id)
00108 Deferred_Shackle_Prompf_Eliminate (map_id);
00109 FOR_CHILDREN (wn, child, ignCount) {
00110 Delete_Shackle_Prompf_Info (child);
00111 }
00112 END_CHILDREN;
00113 }
00114 }
00115
00116 static void
00117 Shackle_LWN_Delete_Tree (WN *wn)
00118 {
00119 Delete_Shackle_Prompf_Info(wn);
00120 PROMPF_INFO *old_prompf_info = Prompf_Info;
00121 Prompf_Info = NULL;
00122 LWN_Delete_Tree (wn);
00123 Prompf_Info = old_prompf_info;
00124 }
00125
00126 extern void sm(WN* wn)
00127 {
00128 INT32 id = WN_MAP32_Get(shackle_prompf_id_map, wn);
00129 fprintf(stdout, "0x%p %d\n", wn, id);
00130 }
00131
00132 static void
00133 Shackle_Copy_Prompf_Id_Map_Info (WN *old_wn, WN *new_wn)
00134 {
00135 if (Prompf_Info != NULL && Prompf_Info->Is_Enabled()) {
00136 FmtAssert (WN_opcode (old_wn) == WN_opcode (new_wn),
00137 ("Can only be called on identical whirl trees!"));
00138 INT32 old_id = WN_MAP32_Get (Prompf_Id_Map, old_wn);
00139 INT32 base_id = WN_MAP32_Get (shackle_prompf_id_map, old_wn);
00140 if (0 != old_id) {
00141 INT32 new_id = WN_MAP32_Get (Prompf_Id_Map, new_wn);
00142 WN_MAP32_Set (shackle_prompf_id_map, new_wn, base_id);
00143 Prompf_Info->Inner_Shackle (base_id, new_id);
00144 }
00145 if (OPC_BLOCK == WN_opcode (old_wn)) {
00146 WN *wn2 = WN_first (new_wn);
00147 for (WN *wn1 = WN_first (old_wn); NULL != wn1;
00148 wn1 = WN_next (wn1)) {
00149 Shackle_Copy_Prompf_Id_Map_Info (wn1, wn2);
00150 wn2 = WN_next (wn2);
00151 }
00152 }
00153 else
00154 for (INT i = 0; i < WN_kid_count (old_wn); i++)
00155 Shackle_Copy_Prompf_Id_Map_Info (WN_kid (old_wn, i),
00156 WN_kid (new_wn, i));
00157 }
00158 }
00159
00160 static void
00161 Copy_Shackle_Prompf_Info (WN *old_wn, WN *new_wn)
00162 {
00163 STACK<WN *> st_old (shackle_if_pool);
00164 STACK<WN *> st_new (shackle_if_pool);
00165 if (Prompf_Info != NULL && Prompf_Info->Is_Enabled()) {
00166 Prompf_Assign_Ids (old_wn, new_wn, &st_old, &st_new, FALSE);
00167 Shackle_Copy_Prompf_Id_Map_Info (old_wn, new_wn);
00168 }
00169 }
00170
00171 static void
00172 Recursively_Add_Bound_Lin_Symbols(QUEUE<ST *> *lin_sym_q,
00173 WN *do_loop)
00174 {
00175 if (!do_loop)
00176 return;
00177 if (OPC_DO_LOOP == WN_opcode (do_loop)) {
00178 DO_LOOP_INFO *dli = Get_Do_Loop_Info (do_loop);
00179 ACCESS_ARRAY *lb, *ub;
00180 lb = dli->LB;
00181 ub = dli->UB;
00182 ACCESS_VECTOR *ar;
00183 INT32 index;
00184
00185 INT32 i;
00186 for (i = 0; i < lb->Num_Vec(); i++) {
00187 ar = lb->Dim(i);
00188 if (NULL != ar->Lin_Symb) {
00189 INTSYMB_CONST_ITER iter(ar->Lin_Symb);
00190 for (const INTSYMB_NODE *node = iter.First();
00191 !iter.Is_Empty();
00192 node = iter.Next()) {
00193 if (0 == node->Coeff)
00194 DevWarn("Access vector has zero coeff. linear symbol");
00195 else {
00196 index = lin_sym_q->Index (node->Symbol.St());
00197 if (-1 == index)
00198 lin_sym_q->Add_Tail_Q (node->Symbol.St());
00199 }
00200 }
00201 }
00202 }
00203 for (i = 0; i < ub->Num_Vec(); i++) {
00204 ar = ub->Dim(i);
00205 if (NULL != ar->Lin_Symb) {
00206 INTSYMB_CONST_ITER iter(ar->Lin_Symb);
00207 for (const INTSYMB_NODE *node = iter.First();
00208 !iter.Is_Empty();
00209 node = iter.Next()) {
00210 if (0 == node->Coeff)
00211 DevWarn("Access vector has zero coeff. linear symbol");
00212 else {
00213 index = lin_sym_q->Index (node->Symbol.St());
00214 if (-1 == index)
00215 lin_sym_q->Add_Tail_Q (node->Symbol.St());
00216 }
00217 }
00218 }
00219 }
00220 }
00221 Recursively_Add_Bound_Lin_Symbols(lin_sym_q,
00222 LWN_Get_Parent (do_loop));
00223 }
00224
00225 static void
00226 Recursively_Add_Parent_If_Lin_Symbols (QUEUE<ST *> *lin_sym_q,
00227 WN *wn)
00228 {
00229 if (!wn)
00230 return;
00231 if (OPC_IF == WN_opcode (wn)) {
00232 IF_INFO *ii = (IF_INFO *) WN_MAP_Get (LNO_Info_Map, wn);
00233 ACCESS_ARRAY *ar = ii->Condition;
00234 ACCESS_VECTOR *v;
00235 for (INT32 i = 0; i < ar->Num_Vec(); i++) {
00236 v = ar->Dim (i);
00237 if (NULL != v->Lin_Symb) {
00238 INTSYMB_CONST_ITER iter (v->Lin_Symb);
00239 for (const INTSYMB_NODE *node = iter.First();
00240 !iter.Is_Empty(); node = iter.Next()) {
00241 INT32 index = lin_sym_q->Index (node->Symbol.St());
00242 if (-1 == index)
00243 lin_sym_q->Add_Tail_Q (node->Symbol.St());
00244 }
00245 }
00246 }
00247 }
00248 Recursively_Add_Parent_If_Lin_Symbols (lin_sym_q,
00249 LWN_Get_Parent (wn));
00250 }
00251
00252 static void
00253 Add_Parent_If_Constraints(WN *wn,
00254 SYSTEM_OF_EQUATIONS *soe,
00255 INT32 size_loop,
00256 INT32 size_sym,
00257 QUEUE<ST *> *lin_sym_q)
00258 {
00259 INT32 size = size_loop + size_sym, index, i, j;
00260 if (!wn)
00261 return;
00262 if (OPC_IF == WN_opcode (wn)) {
00263 IF_INFO *ii = (IF_INFO *) WN_MAP_Get (LNO_Info_Map, wn);
00264 ACCESS_ARRAY *ar = ii->Condition;
00265 mINT32 *row = CXX_NEW_ARRAY (mINT32, size, shackle_if_pool);
00266 for (i = 0; i < ar->Num_Vec(); i++) {
00267 ACCESS_VECTOR *v = ar->Dim (i);
00268 if (NULL == v->Non_Lin_Symb) {
00269 for (j = 0; j < size_loop; j++)
00270 row[j] = v->Loop_Coeff (j);
00271 for (j = size_loop; j < size; j++)
00272 row[j] = 0;
00273 if (NULL != v->Lin_Symb) {
00274 INTSYMB_CONST_ITER iter (v->Lin_Symb);
00275 for (const INTSYMB_NODE *node = iter.First();
00276 !iter.Is_Empty(); node = iter.Next()) {
00277 INT32 index = lin_sym_q->Index (node->Symbol.St());
00278 FmtAssert (0 <= index && index < size,
00279 ("Invalid value for index"));
00280 row[size_loop+index] = node->Coeff;
00281 }
00282 }
00283 soe->Add_Le (row, v->Const_Offset);
00284 }
00285 }
00286 }
00287 Add_Parent_If_Constraints (LWN_Get_Parent (wn), soe,
00288 size_loop, size_sym, lin_sym_q);
00289 }
00290
00291 static void
00292 Add_Parent_Loop_Constraints(WN *wn,
00293 SYSTEM_OF_EQUATIONS *soe,
00294 INT32 size_loop,
00295 INT32 size_sym,
00296 QUEUE<ST*> *lin_sym_q)
00297 {
00298 INT32 size = size_loop + size_sym, index;
00299
00300 if (!wn)
00301 return;
00302 if (OPC_DO_LOOP == WN_opcode (wn)) {
00303 DO_LOOP_INFO *dli = Get_Do_Loop_Info (wn);
00304 ACCESS_ARRAY *lb, *ub;
00305 ACCESS_VECTOR *ar;
00306 lb = dli->LB;
00307 ub = dli->UB;
00308 INT32 i, j;
00309 mINT32 *row = CXX_NEW_ARRAY (mINT32, size, shackle_if_pool);
00310 for (i = 0; i < size; i++)
00311 row[i] = 0;
00312 for (j = 0; j < lb->Num_Vec(); j++) {
00313 ar = lb->Dim(j);
00314 for (i = 0; i < ar->Nest_Depth(); i++)
00315 row[i] = ar->Loop_Coeff (i);
00316 if (NULL != ar->Lin_Symb) {
00317 INTSYMB_CONST_ITER iter(ar->Lin_Symb);
00318 for (const INTSYMB_NODE *node = iter.First();
00319 !iter.Is_Empty();
00320 node = iter.Next()) {
00321 if (0 == node->Coeff)
00322 DevWarn("Access vector has zero coeff linear symbol");
00323 else {
00324 index = lin_sym_q->Index (node->Symbol.St());
00325 assert ((0 <= index) && (index < size_sym));
00326 row[size_loop+index] = node->Coeff;
00327 }
00328 }
00329 }
00330 soe->Add_Le (row, ar->Const_Offset);
00331 }
00332 for (j = 0; j < ub->Num_Vec(); j++) {
00333 ar = ub->Dim(j);
00334 for (i = 0; i < ar->Nest_Depth(); i++)
00335 row[i] = ar->Loop_Coeff (i);
00336 if (NULL != ar->Lin_Symb) {
00337 INTSYMB_CONST_ITER iter(ar->Lin_Symb);
00338 for (const INTSYMB_NODE *node = iter.First();
00339 !iter.Is_Empty();
00340 node = iter.Next()) {
00341 if (0 == node->Coeff)
00342 DevWarn("Access vector has zero coeff. linear symbol");
00343 else {
00344 index = lin_sym_q->Index (node->Symbol.St());
00345 assert ((0 <= index) && (index < size_sym));
00346 row[size_loop+index] = node->Coeff;
00347 }
00348 }
00349 }
00350 soe->Add_Le (row, ar->Const_Offset);
00351 }
00352 }
00353 Add_Parent_Loop_Constraints (LWN_Get_Parent (wn),
00354 soe, size_loop, size_sym,
00355 lin_sym_q);
00356 }
00357
00358 static void
00359 Recursively_Add_Array_Lin_Symbols(QUEUE<ST *> *lin_sym_q,
00360 WN *wn)
00361 {
00362 if (OPR_ARRAY == WN_operator (wn)) {
00363 ACCESS_ARRAY *ar = (ACCESS_ARRAY *) WN_MAP_Get (LNO_Info_Map, wn);
00364 ACCESS_VECTOR *av;
00365 INT32 index;
00366
00367 for (INT32 i = 0; i < ar->Num_Vec(); i++) {
00368 av = ar->Dim (i);
00369 if (NULL != av->Lin_Symb) {
00370 INTSYMB_CONST_ITER iter (av->Lin_Symb);
00371 for (const INTSYMB_NODE *node = iter.First();
00372 !iter.Is_Empty(); node = iter.Next()) {
00373 index = lin_sym_q->Index (node->Symbol.St());
00374 if (-1 == index)
00375 lin_sym_q->Add_Tail_Q (node->Symbol.St());
00376 }
00377 }
00378 }
00379 }
00380 else {
00381 FOR_CHILDREN (wn, child, ignCount) {
00382 Recursively_Add_Array_Lin_Symbols (lin_sym_q, child);
00383 }
00384 END_CHILDREN;
00385 }
00386 }
00387
00388 static void
00389 Simplify_Cond_With_Div_Floor(WN *inp)
00390 {
00391 LWN_Parentize (inp);
00392 OPERATOR opr = WN_operator (inp);
00393 if ((OPR_GT != opr) && (OPR_LT != opr) && (OPR_LE != opr) &&
00394 (OPR_GE != opr))
00395 return;
00396 WN *kid0 = WN_kid0 (inp);
00397 WN *kid1 = WN_kid1 (inp);
00398 INT64 const_val;
00399 WN *d1, *d2;
00400 WN *kid00, *kid01;
00401 TYPE_ID rtype, index_type;
00402 if (OPR_INTCONST != WN_operator (kid1))
00403 return;
00404 if (OPR_INTRINSIC_OP != WN_operator (kid0))
00405 return;
00406 INTRINSIC intrinsic;
00407 intrinsic = (INTRINSIC) WN_intrinsic (kid0);
00408 switch (intrinsic) {
00409 case INTRN_I4DIVFLOOR:
00410 case INTRN_I8DIVFLOOR:
00411 case INTRN_U4DIVFLOOR:
00412 case INTRN_U8DIVFLOOR:
00413 kid00 = WN_kid0 (kid0);
00414 kid01 = WN_kid1 (kid0);
00415 assert (OPR_PARM == WN_operator (kid00));
00416 assert (OPR_PARM == WN_operator (kid01));
00417 kid00 = WN_kid0 (kid00);
00418 kid01 = WN_kid0 (kid01);
00419 if (OPR_INTCONST != WN_operator (kid01))
00420 return;
00421 if (WN_const_val (kid1) < 0)
00422 return;
00423 const_val = WN_const_val (kid1) * WN_const_val (kid01);
00424 if (OPR_GT == opr)
00425 const_val += WN_const_val (kid01);
00426 if (OPR_LE == opr)
00427 const_val += WN_const_val (kid01) - 1;
00428 WN_const_val (kid1) = const_val;
00429 rtype = WN_rtype (kid00);
00430 d1 = WN_CreateIntconst (OPCODE_make_op (OPR_INTCONST,
00431 rtype, MTYPE_V),
00432 (INT64) 0);
00433 Replace_WN (kid00, d1);
00434 Replace_WN (kid0, kid00);
00435 Shackle_LWN_Delete_Tree (kid0);
00436 return;
00437 default:
00438 return;
00439 }
00440 }
00441
00442 static void
00443 Simplify_Coeff_Access_Vector (ACCESS_VECTOR *ar)
00444 {
00445 if (ar->Const_Offset != 0)
00446 return;
00447 if (NULL != ar->Lin_Symb)
00448 return;
00449 if (NULL != ar->Non_Lin_Symb)
00450 return;
00451 INT32 i, val, current = 0;
00452 for (i = 0; i < ar->Nest_Depth(); i++) {
00453 val = ar->Loop_Coeff (i);
00454 if (val < 0)
00455 val = -val;
00456 if (0 == current)
00457 current = val;
00458 else if ((val > 0) && (current != val))
00459 return;
00460 }
00461 for (i = 0; i < ar->Nest_Depth(); i++) {
00462 val = ar->Loop_Coeff (i) / current;
00463 ar->Set_Loop_Coeff (i, val);
00464 }
00465 }
00466
00467 static BOOL
00468 Is_Exp_Divided_By_Const(WN *wn, INT64 const_val)
00469 {
00470 BOOL is_lhs = FALSE, is_rhs = FALSE;
00471
00472 OPERATOR opr = WN_operator (wn);
00473 switch (opr) {
00474 case OPR_NEG:
00475 return Is_Exp_Divided_By_Const (WN_kid0 (wn), const_val);
00476 case OPR_ADD:
00477 is_lhs = Is_Exp_Divided_By_Const (WN_kid0 (wn), const_val);
00478 is_rhs = Is_Exp_Divided_By_Const (WN_kid1 (wn), const_val);
00479 return (is_lhs && is_rhs);
00480 case OPR_MPY:
00481 is_lhs = Is_Exp_Divided_By_Const (WN_kid0 (wn), const_val);
00482 is_rhs = Is_Exp_Divided_By_Const (WN_kid1 (wn), const_val);
00483 return (is_lhs || is_rhs);
00484 case OPR_INTCONST:
00485 return (((WN_const_val(wn) / const_val) * const_val) ==
00486 WN_const_val (wn));
00487 default:
00488 return FALSE;
00489 }
00490 }
00491
00492 static BOOL
00493 Divide_Exp_By_Const (WN *wn, INT64 const_val)
00494 {
00495 BOOL is_lhs = FALSE, is_rhs = FALSE;
00496
00497
00498 OPERATOR opr = WN_operator (wn);
00499 switch (opr) {
00500 case OPR_NEG:
00501 assert (TRUE == Divide_Exp_By_Const (WN_kid0 (wn), const_val));
00502 return TRUE;
00503 case OPR_ADD:
00504 is_lhs = Divide_Exp_By_Const (WN_kid0 (wn), const_val);
00505 assert (is_lhs);
00506 is_rhs = Divide_Exp_By_Const (WN_kid1 (wn), const_val);
00507 assert (is_rhs);
00508 return TRUE;
00509 case OPR_MPY:
00510 is_lhs = Divide_Exp_By_Const (WN_kid0 (wn), const_val);
00511 if (!is_lhs) {
00512 is_rhs = Divide_Exp_By_Const (WN_kid1 (wn), const_val);
00513 assert (is_rhs);
00514 return TRUE;
00515 }
00516 case OPR_INTCONST:
00517 if (((WN_const_val(wn) / const_val) * const_val) ==
00518 WN_const_val (wn)) {
00519 WN_const_val (wn) = WN_const_val (wn) / const_val;
00520 return TRUE;
00521 } else {
00522 return FALSE;
00523 }
00524 default:
00525 return FALSE;
00526 }
00527 }
00528
00529 static WN*
00530 Remove_Consts_From_Conditionals(WN *wn)
00531 {
00532
00533
00534 OPERATOR opr = WN_operator (wn);
00535 if ((OPR_GT != opr) && (OPR_LT != opr) && (OPR_GE != opr) &&
00536 (OPR_LE != opr))
00537 return wn;
00538 assert ((OPR_GT == opr) || (OPR_LT == opr) || (OPR_LE == opr)
00539 || (OPR_GE == opr));
00540 INT64 lhs_a = -1, rhs_a = -1;
00541 INT64 lhs_b = -1, rhs_c = -1;
00542 WN *lhs = WN_kid0 (wn);
00543 WN *rhs = WN_kid1 (wn);
00544 WN *rlhs, *llhs, *rllhs, *rrhs, *rlrhs, *lrhs;
00545
00546 if (OPR_ADD == WN_operator (lhs)) {
00547 rlhs = WN_kid1 (lhs);
00548 llhs = WN_kid0 (lhs);
00549 if (OPR_INTCONST == WN_operator (rlhs))
00550 lhs_b = WN_const_val (rlhs);
00551 if (OPR_MPY == WN_operator (llhs)) {
00552 rllhs = WN_kid1 (llhs);
00553 if (OPR_INTCONST == WN_operator (rllhs))
00554 lhs_a = WN_const_val (rllhs);
00555 }
00556 } else if (OPR_MPY == WN_operator (lhs)) {
00557 rlhs = WN_kid1 (lhs);
00558 if (OPR_INTCONST == WN_operator (rlhs)) {
00559 lhs_a = WN_const_val (rlhs);
00560 lhs_b = 0;
00561 }
00562 }
00563 if (OPR_ADD == WN_operator (rhs)) {
00564 rrhs = WN_kid1 (rhs);
00565 lrhs = WN_kid0 (rhs);
00566 if (OPR_INTCONST == WN_operator (rrhs))
00567 rhs_c = WN_const_val (rrhs);
00568 if (OPR_MPY == WN_operator (lrhs)) {
00569 rlrhs = WN_kid1 (lrhs);
00570 if (OPR_INTCONST == WN_operator (rlrhs))
00571 rhs_a = WN_const_val (rlrhs);
00572 }
00573 } else if (OPR_MPY == WN_operator (rhs)) {
00574 rrhs = WN_kid1 (rhs);
00575 if (OPR_INTCONST == WN_operator (rrhs)) {
00576 rhs_a = WN_const_val (rrhs);
00577 rhs_c = 0;
00578 }
00579 }
00580 if ((-1 != lhs_a) && (-1 != rhs_a) && (lhs_a == rhs_a) &&
00581 (0 <= lhs_b) && (lhs_b < lhs_a) && (0 <= rhs_c) &&
00582 (rhs_c < rhs_a)) {
00583 if (0 == lhs_b)
00584 WN_const_val (rlhs) = 1;
00585 else {
00586 WN_const_val (rlhs) = 0;
00587 WN_const_val (rllhs) = 1;
00588 }
00589 if (0 == rhs_c)
00590 WN_const_val (rrhs) = 1;
00591 else {
00592 WN_const_val (rrhs) = 0;
00593 WN_const_val (rlrhs) = 1;
00594 }
00595 return WN_Simplify_Tree (wn);
00596 } else
00597 return wn;
00598 }
00599
00600 static WN *
00601 Remove_Floor_From_One_Sided_Cond(WN *wn)
00602 {
00603 LWN_Parentize (wn);
00604 OPERATOR opr = WN_operator (wn);
00605 if (OPR_LT != opr && OPR_GT != opr && OPR_LE != opr && OPR_GE != opr)
00606 return wn;
00607 WN *kid0 = WN_kid0 (wn);
00608 WN *kid1 = WN_kid1 (wn);
00609 mBOOL kid0_is_floor = FALSE, kid1_is_floor = FALSE;
00610 if (OPR_INTRINSIC_OP == WN_operator (kid0) &&
00611 (INTRN_I4DIVFLOOR == WN_intrinsic (kid0) ||
00612 INTRN_I8DIVFLOOR == WN_intrinsic (kid0) ||
00613 INTRN_U4DIVFLOOR == WN_intrinsic (kid0) ||
00614 INTRN_U8DIVFLOOR == WN_intrinsic (kid0)))
00615 kid0_is_floor = TRUE;
00616 if (OPR_INTRINSIC_OP == WN_operator (kid1) &&
00617 (INTRN_I4DIVFLOOR == WN_intrinsic (kid1) ||
00618 INTRN_I8DIVFLOOR == WN_intrinsic (kid1) ||
00619 INTRN_U4DIVFLOOR == WN_intrinsic (kid1) ||
00620 INTRN_U8DIVFLOOR == WN_intrinsic (kid1)))
00621 kid1_is_floor = TRUE;
00622 if (kid0_is_floor && kid1_is_floor)
00623 return wn;
00624 if (!kid0_is_floor && !kid1_is_floor)
00625 return wn;
00626 OPERATOR rev_opr;
00627 WN *result;
00628 TYPE_ID rtype = WN_rtype (wn);
00629 TYPE_ID index_type = Promote_Type (WN_desc (wn));
00630 if (kid0_is_floor) {
00631 if (OPR_LT == opr)
00632 rev_opr = OPR_GT;
00633 else if (OPR_LE == opr)
00634 rev_opr = OPR_GE;
00635 else if (OPR_GE == opr)
00636 rev_opr = OPR_LE;
00637 else if (OPR_GT == opr)
00638 rev_opr = OPR_LT;
00639 WN *dummy1 = WN_CreateComment ("dummy1");
00640 WN *dummy2 = WN_CreateComment ("dummy2");
00641 Replace_WN (kid0, dummy1);
00642 Replace_WN (kid1, dummy2);
00643 result = WN_CreateExp2 (OPCODE_make_op (rev_opr,
00644 rtype,
00645 index_type),
00646 kid1, kid0);
00647 LWN_Parentize (result);
00648 if (NULL != LWN_Get_Parent (wn))
00649 Replace_WN (wn, result);
00650 Shackle_LWN_Delete_Tree (wn);
00651 }
00652 else
00653 result = wn;
00654
00655 opr = WN_operator (result);
00656 WN *pm1;
00657 OPERATOR new_opr;
00658 kid0 = WN_kid0 (result);
00659 kid1 = WN_kid1 (result);
00660 if (OPR_LT == opr || OPR_GT == opr) {
00661 if (OPR_LT == opr) {
00662 pm1 = WN_CreateIntconst (OPCODE_make_op (OPR_INTCONST,
00663 index_type,
00664 MTYPE_V),
00665 (INT64) 1);
00666 new_opr = OPR_LE;
00667 } else if (OPR_GT == opr) {
00668 pm1 = WN_CreateIntconst (OPCODE_make_op (OPR_INTCONST,
00669 index_type,
00670 MTYPE_V),
00671 (INT64) -1);
00672 new_opr = OPR_GE;
00673 }
00674 WN *dummy1 = WN_CreateComment ("dummy1");
00675 WN *dummy2 = WN_CreateComment ("dummy2");
00676 Replace_WN (kid0, dummy1);
00677 Replace_WN (kid1, dummy2);
00678 WN *add_wn = WN_CreateExp2 (OPCODE_make_op (OPR_ADD,
00679 index_type,
00680 MTYPE_V),
00681 pm1, kid0);
00682 WN *replace_wn = WN_CreateExp2 (OPCODE_make_op (new_opr,
00683 rtype,
00684 index_type),
00685 add_wn, kid1);
00686 if (NULL != LWN_Get_Parent (result))
00687 Replace_WN (result, replace_wn);
00688 Shackle_LWN_Delete_Tree (result);
00689 result = replace_wn;
00690 LWN_Parentize (result);
00691 kid0 = WN_kid0 (result);
00692 kid1 = WN_kid1 (result);
00693 opr = WN_operator (result);
00694 }
00695 FmtAssert (opr == OPR_LE || opr == OPR_GE,
00696 ("Invalid op After normalization!"));
00697 WN *kid10 = WN_kid0 (kid1);
00698 WN *kid11 = WN_kid1 (kid1);
00699 FmtAssert (OPR_PARM == WN_operator (kid10),
00700 ("Child of intrinsic must be an OPR_PARM"));
00701 FmtAssert (OPR_PARM == WN_operator (kid11),
00702 ("Child of intrinsic must be an OPR_PARM"));
00703 kid10 = WN_kid0 (kid10);
00704 kid11 = WN_kid0 (kid11);
00705 if (OPR_INTCONST != WN_operator (kid11))
00706 return result;
00707 INT64 const_val = WN_const_val (kid11);
00708 if (const_val <= 0)
00709 return result;
00710 WN *dummy1 = WN_CreateComment ("dummy1");
00711 WN *dummy2 = WN_CreateComment ("dummy2");
00712 Replace_WN (kid0, dummy1);
00713 WN *const_val_n =
00714 WN_CreateIntconst (OPCODE_make_op (OPR_INTCONST,
00715 index_type, MTYPE_V),
00716 (INT64) const_val);
00717 WN *kid0_repl =
00718 WN_CreateExp2 (OPCODE_make_op (OPR_MPY, index_type, MTYPE_V),
00719 kid0, const_val_n);
00720 if (OPR_GE == opr) {
00721 WN *const_val_nm1 =
00722 WN_CreateIntconst (OPCODE_make_op (OPR_INTCONST,
00723 index_type, MTYPE_V),
00724 (INT64) const_val - 1);
00725 kid0_repl =
00726 WN_CreateExp2 (OPCODE_make_op (OPR_ADD, index_type, MTYPE_V),
00727 kid0_repl, const_val_nm1);
00728 }
00729 Replace_WN (dummy1, kid0_repl);
00730 Shackle_LWN_Delete_Tree (dummy1);
00731 Replace_WN (kid10, dummy2);
00732 Replace_WN (kid1, kid10);
00733 Shackle_LWN_Delete_Tree (kid1);
00734 return result;
00735 }
00736
00737 static WN *
00738 Convert_Le_With_Floor_2Lt(WN *wn)
00739 {
00740 LWN_Parentize (wn);
00741 OPERATOR opr = WN_operator (wn);
00742 if (OPR_LE != opr)
00743 return wn;
00744 WN *kid0 = WN_kid0 (wn);
00745 WN *kid1 = WN_kid1 (wn);
00746 if (OPR_INTRINSIC_OP != WN_operator (kid0) ||
00747 OPR_INTRINSIC_OP != WN_operator (kid1))
00748 return wn;
00749 INTRINSIC intrinsic1, intrinsic2;
00750 intrinsic1 = (INTRINSIC) WN_intrinsic (kid0);
00751 intrinsic2 = (INTRINSIC) WN_intrinsic (kid1);
00752 if (intrinsic1 != intrinsic2)
00753 return wn;
00754 if ((intrinsic1 != INTRN_I4DIVFLOOR) &&
00755 (intrinsic1 != INTRN_I8DIVFLOOR) &&
00756 (intrinsic1 != INTRN_U4DIVFLOOR) &&
00757 (intrinsic1 != INTRN_U8DIVFLOOR))
00758 return wn;
00759 WN *kid00 = WN_kid0 (kid0);
00760 WN *kid01 = WN_kid1 (kid0);
00761 WN *kid10 = WN_kid0 (kid1);
00762 WN *kid11 = WN_kid1 (kid1);
00763 FmtAssert (OPR_PARM == WN_operator (kid00),
00764 ("Child of intrinsic must be an OPR_PARM"));
00765 FmtAssert (OPR_PARM == WN_operator (kid01),
00766 ("Child of intrinsic must be an OPR_PARM"));
00767 FmtAssert (OPR_PARM == WN_operator (kid10),
00768 ("Child of intrinsic must be an OPR_PARM"));
00769 FmtAssert (OPR_PARM == WN_operator (kid11),
00770 ("Child of intrinsic must be an OPR_PARM"));
00771 kid01 = WN_kid0 (kid01);
00772 kid11 = WN_kid0 (kid11);
00773 if (OPR_INTCONST != WN_operator (kid01) ||
00774 OPR_INTCONST != WN_operator (kid11))
00775 return wn;
00776 if ((WN_const_val (kid01) != WN_const_val (kid11)) ||
00777 (WN_const_val (kid01) <= 0))
00778 return wn;
00779 WN *dummy1 = WN_CreateComment ("dummy1");
00780 TYPE_ID rtype = WN_rtype (kid01), index_type;
00781 INT64 const_val = WN_const_val (kid01);
00782 WN *wn_const_val =
00783 WN_CreateIntconst (OPCODE_make_op (OPR_INTCONST, rtype,
00784 MTYPE_V),
00785 const_val);
00786 kid10 = WN_kid0 (kid10);
00787 Replace_WN (kid10, dummy1);
00788 WN *add_expr =
00789 WN_CreateExp2 (OPCODE_make_op (OPR_ADD, rtype, MTYPE_V),
00790 kid10, wn_const_val);
00791 Replace_WN (dummy1, add_expr);
00792 Shackle_LWN_Delete_Tree (dummy1);
00793 rtype = WN_rtype (wn);
00794 index_type = WN_desc (wn);
00795 WN_set_opcode (wn, OPCODE_make_op (OPR_LT,
00796 rtype, index_type));
00797 return wn;
00798 }
00799 static WN *
00800 Simplify_Cond_With_Floor (WN *wn)
00801 {
00802 LWN_Parentize (wn);
00803 OPERATOR opr = WN_operator (wn);
00804 if (OPR_LE == opr)
00805 wn = Convert_Le_With_Floor_2Lt(wn);
00806 opr = WN_operator (wn);
00807 if ((OPR_LT != opr) && (OPR_GT != opr))
00808 return wn;
00809 WN *kid0 = WN_kid0 (wn);
00810 WN *kid1 = WN_kid1 (wn);
00811 if (OPR_INTRINSIC_OP != WN_operator (kid0))
00812 return wn;
00813 if (OPR_INTRINSIC_OP != WN_operator (kid1))
00814 return wn;
00815 INTRINSIC intrinsic1, intrinsic2;
00816 intrinsic1 = (INTRINSIC) WN_intrinsic (kid0);
00817 intrinsic2 = (INTRINSIC) WN_intrinsic (kid1);
00818 if (intrinsic1 != intrinsic2)
00819 return wn;
00820 if ((intrinsic1 != INTRN_I4DIVFLOOR) &&
00821 (intrinsic1 != INTRN_I8DIVFLOOR) &&
00822 (intrinsic1 != INTRN_U4DIVFLOOR) &&
00823 (intrinsic1 != INTRN_U8DIVFLOOR))
00824 return wn;
00825 WN *kid00 = WN_kid0 (kid0);
00826 WN *kid01 = WN_kid1 (kid0);
00827 WN *kid10 = WN_kid0 (kid1);
00828 WN *kid11 = WN_kid1 (kid1);
00829 FmtAssert (OPR_PARM == WN_operator (kid00),
00830 ("Child of intrinsic must be an OPR_PARM"));
00831 FmtAssert (OPR_PARM == WN_operator (kid01),
00832 ("Child of intrinsic must be an OPR_PARM"));
00833 FmtAssert (OPR_PARM == WN_operator (kid10),
00834 ("Child of intrinsic must be an OPR_PARM"));
00835 FmtAssert (OPR_PARM == WN_operator (kid11),
00836 ("Child of intrinsic must be an OPR_PARM"));
00837 kid01 = WN_kid0 (kid01);
00838 kid11 = WN_kid0 (kid11);
00839 if (OPR_INTCONST != WN_operator (kid01) ||
00840 OPR_INTCONST != WN_operator (kid11))
00841 return wn;
00842 if ((WN_const_val (kid01) != WN_const_val (kid11)) ||
00843 (WN_const_val (kid01) <= 0))
00844 return wn;
00845 WN *dummy1 = WN_CreateComment ("dummy1");
00846 WN *dummy2 = WN_CreateComment ("dummy2");
00847 kid00 = WN_kid0 (kid00);
00848 kid10 = WN_kid0 (kid10);
00849 Replace_WN (kid00, dummy1);
00850 Replace_WN (kid10, dummy2);
00851 Replace_WN (kid0, kid00);
00852 Replace_WN (kid1, kid10);
00853 Shackle_LWN_Delete_Tree (kid0);
00854 Shackle_LWN_Delete_Tree (kid1);
00855 return WN_Simplify_Tree (wn);
00856 }
00857
00858 static WN*
00859 Toggle_Eq_To_Remove_One(WN *wn)
00860 {
00861 OPERATOR opr = WN_operator (wn);
00862 if ((OPR_LT != opr) && (OPR_LE != opr) && (OPR_GE != opr) &&
00863 (OPR_GT != opr))
00864 return wn;
00865 WN *kid0 = WN_kid0 (wn);
00866 WN *kid1 = WN_kid1 (wn);
00867 WN *const_node;
00868 INT64 const_val;
00869 if (OPR_ADD != WN_operator (kid0) ||
00870 OPR_ADD != WN_operator (kid1))
00871 return wn;
00872 mBOOL llhs_is1, rlhs_is1, lrhs_is1, rrhs_is1;
00873
00874 WN *kid10 = WN_kid1 (kid0);
00875 WN *kid00 = WN_kid0 (kid0);
00876 WN *kid11 = WN_kid1 (kid1);
00877 WN *kid01 = WN_kid0 (kid1);
00878 TYPE_ID rtype = WN_rtype (wn);
00879 TYPE_ID index_type = WN_desc (wn);
00880
00881 if (OPR_INTCONST == WN_operator (kid00)) {
00882 if (OPR_INTCONST == WN_operator (kid01)) {
00883 WN_const_val (kid01) -= WN_const_val (kid00);
00884 WN_const_val (kid00) = 0;
00885 }
00886 else if (OPR_INTCONST == WN_operator (kid11)) {
00887 WN_const_val (kid11) -= WN_const_val (kid00);
00888 WN_const_val (kid00) = 0;
00889 }
00890 }
00891 else if (OPR_INTCONST == WN_operator (kid10)) {
00892 if (OPR_INTCONST == WN_operator (kid01)) {
00893 WN_const_val (kid01) -= WN_const_val (kid10);
00894 WN_const_val (kid10) = 0;
00895 }
00896 else if (OPR_INTCONST == WN_operator (kid11)) {
00897 WN_const_val (kid11) -= WN_const_val (kid10);
00898 WN_const_val (kid10) = 0;
00899 }
00900 }
00901 llhs_is1 = ((OPR_INTCONST == WN_operator (kid00))
00902 && (1 == WN_const_val (kid00)));
00903 rlhs_is1 = ((OPR_INTCONST == WN_operator (kid10))
00904 && (1 == WN_const_val (kid10)));
00905 lrhs_is1 = ((OPR_INTCONST == WN_operator (kid01))
00906 && (1 == WN_const_val (kid01)));
00907 rrhs_is1 = ((OPR_INTCONST == WN_operator (kid11))
00908 && (1 == WN_const_val (kid11)));
00909 if ((llhs_is1 || rlhs_is1) && (OPR_LE == opr)) {
00910 WN_set_opcode (wn,
00911 OPCODE_make_op (OPR_LT,
00912 rtype, index_type));
00913 if (llhs_is1)
00914 WN_const_val (kid00) = 0;
00915 else if (rlhs_is1)
00916 WN_const_val (kid10) = 0;
00917 return WN_Simplify_Tree (wn);
00918 } else if ((lrhs_is1 || rrhs_is1) && (OPR_GE == opr)) {
00919 WN_set_opcode (wn,
00920 OPCODE_make_op (OPR_GT,
00921 rtype, index_type));
00922 if (lrhs_is1)
00923 WN_const_val (kid01) = 0;
00924 else if (rrhs_is1)
00925 WN_const_val (kid11) = 0;
00926 return WN_Simplify_Tree (wn);
00927 } else
00928 return WN_Simplify_Tree (wn);
00929 }
00930
00931 WN*
00932 Simplify_If_Conditional(WN *wn)
00933 {
00934 wn = Simplify_Cond_With_Floor (wn);
00935 BOOL disable_simp = WN_Simplifier_Enable (FALSE);
00936 wn = Remove_Floor_From_One_Sided_Cond (wn);
00937 WN_Simplifier_Enable (disable_simp);
00938 wn = WN_Simplify_Tree (wn);
00939 wn = Toggle_Eq_To_Remove_One (wn);
00940 wn = Remove_Consts_From_Conditionals (wn);
00941 OPERATOR opr = WN_operator (wn);
00942 if ((OPR_LT != opr) && (OPR_LE != opr) && (OPR_GE != opr) &&
00943 (OPR_GT != opr))
00944 return wn;
00945 WN *kid0 = WN_kid0 (wn);
00946 WN *kid1 = WN_kid1 (wn);
00947 WN *const_node;
00948 INT64 const_val = 0;
00949 WN *other;
00950
00951 if (OPR_MPY == WN_operator (kid0)) {
00952 if (OPR_INTCONST ==
00953 WN_operator (WN_kid0 (kid0))) {
00954 const_val = WN_const_val (WN_kid0 (kid0));
00955 other = kid1;
00956 }
00957 else if (OPR_INTCONST ==
00958 WN_operator (WN_kid1 (kid0))) {
00959 const_val = WN_const_val (WN_kid1 (kid0));
00960 other = kid1;
00961 }
00962 } else if (OPR_MPY == WN_operator (kid1)) {
00963 if (OPR_INTCONST ==
00964 WN_operator (WN_kid0 (kid1))) {
00965 const_val = WN_const_val (WN_kid0 (kid1));
00966 other = kid0;
00967 }
00968 else if (OPR_INTCONST ==
00969 WN_operator (WN_kid1 (kid1))) {
00970 const_val = WN_const_val (WN_kid1 (kid1));
00971 other = kid0;
00972 }
00973 }
00974 if (0 == const_val)
00975 return wn;
00976 if (!Is_Exp_Divided_By_Const (other, const_val))
00977 return wn;
00978 Divide_Exp_By_Const (kid0, const_val);
00979 Divide_Exp_By_Const (kid1, const_val);
00980 return wn;
00981 }
00982
00983 WN *
00984 Sh_LWN_CreateDivceil (TYPE_ID type,
00985 WN *lhs,
00986 WN *rhs)
00987 {
00988 if (OPR_INTCONST !=
00989 WN_operator (rhs))
00990 return LWN_CreateDivceil (type, lhs, rhs);
00991 INT64 const_val = WN_const_val (rhs);
00992 if (OPR_ADD == WN_operator (lhs)) {
00993 WN *llhs, *rlhs, *rllhs;
00994
00995 llhs = WN_kid0 (lhs);
00996 rlhs = WN_kid1 (lhs);
00997 if (OPR_INTCONST != WN_operator (rlhs))
00998 return LWN_CreateDivceil (type, lhs, rhs);
00999 INT64 const_val2 = WN_const_val (rlhs);
01000 if (OPR_MPY != WN_operator (llhs))
01001 return LWN_CreateDivceil (type, lhs, rhs);
01002 rllhs = WN_kid1 (llhs);
01003 if (OPR_INTCONST != WN_operator (rllhs))
01004 return LWN_CreateDivceil (type, lhs, rhs);
01005 INT64 const_val3 = WN_const_val (rllhs);
01006 if (0 != const_val3 % const_val)
01007 return LWN_CreateDivceil (type, lhs, rhs);
01008 WN_const_val (rllhs) = const_val3 / const_val;
01009 if (const_val2 > 0)
01010 WN_const_val (rlhs) = const_val2 / const_val + 1;
01011 else
01012 WN_const_val (rlhs) = - (-const_val2 / const_val);
01013 Shackle_LWN_Delete_Tree (rhs);
01014 return WN_Simplify_Tree (lhs);
01015 }
01016 if ((OPR_MPY != WN_operator (lhs)) ||
01017 (const_val <= 0))
01018 return LWN_CreateDivceil (type, lhs, rhs);
01019 WN *l_lhs = WN_kid0 (lhs);
01020 WN *r_lhs = WN_kid1 (lhs);
01021 if ((OPR_INTCONST != WN_operator (l_lhs)) &&
01022 (OPR_INTCONST != WN_operator (r_lhs)))
01023 return LWN_CreateDivceil (type, lhs, rhs);
01024 if ((OPR_INTCONST == WN_operator (l_lhs)) &&
01025 (OPR_INTCONST == WN_operator (r_lhs))) {
01026 INT64 result =
01027 1 + (((WN_const_val (l_lhs)*WN_const_val (r_lhs))-1)/const_val);
01028 Shackle_LWN_Delete_Tree (lhs);
01029 Shackle_LWN_Delete_Tree (rhs);
01030 return
01031 WN_CreateIntconst (OPCODE_make_op (OPR_INTCONST,
01032 type, MTYPE_V),
01033 (INT64) result);
01034 }
01035 else if (OPR_INTCONST == WN_operator (r_lhs)) {
01036 BOOL divides =
01037 (0 == (WN_const_val (r_lhs) % const_val));
01038 if (divides) {
01039 Shackle_LWN_Delete_Tree (rhs);
01040 WN_const_val (r_lhs) = WN_const_val (r_lhs) / const_val;
01041 return WN_Simplify_Tree (lhs);
01042 }
01043 else
01044 return LWN_CreateDivceil (type, lhs, rhs);
01045 } else {
01046 BOOL divides = (0 == (WN_const_val (l_lhs) % const_val));
01047 if (divides) {
01048 Shackle_LWN_Delete_Tree (rhs);
01049 WN_const_val (l_lhs) = WN_const_val (l_lhs) / const_val;
01050 return WN_Simplify_Tree (lhs);
01051 }
01052 else
01053 return LWN_CreateDivceil (type, lhs, rhs);
01054 }
01055 }
01056
01057 INT64
01058 Int_DivFloor (INT64 num, INT64 denom)
01059 {
01060 if ((num > 0) && (denom > 0))
01061 return (num/denom);
01062 else if (num == 0)
01063 return 0;
01064 else if ((num < 0) && (denom > 0))
01065 return -1 - ((-num - 1) / denom);
01066 else {
01067 FmtAssert (denom > 0, ("Denominator must be positive"));
01068 return -1;
01069 }
01070 }
01071
01072 WN *
01073 Sh_LWN_CreateDivfloor (TYPE_ID type,
01074 WN *lhs,
01075 WN *rhs)
01076 {
01077 if (OPR_INTCONST !=
01078 WN_operator (rhs))
01079 return LWN_CreateDivfloor (type, lhs, rhs);
01080 INT64 const_val = WN_const_val (rhs);
01081 if ((OPR_MPY != WN_operator (lhs)) ||
01082 (const_val <= 0))
01083 return LWN_CreateDivfloor (type, lhs, rhs);
01084 WN *l_lhs = WN_kid0 (lhs);
01085 WN *r_lhs = WN_kid1 (lhs);
01086 if ((OPR_INTCONST != WN_operator (l_lhs)) &&
01087 (OPR_INTCONST != WN_operator (r_lhs)))
01088 return LWN_CreateDivfloor (type, lhs, rhs);
01089 if ((OPR_INTCONST == WN_operator (l_lhs)) &&
01090 (OPR_INTCONST == WN_operator (r_lhs))) {
01091 INT64 result =
01092 (WN_const_val (l_lhs) * WN_const_val (r_lhs)) / const_val;
01093 Shackle_LWN_Delete_Tree (lhs);
01094 Shackle_LWN_Delete_Tree (rhs);
01095 return
01096 WN_CreateIntconst (OPCODE_make_op (OPR_INTCONST,
01097 type, MTYPE_V),
01098 (INT64) result);
01099 }
01100 else if (OPR_INTCONST == WN_operator (r_lhs)) {
01101 BOOL divides =
01102 (0 == (WN_const_val (r_lhs) % const_val));
01103 if (divides) {
01104 Shackle_LWN_Delete_Tree (rhs);
01105 WN_const_val (r_lhs) = WN_const_val (r_lhs) / const_val;
01106 return WN_Simplify_Tree (lhs);
01107 }
01108 else
01109 return LWN_CreateDivfloor (type, lhs, rhs);
01110 } else {
01111 BOOL divides = (0 == (WN_const_val (l_lhs) % const_val));
01112 if (divides) {
01113 Shackle_LWN_Delete_Tree (rhs);
01114 WN_const_val (l_lhs) = WN_const_val (l_lhs) / const_val;
01115 return WN_Simplify_Tree (lhs);
01116 }
01117 else
01118 return LWN_CreateDivfloor (type, lhs, rhs);
01119 }
01120 }
01121
01122
01123
01124
01125 static BOOL
01126 is_vector_trivial(ACCESS_ARRAY *lb,
01127 ACCESS_ARRAY *ub,
01128 ACCESS_VECTOR *cond,
01129 INT32 size_loop,
01130 INT32 size_sym,
01131 QUEUE<ST *> *lin_sym_q,
01132 WN *do_loop)
01133 {
01134 INT32 size = size_loop + size_sym, index;
01135
01136 mINT32 *row = CXX_NEW_ARRAY (mINT32, size, shackle_if_pool);
01137 ACCESS_VECTOR *dup =
01138 CXX_NEW (ACCESS_VECTOR (cond, shackle_if_pool),
01139 shackle_if_pool);
01140 INT32 i, j;
01141 SYSTEM_OF_EQUATIONS *soe;
01142 ACCESS_VECTOR *v;
01143
01144 dup->Negate_Me();
01145 dup->Const_Offset--;
01146
01147 soe = CXX_NEW (SYSTEM_OF_EQUATIONS (0, 0, size, shackle_if_pool),
01148 shackle_if_pool);
01149 for (i = 0; i < lb->Num_Vec(); i++) {
01150 v = lb->Dim(i);
01151 assert (!v->Too_Messy);
01152 for (j = 0; j < size; j++)
01153 row[j] = v->Loop_Coeff (j);
01154 if (NULL != v->Lin_Symb) {
01155 INTSYMB_CONST_ITER iter(v->Lin_Symb);
01156 for (const INTSYMB_NODE *node = iter.First();
01157 !iter.Is_Empty();
01158 node = iter.Next()) {
01159 if (0 == node->Coeff)
01160 DevWarn("Access vector has zero coeff linear symbol");
01161 else {
01162 index = lin_sym_q->Index (node->Symbol.St());
01163 assert ((0 <= index) && (index < size_sym));
01164 row[size_loop+index] = node->Coeff;
01165 }
01166 }
01167 }
01168 soe->Add_Le (row, (INT64) v->Const_Offset);
01169 }
01170 for (i = 0; i < ub->Num_Vec(); i++) {
01171 v = ub->Dim(i);
01172 assert (!v->Too_Messy);
01173 for (j = 0; j < size; j++)
01174 row[j] = v->Loop_Coeff (j);
01175 if (NULL != v->Lin_Symb) {
01176 INTSYMB_CONST_ITER iter(v->Lin_Symb);
01177 for (const INTSYMB_NODE *node = iter.First();
01178 !iter.Is_Empty();
01179 node = iter.Next()) {
01180 if (0 == node->Coeff)
01181 DevWarn("Access vector has zero coeff linear symbol");
01182 else {
01183 index = lin_sym_q->Index (node->Symbol.St());
01184 assert ((0 <= index) && (index < size_sym));
01185 row[size_loop+index] = node->Coeff;
01186 }
01187 }
01188 }
01189 soe->Add_Le (row, (INT64) v->Const_Offset);
01190 }
01191 for (j = 0; j < size; j++)
01192 row[j] = dup->Loop_Coeff (j);
01193 if (NULL != dup->Lin_Symb) {
01194 INTSYMB_CONST_ITER iter(dup->Lin_Symb);
01195 for (const INTSYMB_NODE *node = iter.First();
01196 !iter.Is_Empty();
01197 node = iter.Next()) {
01198 if (0 == node->Coeff)
01199 DevWarn("Access vector has zero coeff linear symbol");
01200 else {
01201 index = lin_sym_q->Index (node->Symbol.St());
01202 assert ((0 <= index) && (index < size_sym));
01203 row[size_loop+index] = node->Coeff;
01204 }
01205 }
01206 }
01207 soe->Add_Le (row, dup->Const_Offset);
01208 Add_Parent_If_Constraints (do_loop, soe, size_loop,
01209 size_sym, lin_sym_q);
01210 Add_Parent_Loop_Constraints (do_loop, soe, size_loop,
01211 size_sym, lin_sym_q);
01212 if (shackle_if_debug_level > 1)
01213 soe->Print (stdout);
01214 return !soe->Is_Consistent();
01215 }
01216
01217
01218
01219
01220 static BOOL
01221 is_vector_inconsistent(ACCESS_ARRAY *lb,
01222 ACCESS_ARRAY *ub,
01223 ACCESS_VECTOR *cond,
01224 INT32 size_loop,
01225 INT32 size_sym,
01226 QUEUE<ST*> *lin_sym_q,
01227 WN *do_loop)
01228 {
01229 INT32 size = size_loop + size_sym, index;
01230
01231 mINT32 *row = CXX_NEW_ARRAY (mINT32, size, shackle_if_pool);
01232 ACCESS_VECTOR *dup =
01233 CXX_NEW (ACCESS_VECTOR (cond, shackle_if_pool),
01234 shackle_if_pool);
01235 INT32 i, j;
01236 SYSTEM_OF_EQUATIONS *soe;
01237 ACCESS_VECTOR *v;
01238
01239 soe = CXX_NEW (SYSTEM_OF_EQUATIONS (0, 0, size, shackle_if_pool),
01240 shackle_if_pool);
01241 for (i = 0; i < lb->Num_Vec(); i++) {
01242 v = lb->Dim(i);
01243 FmtAssert (!v->Too_Messy, ("How could it be?"));
01244 for (j = 0; j < size; j++)
01245 row[j] = v->Loop_Coeff (j);
01246 if (NULL != v->Lin_Symb) {
01247 INTSYMB_CONST_ITER iter(v->Lin_Symb);
01248 for (const INTSYMB_NODE *node = iter.First();
01249 !iter.Is_Empty();
01250 node = iter.Next()) {
01251 if (0 == node->Coeff)
01252 DevWarn("Access vector has zero coeff linear symbol");
01253 else {
01254 index = lin_sym_q->Index (node->Symbol.St());
01255 assert ((0 <= index) && (index < size_sym));
01256 row[size_loop+index] = node->Coeff;
01257 }
01258 }
01259 }
01260 soe->Add_Le (row, (INT64) v->Const_Offset);
01261 }
01262 for (i = 0; i < ub->Num_Vec(); i++) {
01263 v = ub->Dim(i);
01264 assert (!v->Too_Messy);
01265 for (j = 0; j < size; j++)
01266 row[j] = v->Loop_Coeff (j);
01267 if (NULL != v->Lin_Symb) {
01268 INTSYMB_CONST_ITER iter(v->Lin_Symb);
01269 for (const INTSYMB_NODE *node = iter.First();
01270 !iter.Is_Empty();
01271 node = iter.Next()) {
01272 if (0 == node->Coeff)
01273 DevWarn("Access vector has zero coeff linear symbol");
01274 else {
01275 index = lin_sym_q->Index (node->Symbol.St());
01276 assert ((0 <= index) && (index < size_sym));
01277 row[size_loop+index] = node->Coeff;
01278 }
01279 }
01280 }
01281 soe->Add_Le (row, (INT64) v->Const_Offset);
01282 }
01283 for (j = 0; j < size; j++)
01284 row[j] = dup->Loop_Coeff (j);
01285 if (NULL != dup->Lin_Symb) {
01286 INTSYMB_CONST_ITER iter(dup->Lin_Symb);
01287 for (const INTSYMB_NODE *node = iter.First();
01288 !iter.Is_Empty();
01289 node = iter.Next()) {
01290 if (0 == node->Coeff)
01291 DevWarn("Access vector has zero coeff linear symbol");
01292 else {
01293 index = lin_sym_q->Index (node->Symbol.St());
01294 FmtAssert (0 <= index && index < size_sym,
01295 ("Incorrect value for index"));
01296 row[size_loop+index] = node->Coeff;
01297 }
01298 }
01299 }
01300 soe->Add_Le (row, dup->Const_Offset);
01301 Add_Parent_If_Constraints (do_loop, soe, size_loop,
01302 size_sym, lin_sym_q);
01303 Add_Parent_Loop_Constraints (do_loop, soe, size_loop,
01304 size_sym, lin_sym_q);
01305 if (shackle_if_debug_level > 1)
01306 soe->Print (stdout);
01307 return !soe->Is_Consistent();
01308 }
01309
01310 static BOOL
01311 Interferes_With_Symbolic_Bound(ACCESS_VECTOR *if_test,
01312 INT32 pos,
01313 ACCESS_ARRAY *lb,
01314 ACCESS_ARRAY *ub)
01315 {
01316 INT32 i;
01317 ACCESS_VECTOR *tmp;
01318
01319 assert (0 != if_test->Loop_Coeff (pos));
01320 if (if_test->Loop_Coeff (pos) < 0) {
01321 for (i = 0; i < lb->Num_Vec(); i++) {
01322 tmp = lb->Dim(i);
01323 if (NULL != tmp->Lin_Symb)
01324 return TRUE;
01325 }
01326 return FALSE;
01327 } else {
01328 for (i = 0; i < ub->Num_Vec(); i++) {
01329 tmp = ub->Dim(i);
01330 if (NULL != tmp->Lin_Symb)
01331 return TRUE;
01332 }
01333 return FALSE;
01334 }
01335 }
01336
01337 static void
01338 copy_access_array_from_src2dst(ACCESS_ARRAY *dst,
01339 ACCESS_ARRAY *src,
01340 INT32 depth)
01341 {
01342 INT32 i, j;
01343 ACCESS_VECTOR *v1, *v2;
01344
01345 assert (dst->Num_Vec() <= src->Num_Vec());
01346 for (i = 0; i < dst->Num_Vec(); i++ ) {
01347 v1 = dst->Dim(i);
01348 v2 = src->Dim(i);
01349 assert (depth <= v1->Nest_Depth());
01350 assert (depth <= v2->Nest_Depth());
01351 for (j = 0; j < depth; j++) {
01352 v1->Set_Loop_Coeff (j, v2->Loop_Coeff (j));
01353 }
01354 v1->Const_Offset = v2->Const_Offset;
01355 }
01356 return;
01357 }
01358
01359 static INT64
01360 determine_if_sinkable_in_do(WN *if_stmt,
01361 WN *do_stmt)
01362 {
01363 IF_INFO *if_info = Get_If_Info (if_stmt);
01364 assert (NULL != if_info);
01365 ACCESS_ARRAY *ar = if_info->Condition;
01366 ACCESS_VECTOR *v1, *step;
01367 WN *wn1, *wn2, *kid, *add0, *add1;
01368 ST *do_index;
01369 DO_LOOP_INFO *dli;
01370
01371
01372 if (1 != ar->Num_Vec())
01373 return 0;
01374 v1 = ar->Dim(0);
01375
01376 if (v1->Too_Messy)
01377 return 0;
01378
01379 if (v1->Contains_Non_Lin_Symb())
01380 return 0;
01381
01382
01383 dli = Get_Do_Loop_Info (do_stmt);
01384 step = dli->Step;
01385 if (step->Is_Const()) {
01386 if (step->Const_Offset > 0)
01387 return step->Const_Offset;
01388 else
01389 return 0;
01390 }
01391 else
01392 return 0;
01393 }
01394
01395 static WN *
01396 Enclosing_Ith_Do_Loop (WN *stmt, INT32 level)
01397 {
01398 WN *loop;
01399 INT32 i;
01400
01401 loop = stmt;
01402 for (i = 0; i < level; i++) {
01403
01404
01405
01406
01407 loop = LWN_Get_Parent (loop);
01408 loop = Enclosing_Do_Loop (loop);
01409 if (NULL == loop)
01410 return NULL;
01411 }
01412 return loop;
01413 }
01414
01415
01416
01417
01418 static WN*
01419 canonicalize_if_condition(WN *cond, INT32 depth)
01420 {
01421 WN *fake_unroll[2];
01422 if (!OPCODE_is_compare (WN_opcode (cond)))
01423 return NULL;
01424 Simplify_Cond_With_Div_Floor (cond);
01425
01426 OPERATOR opr = WN_operator (cond);
01427 TYPE_ID index_type;
01428 WN *wnm1, *tmp1, *tmp2, *unchng, *tmp3;
01429
01430 if ((OPR_GE != opr) && (OPR_GT != opr) && (OPR_LE != opr) &&
01431 (OPR_LT != opr))
01432 return NULL;
01433 if ((OPR_LE == opr) || (OPR_LT == opr)) {
01434 unchng = LWN_Copy_Tree (WN_kid0(cond));
01435 fake_unroll[0] = WN_kid0 (cond);
01436 fake_unroll[1] = unchng;
01437 Unrolled_DU_Update (fake_unroll, 2, depth);
01438
01439 tmp1 = LWN_Copy_Tree (WN_kid1(cond));
01440 fake_unroll[0] = WN_kid1(cond);
01441 fake_unroll[1] = tmp1;
01442 Unrolled_DU_Update (fake_unroll, 2, depth);
01443 }
01444 else {
01445 assert ((OPR_GT == opr) || (OPR_GE == opr));
01446
01447 unchng = LWN_Copy_Tree (WN_kid1 (cond));
01448 fake_unroll[0] = WN_kid1 (cond);
01449 fake_unroll[1] = unchng;
01450 Unrolled_DU_Update (fake_unroll, 2, depth);
01451
01452 tmp1 = LWN_Copy_Tree (WN_kid0 (cond));
01453 fake_unroll[0] = WN_kid0(cond);
01454 fake_unroll[1] = tmp1;
01455 Unrolled_DU_Update (fake_unroll, 2, depth);
01456 }
01457 index_type = WN_rtype (tmp1);
01458 wnm1 = WN_CreateIntconst
01459 (OPCODE_make_op (OPR_INTCONST, Promote_Type (index_type),
01460 MTYPE_V),
01461 (INT64) 1);
01462 if ((OPR_GT == opr) || (OPR_LT == opr)) {
01463 tmp2 = WN_CreateExp2
01464 (OPCODE_make_op (OPR_ADD, Promote_Type (index_type),
01465 MTYPE_V),
01466 unchng, wnm1);
01467
01468
01469 }
01470 else
01471 tmp2 = unchng;
01472 index_type = WN_rtype (tmp1);
01473 tmp3 = WN_CreateExp1
01474 (OPCODE_make_op (OPR_NEG, Promote_Type (index_type),
01475 MTYPE_V),
01476 tmp1);
01477
01478 tmp1 = WN_CreateExp2
01479 (OPCODE_make_op (OPR_ADD, Promote_Type (index_type),
01480 MTYPE_V),
01481 tmp3, tmp2);
01482
01483
01484 return tmp1;
01485 }
01486
01487 INT32
01488 Return_Floor_Given_Ceil(INT32 inp)
01489 {
01490 switch (inp) {
01491 case INTRN_I4DIVCEIL:
01492 return INTRN_I4DIVFLOOR;
01493 case INTRN_U4DIVCEIL:
01494 return INTRN_U4DIVFLOOR;
01495 case INTRN_I8DIVCEIL:
01496 return INTRN_I8DIVFLOOR;
01497 case INTRN_U8DIVCEIL:
01498 return INTRN_U8DIVFLOOR;
01499 default:
01500 FmtAssert (0, ("Must pass an INTRN Div/Floor as argument"));
01501 return -1;
01502 }
01503 }
01504
01505
01506 static WN*
01507 return_upper_boundplus1(WN *upper_bound, INT32 depth)
01508 {
01509 WN *wnp1, *tmp;
01510 WN *fake_unroll[2];
01511 WN *dup;
01512 TYPE_ID index_type;
01513
01514 if (OPR_INTRINSIC_OP ==
01515 WN_operator (upper_bound)) {
01516 INT32 intr = WN_intrinsic(upper_bound);
01517 if ((intr == INTRN_I4DIVFLOOR) || (intr == INTRN_I8DIVFLOOR)||
01518 (intr == INTRN_U4DIVFLOOR) || (intr == INTRN_U8DIVFLOOR)) {
01519 WN *const_kid = WN_kid0 (WN_kid1 (upper_bound));
01520 if ((OPR_INTCONST == WN_operator(const_kid)) &&
01521 (WN_const_val (const_kid) > 0)) {
01522 WN *replace = WN_kid0 (WN_kid0 (upper_bound));
01523 dup = LWN_Copy_Tree (replace);
01524 fake_unroll[0] = replace;
01525 fake_unroll[1] = dup;
01526 Unrolled_DU_Update (fake_unroll, 2, depth);
01527 index_type = WN_rtype (upper_bound);
01528 WN *incr = WN_CreateIntconst
01529 (OPCODE_make_op (OPR_INTCONST, Promote_Type (index_type),
01530 MTYPE_V),
01531 (INT64) WN_const_val (const_kid));
01532 WN *replace_by = WN_CreateExp2
01533 (OPCODE_make_op (OPR_ADD, Promote_Type (index_type),
01534 MTYPE_V),
01535 dup, incr);
01536 Replace_WN (replace, replace_by);
01537 Shackle_LWN_Delete_Tree (replace);
01538 return upper_bound;
01539 }
01540 } else if ((intr == INTRN_I4DIVCEIL) || (intr == INTRN_I8DIVCEIL) ||
01541 (intr == INTRN_U4DIVCEIL) || (intr == INTRN_U8DIVCEIL)) {
01542 WN *const_kid = WN_kid0 (WN_kid1 (upper_bound));
01543 if ((OPR_INTCONST == WN_operator (const_kid)) &&
01544 (WN_const_val (const_kid) > 0)) {
01545 WN *old = WN_kid0 (WN_kid0 (upper_bound));
01546 dup = LWN_Copy_Tree (old);
01547 fake_unroll[0] = old;
01548 fake_unroll[1] = dup;
01549 Unrolled_DU_Update (fake_unroll, 2, depth);
01550 index_type = WN_rtype (upper_bound);
01551 WN *incr = WN_CreateIntconst
01552 (OPCODE_make_op (OPR_INTCONST, Promote_Type (index_type),
01553 MTYPE_V),
01554 (INT64) (2*WN_const_val(const_kid) - 1));
01555 WN *new_num = WN_CreateExp2
01556 (OPCODE_make_op (OPR_ADD, Promote_Type (index_type),
01557 MTYPE_V),
01558 dup, incr);
01559 WN *new_denom = WN_CreateIntconst
01560 (OPCODE_make_op (OPR_INTCONST, Promote_Type (index_type),
01561 MTYPE_V),
01562 (INT64) WN_const_val (const_kid));
01563 Shackle_LWN_Delete_Tree (upper_bound);
01564 return Sh_LWN_CreateDivfloor (Promote_Type (index_type),
01565 new_num, new_denom);
01566 }
01567 }
01568 }
01569 dup = upper_bound;
01570 index_type = WN_rtype (upper_bound);
01571 wnp1 = WN_CreateIntconst
01572 (OPCODE_make_op (OPR_INTCONST, Promote_Type (index_type),
01573 MTYPE_V),
01574 (INT64) 1);
01575 tmp = WN_CreateExp2
01576 (OPCODE_make_op (OPR_ADD, Promote_Type (index_type),
01577 MTYPE_V),
01578 dup, wnp1);
01579
01580
01581 return WN_Simplify_Tree (tmp);
01582 }
01583
01584
01585 static WN*
01586 return_upper_bound(WN *canonical_inp,
01587 SYMBOL symbol_to_remove,
01588 INT32 loop_coeff,
01589 BOOL is_coeff_pos)
01590 {
01591 TYPE_ID index_type;
01592
01593
01594
01595 if (OPR_LDID == WN_operator (canonical_inp)) {
01596 if (symbol_to_remove == SYMBOL (canonical_inp)) {
01597 index_type = WN_rtype (canonical_inp);
01598 Shackle_LWN_Delete_Tree (canonical_inp);
01599 return WN_CreateIntconst
01600 (OPCODE_make_op (OPR_INTCONST, Promote_Type (index_type),
01601 MTYPE_V),
01602 (INT64) 0);
01603 }
01604 }
01605
01606
01607 WN *wn, *wnm1, *zero;
01608 WN *dup, *return_val;
01609 WN *fake_unroll[2];
01610
01611 LWN_Parentize (canonical_inp);
01612 dup = canonical_inp;
01613 index_type = WN_rtype (dup);
01614
01615 zero = WN_CreateIntconst
01616 (OPCODE_make_op (OPR_INTCONST, Promote_Type (index_type),
01617 MTYPE_V),
01618 (INT64) 0);
01619 Replace_Ldid_With_Exp_Copy (symbol_to_remove,
01620 dup,
01621 zero);
01622 dup = WN_Simplify_Tree (dup);
01623 index_type = WN_rtype (dup);
01624
01625 if ((1 == loop_coeff) || (-1 == loop_coeff)) {
01626 if (!is_coeff_pos) {
01627 wnm1 = WN_CreateIntconst
01628 (OPCODE_make_op (OPR_INTCONST, Promote_Type (index_type),
01629 MTYPE_V),
01630 (INT64) -1);
01631 return_val = WN_CreateExp2
01632 (OPCODE_make_op (OPR_ADD, Promote_Type (index_type),
01633 MTYPE_V),
01634 dup, wnm1);
01635
01636
01637 return WN_Simplify_Tree (return_val);
01638 }
01639 else {
01640 return_val = WN_CreateExp1
01641 (OPCODE_make_op (OPR_NEG, Promote_Type (index_type),
01642 MTYPE_V),
01643 dup);
01644
01645 return WN_Simplify_Tree (return_val);
01646 }
01647 }
01648 else {
01649
01650 UINT32 divisor = (loop_coeff > 0) ? loop_coeff : -loop_coeff;
01651 assert (divisor > 0);
01652 WN *div_result = WN_CreateIntconst
01653 (OPCODE_make_op (OPR_INTCONST, Promote_Type (index_type),
01654 MTYPE_V),
01655 divisor);
01656 WN *tmp_result;
01657 if (!is_coeff_pos) {
01658 wnm1 = WN_CreateIntconst
01659 (OPCODE_make_op (OPR_INTCONST, Promote_Type (index_type),
01660 MTYPE_V),
01661 (INT64) -1);
01662 tmp_result = WN_CreateExp2
01663 (OPCODE_make_op (OPR_ADD, Promote_Type (index_type),
01664 MTYPE_V),
01665 dup, wnm1);
01666 return Sh_LWN_CreateDivfloor (Promote_Type (index_type),
01667 tmp_result, div_result);
01668
01669
01670
01671
01672
01673
01674
01675
01676
01677 }
01678 else {
01679 tmp_result = WN_CreateExp1
01680 (OPCODE_make_op (OPR_NEG, Promote_Type (index_type),
01681 MTYPE_V),
01682 WN_Simplify_Tree (dup));
01683 tmp_result = WN_Simplify_Tree (tmp_result);
01684 return
01685 WN_Simplify_Tree (Sh_LWN_CreateDivfloor (Promote_Type (index_type),
01686 tmp_result, div_result));
01687 }
01688 }
01689 }
01690
01691 BOOL
01692 Is_Parent_Of(WN *parent, WN *kid)
01693 {
01694 WN *step = kid;
01695 while (NULL != step) {
01696 if (step == parent)
01697 return TRUE;
01698 else
01699 step = LWN_Get_Parent (step);
01700 }
01701 return FALSE;
01702 }
01703
01704
01705
01706
01707
01708 static WN *
01709 Largest_Empty_Subtree(WN *wn)
01710 {
01711 WN *wn_then, *wn_else, *wn_body, *wn_kid;
01712 WN *wn_index, *last_child_saved, *delete_stmt;
01713 USE_LIST *use_list;
01714 USE_LIST_ITER *iter1, *iter2;
01715
01716 switch (WN_opcode (wn)) {
01717 case OPC_IF:
01718 wn_then = Largest_Empty_Subtree (WN_then (wn));
01719 wn_else = Largest_Empty_Subtree (WN_else (wn));
01720 if ((WN_then (wn) == wn_then) &&
01721 (WN_else (wn) == wn_else))
01722 return wn;
01723 else if (WN_then (wn) == wn_then)
01724 return wn_else;
01725 else
01726 return wn_then;
01727 case OPC_DO_LOOP:
01728 {
01729 wn_body = Largest_Empty_Subtree (WN_do_body (wn));
01730 if (wn_body != WN_do_body (wn))
01731 return wn_body;
01732 wn_index = WN_start (wn);
01733 assert (OPR_STID == WN_operator (wn_index));
01734 use_list = Du_Mgr->Du_Get_Use (wn_index);
01735 iter1 = CXX_NEW (USE_LIST_ITER (use_list), shackle_if_pool);
01736 for (const DU_NODE *node1 = iter1->First();
01737 !iter1->Is_Empty(); node1 = iter1->Next()) {
01738 WN *use = node1->Wn();
01739
01740 if (!Is_Parent_Of (wn, use))
01741 return wn_body;
01742 }
01743 wn_index = WN_step (wn);
01744 assert (OPR_STID == WN_operator (wn_index));
01745 use_list = Du_Mgr->Du_Get_Use (wn_index);
01746 iter2 = CXX_NEW (USE_LIST_ITER (use_list), shackle_if_pool);
01747 for (const DU_NODE *node2 = iter2->First();
01748 !iter2->Is_Empty(); node2 = iter2->Next()) {
01749 WN *use = node2->Wn();
01750
01751 if (!Is_Parent_Of (wn, use))
01752 return wn_body;
01753 }
01754
01755
01756 return wn;
01757 }
01758 case OPC_BLOCK:
01759 if (WN_block_empty (wn))
01760 return wn;
01761 FOR_CHILDREN (wn, child, ignCount) {
01762 wn_kid = Largest_Empty_Subtree (child);
01763
01764 if (wn_kid) {
01765 delete_stmt = LWN_Extract_From_Block (wn_kid);
01766 Shackle_LWN_Delete_Tree (delete_stmt);
01767 }
01768 }
01769 END_CHILDREN;
01770 if (WN_block_empty (wn))
01771 return wn;
01772 else
01773 return NULL;
01774 case OPC_FUNC_ENTRY:
01775 wn_kid = Largest_Empty_Subtree (WN_func_body (wn));
01776 if (wn_kid) {
01777 delete_stmt = LWN_Extract_From_Block (wn_kid);
01778 Shackle_LWN_Delete_Tree (delete_stmt);
01779 }
01780 return NULL;
01781 default:
01782 return NULL;
01783 }
01784 }
01785 static void
01786 Handle_Sink_Inconsistent_Case (WN *if_stmt)
01787 {
01788
01789
01790
01791 WN *delete_stmt = LWN_Extract_From_Block (if_stmt);
01792 Shackle_LWN_Delete_Tree (delete_stmt);
01793 return;
01794 }
01795
01796 static void
01797 Handle_Sink_Redundant_Case (WN *if_stmt)
01798 {
01799
01800
01801 WN *delete_stmt;
01802
01803 FOR_CHILDREN (WN_then (if_stmt), child, ignCount) {
01804 delete_stmt = LWN_Extract_From_Block (child);
01805 LWN_Insert_Block_Before (NULL, if_stmt, delete_stmt);
01806 }
01807 END_CHILDREN;
01808 delete_stmt = LWN_Extract_From_Block (if_stmt);
01809 Shackle_LWN_Delete_Tree (delete_stmt);
01810 return;
01811 }
01812
01813 static void
01814 Handle_Sink_General_Case(WN *if_stmt, WN *do_loop,
01815 INT32 loop_depth, ACCESS_VECTOR *cond)
01816 {
01817 assert (cond->Loop_Coeff (loop_depth) != 0);
01818 WN *dup_loop = LWN_Copy_Tree (do_loop, TRUE, LNO_Info_Map,
01819 TRUE, shackle_if_copy_map1, TRUE);
01820 Copy_Shackle_Prompf_Info (do_loop, dup_loop);
01821 LWN_Insert_Block_After (NULL, do_loop, dup_loop);
01822 BOOL true_branch_first = (cond->Loop_Coeff (loop_depth) > 0);
01823 ARRAY_DIRECTED_GRAPH16 *dg = Array_Dependence_Graph;
01824
01825 dg->Versioned_Dependences_Update (do_loop, dup_loop,
01826 loop_depth,
01827 shackle_if_copy_map1);
01828 WN *fake_unroll[2];
01829 fake_unroll[0] = do_loop;
01830 fake_unroll[1] = dup_loop;
01831 Unrolled_DU_Update (fake_unroll, 2, loop_depth - 1);
01832 WN *dup_if_stmt = (WN *) WN_MAP_Get (shackle_if_copy_map1, if_stmt);
01833
01834
01835
01836 WN *canonical_cond, *ubnd, *lbnd;
01837
01838 canonical_cond = canonicalize_if_condition (WN_if_test (dup_if_stmt),
01839 loop_depth);
01840 ubnd = return_upper_bound (canonical_cond,
01841 SYMBOL (WN_index (dup_loop)),
01842 cond->Loop_Coeff (loop_depth),
01843 true_branch_first);
01844 lbnd = return_upper_boundplus1 (ubnd, loop_depth);
01845 TYPE_ID index_type = WN_rtype (lbnd);
01846 assert (OPR_STID ==
01847 WN_operator (WN_start (dup_loop)));
01848 assert(index_type == WN_desc (WN_start (dup_loop)));
01849 WN *delete_node = WN_kid0 (WN_start (dup_loop));
01850 Replace_WN (delete_node, lbnd);
01851 Shackle_LWN_Delete_Tree (delete_node);
01852
01853 canonical_cond = canonicalize_if_condition (WN_if_test (if_stmt),
01854 loop_depth);
01855 ubnd = return_upper_bound (canonical_cond,
01856 SYMBOL (WN_index (do_loop)),
01857 cond->Loop_Coeff (loop_depth),
01858 true_branch_first);
01859 index_type = WN_desc (WN_start (do_loop));
01860 assert (Promote_Type (index_type) ==
01861 Promote_Type (WN_rtype (ubnd)));
01862 OPCODE load_opc =
01863 OPCODE_make_op (OPR_LDID, Promote_Type (index_type),
01864 index_type);
01865 WN *end_lhs = LWN_CreateLdid (load_opc, WN_start (do_loop));
01866 Du_Mgr->Add_Def_Use (WN_start (do_loop), end_lhs);
01867 Du_Mgr->Add_Def_Use (WN_step (do_loop), end_lhs);
01868 Du_Mgr->Ud_Get_Def(end_lhs)->Set_loop_stmt(do_loop);
01869 TYPE_ID rtype = WN_rtype (WN_end (do_loop));
01870 WN_set_opcode (WN_end (do_loop),
01871 OPCODE_make_op (OPR_LE, rtype,
01872 Promote_Type (index_type)));
01873 delete_node = WN_kid0 (WN_end (do_loop));
01874 Replace_WN (delete_node, end_lhs);
01875 Shackle_LWN_Delete_Tree (delete_node);
01876 delete_node = WN_kid1 (WN_end (do_loop));
01877 Replace_WN (delete_node, ubnd);
01878 Shackle_LWN_Delete_Tree (delete_node);
01879
01880 WN *true_branch, *false_branch;
01881
01882 true_branch = (true_branch_first) ? if_stmt : dup_if_stmt;
01883 false_branch = (true_branch_first) ? dup_if_stmt : if_stmt;
01884
01885 WN *delete_stmt = LWN_Extract_From_Block (false_branch);
01886 Shackle_LWN_Delete_Tree (delete_stmt);
01887
01888 FOR_CHILDREN (WN_then (true_branch), child, ignCount) {
01889 delete_stmt = LWN_Extract_From_Block (child);
01890 LWN_Insert_Block_Before (NULL, true_branch, child);
01891 }
01892 END_CHILDREN;
01893 delete_stmt = LWN_Extract_From_Block (true_branch);
01894 Shackle_LWN_Delete_Tree (delete_stmt);
01895 }
01896
01897 static BOOL
01898 Is_Provably_In_Bounds(ACCESS_ARRAY *LB_ARRAY,
01899 ACCESS_ARRAY *UB_ARRAY,
01900 ACCESS_VECTOR *v3,
01901 INT32 size_loop,
01902 INT32 size_sym,
01903 QUEUE<ST *> *lin_sym_q,
01904 INT32 pos,
01905 WN *do_loop,
01906 enum SHACKLE_BOUND which_shackle)
01907 {
01908 UINT32 i;
01909 INT32 size = size_loop + size_sym, index;
01910 INT32 lb_coeff, v3_coeff, ub_coeff;
01911 ACCESS_VECTOR *lb_v3, *ub_v3;
01912 BOOL retval;
01913 SYSTEM_OF_EQUATIONS *soe;
01914 BOOL lb_sat, ub_sat;
01915 ACCESS_VECTOR *LB = LB_ARRAY->Dim(0);
01916 ACCESS_VECTOR *UB = UB_ARRAY->Dim(0);
01917
01918 lb_coeff = LB->Loop_Coeff (pos);
01919 v3_coeff = v3->Loop_Coeff (pos);
01920 ub_coeff = UB->Loop_Coeff (pos);
01921 assert (v3_coeff != 0);
01922 lb_v3 = CXX_NEW (ACCESS_VECTOR (v3, shackle_if_pool),
01923 shackle_if_pool);
01924 ub_v3 = CXX_NEW (ACCESS_VECTOR (v3, shackle_if_pool),
01925 shackle_if_pool);
01926 if (v3_coeff < 0) {
01927 ub_v3->Negate_Me();
01928 ub_v3->Const_Offset--;
01929 v3_coeff = - v3_coeff;
01930 }
01931 else {
01932 lb_v3->Negate_Me();
01933 lb_v3->Const_Offset--;
01934 }
01935 lb_coeff = -lb_coeff;
01936 assert (ub_coeff > 0);
01937 assert (lb_coeff > 0);
01938 assert (v3_coeff > 0);
01939 mINT32 *row = CXX_NEW_ARRAY (mINT32, size, shackle_if_pool);
01940 ACCESS_VECTOR *dup =
01941 CXX_NEW (ACCESS_VECTOR (size_loop, shackle_if_pool),
01942 shackle_if_pool);
01943 dup->Too_Messy = FALSE;
01944 {
01945
01946 soe = CXX_NEW (SYSTEM_OF_EQUATIONS (0, 0, size, shackle_if_pool),
01947 shackle_if_pool);
01948 for (i = 0; i < size; i++)
01949 row[i] = 0;
01950 for (i = 0; i < size_loop; i++) {
01951 row[i] = v3_coeff * LB->Loop_Coeff (i) -
01952 lb_coeff * lb_v3->Loop_Coeff (i);
01953 }
01954 if (NULL != LB->Lin_Symb) {
01955 INTSYMB_CONST_ITER iter (LB->Lin_Symb);
01956 for (const INTSYMB_NODE *node = iter.First();
01957 !iter.Is_Empty(); node = iter.Next()) {
01958 index = lin_sym_q->Index (node->Symbol.St());
01959 FmtAssert (0 <= index && index < size_sym,
01960 ("Incorrect value for index"));
01961 row[size_loop+index] += v3_coeff * node->Coeff;
01962 }
01963 }
01964 if (NULL != lb_v3->Lin_Symb) {
01965 INTSYMB_CONST_ITER iter (lb_v3->Lin_Symb);
01966 for (const INTSYMB_NODE *node = iter.First();
01967 !iter.Is_Empty(); node = iter.Next()) {
01968 index = lin_sym_q->Index (node->Symbol.St());
01969 FmtAssert (0 <= index && index < size_sym,
01970 ("Incorrect value for index"));
01971 row[size_loop+index] -= lb_coeff * node->Coeff;
01972 }
01973 }
01974 assert (0 == row[pos]);
01975 INT64 lb_const_offset = v3_coeff * lb_coeff - lb_coeff +
01976 v3_coeff * LB->Const_Offset - lb_coeff * lb_v3->Const_Offset;
01977
01978 for (i = 0; i < size; i++)
01979 row[i] = -row[i];
01980 lb_const_offset = - lb_const_offset;
01981 lb_const_offset--;
01982 Add_Parent_If_Constraints (do_loop, soe, size_loop,
01983 size_sym, lin_sym_q);
01984 Add_Parent_Loop_Constraints (do_loop, soe, size_loop,
01985 size_sym, lin_sym_q);
01986 soe->Add_Le (row, lb_const_offset);
01987 lb_sat = !soe->Is_Consistent();
01988 }
01989 {
01990
01991 soe = CXX_NEW (SYSTEM_OF_EQUATIONS (0, 0, size, shackle_if_pool),
01992 shackle_if_pool);
01993 for (i = 0; i < size; i++)
01994 row[i] = 0;
01995 for (i = 0; i < size_loop; i++) {
01996 row[i] = v3_coeff * UB->Loop_Coeff (i) -
01997 ub_coeff * ub_v3->Loop_Coeff (i);
01998 }
01999 if (NULL != UB->Lin_Symb) {
02000 INTSYMB_CONST_ITER iter(UB->Lin_Symb);
02001 for (const INTSYMB_NODE *node = iter.First();
02002 !iter.Is_Empty(); node = iter.Next()) {
02003 index = lin_sym_q->Index (node->Symbol.St());
02004 FmtAssert (0 <= index && index < size_sym,
02005 ("Incorrect value for index"));
02006 row[size_loop+index] += v3_coeff * node->Coeff;
02007 }
02008 }
02009 if (NULL != ub_v3->Lin_Symb) {
02010 INTSYMB_CONST_ITER iter (ub_v3->Lin_Symb);
02011 for (const INTSYMB_NODE *node = iter.First();
02012 !iter.Is_Empty(); node = iter.Next()) {
02013 index = lin_sym_q->Index (node->Symbol.St());
02014 FmtAssert (0 <= index && index < size_sym,
02015 ("Incorrect value for index"));
02016 row[size_loop+index] -= ub_coeff * node->Coeff;
02017 }
02018 }
02019 assert (0 == row[pos]);
02020 INT64 ub_const_offset = - ub_coeff + v3_coeff * ub_coeff +
02021 v3_coeff * UB->Const_Offset - ub_coeff * ub_v3->Const_Offset;
02022
02023 for (i = 0; i < size; i++)
02024 row[i] = -row[i];
02025 ub_const_offset = -ub_const_offset;
02026 ub_const_offset--;
02027 Add_Parent_If_Constraints (do_loop, soe, size_loop,
02028 size_sym, lin_sym_q);
02029 Add_Parent_Loop_Constraints (do_loop, soe, size_loop,
02030 size_sym, lin_sym_q);
02031 soe->Add_Le (row, ub_const_offset);
02032 ub_sat = !soe->Is_Consistent();
02033 }
02034 switch (which_shackle) {
02035 case SHACKLE_LOWER:
02036 return lb_sat;
02037 case SHACKLE_UPPER:
02038 return ub_sat;
02039 case SHACKLE_BOTH:
02040 return (lb_sat && ub_sat);
02041 }
02042 return FALSE;
02043 }
02044
02045 static void
02046 Handle_Sink_Symbolic_Non_Promotion_Case (WN *if_stmt,
02047 WN *do_loop,
02048 INT32 loop_depth,
02049 ACCESS_VECTOR *cond)
02050 {
02051 assert (cond->Loop_Coeff (loop_depth) != 0);
02052 WN *canonical_cond, *ubnd, *lbnd;
02053 canonical_cond =
02054 canonicalize_if_condition (WN_if_test (if_stmt),
02055 loop_depth);
02056 ubnd = return_upper_bound (canonical_cond,
02057 SYMBOL (WN_index (do_loop)),
02058 cond->Loop_Coeff (loop_depth),
02059 (cond->Loop_Coeff (loop_depth) > 0));
02060 lbnd = NULL;
02061 if (cond->Loop_Coeff (loop_depth) < 0) {
02062 lbnd = return_upper_boundplus1 (ubnd, loop_depth);
02063 ubnd = NULL;
02064 }
02065 if (cond->Loop_Coeff (loop_depth) > 0) {
02066 WN *do_end = WN_end (do_loop);
02067 OPERATOR opr = WN_operator (do_end);
02068 assert ((OPR_LE == opr) || (OPR_LT == opr)
02069 || (OPR_GE == opr) || (OPR_GT == opr));
02070 Upper_Bound_Standardize (WN_end (do_loop), FALSE);
02071 WN *do_end_rhs = WN_kid1 (WN_end (do_loop));
02072 TYPE_ID index_type = WN_rtype (do_end_rhs);
02073 WN *dummy_one =
02074 WN_CreateIntconst (OPCODE_make_op (OPR_INTCONST,
02075 Promote_Type (index_type),
02076 MTYPE_V),
02077 (INT64) 1);
02078 Replace_WN (do_end_rhs, dummy_one);
02079 WN *new_do_end_rhs =
02080 WN_CreateExp2 (OPCODE_make_op (OPR_MIN,
02081 Promote_Type (index_type),
02082 MTYPE_V),
02083 ubnd, do_end_rhs);
02084 Replace_WN (dummy_one, new_do_end_rhs);
02085 Shackle_LWN_Delete_Tree (dummy_one);
02086 }
02087 else {
02088 assert (cond->Loop_Coeff (loop_depth) < 0);
02089 WN *do_begin = WN_start (do_loop);
02090 OPERATOR opr = WN_operator (do_begin);
02091 assert (OPR_STID == opr);
02092 WN *do_begin_rhs = WN_kid0 (do_begin);
02093 TYPE_ID index_type = WN_desc (do_begin_rhs);
02094 WN *dummy_one =
02095 WN_CreateIntconst (OPCODE_make_op (OPR_INTCONST,
02096 Promote_Type (index_type),
02097 MTYPE_V),
02098 (INT64) 1);
02099 Replace_WN (do_begin_rhs, dummy_one);
02100 WN *new_do_begin_rhs =
02101 WN_CreateExp2 (OPCODE_make_op (OPR_MAX,
02102 Promote_Type (index_type),
02103 MTYPE_V),
02104 lbnd, do_begin_rhs);
02105 Replace_WN (dummy_one, new_do_begin_rhs);
02106 Shackle_LWN_Delete_Tree (dummy_one);
02107 }
02108
02109 WN *delete_stmt;
02110 FOR_CHILDREN (WN_then (if_stmt), child, ignCount) {
02111 delete_stmt = LWN_Extract_From_Block (child);
02112 LWN_Insert_Block_Before (NULL, if_stmt, delete_stmt);
02113 }
02114 END_CHILDREN;
02115 delete_stmt = LWN_Extract_From_Block (if_stmt);
02116 Shackle_LWN_Delete_Tree (delete_stmt);
02117 return;
02118 }
02119
02120 static BOOL
02121 Soe_Implies_Access_Vector(SYSTEM_OF_EQUATIONS *soe,
02122 ACCESS_VECTOR *v,
02123 UINT32 size)
02124 {
02125 INT32 i;
02126 if (shackle_if_debug_level > 0) {
02127 fprintf(stdout, "Before system\n");
02128 if (shackle_if_debug_level > 1)
02129 soe->Print (stdout);
02130 v->Print (stdout, FALSE);
02131 fprintf(stdout, "Analysis started\n");
02132 }
02133 ACCESS_VECTOR *dup =
02134 CXX_NEW (ACCESS_VECTOR (v, shackle_if_pool),
02135 shackle_if_pool);
02136 dup->Negate_Me();
02137 dup->Const_Offset--;
02138 SYSTEM_OF_EQUATIONS *dup_soe =
02139 CXX_NEW (SYSTEM_OF_EQUATIONS (0, 0, size, shackle_if_pool),
02140 shackle_if_pool);
02141 dup_soe->Add_Soe (soe);
02142 mINT32 *row = CXX_NEW_ARRAY (mINT32, size, shackle_if_pool);
02143 for (i = 0; i < size; i++) {
02144 row[i] = dup->Loop_Coeff (i);
02145 }
02146 dup_soe->Add_Le (row, dup->Const_Offset);
02147 if (shackle_if_debug_level > 1)
02148 dup_soe->Print (stdout);
02149 return !dup_soe->Is_Consistent();
02150 }
02151
02152 static BOOL
02153 V3geLB_Implies_V3geUB(ACCESS_VECTOR *LB,
02154 ACCESS_VECTOR *UB,
02155 ACCESS_VECTOR *v3,
02156 UINT32 size,
02157 UINT32 pos)
02158 {
02159 UINT32 i;
02160 INT32 lb_coeff, ub_coeff, ub_v3;
02161
02162 lb_coeff = LB->Loop_Coeff (pos);
02163 ub_coeff = UB->Loop_Coeff (pos);
02164 ub_v3 = v3->Loop_Coeff (pos);
02165 assert (lb_coeff < 0);
02166 assert (ub_coeff > 0);
02167 assert (ub_v3 > 0);
02168
02169 lb_coeff = -lb_coeff;
02170 mINT32 *row = CXX_NEW_ARRAY (mINT32, size, shackle_if_pool);
02171 for (i = 0; i < size; i++) {
02172 row[i] = ub_v3 * LB->Loop_Coeff (i) + lb_coeff * v3->Loop_Coeff (i);
02173 }
02174 assert (0 == row[pos]);
02175 SYSTEM_OF_EQUATIONS *soe =
02176 CXX_NEW (SYSTEM_OF_EQUATIONS (0, 0, size, shackle_if_pool),
02177 shackle_if_pool);
02178 soe->Add_Le (row, ub_v3 * LB->Const_Offset +
02179 lb_coeff * v3->Const_Offset);
02180 ACCESS_VECTOR *dup =
02181 CXX_NEW (ACCESS_VECTOR (size, shackle_if_pool), shackle_if_pool);
02182 for (i = 0; i < size; i++) {
02183 dup->Set_Loop_Coeff (i, ub_coeff * v3->Loop_Coeff (i) -
02184 ub_v3 * UB->Loop_Coeff (i));
02185 }
02186 dup->Const_Offset = ub_coeff * v3->Const_Offset -
02187 ub_v3 * UB->Const_Offset;
02188 dup->Too_Messy = FALSE;
02189 assert (0 == dup->Loop_Coeff (pos));
02190 return Soe_Implies_Access_Vector (soe, dup, size);
02191 }
02192
02193 static BOOL
02194 V3leUB_Implies_V3leLB(ACCESS_VECTOR *LB,
02195 ACCESS_VECTOR *UB,
02196 ACCESS_VECTOR *v3,
02197 UINT32 size,
02198 UINT32 pos)
02199 {
02200 UINT32 i;
02201 INT32 lb_coeff, ub_coeff, lb_v3;
02202 lb_coeff = LB->Loop_Coeff (pos);
02203 ub_coeff = UB->Loop_Coeff (pos);
02204 lb_v3 = v3->Loop_Coeff (pos);
02205 assert (lb_coeff < 0);
02206 assert (ub_coeff > 0);
02207 assert (lb_v3 < 0);
02208
02209 lb_coeff = -lb_coeff;
02210 lb_v3 = -lb_v3;
02211 mINT32 *row = CXX_NEW_ARRAY (mINT32, size, shackle_if_pool);
02212 for (i = 0; i < size; i++) {
02213 row[i] = lb_v3 * UB->Loop_Coeff (i) + ub_coeff * v3->Loop_Coeff (i);
02214 }
02215 assert (0 == row[pos]);
02216 SYSTEM_OF_EQUATIONS *soe =
02217 CXX_NEW (SYSTEM_OF_EQUATIONS (0, 0, size, shackle_if_pool),
02218 shackle_if_pool);
02219 soe->Add_Le (row, lb_v3 * UB->Const_Offset +
02220 ub_coeff * v3->Const_Offset);
02221 ACCESS_VECTOR *dup =
02222 CXX_NEW (ACCESS_VECTOR (size, shackle_if_pool), shackle_if_pool);
02223 for (i = 0; i < size; i++) {
02224 dup->Set_Loop_Coeff (i, lb_coeff * v3->Loop_Coeff (i) -
02225 lb_v3 * LB->Loop_Coeff (i));
02226 }
02227 dup->Const_Offset = lb_coeff * v3->Const_Offset -
02228 lb_v3 * LB->Const_Offset;
02229 dup->Too_Messy = FALSE;
02230 assert (0 == dup->Loop_Coeff (pos));
02231 return Soe_Implies_Access_Vector (soe, dup, size);
02232 }
02233
02234 static BOOL
02235 is_promotion_case (ACCESS_ARRAY *LB, ACCESS_ARRAY *UB,
02236 ACCESS_VECTOR *cond, INT32 depth)
02237 {
02238 assert (1 == LB->Num_Vec());
02239 assert (1 == UB->Num_Vec());
02240
02241 assert (0 != cond->Loop_Coeff (depth));
02242 if (cond->Loop_Coeff (depth) > 0)
02243 return V3geLB_Implies_V3geUB (LB->Dim(0), UB->Dim(0),
02244 cond, depth+1, depth);
02245 else
02246 return V3leUB_Implies_V3leLB (LB->Dim(0), UB->Dim(0),
02247 cond, depth+1, depth);
02248 }
02249
02250 static void
02251 Handle_Sink_Promotion_Case (WN *if_stmt, WN *do_loop,
02252 INT32 loop_depth,
02253 ACCESS_VECTOR *cond)
02254 {
02255
02256
02257
02258
02259
02260
02261 WN *fake_unroll[2];
02262 WN *dup_loop = LWN_Copy_Tree (do_loop, TRUE, LNO_Info_Map,
02263 TRUE, shackle_if_copy_map1,
02264 TRUE);
02265 Copy_Shackle_Prompf_Info (do_loop, dup_loop);
02266 LWN_Insert_Block_After (NULL, do_loop, dup_loop);
02267 ARRAY_DIRECTED_GRAPH16 *dg = Array_Dependence_Graph;
02268 dg->Versioned_Dependences_Update (do_loop, dup_loop,
02269 loop_depth,
02270 shackle_if_copy_map1);
02271 fake_unroll[0] = do_loop;
02272 fake_unroll[1] = dup_loop;
02273 Unrolled_DU_Update (fake_unroll, 2, loop_depth - 1);
02274 WN *dup_if_stmt = (WN *) WN_MAP_Get (shackle_if_copy_map1,
02275 if_stmt);
02276 {
02277 WN *main_if, *main_cond1, *main_cond2;
02278 WN *cond1 = canonicalize_if_condition (WN_if_test (if_stmt),
02279 loop_depth);
02280 main_cond1 =
02281 return_upper_bound (cond1,
02282 SYMBOL (WN_index (do_loop)),
02283 cond->Loop_Coeff (loop_depth),
02284 (cond->Loop_Coeff (loop_depth) > 0));
02285 if (cond->Loop_Coeff (loop_depth) < 0)
02286 main_cond1 = return_upper_boundplus1 (main_cond1,
02287 loop_depth);
02288
02289
02290
02291 if (cond->Loop_Coeff (loop_depth) < 0) {
02292 Upper_Bound_Standardize (WN_end (do_loop), FALSE);
02293 main_cond2 = LWN_Copy_Tree (WN_kid1 (WN_end (do_loop)));
02294
02295 fake_unroll[0] = WN_kid1 (WN_end (do_loop));
02296 fake_unroll[1] = main_cond2;
02297 Unrolled_DU_Update (fake_unroll, 2, loop_depth);
02298 } else {
02299 assert (OPR_STID ==
02300 WN_operator (WN_start (do_loop)));
02301 main_cond2 = LWN_Copy_Tree (WN_kid0 (WN_start (do_loop)));
02302 fake_unroll[0] = WN_kid0 (WN_start (do_loop));
02303 fake_unroll[1] = main_cond2;
02304 Unrolled_DU_Update (fake_unroll, 2, loop_depth);
02305 }
02306 assert (WN_rtype (main_cond1) ==
02307 WN_rtype (main_cond2));
02308 TYPE_ID index_type = WN_rtype (main_cond1);
02309 TYPE_ID rtype = WN_rtype (WN_if_test (if_stmt));
02310 WN *main_cond_to_insert;
02311 if (cond->Loop_Coeff (loop_depth) > 0) {
02312 main_cond_to_insert = WN_CreateExp2
02313 (OPCODE_make_op (OPR_GE, rtype, Promote_Type (index_type)),
02314 main_cond1, main_cond2);
02315 } else {
02316 main_cond_to_insert = WN_CreateExp2
02317 (OPCODE_make_op (OPR_LE, rtype, Promote_Type (index_type)),
02318 main_cond1, main_cond2);
02319 }
02320 main_cond_to_insert =
02321 Simplify_If_Conditional (main_cond_to_insert);
02322 Simplify_Cond_With_Div_Floor (main_cond_to_insert);
02323 main_if = LWN_CreateIf (main_cond_to_insert,
02324 WN_CreateBlock(),
02325 WN_CreateBlock());
02326 Replace_WN (do_loop, main_if);
02327 LWN_Insert_Block_After (WN_then (main_if), NULL, do_loop);
02328 IF_INFO *ii =
02329 CXX_NEW (IF_INFO (&LNO_default_pool, TRUE,
02330 Tree_Has_Regions (main_if)),
02331 &LNO_default_pool);
02332 WN_MAP_Set (LNO_Info_Map, main_if, (void *) ii);
02333 DOLOOP_STACK do_stack (shackle_if_pool);
02334 Build_Doloop_Stack (main_if, &do_stack);
02335 LNO_Build_If_Access (main_if, &do_stack);
02336 }
02337 {
02338 WN *main_if, *main_cond1, *main_cond2;
02339 WN *cond1 = canonicalize_if_condition (WN_if_test (dup_if_stmt),
02340 loop_depth);
02341 main_cond1 =
02342 return_upper_bound (cond1,
02343 SYMBOL (WN_index (dup_loop)),
02344 cond->Loop_Coeff (loop_depth),
02345 (cond->Loop_Coeff (loop_depth) > 0));
02346 if (cond->Loop_Coeff (loop_depth) < 0)
02347 main_cond1 = return_upper_boundplus1 (main_cond1,
02348 loop_depth);
02349
02350
02351 if (cond->Loop_Coeff (loop_depth) < 0) {
02352 Upper_Bound_Standardize (WN_end (dup_loop), FALSE);
02353 main_cond2 = LWN_Copy_Tree (WN_kid1 (WN_end (dup_loop)));
02354
02355 fake_unroll[0] = WN_kid1 (WN_end (dup_loop));
02356 fake_unroll[1] = main_cond2;
02357 Unrolled_DU_Update (fake_unroll, 2, loop_depth);
02358 } else {
02359 FmtAssert (OPR_STID == WN_operator (WN_start (dup_loop)),
02360 ("Do loop with Non STID start!"));
02361 main_cond2 = LWN_Copy_Tree (WN_kid0 (WN_start (dup_loop)));
02362 fake_unroll[0] = WN_kid0 (WN_start (dup_loop));
02363 fake_unroll[1] = main_cond2;
02364 Unrolled_DU_Update (fake_unroll, 2, loop_depth);
02365 }
02366 FmtAssert (WN_rtype (main_cond1) == WN_rtype (main_cond2),
02367 ("Two halves of a cond with different rtypes!"));
02368 TYPE_ID index_type = WN_rtype (main_cond1);
02369 TYPE_ID rtype = WN_rtype (WN_if_test (dup_if_stmt));
02370 WN *main_cond_to_insert;
02371 if (cond->Loop_Coeff (loop_depth) > 0) {
02372 main_cond_to_insert = WN_CreateExp2
02373 (OPCODE_make_op (OPR_LT, rtype, Promote_Type (index_type)),
02374 main_cond1, main_cond2);
02375 } else {
02376 main_cond_to_insert = WN_CreateExp2
02377 (OPCODE_make_op (OPR_GT, rtype, Promote_Type (index_type)),
02378 main_cond1, main_cond2);
02379 }
02380 main_cond_to_insert =
02381 Simplify_If_Conditional (main_cond_to_insert);
02382 Simplify_Cond_With_Div_Floor (main_cond_to_insert);
02383 main_if = LWN_CreateIf (main_cond_to_insert,
02384 WN_CreateBlock(),
02385 WN_CreateBlock());
02386 Replace_WN (dup_loop, main_if);
02387 LWN_Insert_Block_After (WN_then (main_if), NULL, dup_loop);
02388 IF_INFO *ii =
02389 CXX_NEW (IF_INFO (&LNO_default_pool, TRUE,
02390 Tree_Has_Regions (main_if)),
02391 &LNO_default_pool);
02392 WN_MAP_Set (LNO_Info_Map, main_if, (void *) ii);
02393 DOLOOP_STACK do_stack (shackle_if_pool);
02394 Build_Doloop_Stack (main_if, &do_stack);
02395 LNO_Build_If_Access (main_if, &do_stack);
02396 }
02397 for (INT32 i = 0; i < 2; i++) {
02398 }
02399 }
02400
02401 static BOOL
02402 Sink_If2do(WN *if_stmt, ACCESS_ARRAY *ar)
02403 {
02404 if (1 != ar->Num_Vec())
02405 return FALSE;
02406
02407 assert (1 == ar->Num_Vec());
02408 assert (!ar->Too_Messy);
02409 INT32 if_depth = Num_Common_Loops (if_stmt, if_stmt);
02410
02411
02412 assert (ar->Dim(0)->Nest_Depth() >= if_depth);
02413 ACCESS_VECTOR *vector_to_sink = ar->Dim(0);
02414 assert (!vector_to_sink->Too_Messy);
02415
02416 INT32 i;
02417 for (i = if_depth - 1; i >= 0; i--)
02418 if (0 != vector_to_sink->Loop_Coeff (i))
02419 break;
02420
02421 INT32 posn_of_do_loop = i;
02422 if (posn_of_do_loop < 0) {
02423 if (NULL == vector_to_sink->Lin_Symb) {
02424
02425
02426 if (vector_to_sink->Const_Offset < 0)
02427 Handle_Sink_Inconsistent_Case (if_stmt);
02428 else
02429 Handle_Sink_Redundant_Case (if_stmt);
02430 return TRUE;
02431 } else {
02432
02433
02434
02435
02436 if (FALSE == Has_Sibling_In_Block (if_stmt)) {
02437 WN *delete_stmt;
02438 WN *do_loop = Enclosing_Ith_Do_Loop (if_stmt, if_depth);
02439 FOR_CHILDREN (WN_then (if_stmt), child, ignCount) {
02440 delete_stmt = LWN_Extract_From_Block (child);
02441 LWN_Insert_Block_Before (NULL, if_stmt, delete_stmt);
02442 }
02443 END_CHILDREN;
02444 delete_stmt = LWN_Extract_From_Block (if_stmt);
02445 Replace_WN (do_loop, delete_stmt);
02446 LWN_Insert_Block_After (WN_then (delete_stmt), NULL, do_loop);
02447 return TRUE;
02448 } else {
02449 Shackle_If_Seen_Set (if_stmt);
02450 return FALSE;
02451 }
02452 }
02453 }
02454 WN *do_loop = Enclosing_Ith_Do_Loop (if_stmt,
02455 if_depth - posn_of_do_loop);
02456 assert (NULL != do_loop);
02457 INT32 loop_depth = Num_Common_Loops (do_loop, do_loop) - 1;
02458 assert (loop_depth == posn_of_do_loop);
02459
02460 DO_LOOP_INFO *dli = Get_Do_Loop_Info (do_loop);
02461 QUEUE<ST *> *lin_sym_q =
02462 CXX_NEW (QUEUE<ST *> (shackle_if_pool), shackle_if_pool);
02463 Recursively_Add_Bound_Lin_Symbols(lin_sym_q, if_stmt);
02464 Recursively_Add_Array_Lin_Symbols(lin_sym_q, if_stmt);
02465 Recursively_Add_Parent_If_Lin_Symbols (lin_sym_q, if_stmt);
02466
02467 if (shackle_if_debug_level > 0)
02468 fprintf(stdout, "Attempt: %d\n", shackle_debug_exec_count++);
02469 if (is_vector_inconsistent (dli->LB, dli->UB, vector_to_sink,
02470 loop_depth + 1,
02471 lin_sym_q->Queue_Length(),
02472 lin_sym_q,
02473 do_loop)) {
02474 Handle_Sink_Inconsistent_Case (if_stmt);
02475 return TRUE;
02476 }
02477 else if (is_vector_trivial (dli->LB, dli->UB, vector_to_sink,
02478 loop_depth + 1,
02479 lin_sym_q->Queue_Length(),
02480 lin_sym_q,
02481 do_loop)) {
02482 Handle_Sink_Redundant_Case (if_stmt);
02483 return TRUE;
02484 }
02485 else if (Is_Provably_In_Bounds (dli->LB, dli->UB, vector_to_sink,
02486 loop_depth+1,
02487 lin_sym_q->Queue_Length(),
02488 lin_sym_q,
02489 loop_depth, do_loop,
02490 SHACKLE_BOTH)) {
02491 Handle_Sink_General_Case (if_stmt, do_loop, loop_depth,
02492 ar->Dim(0));
02493 return TRUE;
02494 }
02495
02496
02497
02498
02499
02500
02501
02502
02503
02504
02505
02506 else if (1 || is_promotion_case (dli->LB, dli->UB, vector_to_sink,
02507 loop_depth)) {
02508 Maybe_Handle_Sink_Promotion_Case (if_stmt, do_loop,
02509 loop_depth,
02510 ar->Dim(0));
02511 return TRUE;
02512 }
02513 }
02514
02515 static void
02516 Remove_Redundant_And_Inconsistent_If(WN *wn)
02517 {
02518 if (OPC_IF == WN_opcode (wn)) {
02519 IF_INFO *ii = (IF_INFO *) WN_MAP_Get (LNO_Info_Map, wn);
02520 ACCESS_ARRAY *ar = ii->Condition;
02521 if (!ar->Too_Messy && (1 == ar->Num_Vec())) {
02522 INT32 if_depth = Num_Common_Loops (wn, wn);
02523 assert (ar->Dim(0)->Nest_Depth() >= if_depth);
02524 ACCESS_VECTOR *vector_to_sink = ar->Dim (0);
02525 if (!vector_to_sink->Too_Messy) {
02526 INT32 i;
02527 for (i = if_depth - 1; i >= 0; i--)
02528 if (0 != vector_to_sink->Loop_Coeff (i))
02529 break;
02530 INT32 posn_of_do_loop = i;
02531 if (posn_of_do_loop >= 0) {
02532 WN *do_loop =
02533 Enclosing_Ith_Do_Loop (wn, if_depth - posn_of_do_loop);
02534 FmtAssert (NULL != do_loop, ("Impossible for a 0 do loop"));
02535 INT32 loop_depth = Num_Common_Loops (do_loop, do_loop) - 1;
02536 FmtAssert (loop_depth == posn_of_do_loop,
02537 ("Loop depth and posn of do loop must be same"));
02538 DO_LOOP_INFO *dli = Get_Do_Loop_Info (do_loop);
02539 QUEUE<ST *> *lin_sym_q =
02540 CXX_NEW (QUEUE<ST *> (shackle_if_pool), shackle_if_pool);
02541 Recursively_Add_Bound_Lin_Symbols (lin_sym_q, wn);
02542 Recursively_Add_Array_Lin_Symbols (lin_sym_q, wn);
02543 Recursively_Add_Parent_If_Lin_Symbols (lin_sym_q, wn);
02544 if (is_vector_inconsistent (dli->LB, dli->UB, vector_to_sink,
02545 loop_depth+1,
02546 lin_sym_q->Queue_Length(),
02547 lin_sym_q, do_loop)) {
02548 Handle_Sink_Inconsistent_Case (wn);
02549 return;
02550 }
02551 else if (is_vector_trivial (dli->LB, dli->UB, vector_to_sink,
02552 loop_depth + 1,
02553 lin_sym_q->Queue_Length(),
02554 lin_sym_q, do_loop)) {
02555 FOR_CHILDREN (wn, child, ignCount) {
02556 Remove_Redundant_And_Inconsistent_If (child);
02557 }
02558 END_CHILDREN;
02559 Handle_Sink_Redundant_Case (wn);
02560 return;
02561 }
02562 }
02563 }
02564 }
02565 }
02566 FOR_CHILDREN (wn, child, ignCount) {
02567 Remove_Redundant_And_Inconsistent_If (child);
02568 }
02569 END_CHILDREN;
02570 }
02571
02572 static WN *
02573 Find_Topmost_Unseen_If_Containing_Node(WN *wn)
02574 {
02575 WN *step = wn, *prev = NULL;
02576 while (step) {
02577 if ((OPC_IF == WN_opcode (step)) && Shackle_If_Unseen (step))
02578 prev = step;
02579 step = LWN_Get_Parent(step);
02580 }
02581 if (prev)
02582 assert (OPC_IF == WN_opcode (prev));
02583 return prev;
02584 }
02585
02586
02587
02588
02589 static WN *
02590 Find_Unseen_If_Outside_Do(WN *inp)
02591 {
02592 WN *step = inp;
02593
02594 while (step) {
02595 if (OPC_DO_LOOP == WN_opcode (step))
02596 break;
02597 step = LWN_Get_Parent (step);
02598 }
02599
02600 if (!step)
02601 return NULL;
02602 assert (OPC_DO_LOOP == WN_opcode (step));
02603 while (step) {
02604 if ((OPC_IF == WN_opcode (step)) && Shackle_If_Unseen (step))
02605 break;
02606 step = LWN_Get_Parent (step);
02607 }
02608
02609 if (!step)
02610 return NULL;
02611 assert (OPC_IF == WN_opcode (step));
02612 return step;
02613 }
02614
02615 static WN *
02616 Find_Enclosing_Unseen_If (WN *inp)
02617 {
02618 WN *step = LWN_Get_Parent (inp);
02619 while (step) {
02620 if ((OPC_IF == WN_opcode (step)) && Shackle_If_Unseen (step))
02621 return step;
02622 step = LWN_Get_Parent (step);
02623 }
02624 return NULL;
02625 }
02626
02627 static WN *
02628 Find_Unseen_If_Outside_Do(QUEUE<WN *> *inp)
02629 {
02630 WN *if_stmt;
02631 QUEUE_ITER<WN *> iter(inp);
02632 WN *step;
02633
02634 while (iter.Step(&step)) {
02635 if_stmt = Find_Unseen_If_Outside_Do (step);
02636 if (NULL != if_stmt)
02637 return step;
02638 }
02639 return NULL;
02640 }
02641
02642 static WN *
02643 Find_Stmt_With_Enclosing_If(QUEUE<WN *> *inp)
02644 {
02645 WN *step;
02646 QUEUE_ITER<WN *> iter(inp);
02647 WN *if_stmt;
02648
02649 while (iter.Step (&step)) {
02650 if_stmt = Find_Enclosing_Unseen_If (step);
02651 if (NULL != if_stmt)
02652 return step;
02653 }
02654 return NULL;
02655 }
02656
02657 static BOOL
02658 _xanalyze_stmt_for_conds(WN *stmt)
02659 {
02660 WN *step, *dup, *enclosing_do;
02661 IF_INFO *if_info;
02662 ACCESS_ARRAY *ar;
02663 INT64 do_step;
02664 BOOL retval;
02665
02666 step = Shackle_Unseen_Highest_Enclosing_If (stmt);
02667 if (NULL == step) {
02668 return FALSE;
02669 }
02670 assert (OPC_IF == WN_opcode (step));
02671 enclosing_do = Enclosing_Do_Loop (step);
02672 if (NULL == enclosing_do) {
02673 Shackle_If_Seen_Set (step);
02674 return FALSE;
02675 }
02676 do_step = determine_if_sinkable_in_do (step, enclosing_do);
02677 if (shackle_if_debug_level > 1) {
02678 fprintf(stdout, "The step of the do loop is %d\n",
02679 (INT32) do_step);
02680 }
02681 if_info = Get_If_Info (step);
02682 ar = if_info->Condition;
02683 if (shackle_if_debug_level > 1) {
02684 fprintf(stdout, "Analysing if condition\n");
02685 ar->Print (stdout, TRUE);
02686 }
02687 if (0 != do_step) {
02688 MEM_POOL_Push (shackle_if_pool);
02689 retval = Sink_If2do (step, ar);
02690 MEM_POOL_Pop (shackle_if_pool);
02691 return retval;
02692 } else {
02693 Shackle_If_Seen_Set (step);
02694
02695 }
02696
02697 return FALSE;
02698 }
02699
02700 static void
02701 Initialize_Ifs_Unseen(WN *func_nd)
02702 {
02703 switch (WN_opcode (func_nd)) {
02704 case OPC_IF:
02705 Shackle_If_Unseen_Set (func_nd);
02706 break;
02707 }
02708 FOR_CHILDREN (func_nd, child, ignCount) {
02709 Initialize_Ifs_Unseen (child);
02710 }
02711 END_CHILDREN;
02712 }
02713
02714 BOOL
02715 analyze_stmts_in_func_for_if (WN *func_nd)
02716 {
02717 QUEUE_ITER<WN *> *iter;
02718 WN *stmt;
02719 IF_INFO *if_info;
02720 ACCESS_ARRAY *ar;
02721 WN *dup;
02722 BOOL recomp;
02723 QUEUE<WN *> *new_stmts;
02724 extern QUEUE<WN *> *gather_stmts_in_func(WN *);
02725 WN *empty, *delete_stmt;
02726
02727 Initialize_Ifs_Unseen (func_nd);
02728 new_stmts = gather_stmts_in_func (func_nd);
02729 while (1) {
02730 stmt = Find_Unseen_If_Outside_Do (new_stmts);
02731 if (NULL == stmt)
02732 stmt = Find_Stmt_With_Enclosing_If (new_stmts);
02733 if (NULL == stmt)
02734 return FALSE;
02735 recomp = _xanalyze_stmt_for_conds (stmt);
02736 if (recomp) {
02737 LWN_Parentize (func_nd);
02738 LNO_Build_Access (func_nd, &LNO_default_pool);
02739 Remove_Redundant_And_Inconsistent_If (func_nd);
02740 empty = Largest_Empty_Subtree (func_nd);
02741 if (empty) {
02742 delete_stmt = LWN_Extract_From_Block (empty);
02743 Shackle_LWN_Delete_Tree (delete_stmt);
02744 }
02745 new_stmts = gather_stmts_in_func (func_nd);
02746 }
02747 }
02748 }
02749
02750
02751
02752
02753 static WN *
02754 Another_Expression_Comes_From_Loop(WN *root, WN *mask)
02755 {
02756 if (root == mask)
02757 return NULL;
02758 DU_MANAGER *du = Du_Mgr;
02759 if (OPR_LDID == WN_operator (root)) {
02760 DEF_LIST *def_list = du->Ud_Get_Def (root);
02761 DEF_LIST_ITER iter (def_list);
02762 const DU_NODE *node = NULL;
02763 for (node = iter.First();
02764 !iter.Is_Empty();
02765 node = iter.Next()) {
02766 WN *def = node->Wn();
02767 if ((NULL != LWN_Get_Parent (def)) &&
02768 (OPC_DO_LOOP == WN_opcode (LWN_Get_Parent (def))))
02769 return root;
02770 }
02771 return NULL;
02772 } else {
02773 FOR_CHILDREN (root, child, ignCount) {
02774 WN *result =
02775 Another_Expression_Comes_From_Loop (child, mask);
02776 if (NULL != result)
02777 return result;
02778 }
02779 END_CHILDREN;
02780 return NULL;
02781 }
02782 }
02783 static WN*
02784 Find_Do_Loop_With_Min(WN *root, WN **expr1, WN **expr2)
02785 {
02786 if (OPC_DO_LOOP == WN_opcode (root)) {
02787 if (!Do_Loop_Is_Unsigned (root))
02788 if (FALSE == Upper_Bound_Standardize (WN_end (root), TRUE)) {
02789 *expr1 = NULL;
02790 *expr2 = NULL;
02791 return NULL;
02792 }
02793 WN *wn1 =
02794 Another_Expression_Comes_From_Loop (WN_kid1 (WN_end (root)),
02795 NULL);
02796 if (NULL == wn1) {
02797 *expr1 = NULL;
02798 *expr2 = NULL;
02799 return NULL;
02800 }
02801 WN *parent, *other, *wn2 = NULL, *same;
02802 parent = LWN_Get_Parent (wn1);
02803 same = wn1;
02804
02805 while (NULL != parent) {
02806 if (OPR_MIN == WN_operator (parent)) {
02807 if (same == WN_kid0 (parent))
02808 other = WN_kid1 (parent);
02809 else {
02810 assert (WN_kid1 (parent) == same);
02811 other = WN_kid0 (parent);
02812 }
02813 wn2 = Another_Expression_Comes_From_Loop (other, NULL);
02814 if (NULL != wn2) {
02815 while (OPR_MIN !=
02816 WN_operator (LWN_Get_Parent (wn1)))
02817 wn1 = LWN_Get_Parent (wn1);
02818 while (OPR_MIN !=
02819 WN_operator (LWN_Get_Parent (wn2)))
02820 wn2 = LWN_Get_Parent (wn2);
02821 *expr1 = wn1;
02822 *expr2 = wn2;
02823 return root;
02824 }
02825 }
02826 same = parent;
02827 parent = LWN_Get_Parent (parent);
02828 }
02829 *expr1 = *expr2 = NULL;
02830 return NULL;
02831 }
02832 *expr1 = *expr2 = NULL;
02833 return NULL;
02834 }
02835
02836 static WN *
02837 Recursively_Find_Do_Loop_With_Min(WN *root, WN **expr1, WN **expr2)
02838 {
02839 WN *result = NULL;
02840
02841 if (OPC_DO_LOOP == WN_opcode (root)) {
02842 result = Find_Do_Loop_With_Min (root, expr1, expr2);
02843 if (NULL != result)
02844 return result;
02845 }
02846 FOR_CHILDREN (root, child, ignCount) {
02847 result = Recursively_Find_Do_Loop_With_Min (child, expr1, expr2);
02848 if (NULL != result)
02849 return result;
02850 }
02851 END_CHILDREN;
02852 *expr1 = *expr2 = NULL;
02853 return NULL;
02854 }
02855
02856 static WN *
02857 Sibling(WN *wn)
02858 {
02859 WN *parent = LWN_Get_Parent (wn);
02860 if (wn == WN_kid0 (parent))
02861 return WN_kid1 (parent);
02862 else
02863 return WN_kid0 (parent);
02864 }
02865
02866 static BOOL
02867 Has_Sibling_In_Block(WN *wn)
02868 {
02869 WN *parent = LWN_Get_Parent (wn);
02870 FmtAssert (OPC_BLOCK == WN_opcode (parent),
02871 ("Parent must be a block"));
02872 FOR_CHILDREN (parent, child, ignCount) {
02873 if (child != wn)
02874 return TRUE;
02875 }
02876 END_CHILDREN;
02877 return FALSE;
02878 }
02879
02880 void
02881 Convert_Do_Loops_Conditionals(WN *func_nd)
02882 {
02883 WN *do_loop, *wn1, *wn2;
02884 extern QUEUE<WN *> *gather_stmts_in_func(WN *);
02885 WN *fake_unroll[2];
02886
02887 do_loop = Recursively_Find_Do_Loop_With_Min (func_nd, &wn1, &wn2);
02888 if (NULL == do_loop)
02889 return;
02890 assert (NULL != do_loop);
02891 assert ((NULL != wn1) && (NULL != wn2) && (wn1 != wn2));
02892 INT32 loop_depth = Num_Common_Loops (do_loop, do_loop) - 1;
02893
02894
02895
02896 {
02897 WN *do_start = WN_start (do_loop);
02898 assert (OPR_STID == WN_operator (do_start));
02899 WN *do_start_kid = WN_kid0 (do_start);
02900 WN *if1_wn1 = LWN_Copy_Tree (wn1);
02901 fake_unroll[0] = wn1;
02902 fake_unroll[1] = if1_wn1;
02903 Unrolled_DU_Update (fake_unroll, 2, loop_depth-1);
02904 WN *if1_wn2 = LWN_Copy_Tree (do_start_kid);
02905 fake_unroll[0] = do_start_kid;
02906 fake_unroll[1] = if1_wn2;
02907 Unrolled_DU_Update (fake_unroll, 2, loop_depth-1);
02908 TYPE_ID rtype = WN_rtype (WN_end (do_loop));
02909 TYPE_ID index_type = WN_desc (do_start);
02910 WN *if1_cond = WN_CreateExp2
02911 (OPCODE_make_op (OPR_GE, rtype, Promote_Type (index_type)),
02912 if1_wn1, if1_wn2);
02913 if1_cond = Simplify_If_Conditional (if1_cond);
02914 WN *if1 = LWN_CreateIf (if1_cond,
02915 WN_CreateBlock(),
02916 WN_CreateBlock());
02917 Replace_WN (do_loop, if1);
02918 LWN_Insert_Block_After (WN_then (if1), NULL, do_loop);
02919 IF_INFO *ii =
02920 CXX_NEW (IF_INFO (&LNO_default_pool, TRUE,
02921 Tree_Has_Regions (if1)),
02922 &LNO_default_pool);
02923 WN_MAP_Set (LNO_Info_Map, if1, (void *) ii);
02924 DOLOOP_STACK do_stack (shackle_if_pool);
02925 Build_Doloop_Stack (if1, &do_stack);
02926 LNO_Build_If_Access (if1, &do_stack);
02927
02928 WN *if2_wn1 = LWN_Copy_Tree (wn2);
02929 fake_unroll[0] = wn2;
02930 fake_unroll[1] = if2_wn1;
02931 Unrolled_DU_Update (fake_unroll, 2, loop_depth-1);
02932 WN *if2_wn2 = LWN_Copy_Tree (do_start_kid);
02933 fake_unroll[0] = do_start_kid;
02934 fake_unroll[1] = if2_wn2;
02935 Unrolled_DU_Update (fake_unroll, 2, loop_depth-1);
02936 WN *if2_cond = WN_CreateExp2
02937 (OPCODE_make_op (OPR_GE, rtype, Promote_Type (index_type)),
02938 if2_wn1, if2_wn2);
02939 if2_cond = Simplify_If_Conditional (if2_cond);
02940 WN *if2 = LWN_CreateIf (if2_cond, WN_CreateBlock(),
02941 WN_CreateBlock());
02942 Replace_WN (if1, if2);
02943 LWN_Insert_Block_After (WN_then (if2), NULL, if1);
02944 ii = CXX_NEW (IF_INFO (&LNO_default_pool, TRUE,
02945 Tree_Has_Regions (if2)),
02946 &LNO_default_pool);
02947 WN_MAP_Set (LNO_Info_Map, if2, (void *) ii);
02948 Build_Doloop_Stack (if2, &do_stack);
02949 LNO_Build_If_Access (if2, &do_stack);
02950 }
02951
02952 WN *dup_loop = LWN_Copy_Tree (do_loop, TRUE, LNO_Info_Map,
02953 TRUE, shackle_if_copy_map1, TRUE);
02954
02955
02956
02957
02958
02959 {
02960 LWN_Insert_Block_After (NULL, do_loop, dup_loop);
02961 ARRAY_DIRECTED_GRAPH16 *dg = Array_Dependence_Graph;
02962 dg->Versioned_Dependences_Update (do_loop, dup_loop,
02963 loop_depth,
02964 shackle_if_copy_map1);
02965 fake_unroll[0] = do_loop;
02966 fake_unroll[1] = dup_loop;
02967 Unrolled_DU_Update (fake_unroll, 2, loop_depth-1);
02968
02969
02970 TYPE_ID rtype = WN_rtype (WN_end (do_loop));
02971 assert (WN_rtype (wn1) ==
02972 WN_rtype (wn2));
02973 TYPE_ID index_type = WN_rtype (wn1);
02974 WN *if_wn1 = LWN_Copy_Tree (wn1);
02975 WN *if_wn2 = LWN_Copy_Tree (wn2);
02976 fake_unroll[0] = wn1;
02977 fake_unroll[1] = if_wn1;
02978 Unrolled_DU_Update (fake_unroll, 2, loop_depth-1);
02979 fake_unroll[0] = wn2;
02980 fake_unroll[1] = if_wn2;
02981 Unrolled_DU_Update (fake_unroll, 2, loop_depth-1);
02982 WN *cond_to_insert = WN_CreateExp2
02983 (OPCODE_make_op (OPR_GT, rtype, Promote_Type (index_type)),
02984 if_wn1, if_wn2);
02985 cond_to_insert = Simplify_If_Conditional (cond_to_insert);
02986 WN *if_to_insert = LWN_CreateIf (cond_to_insert,
02987 WN_CreateBlock(),
02988 WN_CreateBlock());
02989 Replace_WN (do_loop, if_to_insert);
02990 LWN_Insert_Block_After (WN_then (if_to_insert), NULL,
02991 do_loop);
02992 IF_INFO *ii =
02993 CXX_NEW (IF_INFO (&LNO_default_pool, TRUE,
02994 Tree_Has_Regions (if_to_insert)),
02995 &LNO_default_pool);
02996 WN_MAP_Set (LNO_Info_Map, if_to_insert, (void *) ii);
02997 DOLOOP_STACK do_stack (shackle_if_pool);
02998 Build_Doloop_Stack (if_to_insert, &do_stack);
02999 LNO_Build_If_Access (if_to_insert, &do_stack);
03000
03001 WN *dup_wn1 = (WN *) WN_MAP_Get (shackle_if_copy_map1, wn1);
03002 WN *dup_wn2 = (WN *) WN_MAP_Get (shackle_if_copy_map1, wn2);
03003 WN *dup_if_wn1 = LWN_Copy_Tree (dup_wn1);
03004 WN *dup_if_wn2 = LWN_Copy_Tree (dup_wn2);
03005 fake_unroll[0] = dup_wn1;
03006 fake_unroll[1] = dup_if_wn1;
03007 Unrolled_DU_Update (fake_unroll, 2, loop_depth - 1);
03008 fake_unroll[0] = dup_wn2;
03009 fake_unroll[1] = dup_if_wn2;
03010 Unrolled_DU_Update (fake_unroll, 2, loop_depth - 1);
03011 WN *dup_cond_to_insert = WN_CreateExp2
03012 (OPCODE_make_op (OPR_LE, rtype, Promote_Type (index_type)),
03013 dup_if_wn1, dup_if_wn2);
03014 dup_cond_to_insert = Simplify_If_Conditional (dup_cond_to_insert);
03015 WN *dup_if_to_insert = LWN_CreateIf (dup_cond_to_insert,
03016 WN_CreateBlock(),
03017 WN_CreateBlock());
03018 Replace_WN (dup_loop, dup_if_to_insert);
03019 LWN_Insert_Block_After (WN_then (dup_if_to_insert), NULL,
03020 dup_loop);
03021 ii = CXX_NEW (IF_INFO (&LNO_default_pool, TRUE,
03022 Tree_Has_Regions (dup_if_to_insert)),
03023 &LNO_default_pool);
03024 WN_MAP_Set (LNO_Info_Map, dup_if_to_insert, (void *) ii);
03025 Build_Doloop_Stack (dup_if_to_insert, &do_stack);
03026 LNO_Build_If_Access (dup_if_to_insert, &do_stack);
03027
03028 WN *dummy_one = WN_CreateIntconst
03029 (OPCODE_make_op (OPR_INTCONST, Promote_Type (index_type),
03030 MTYPE_V),
03031 (INT64) 1);
03032 WN *dummy_two = WN_CreateIntconst
03033 (OPCODE_make_op (OPR_INTCONST, Promote_Type (index_type),
03034 MTYPE_V),
03035 (INT64) 2);
03036 WN *sib_wn1 = Sibling (wn1);
03037 if (sib_wn1 == wn2) {
03038 WN *parent = LWN_Get_Parent (wn1);
03039 FmtAssert (OPR_MIN == WN_operator (parent),
03040 ("Parent must be an OPR_MIN"));
03041 assert (LWN_Get_Parent (wn2) == parent);
03042 Replace_WN (wn2, dummy_one);
03043 Replace_WN (parent, wn2);
03044 Shackle_LWN_Delete_Tree (parent);
03045 Shackle_LWN_Delete_Tree (dummy_two);
03046 }
03047 else if (OPR_MIN == WN_operator (sib_wn1)) {
03048 WN *sib_wn1_kid0 = WN_kid0 (sib_wn1);
03049 WN *sib_wn1_kid1 = WN_kid1 (sib_wn1);
03050 Replace_WN (sib_wn1_kid0, dummy_one);
03051 Replace_WN (sib_wn1_kid1, dummy_two);
03052 Replace_WN (wn1, sib_wn1_kid0);
03053 Replace_WN (sib_wn1, sib_wn1_kid1);
03054 Shackle_LWN_Delete_Tree (wn1);
03055 Shackle_LWN_Delete_Tree (sib_wn1);
03056 } else {
03057 WN *grand_parent = LWN_Get_Parent (LWN_Get_Parent (wn1));
03058 FmtAssert (NULL != grand_parent, ("Grand parent cannot be 0"));
03059 FmtAssert (OPR_MIN ==
03060 WN_operator (grand_parent),
03061 ("Grand parent must have OPR_MIN as operator"));
03062 Replace_WN (sib_wn1, dummy_one);
03063 Replace_WN (LWN_Get_Parent (wn1), sib_wn1);
03064 Shackle_LWN_Delete_Tree (dummy_two);
03065 Shackle_LWN_Delete_Tree (LWN_Get_Parent (wn1));
03066 }
03067 dummy_one = WN_CreateIntconst
03068 (OPCODE_make_op (OPR_INTCONST, Promote_Type (index_type),
03069 MTYPE_V),
03070 (INT64) 1);
03071 dummy_two = WN_CreateIntconst
03072 (OPCODE_make_op (OPR_INTCONST, Promote_Type (index_type),
03073 MTYPE_V),
03074 (INT64) 2);
03075 WN *sib_dup_wn2 = Sibling (dup_wn2);
03076 if (sib_dup_wn2 == dup_wn1) {
03077 WN *parent = LWN_Get_Parent (dup_wn1);
03078 FmtAssert (OPR_MIN == WN_operator (parent),
03079 ("Parent must be an OPR_MIN"));
03080 FmtAssert (LWN_Get_Parent (dup_wn2) == parent,
03081 ("Parents of siblings must be identical"));
03082 Replace_WN (dup_wn1, dummy_one);
03083 Replace_WN (parent, dup_wn1);
03084 Shackle_LWN_Delete_Tree (parent);
03085 Shackle_LWN_Delete_Tree (dummy_two);
03086 }
03087 else if (OPR_MIN == WN_operator (sib_dup_wn2)) {
03088 WN *sib_dup_wn2_kid0 = WN_kid0 (sib_dup_wn2);
03089 WN *sib_dup_wn2_kid1 = WN_kid1 (sib_dup_wn2);
03090 Replace_WN (sib_dup_wn2_kid0, dummy_one);
03091 Replace_WN (sib_dup_wn2_kid1, dummy_two);
03092 Replace_WN (dup_wn2, sib_dup_wn2_kid0);
03093 Replace_WN (sib_dup_wn2, sib_dup_wn2_kid1);
03094 Shackle_LWN_Delete_Tree (dup_wn2);
03095 Shackle_LWN_Delete_Tree (sib_dup_wn2);
03096 } else {
03097 WN *grand_parent = LWN_Get_Parent (LWN_Get_Parent (dup_wn2));
03098 FmtAssert (NULL != grand_parent, ("Grand parent cannot be 0"));
03099 FmtAssert (OPR_MIN ==
03100 WN_operator (grand_parent),
03101 ("Grand parent must have OPR_MIN as operator"));
03102 Replace_WN (sib_dup_wn2, dummy_one);
03103 Replace_WN (LWN_Get_Parent (dup_wn2), sib_dup_wn2);
03104 Shackle_LWN_Delete_Tree (LWN_Get_Parent (dup_wn2));
03105 Shackle_LWN_Delete_Tree (dummy_two);
03106 }
03107 QUEUE<WN *> *new_stmts = gather_stmts_in_func (func_nd);
03108 analyze_stmts_in_func_for_if (func_nd);
03109 Convert_Do_Loops_Conditionals (func_nd);
03110 }
03111 }
03112
03113 static void
03114 Invert_Conditional (WN *wn)
03115 {
03116 OPERATOR opr = WN_operator (wn);
03117 FmtAssert (OPR_LE == opr || OPR_LT == opr || OPR_GE == opr ||
03118 OPR_GT == opr || OPR_INTCONST == opr,
03119 ("Unforseen operator in conditional!"));
03120 TYPE_ID index_type = WN_desc (wn);
03121 TYPE_ID rtype = WN_rtype (wn);
03122 if (OPR_INTCONST == opr) {
03123 if (0 == WN_const_val (wn))
03124 WN_const_val (wn) = (INT64) 1;
03125 else
03126 WN_const_val (wn) = (INT64) 0;
03127 }
03128 else {
03129 WN *wn1 = WN_kid0 (wn);
03130 WN *wn2 = WN_kid1 (wn);
03131 OPERATOR new_opr;
03132 if (OPR_LT == opr)
03133 new_opr = OPR_GE;
03134 else if (OPR_LE == opr)
03135 new_opr = OPR_GT;
03136 else if (OPR_GT == opr)
03137 new_opr = OPR_LE;
03138 else if (OPR_GE == opr)
03139 new_opr = OPR_LT;
03140 WN *dummy1 = WN_CreateComment ("dummy1");
03141 WN *dummy2 = WN_CreateComment ("dummy2");
03142 Replace_WN (wn1, dummy1);
03143 Replace_WN (wn2, dummy2);
03144 WN *new_cond = WN_CreateExp2 (OPCODE_make_op (new_opr,
03145 rtype,
03146 index_type),
03147 wn1, wn2);
03148 Replace_WN (wn, new_cond);
03149 Shackle_LWN_Delete_Tree (wn);
03150 }
03151 }
03152
03153 static void
03154 Maybe_Handle_Sink_Promotion_Case (WN *if_stmt,
03155 WN *do_loop,
03156 INT32 loop_depth,
03157 ACCESS_VECTOR *cond)
03158 {
03159 WN *new_if;
03160
03161
03162
03163
03164
03165
03166 {
03167 WN *main_if, *main_cond1, *main_cond2, *fake_unroll[2];
03168 WN *cond1 = canonicalize_if_condition (WN_if_test (if_stmt),
03169 loop_depth);
03170 main_cond1 =
03171 return_upper_bound (cond1,
03172 SYMBOL (WN_index (do_loop)),
03173 cond->Loop_Coeff (loop_depth),
03174 (cond->Loop_Coeff (loop_depth) > 0));
03175 if (cond->Loop_Coeff (loop_depth) < 0)
03176 main_cond1 = return_upper_boundplus1 (main_cond1,
03177 loop_depth);
03178
03179
03180
03181 if (cond->Loop_Coeff (loop_depth) < 0) {
03182 Upper_Bound_Standardize (WN_end (do_loop), FALSE);
03183 main_cond2 = LWN_Copy_Tree (WN_kid1 (WN_end (do_loop)));
03184
03185 fake_unroll[0] = WN_kid1 (WN_end (do_loop));
03186 fake_unroll[1] = main_cond2;
03187 Unrolled_DU_Update (fake_unroll, 2, loop_depth);
03188 } else {
03189 assert (OPR_STID ==
03190 WN_operator (WN_start (do_loop)));
03191 main_cond2 = LWN_Copy_Tree (WN_kid0 (WN_start (do_loop)));
03192 fake_unroll[0] = WN_kid0 (WN_start (do_loop));
03193 fake_unroll[1] = main_cond2;
03194 Unrolled_DU_Update (fake_unroll, 2, loop_depth);
03195 }
03196 #ifdef KEY
03197
03198
03199
03200
03201
03202
03203
03204 assert ((WN_rtype(main_cond1) == WN_rtype(main_cond2)) ||
03205 (MTYPE_is_integral(WN_rtype(main_cond1)) &&
03206 MTYPE_is_integral(WN_rtype(main_cond2)) &&
03207 MTYPE_size_reg(WN_rtype(main_cond1)) ==
03208 MTYPE_size_reg(WN_rtype(main_cond2)) &&
03209 ((WN_operator(main_cond1) == OPR_INTCONST &&
03210 !MTYPE_is_signed(WN_rtype(main_cond1)) &&
03211 MTYPE_is_signed(WN_rtype(main_cond2))) ||
03212 (WN_operator(main_cond2) == OPR_INTCONST &&
03213 !MTYPE_is_signed(WN_rtype(main_cond2)) &&
03214 MTYPE_is_signed(WN_rtype(main_cond1))))));
03215 #else
03216 assert (WN_rtype (main_cond1) ==
03217 WN_rtype (main_cond2));
03218 #endif
03219 TYPE_ID index_type = WN_rtype (main_cond1);
03220 TYPE_ID rtype = WN_rtype (WN_if_test (if_stmt));
03221 WN *main_cond_to_insert;
03222 if (cond->Loop_Coeff (loop_depth) > 0) {
03223 main_cond_to_insert = WN_CreateExp2
03224 (OPCODE_make_op (OPR_GE, rtype, Promote_Type (index_type)),
03225 main_cond1, main_cond2);
03226 } else {
03227 main_cond_to_insert = WN_CreateExp2
03228 (OPCODE_make_op (OPR_LE, rtype, Promote_Type (index_type)),
03229 main_cond1, main_cond2);
03230 }
03231 main_cond_to_insert =
03232 Simplify_If_Conditional (main_cond_to_insert);
03233 Simplify_Cond_With_Div_Floor (main_cond_to_insert);
03234 main_if = LWN_CreateIf (main_cond_to_insert,
03235 WN_CreateBlock(),
03236 WN_CreateBlock());
03237 new_if = main_if;
03238 Replace_WN (do_loop, main_if);
03239 LWN_Insert_Block_After (WN_then (main_if), NULL, do_loop);
03240 IF_INFO *ii =
03241 CXX_NEW (IF_INFO (&LNO_default_pool, TRUE,
03242 Tree_Has_Regions (main_if)),
03243 &LNO_default_pool);
03244 WN_MAP_Set (LNO_Info_Map, main_if, (void *) ii);
03245 DOLOOP_STACK do_stack (shackle_if_pool);
03246 Build_Doloop_Stack (main_if, &do_stack);
03247 LNO_Build_If_Access (main_if, &do_stack);
03248 }
03249
03250
03251
03252 WN *if_to_insert, *delete_stmt, *ubnd, *lbnd, *delete_node;
03253 TYPE_ID index_type;
03254 TYPE_ID rtype = WN_rtype (WN_if_test (if_stmt));
03255
03256 assert (cond->Loop_Coeff (loop_depth) != 0);
03257 WN *dup_loop = LWN_Copy_Tree (do_loop, TRUE, LNO_Info_Map,
03258 TRUE, shackle_if_copy_map1, TRUE);
03259 Copy_Shackle_Prompf_Info (do_loop, dup_loop);
03260 LWN_Insert_Block_After (NULL, do_loop, dup_loop);
03261 ARRAY_DIRECTED_GRAPH16 *dg = Array_Dependence_Graph;
03262 dg->Versioned_Dependences_Update (do_loop, dup_loop, loop_depth,
03263 shackle_if_copy_map1);
03264 WN *fake_unroll[2];
03265 fake_unroll[0] = do_loop;
03266 fake_unroll[1] = dup_loop;
03267 Unrolled_DU_Update (fake_unroll, 2, loop_depth - 1);
03268 WN *dup_if_stmt = (WN *) WN_MAP_Get (shackle_if_copy_map1,
03269 if_stmt);
03270
03271
03272
03273
03274
03275
03276
03277
03278
03279
03280
03281 {
03282 WN *cond1 = canonicalize_if_condition (WN_if_test (if_stmt),
03283 loop_depth);
03284 WN *up_cond1 =
03285 return_upper_bound (cond1,
03286 SYMBOL (WN_index (do_loop)),
03287 cond->Loop_Coeff (loop_depth),
03288 (cond->Loop_Coeff (loop_depth) > 0));
03289 if (cond->Loop_Coeff (loop_depth) < 0) {
03290 up_cond1 = return_upper_boundplus1 (up_cond1,
03291 loop_depth);
03292 }
03293 WN *up_cond2;
03294 if (cond->Loop_Coeff (loop_depth) > 0) {
03295 WN *cond2 = canonicalize_if_condition (WN_end (do_loop),
03296 loop_depth);
03297 up_cond2 = return_upper_bound (cond2,
03298 SYMBOL (WN_index (do_loop)),
03299 cond->Loop_Coeff (loop_depth),
03300 TRUE);
03301 } else {
03302 assert (OPR_STID ==
03303 WN_operator (WN_start (do_loop)));
03304 up_cond2 = LWN_Copy_Tree (WN_kid0 (WN_start (do_loop)));
03305 fake_unroll[0] = WN_kid0 (WN_start (do_loop));
03306 fake_unroll[1] = up_cond2;
03307 Unrolled_DU_Update (fake_unroll, 2, loop_depth);
03308 }
03309 #ifdef KEY
03310
03311
03312
03313
03314
03315
03316
03317 assert ((WN_rtype(up_cond1) == WN_rtype(up_cond2)) ||
03318 (MTYPE_is_integral(WN_rtype(up_cond1)) &&
03319 MTYPE_is_integral(WN_rtype(up_cond2)) &&
03320 MTYPE_size_reg(WN_rtype(up_cond1)) ==
03321 MTYPE_size_reg(WN_rtype(up_cond2)) &&
03322 ((WN_operator(up_cond1) == OPR_INTCONST &&
03323 !MTYPE_is_signed(WN_rtype(up_cond1)) &&
03324 MTYPE_is_signed(WN_rtype(up_cond2))) ||
03325 (WN_operator(up_cond2) == OPR_INTCONST &&
03326 !MTYPE_is_signed(WN_rtype(up_cond2)) &&
03327 MTYPE_is_signed(WN_rtype(up_cond1))))));
03328 #else
03329 assert (WN_rtype (up_cond1) ==
03330 WN_rtype (up_cond2));
03331 #endif
03332 TYPE_ID index_type = WN_rtype (up_cond1);
03333 WN *cond_to_insert;
03334 if (cond->Loop_Coeff (loop_depth) > 0) {
03335 cond_to_insert = WN_CreateExp2
03336 (OPCODE_make_op (OPR_GT, rtype, Promote_Type (index_type)),
03337 up_cond1, up_cond2);
03338 } else {
03339 cond_to_insert = WN_CreateExp2
03340 (OPCODE_make_op (OPR_LT, rtype, Promote_Type (index_type)),
03341 up_cond1, up_cond2);
03342 }
03343 cond_to_insert = Simplify_If_Conditional (cond_to_insert);
03344 Simplify_Cond_With_Div_Floor (cond_to_insert);
03345 if_to_insert = LWN_CreateIf (cond_to_insert,
03346 WN_CreateBlock(),
03347 WN_CreateBlock());
03348 Replace_WN (do_loop, if_to_insert);
03349 LWN_Insert_Block_After (WN_then (if_to_insert), NULL,
03350 do_loop);
03351 }
03352 IF_INFO *ii =
03353 CXX_NEW (IF_INFO (&LNO_default_pool, TRUE,
03354 Tree_Has_Regions (if_to_insert)),
03355 &LNO_default_pool);
03356 WN_MAP_Set (LNO_Info_Map, if_to_insert, (void *) ii);
03357 DOLOOP_STACK do_stack (shackle_if_pool);
03358 Build_Doloop_Stack (if_to_insert, &do_stack);
03359 LNO_Build_If_Access (if_to_insert, &do_stack);
03360
03361
03362
03363
03364 {
03365 WN *cond1 = canonicalize_if_condition (WN_if_test (dup_if_stmt),
03366 loop_depth);
03367 WN *up_cond1 =
03368 return_upper_bound (cond1,
03369 SYMBOL (WN_index (dup_loop)),
03370 cond->Loop_Coeff (loop_depth),
03371 (cond->Loop_Coeff (loop_depth) > 0));
03372 if (cond->Loop_Coeff (loop_depth) < 0)
03373 up_cond1 = return_upper_boundplus1 (up_cond1,
03374 loop_depth);
03375 WN *up_cond2;
03376 if (cond->Loop_Coeff (loop_depth) > 0) {
03377 WN *cond2 = canonicalize_if_condition (WN_end (dup_loop),
03378 loop_depth);
03379 up_cond2 = return_upper_bound (cond2,
03380 SYMBOL (WN_index (dup_loop)),
03381 cond->Loop_Coeff (loop_depth),
03382 TRUE);
03383 } else {
03384 assert (OPR_STID ==
03385 WN_operator (WN_start (dup_loop)));
03386 up_cond2 = LWN_Copy_Tree (WN_kid0 (WN_start (dup_loop)));
03387 fake_unroll[0] = WN_kid0 (WN_start (dup_loop));
03388 fake_unroll[1] = up_cond2;
03389 Unrolled_DU_Update (fake_unroll, 2, loop_depth);
03390 }
03391 #ifdef KEY
03392
03393
03394
03395
03396
03397
03398
03399 assert ((WN_rtype(up_cond1) == WN_rtype(up_cond2)) ||
03400 (MTYPE_is_integral(WN_rtype(up_cond1)) &&
03401 MTYPE_is_integral(WN_rtype(up_cond2)) &&
03402 MTYPE_size_reg(WN_rtype(up_cond1)) ==
03403 MTYPE_size_reg(WN_rtype(up_cond2)) &&
03404 ((WN_operator(up_cond1) == OPR_INTCONST &&
03405 !MTYPE_is_signed(WN_rtype(up_cond1)) &&
03406 MTYPE_is_signed(WN_rtype(up_cond2))) ||
03407 (WN_operator(up_cond2) == OPR_INTCONST &&
03408 !MTYPE_is_signed(WN_rtype(up_cond2)) &&
03409 MTYPE_is_signed(WN_rtype(up_cond1))))));
03410 #else
03411 assert (WN_rtype (up_cond1) ==
03412 WN_rtype (up_cond2));
03413 #endif
03414 TYPE_ID index_type = WN_rtype (up_cond1);
03415 WN *cond_to_insert;
03416 if (cond->Loop_Coeff (loop_depth) > 0)
03417 cond_to_insert = WN_CreateExp2
03418 (OPCODE_make_op (OPR_GT, rtype, Promote_Type (index_type)),
03419 up_cond1, up_cond2);
03420 else
03421 cond_to_insert = WN_CreateExp2
03422 (OPCODE_make_op (OPR_LT, rtype, Promote_Type (index_type)),
03423 up_cond1, up_cond2);
03424 cond_to_insert = Simplify_If_Conditional (cond_to_insert);
03425 Simplify_Cond_With_Div_Floor (cond_to_insert);
03426 if_to_insert = LWN_CreateIf (cond_to_insert,
03427 WN_CreateBlock(),
03428 WN_CreateBlock());
03429 Invert_Conditional (cond_to_insert);
03430 Replace_WN (dup_loop, if_to_insert);
03431 LWN_Insert_Block_After (WN_then (if_to_insert), NULL,
03432 dup_loop);
03433 }
03434 ii = CXX_NEW (IF_INFO (&LNO_default_pool, TRUE,
03435 Tree_Has_Regions (if_to_insert)),
03436 &LNO_default_pool);
03437 WN_MAP_Set (LNO_Info_Map, if_to_insert, (void *) ii);
03438 Build_Doloop_Stack (if_to_insert, &do_stack);
03439 LNO_Build_If_Access (if_to_insert, &do_stack);
03440
03441 {
03442 WN *dummy1, *dummy2, *dummy3;
03443 TYPE_ID index_type, rtype;
03444 WN *dup_if = LWN_Copy_Tree (new_if, TRUE, LNO_Info_Map,
03445 TRUE, shackle_if_copy_map1);
03446 Copy_Shackle_Prompf_Info (new_if, dup_if);
03447 LWN_Insert_Block_After (NULL, new_if, dup_if);
03448 ARRAY_DIRECTED_GRAPH16 *dg = Array_Dependence_Graph;
03449 dg->Versioned_Dependences_Update (new_if, dup_if,
03450 loop_depth,
03451 shackle_if_copy_map1);
03452 WN *fake_unroll[2];
03453 fake_unroll[0] = new_if;
03454 fake_unroll[1] = dup_if;
03455 Unrolled_DU_Update (fake_unroll, 2, loop_depth - 1);
03456
03457 WN *cond = WN_if_test (dup_if);
03458 Invert_Conditional (cond);
03459 ii = CXX_NEW (IF_INFO (&LNO_default_pool, TRUE,
03460 Tree_Has_Regions (dup_if)),
03461 &LNO_default_pool);
03462 WN_MAP_Set (LNO_Info_Map, dup_if, (void *) ii);
03463 Build_Doloop_Stack (dup_if, &do_stack);
03464 LNO_Build_If_Access (dup_if, &do_stack);
03465 }
03466 for (INT32 i = 0; i < 2; i++) {
03467 }
03468 }
03469
03470 static QUEUE<WN *> *
03471 Shackleable_Ifs_Surrounding_Stmt(WN *wn)
03472 {
03473 QUEUE<WN *> *result =
03474 CXX_NEW (QUEUE<WN *> (shackle_if_pool), shackle_if_pool);
03475 WN *step = wn;
03476 BOOL this_if_bad;
03477
03478 while (NULL != step) {
03479 this_if_bad = FALSE;
03480 if (OPC_IF == WN_opcode (step) && Shackle_If_Unseen (step)) {
03481 IF_INFO *ii = (IF_INFO *) WN_MAP_Get (LNO_Info_Map, step);
03482 ACCESS_ARRAY *ar = ii->Condition;
03483 if (ar->Too_Messy)
03484 this_if_bad = TRUE;
03485 else
03486 for (INT32 i = 0; i < ar->Num_Vec(); i++)
03487 if (ar->Dim (i)->Too_Messy) {
03488 this_if_bad = TRUE;
03489 break;
03490 }
03491 if (!this_if_bad)
03492 result->Add_Tail_Q (step);
03493 else
03494 Shackle_If_Seen_Set (step);
03495 }
03496 step = LWN_Get_Parent (step);
03497 }
03498 return result;
03499 }
03500
03501 static INT32
03502 Shackle_Do_Depth_For_If(WN *if_stmt)
03503 {
03504 FmtAssert (OPC_IF == WN_opcode (if_stmt),
03505 ("Shackle_Do_Depth_For_If called with non if!"));
03506 INT32 i, j;
03507 IF_INFO *ii = (IF_INFO *) WN_MAP_Get (LNO_Info_Map, if_stmt);
03508 ACCESS_ARRAY *ar = ii->Condition;
03509 if (ar->Too_Messy)
03510 return -1;
03511 for (j = 0; j < ar->Num_Vec(); j++)
03512 if (ar->Dim(j)->Too_Messy)
03513 return -1;
03514 INT32 max_depth = ar->Dim(0)->Nest_Depth();
03515 for (i = max_depth; i >= 0; i--) {
03516 for (j = 0; j < ar->Num_Vec(); j++)
03517 if (ar->Dim(j)->Loop_Coeff (i) != 0)
03518 return i;
03519 }
03520
03521
03522 return 0;
03523 }
03524
03525
03526 static WN*
03527 Shackle_Unseen_Highest_Enclosing_If(WN *stmt)
03528 {
03529 QUEUE<WN *> *enclosing_ifs =
03530 Shackleable_Ifs_Surrounding_Stmt (stmt);
03531 if (enclosing_ifs->Queue_Isempty())
03532 return NULL;
03533 QUEUE_ITER<WN *> iter(enclosing_ifs);
03534 WN *step;
03535 BOOL found_if = FALSE;
03536 INT32 depth, min;
03537 WN *result_if = NULL;
03538
03539 while (iter.Step (&step)) {
03540 if (Shackle_If_Unseen (step)) {
03541 depth = Shackle_Do_Depth_For_If (step);
03542 if (-1 != depth && !found_if) {
03543 found_if = TRUE;
03544 result_if = step;
03545 min = depth;
03546 }
03547 else if (-1 != depth && depth <= min) {
03548 min = depth;
03549 result_if = step;
03550 }
03551 }
03552 }
03553 return result_if;
03554 }
03555
03556
03557
03558 void
03559 shackle_if_init(MEM_POOL *pool)
03560 {
03561 shackle_if_pool = pool;
03562 MEM_POOL_Push (shackle_if_pool);
03563 shackle_if_copy_map1 = WN_MAP_Create (&shackle_map_pool);
03564 shackle_if_if_map = WN_MAP32_Create (&shackle_map_pool);
03565 if (Get_Trace(TP_LNOPT2, TT_SHACKLE_DEBUG))
03566 shackle_if_debug_level = 1;
03567 else
03568 shackle_if_debug_level = 0;
03569 if (Prompf_Info != NULL && Prompf_Info->Is_Enabled())
03570 Prompf_Elimination_Queue =
03571 CXX_NEW (QUEUE<INT32> (&LNO_local_pool),
03572 &LNO_local_pool);
03573 }
03574
03575 static void
03576 Deferred_Shackle_Prompf_Eliminate(INT32 map_id)
03577 {
03578
03579 Prompf_Elimination_Queue->Add_Tail_Q (map_id);
03580 }
03581 static void
03582 Finalize_Shackle_Prompf_Elimination(void)
03583 {
03584 QUEUE_ITER<INT32> iter(Prompf_Elimination_Queue);
03585 INT32 map_id;
03586
03587 while (iter.Step (&map_id)) {
03588 Prompf_Info->Elimination (map_id);
03589 }
03590 }
03591
03592 void
03593 shackle_if_finalize()
03594 {
03595 if (Prompf_Info != NULL && Prompf_Info->Is_Enabled())
03596 Finalize_Shackle_Prompf_Elimination();
03597 WN_MAP_Delete (shackle_if_if_map);
03598 WN_MAP_Delete (shackle_if_copy_map1);
03599 MEM_POOL_Pop (shackle_if_pool);
03600 }
03601