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 #define __STDC_LIMIT_MACROS
00041 #include <stdint.h>
00042 #ifdef USE_PCH
00043 #include "lno_pch.h"
00044 #endif // USE_PCH
00045 #pragma hdrstop
00046
00047 #include <sys/types.h>
00048 #include <stdio.h>
00049 #include <assert.h>
00050 #include "lnopt_main.h"
00051 #include "access_main.h"
00052 #include "access_vector.h"
00053 #include "dep.h"
00054 #include "cxx_memory.h"
00055 #include "soe.h"
00056 #include "dnf.h"
00057 #include "cxx_queue.h"
00058 #include "lwn_util.h"
00059 #include "shackle_ifs.h"
00060 #include "opt_du.h"
00061 #include "lego_util.h"
00062 #include "fiz_fuse.h"
00063 #include "errors.h"
00064 #include "whirl2src.h"
00065 #include "scalar_expand.h"
00066 #include "shackle.h"
00067 #include "prompf.h"
00068 #include "anl_driver.h"
00069 #include "debug.h"
00070 #ifdef KEY
00071 #include "wn_simp.h"
00072 #endif
00073
00074 #pragma weak New_Construct_Id
00075
00076 #define SHACKLE_CHAIN_VISITED 1
00077 #define SHACKLE_CHAIN_NOT_VISITED 0
00078
00079 #define Shackle_Chain_Visited_Set(wn) \
00080 WN_MAP32_Set (shackle_chain_map, (wn), SHACKLE_CHAIN_VISITED)
00081 #define Shackle_Chain_Not_Visited_Set(wn) \
00082 WN_MAP32_Set (shackle_chain_map, (wn), SHACKLE_CHAIN_NOT_VISITED)
00083 #define Shackle_Chain_Visited(wn) \
00084 (SHACKLE_CHAIN_VISITED == WN_MAP32_Get (shackle_chain_map, (wn)))
00085 #define Shackle_Chain_Not_Visited(wn) \
00086 (SHACKLE_CHAIN_NOT_VISITED==WN_MAP32_Get(shackle_chain_map,(wn)))
00087
00088
00089
00090 FILE *shackle_debug_file = stdout;
00091 extern ST *Get_ST_Base(WN *);
00092 static QUEUE<WN *> **shackle_chain_info;
00093 extern MEM_POOL LNO_default_pool;
00094
00095 MEM_POOL shackle_default_pool;
00096 MEM_POOL shackle_map_pool;
00097 WN_MAP shackle_prompf_id_map;
00098 WN_MAP shackle_ref_map;
00099 WN_MAP shackle_chain_map;
00100 WN_MAP shackle_chain_id_map;
00101 static INT32 shackle_chain_id_map_cnt;
00102 WN_MAP shackle_shackle_map;
00103 static INT32 shackle_debug_level;
00104 extern WN *Sh_LWN_CreateDivceil (TYPE_ID, WN *, WN *);
00105 extern WN *Sh_LWN_CreateDivfloor (TYPE_ID, WN *, WN *);
00106 extern BOOL Is_Parent_Of (WN *, WN*);
00107 extern WN *Simplify_If_Conditional (WN *);
00108 static BOOL _xis_legal_shackle(QUEUE<WN *> *stmts,
00109 QUEUE<SHACKLE_INFO*> *shq);
00110 extern BOOL Appropriate_Shackle_Size_Set (WN *,
00111 QUEUE<SHACKLE_INFO*>*);
00112 extern void Shackle_Mem_Initialize(MEM_POOL *);
00113 QUEUE<WN *> * gather_stmts_in_func(WN *func_nd);
00114 ST* Identical_Array_Refbase (WN *array1, WN *array2);
00115 SHACKLE_INFO * Shackle_Info_For_Symbol(QUEUE<SHACKLE_INFO *> *,
00116 const ST *);
00117 static void Dump_Shackle_Map_Info (WN *func_nd,
00118 QUEUE<WN *> *s);
00119
00120
00121
00122 static QUEUE<SHACKLE_INFO *> *
00123 Shackle_Info_For_Shackled_Arrays(WN *main_snl,
00124 QUEUE<SHACKLE_INFO *> *shq)
00125 {
00126 QUEUE<SHACKLE_INFO *> *result =
00127 CXX_NEW (QUEUE<SHACKLE_INFO *> (&shackle_default_pool),
00128 &shackle_default_pool);
00129 QUEUE<WN *> *stmts = gather_stmts_in_func (main_snl);
00130 QUEUE_ITER<WN *> iter(stmts);
00131 WN *step;
00132
00133 while (iter.Step (&step)) {
00134 QUEUE<WN *> *shackle = (QUEUE<WN *> *)
00135 WN_MAP_Get (shackle_shackle_map, step);
00136 FmtAssert (NULL != shackle && !shackle->Queue_Isempty(),
00137 ("Some shackled ref must exist!"));
00138 QUEUE_ITER<WN *> iter2(shackle);
00139 WN *step2;
00140 while (iter2.Step (&step2)) {
00141 const ST *st = Identical_Array_Refbase (step2, step2);
00142 FmtAssert (NULL != st, ("Can't have a NULL st shackle!"));
00143 SHACKLE_INFO *sh = Shackle_Info_For_Symbol (shq, st);
00144 FmtAssert (NULL != sh, ("Shackle info must exist for st!"));
00145 result->Index (sh, TRUE);
00146 }
00147 }
00148 return result;
00149 }
00150
00151 static void
00152 Shackle_Prompf_Map_Initialize (WN *wn)
00153 {
00154 if (Prompf_Info != NULL && Prompf_Info->Is_Enabled()) {
00155 INT32 id = WN_MAP32_Get (Prompf_Id_Map, wn);
00156 if (0 != id)
00157 WN_MAP32_Set (shackle_prompf_id_map, wn, id);
00158 FOR_CHILDREN (wn, child, ignCount) {
00159 Shackle_Prompf_Map_Initialize (child);
00160 }
00161 END_CHILDREN;
00162 }
00163 }
00164
00165 static BOOL
00166 Ref_Contains_Reuse_For_Loop (WN *array_ref, INT32 index,
00167 SHACKLE_INFO *sh)
00168 {
00169 if (NULL == array_ref)
00170 return FALSE;
00171 FmtAssert (OPR_ARRAY == WN_operator (array_ref),
00172 ("Call Ref_Contains_Reuse_For_Loop with OPR_ARRAY!"));
00173 const ST *st = Identical_Array_Refbase (array_ref, array_ref);
00174 if (st != sh->Symbol())
00175 return FALSE;
00176 ACCESS_ARRAY *ar =
00177 (ACCESS_ARRAY *) WN_MAP_Get (LNO_Info_Map, array_ref);
00178 if (ar->Too_Messy)
00179 return FALSE;
00180 INT32 i;
00181
00182 for (i = 0; i < ar->Num_Vec(); i++) {
00183 ACCESS_VECTOR *av = ar->Dim (i);
00184 if (av->Too_Messy)
00185 return FALSE;
00186 FmtAssert (0 <= index && index < av->Nest_Depth(),
00187 ("Invalid index for this array reference"));
00188
00189 if (0 != av->Loop_Coeff (index))
00190 return FALSE;
00191 }
00192 return TRUE;
00193 }
00194
00195 static BOOL
00196 Reuse_Exists_For_Loop_For_Array (WN *main_snl, INT32 index,
00197 SHACKLE_INFO *sh)
00198 {
00199 if (OPC_DO_LOOP == WN_opcode (main_snl))
00200 return Reuse_Exists_For_Loop_For_Array (WN_do_body (main_snl),
00201 index, sh);
00202 else if (OPR_ARRAY == WN_operator (main_snl))
00203 return Ref_Contains_Reuse_For_Loop (main_snl, index, sh);
00204 else {
00205 FOR_CHILDREN (main_snl, child, ignCount) {
00206 BOOL result =
00207 Reuse_Exists_For_Loop_For_Array (child, index, sh);
00208 if (TRUE == result)
00209 return TRUE;
00210 }
00211 END_CHILDREN;
00212 return FALSE;
00213 }
00214 }
00215
00216 static BOOL
00217 Reuse_Exists_In_Loop (WN *main_snl, QUEUE<SHACKLE_INFO *> *shq)
00218 {
00219 FmtAssert (OPC_DO_LOOP == WN_opcode (main_snl),
00220 ("Reuse_Exists_In_Loop must be called w/ do_loop"));
00221 INT32 depth = Do_Loop_Depth (main_snl);
00222 QUEUE<SHACKLE_INFO *> *shackled =
00223 Shackle_Info_For_Shackled_Arrays (main_snl, shq);
00224 QUEUE_ITER<SHACKLE_INFO *> iter(shackled);
00225 SHACKLE_INFO *sh;
00226
00227 while (iter.Step (&sh)) {
00228 if (Reuse_Exists_For_Loop_For_Array (main_snl, depth, sh))
00229 return TRUE;
00230 }
00231 return FALSE;
00232 }
00233
00234 static void
00235 Shackle_Postprocess_Do_Loop_Bounds(WN *wn)
00236 {
00237 if (OPC_DO_LOOP == WN_opcode (wn)) {
00238 DO_LOOP_INFO *dli = Get_Do_Loop_Info (wn);
00239 DOLOOP_STACK do_stack (&shackle_default_pool);
00240 Build_Doloop_Stack (wn, &do_stack);
00241 dli->Set_Est_Num_Iterations (&do_stack);
00242 }
00243 FOR_CHILDREN (wn, child, ignCount) {
00244 Shackle_Postprocess_Do_Loop_Bounds (child);
00245 }
00246 END_CHILDREN;
00247 }
00248
00249
00250 static WN *
00251 Find_Wn_Storing_ST_IDX(ST_IDX st, WN *wn)
00252 {
00253 WN *result;
00254
00255 switch (WN_operator (wn)) {
00256 case OPR_STID:
00257 if (st == WN_st_idx (wn))
00258 return wn;
00259 else
00260 return NULL;
00261 default:
00262 FOR_CHILDREN (wn, child, ignCount) {
00263 result = Find_Wn_Storing_ST_IDX (st, child);
00264 if (NULL != result)
00265 return result;
00266 }
00267 END_CHILDREN;
00268 return NULL;
00269 }
00270 }
00271
00272 INT64
00273 Shackle_Base_Type_Size (TY_IDX array_type)
00274 {
00275 if (array_type == TY_IDX_ZERO)
00276 return 0;
00277 else if (KIND_ARRAY != TY_kind (array_type))
00278 return 0;
00279 else {
00280 TY_IDX step = array_type;
00281 while (1) {
00282 if (KIND_SCALAR == TY_kind (step) ||
00283 KIND_STRUCT == TY_kind (step))
00284 return TY_size (step);
00285 else if (KIND_ARRAY == TY_kind (step))
00286 step = TY_etype (step);
00287 else
00288 return 0;
00289 }
00290 }
00291 }
00292
00293 TY_IDX
00294 Shackle_Is_Array_Type(TY_IDX ty)
00295 {
00296 if (ty == TY_IDX_ZERO)
00297 return TY_IDX_ZERO;
00298 if (KIND_ARRAY == TY_kind (ty))
00299 return ((Shackle_Base_Type_Size (ty) == 0) ? TY_IDX_ZERO : ty);
00300 else if (KIND_POINTER == TY_kind (ty)) {
00301 if (KIND_ARRAY == TY_kind (TY_pointed (ty)))
00302 return ((Shackle_Base_Type_Size (TY_pointed (ty)) == 0) ?
00303 TY_IDX_ZERO : TY_pointed (ty));
00304 else
00305 return TY_IDX_ZERO;
00306 }
00307 else
00308 return TY_IDX_ZERO;
00309 }
00310
00311 static WN *
00312 Find_Do_Loop(WN *root)
00313 {
00314 QUEUE_WKLIST_ITER<WN *> wklist (root, &shackle_default_pool);
00315 WN *wk_item;
00316
00317 while (wklist.Step (&wk_item)) {
00318 switch (WN_opcode (wk_item)) {
00319 case OPC_DO_LOOP:
00320 return wk_item;
00321 default:
00322 FOR_CHILDREN (wk_item, child, ignCount) {
00323 wklist.Wklist_Queue()->Add_Tail_Q (child);
00324 }
00325 END_CHILDREN;
00326 }
00327 }
00328 return NULL;
00329 }
00330
00331
00332
00333 static TYPE_ID
00334 Find_Highest_Type_Of_Loop(WN *func_nd)
00335 {
00336 WN *step = func_nd;
00337 TYPE_ID retval, current;
00338 BOOL type_found = FALSE;
00339
00340 QUEUE_WKLIST_ITER<WN *> wklist (func_nd, &shackle_default_pool);
00341 WN *wk_item;
00342
00343 while (wklist.Step (&wk_item)) {
00344 switch (WN_opcode (wk_item)) {
00345 case OPC_DO_LOOP:
00346 current = Promote_Type (Do_Wtype (wk_item));
00347 if (FALSE == type_found)
00348 retval = current;
00349 else if (current != retval) {
00350 if (((retval == MTYPE_U4) && (current == MTYPE_U8)) ||
00351 ((MTYPE_U8 == retval) && (MTYPE_U4 == current)))
00352 retval = MTYPE_U8;
00353 else if (((retval == MTYPE_I4) && (current == MTYPE_I8)) ||
00354 ((MTYPE_I8 == retval) && (MTYPE_I4 == current)))
00355 retval = MTYPE_I8;
00356 else
00357 return MTYPE_V;
00358 }
00359 wklist.Wklist_Queue()->Add_Tail_Q (WN_do_body (wk_item));
00360 break;
00361 default:
00362 FOR_CHILDREN (wk_item, child, ignCount) {
00363 wklist.Wklist_Queue()->Add_Tail_Q (child);
00364 }
00365 END_CHILDREN;
00366 }
00367 }
00368 return retval;
00369 }
00370
00371 static WN *
00372 Create_Loop_Symbol (const ST *st, INT32 i,
00373 TYPE_ID type)
00374 {
00375 char buf[128];
00376
00377 sprintf(buf, "S%s%d", ST_name (st), i);
00378 SYMBOL newsym = Create_Preg_Symbol (buf, type);
00379 return WN_CreateIdname (newsym.WN_Offset(), newsym.St());
00380 }
00381
00382 SHACKLE_INFO::SHACKLE_INFO(const ST *st,
00383 WN *func_nd,
00384 MEM_POOL *pool,
00385 TYPE_ID type,
00386 BOOL inquire_info)
00387 {
00388 #ifndef _NEW_SYMTAB
00389
00390 TY_IDX ty = Shackle_Is_Array_Type (ST_type (st));
00391 INT32 i;
00392 const INT32 _default_shackle_size = 0;
00393
00394 _pool = pool;
00395 _next_loop_count = 0;
00396 _st_is_reshaped = FALSE;
00397 if (ty != TY_IDX_ZERO) {
00398 _st = st;
00399 _ndim = ARI_ndims (TY_arinfo (ty));
00400 _is_shackled = CXX_NEW_ARRAY (BOOL, _ndim, pool);
00401 _shackle_sizes = CXX_NEW_ARRAY (INT32, _ndim, pool);
00402 _loop_stmts = CXX_NEW_ARRAY (WN *, _ndim, pool);
00403 _array_bounds = ARI_bnds (TY_arinfo (ty));
00404 _type_to_give = type;
00405
00406 for (i = 0; i < _ndim; i++) {
00407 if (inquire_info) {
00408 INT32 size;
00409 scanf("%d", &size);
00410 if (size > 0) {
00411 _is_shackled[i] = TRUE;
00412 _shackle_sizes[i] = size;
00413 _loop_stmts[i] = NULL;
00414 } else {
00415 _is_shackled[i] = FALSE;
00416 _shackle_sizes[i] = 0;
00417 _loop_stmts[i] = NULL;
00418 }
00419 } else {
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433 _is_shackled[i] = TRUE;
00434 _shackle_sizes[i] = _default_shackle_size;
00435 _loop_stmts[i] = NULL;
00436 }
00437 }
00438
00439 }
00440 else {
00441 _st = NULL;
00442 _ndim = 0;
00443 _is_shackled = NULL;
00444 _shackle_sizes = NULL;
00445 _array_bounds = NULL;
00446 _loop_stmts = NULL;
00447 _type_to_give = MTYPE_V;
00448 }
00449 #else
00450 TY_IDX ty = Shackle_Is_Array_Type (ST_type (st));
00451 INT32 i;
00452 const INT32 _default_shackle_size = 0;
00453
00454 _pool = pool;
00455 _next_loop_count = 0;
00456 _st_is_reshaped = FALSE;
00457 if (ty != TY_IDX_ZERO) {
00458 _st = st;
00459 _ndim = TY_AR_ndims (ty);
00460 _is_shackled = CXX_NEW_ARRAY (BOOL, _ndim, pool);
00461 _shackle_sizes = CXX_NEW_ARRAY (INT32, _ndim, pool);
00462 _loop_stmts = CXX_NEW_ARRAY (WN *, _ndim, pool);
00463 _cached_lb_expr_st = CXX_NEW_ARRAY (WN*, _ndim, pool);
00464 _cached_ub_expr_st = CXX_NEW_ARRAY (WN*, _ndim, pool);
00465 _array_bounds = TY_arb (ty);
00466 _type_to_give = type;
00467
00468 for (i = 0; i < _ndim; i++) {
00469 if (inquire_info) {
00470 INT32 size;
00471 scanf("%d", &size);
00472 if (size > 0) {
00473 _is_shackled[i] = TRUE;
00474 _shackle_sizes[i] = size;
00475 _loop_stmts[i] = NULL;
00476 } else {
00477 _is_shackled[i] = FALSE;
00478 _shackle_sizes[i] = 0;
00479 _loop_stmts[i] = NULL;
00480 }
00481 } else {
00482 _is_shackled[i] = TRUE;
00483 _shackle_sizes[i] = _default_shackle_size;
00484 _loop_stmts[i] = NULL;
00485 }
00486 TYPE_ID desc_type;
00487 if (!TY_AR_const_lbnd (ty, i)) {
00488 WN *st_lb =
00489 Find_Wn_Storing_ST_IDX (TY_AR_lbnd_var (ty, i), func_nd);
00490 _cached_lb_expr_st[i] = st_lb;
00491 if (NULL == st_lb)
00492 _is_shackled[i] = FALSE;
00493 }
00494 else {
00495 _cached_lb_expr_st[i] = NULL;
00496 }
00497 if (!TY_AR_const_ubnd (ty, i)) {
00498 ST_IDX st_ub_idx = TY_AR_ubnd_var (ty, i);
00499 WN *st_ub = Find_Wn_Storing_ST_IDX (st_ub_idx, func_nd);
00500 _cached_ub_expr_st[i] = st_ub;
00501 if (NULL == st_ub)
00502 _is_shackled[i] = FALSE;
00503 }
00504 else {
00505 _cached_ub_expr_st[i] = NULL;
00506 }
00507 }
00508 } else {
00509 _st = NULL;
00510 _ndim = 0;
00511 _is_shackled = NULL;
00512 _shackle_sizes = NULL;
00513 _array_bounds = ARB_HANDLE();
00514 _loop_stmts = NULL;
00515 _type_to_give = MTYPE_V;
00516 }
00517 #endif
00518 }
00519
00520 INT32
00521 SHACKLE_INFO::Ndim_Shackled()
00522 {
00523 INT32 i, count = 0;
00524 for (i = 0; i < _ndim; i++) {
00525 if (_is_shackled[i])
00526 count++;
00527 }
00528 return count;
00529 }
00530 WN*
00531 SHACKLE_INFO::Loop()
00532 {
00533 return Create_Loop_Symbol (_st, ++_next_loop_count, _type_to_give);
00534 }
00535
00536 QUEUE<WN *> *
00537 gather_stmts_in_func(WN *func_nd)
00538 {
00539 QUEUE<WN *> *result = CXX_NEW (QUEUE<WN *>(&shackle_default_pool),
00540 &shackle_default_pool);
00541 QUEUE_WKLIST_ITER<WN *> wklist(func_nd, &shackle_default_pool);
00542 WN * wk_item;
00543
00544 while (wklist.Step(&wk_item)) {
00545 switch (WN_opcode (wk_item)) {
00546 case OPC_DO_LOOP:
00547
00548
00549 wklist.Wklist_Queue()->Add_Tail_Q (WN_do_body (wk_item));
00550 break;
00551 default:
00552 if (OPCODE_is_stmt (WN_opcode (wk_item))) {
00553 if ((WN_opcode (wk_item) != OPC_RETURN) &&
00554 (WN_opcode (wk_item) != OPC_PRAGMA) &&
00555 (WN_opcode (wk_item) != OPC_XPRAGMA)) {
00556
00557 result->Add_Tail_Q (wk_item);
00558 }
00559 }
00560 else {
00561 FOR_CHILDREN (wk_item, child, ignCount) {
00562 assert (child != (WN *) NULL);
00563 wklist.Wklist_Queue()->Add_Tail_Q (child);
00564 }
00565 END_CHILDREN;
00566 }
00567 }
00568 }
00569 return result;
00570 }
00571
00572 static BOOL
00573 _xfunc_has_stmts2prevent_shackle(QUEUE<WN *> *stmts)
00574 {
00575
00576
00577
00578
00579 QUEUE_ITER<WN *> iter(stmts);
00580 WN * stmt;
00581
00582 while (iter.Step(&stmt)) {
00583 if (!OPCODE_is_store (WN_opcode (stmt)))
00584 return TRUE;
00585 }
00586 return FALSE;
00587 }
00588
00589 #ifdef KEY
00590
00591 static ST* Array_Base_St (WN* node)
00592 {
00593 if (OPCODE_is_load(WN_opcode(node))) return WN_st(node);
00594
00595
00596 ST* sym;
00597 for (INT kid = 0; kid < WN_kid_count(node); kid ++)
00598 if (sym = Array_Base_St(WN_kid(node, kid)))
00599 return sym;
00600
00601 return NULL;
00602 }
00603 #endif
00604
00605 ST*
00606 Identical_Array_Refbase (WN *array1, WN *array2)
00607 {
00608 ST *base1, *base2;
00609 WN *t1, *t2;
00610
00611 WN *p1 = LWN_Get_Parent (array1);
00612 WN *p2 = LWN_Get_Parent (array2);
00613
00614
00615
00616 if (OPR_LDID == WN_operator (p1) || OPR_STID == WN_operator (p1) ||
00617 OPR_LDID == WN_operator (p2) || OPR_STID == WN_operator (p2))
00618 return NULL;
00619
00620
00621 t1 = WN_array_base (array1);
00622 t2 = WN_array_base (array2);
00623
00624 if ((OPCODE_is_load (WN_opcode (p1)) ||
00625 OPCODE_is_store (WN_opcode (p1))) &&
00626 (OPCODE_is_load (WN_opcode (p2)) ||
00627 OPCODE_is_store (WN_opcode (p2)))) {
00628 if (DEP_CONTINUE == DEPV_COMPUTE::Base_Test (p1, NULL,
00629 p2, NULL)) {
00630
00631 #ifdef KEY // Bug 2484
00632 if (WN_Simp_Compare_Trees(t1, t2) != 0)
00633 return NULL;
00634 else if (WN_kid_count(t1) != 0)
00635 return Array_Base_St(t1);
00636 #endif
00637 if (WN_st (t1) == WN_st (t2))
00638 return WN_st (t1);
00639 else
00640 return NULL;
00641 }
00642 }
00643 assert (WN_operator (array1) == OPR_ARRAY);
00644 assert (WN_operator (array2) == OPR_ARRAY);
00645
00646
00647 if (WN_operator (t1) !=
00648 WN_operator (t2))
00649 return NULL;
00650 if (OPR_LDID == WN_operator (t1)) {
00651 if ((WN_st (t1) == WN_st (t2)) &&
00652 (WN_offset (t1) == WN_offset (t2)))
00653 return WN_st (t1);
00654 }
00655 base1 = Get_ST_Base (array1);
00656 base2 = Get_ST_Base (array2);
00657
00658 if ((NULL == base1) || (NULL == base2)) {
00659 return NULL;
00660 }
00661 else if (base1 == base2)
00662 return base1;
00663 else
00664 return NULL;
00665 }
00666
00667 static BOOL
00668 _xis_simple_shackle_case (QUEUE<WN *> *stmts)
00669 {
00670 WN *array, *first_array;
00671 INT32 count = 0;
00672 ACCESS_ARRAY *ar;
00673 QUEUE_ITER<WN *> iter (stmts);
00674 WN *stmt;
00675
00676
00677
00678
00679
00680 while (iter.Step(&stmt)) {
00681 assert (OPCODE_is_store (WN_opcode (stmt)));
00682 assert (WN_operator (stmt) != OPR_ISTOREX);
00683
00684 if (OPR_STID == WN_operator (stmt)) {
00685 return FALSE;
00686 }
00687
00688
00689
00690
00691 array = WN_kid (stmt, 1);
00692
00693 if (WN_operator(array) != OPR_ARRAY)
00694 return FALSE;
00695 if (0 == count) {
00696 first_array = array;
00697 }
00698
00699 ar = (ACCESS_ARRAY *)WN_MAP_Get (LNO_Info_Map, array);
00700 if (shackle_debug_level > 0)
00701 ar->Print (stdout, FALSE);
00702
00703 if (Bound_Is_Too_Messy (ar))
00704 return FALSE;
00705
00706
00707 if (NULL == Identical_Array_Refbase (array, first_array))
00708 return FALSE;
00709 count++;
00710 }
00711 return TRUE;
00712 }
00713
00714 static void
00715 Form_Statement_Refs(QUEUE<WN *> *stmts)
00716 {
00717
00718
00719
00720 INT32 count, i;
00721 QUEUE<WN *> *tmp;
00722 QUEUE_ITER<WN *> iter(stmts);
00723 WN *stmt, *wk_item;
00724 QUEUE_WKLIST_ITER<WN *> *wklist;
00725
00726 while (iter.Step(&stmt)) {
00727 tmp = CXX_NEW (QUEUE<WN *> (&shackle_default_pool),
00728 &shackle_default_pool);
00729 wklist = CXX_NEW (QUEUE_WKLIST_ITER<WN *> (stmt,
00730 &shackle_default_pool),
00731 &shackle_default_pool);
00732 while (wklist->Step(&wk_item)) {
00733 if (WN_operator (wk_item) == OPR_ARRAY)
00734 tmp->Add_Tail_Q (wk_item);
00735 else {
00736 FOR_CHILDREN (wk_item, child, ignCount) {
00737 assert (child != (WN *) NULL);
00738 wklist->Wklist_Queue()->Add_Tail_Q (child);
00739 }
00740 END_CHILDREN;
00741 }
00742 }
00743
00744
00745
00746 if (shackle_debug_level > 0)
00747 printf("Number of refs in Stmt: %d\n", tmp->Queue_Length());
00748 WN_MAP_Set (shackle_ref_map, stmt, (void *) tmp);
00749 }
00750 }
00751
00752 static BOOL
00753 _xis_avect_linear_comb_amat_queue(QUEUE<ACCESS_ARRAY*> *s,
00754 ACCESS_VECTOR *q)
00755 {
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766 mUINT16 count;
00767 INT32 i, j, k;
00768 INT32 nvars;
00769 mINT32 *eqrow;
00770 SYSTEM_OF_EQUATIONS *soe;
00771 ACCESS_VECTOR *v;
00772 QUEUE_ITER<ACCESS_ARRAY*> *iter;
00773 ACCESS_ARRAY *m;
00774
00775 nvars = 0;
00776 iter = CXX_NEW (QUEUE_ITER<ACCESS_ARRAY *>(s),
00777 &shackle_default_pool);
00778 while (iter->Step(&m)) {
00779 nvars += m->Num_Vec();
00780 }
00781 soe = CXX_NEW (SYSTEM_OF_EQUATIONS (0, 0, nvars,
00782 &shackle_default_pool),
00783 &shackle_default_pool);
00784 eqrow = CXX_NEW_ARRAY (mINT32, nvars, &shackle_default_pool);
00785 for (i = 0; i < q->Nest_Depth(); i++) {
00786 count = 0;
00787 iter = CXX_NEW (QUEUE_ITER<ACCESS_ARRAY *>(s),
00788 &shackle_default_pool);
00789 while (iter->Step(&m)) {
00790 for (j = 0; j < m->Num_Vec(); j++) {
00791 eqrow[count] = m->Dim(j)->Loop_Coeff(i);
00792 count++;
00793 }
00794 }
00795 soe->Add_Eq (eqrow, (INT64) q->Loop_Coeff (i));
00796 }
00797
00798
00799
00800 return soe->Is_Consistent();
00801 }
00802
00803
00804
00805
00806 BOOL
00807 Ref_Is_Significant(QUEUE<ACCESS_ARRAY *> *s,
00808 ACCESS_ARRAY *q)
00809 {
00810 INT32 i;
00811
00812
00813
00814 for (i = 0; i < q->Num_Vec(); i++) {
00815 if (!_xis_avect_linear_comb_amat_queue (s, q->Dim(i)))
00816 return TRUE;
00817 }
00818 return FALSE;
00819 }
00820
00821 static void
00822 test_significance(QUEUE<WN *> *s)
00823 {
00824
00825 QUEUE<ACCESS_ARRAY*> *tst;
00826 QUEUE<WN *> *refQ;
00827 ACCESS_ARRAY *a1, *a2;
00828 WN *t1, *t2, *stmt;
00829 BOOL b;
00830 QUEUE_ITER<WN*> iter_s (s), *iter_ref;
00831
00832
00833 while (iter_s.Step(&stmt)) {
00834 refQ = (QUEUE<WN *> *) WN_MAP_Get (shackle_ref_map, stmt);
00835 tst = CXX_NEW (QUEUE<ACCESS_ARRAY *> (&shackle_default_pool),
00836 &shackle_default_pool);
00837 t1 = refQ->Queue_First()->Qnode_Item();
00838 a1 = (ACCESS_ARRAY *) WN_MAP_Get (LNO_Info_Map, t1);
00839 tst->Add_Tail_Q (a1);
00840 a1->Print (stdout, FALSE);
00841 iter_ref = CXX_NEW (QUEUE_ITER<WN*> (refQ), &shackle_default_pool);
00842 while (iter_ref->Step(&t2)) {
00843 a2 = (ACCESS_ARRAY *) WN_MAP_Get (LNO_Info_Map, t2);
00844 fprintf(stdout, "\t");
00845 b = Ref_Is_Significant (tst, a2);
00846 if (FALSE == b)
00847 fprintf(stdout, "Not significant: ");
00848 else
00849 fprintf(stdout, "Significant: ");
00850 a2->Print (stdout, FALSE);
00851 }
00852 }
00853 }
00854
00855 static void
00856 _xcreate_simple_basic_shackle(QUEUE<WN *> *s)
00857 {
00858
00859
00860
00861
00862 INT32 i, count;
00863 QUEUE<WN *> *ref_list, *shackle_list;
00864 WN *ref;
00865 QUEUE_ITER<WN*> iter(s), *iter2;
00866 WN *stmt;
00867
00868
00869
00870 if (shackle_debug_level > 0)
00871 printf("%d Statements in Func\n", s->Queue_Length());
00872 if (1 == s->Queue_Length()) {
00873 iter.Step(&stmt);
00874 UINT32 max_dim;
00875 assert (OPCODE_is_store (WN_opcode (stmt)));
00876 assert (OPCODE_is_stmt (WN_opcode (stmt)));
00877 ref_list = (QUEUE<WN *> *) WN_MAP_Get (shackle_ref_map, stmt);
00878 assert (NULL != ref_list);
00879 iter2 = CXX_NEW (QUEUE_ITER<WN *> (ref_list),
00880 &shackle_default_pool);
00881 max_dim = 0;
00882 while (iter2->Step (&ref)) {
00883 ACCESS_ARRAY *ar =
00884 (ACCESS_ARRAY *) WN_MAP_Get (LNO_Info_Map, ref);
00885 if ((!ar->Too_Messy) && (ar->Num_Vec() > max_dim))
00886 max_dim = ar->Num_Vec();
00887 }
00888
00889 assert (0 != max_dim);
00890 iter2 = CXX_NEW (QUEUE_ITER<WN *> (ref_list),
00891 &shackle_default_pool);
00892 while (iter2->Step(&ref)) {
00893 ACCESS_ARRAY *ar =
00894 (ACCESS_ARRAY *) WN_MAP_Get (LNO_Info_Map, ref);
00895 if ((!ar->Too_Messy) && (ar->Num_Vec() == max_dim)) {
00896 shackle_list = CXX_NEW (QUEUE<WN*> (&shackle_default_pool),
00897 &shackle_default_pool);
00898 shackle_list->Add_Tail_Q (ref);
00899 WN_MAP_Set (shackle_shackle_map, stmt, (void *) shackle_list);
00900 return;
00901 }
00902 }
00903 }
00904 else {
00905 while (iter.Step(&stmt)) {
00906 assert (OPCODE_is_store (WN_opcode (stmt)));
00907 assert (OPCODE_is_stmt (WN_opcode (stmt)));
00908 ref_list = (QUEUE<WN *> *) WN_MAP_Get (shackle_ref_map, stmt);
00909 assert (ref_list != NULL);
00910 shackle_list = CXX_NEW (QUEUE<WN*> (&shackle_default_pool),
00911 &shackle_default_pool);
00912 ref = ref_list->Queue_First()->Qnode_Item();
00913 shackle_list->Add_Tail_Q (ref);
00914 WN_MAP_Set (shackle_shackle_map, stmt, (void *) shackle_list);
00915 }
00916 }
00917 }
00918 static BOOL
00919 Is_Ref_Significant_In_Stmt(WN *query_ref, WN *stmt)
00920 {
00921 QUEUE_ITER<WN *> *shackle_iter;
00922 WN *shackle;
00923 QUEUE<WN *> *shackleQ;
00924 QUEUE<ACCESS_ARRAY *> *arq;
00925 ACCESS_ARRAY *ar;
00926
00927 shackleQ = (QUEUE<WN *> *) WN_MAP_Get (shackle_shackle_map,
00928 stmt);
00929 shackle_iter = CXX_NEW (QUEUE_ITER<WN *> (shackleQ),
00930 &shackle_default_pool);
00931
00932 arq = CXX_NEW (QUEUE<ACCESS_ARRAY*>(&shackle_default_pool),
00933 &shackle_default_pool);
00934 while (shackle_iter->Step(&shackle)) {
00935 ar = (ACCESS_ARRAY *) WN_MAP_Get (LNO_Info_Map, shackle);
00936 if (!ar->Too_Messy)
00937 arq->Add_Tail_Q (ar);
00938 }
00939 ar = (ACCESS_ARRAY *) WN_MAP_Get (LNO_Info_Map, query_ref);
00940 if (!ar->Too_Messy)
00941 return Ref_Is_Significant (arq, ar);
00942 else
00943 return FALSE;
00944 }
00945
00946 static WN*
00947 Has_Stmt_Significant_Ref(WN *stmt)
00948 {
00949 WN *ref;
00950 QUEUE<WN *> *refQ;
00951 QUEUE_ITER<WN *> *ref_iter;
00952
00953 refQ = (QUEUE<WN *> *) WN_MAP_Get (shackle_ref_map, stmt);
00954 ref_iter = CXX_NEW (QUEUE_ITER<WN *> (refQ),
00955 &shackle_default_pool);
00956 while (ref_iter->Step (&ref)) {
00957 if (Is_Ref_Significant_In_Stmt (ref, stmt))
00958 return ref;
00959 }
00960 return NULL;
00961 }
00962
00963 static void
00964 Augment_Simple_Basic_Shackle (QUEUE<WN *> *s,
00965 QUEUE<SHACKLE_INFO*> *sinfo)
00966 {
00967 QUEUE_ITER<WN *> *iter, *ref_iter, *shackle_iter;
00968 WN *step, *step2, *ref, *ref2;
00969 QUEUE<WN *> *refQ, *shackleQ, *refQ2, *shackleQ2;
00970 BOOL can_be_augmented = FALSE;
00971
00972
00973 iter = CXX_NEW (QUEUE_ITER<WN *> (s), &shackle_default_pool);
00974 while (iter->Step (&step)) {
00975 if (Has_Stmt_Significant_Ref (step)) {
00976 can_be_augmented = TRUE;
00977 break;
00978 }
00979 }
00980 if (!can_be_augmented)
00981 return;
00982 refQ = (QUEUE<WN*> *) WN_MAP_Get (shackle_ref_map, step);
00983 ref_iter = CXX_NEW (QUEUE_ITER<WN *> (refQ),
00984 &shackle_default_pool);
00985 while (ref_iter->Step (&ref)) {
00986 if (Is_Ref_Significant_In_Stmt (ref, step)) {
00987 shackleQ = (QUEUE<WN *> *) WN_MAP_Get (shackle_shackle_map,
00988 step);
00989 shackleQ->Add_Tail_Q (ref);
00990 WN_MAP_Set (shackle_shackle_map, step,
00991 (void *) shackleQ);
00992 iter = CXX_NEW (QUEUE_ITER<WN *> (s), &shackle_default_pool);
00993 while (iter->Step (&step2)) {
00994 if (step != step2) {
00995 shackleQ2 =
00996 (QUEUE<WN *> *) WN_MAP_Get (shackle_shackle_map,
00997 step2);
00998 ref2 = Has_Stmt_Significant_Ref (step2);
00999 if (NULL == ref2) {
01000 ref2 = shackleQ2->Queue_First()->Qnode_Item();
01001 }
01002 assert (ref2 != NULL);
01003 shackleQ2->Add_Tail_Q (ref2);
01004 WN_MAP_Set (shackle_shackle_map, step2,
01005 (void *) shackleQ2);
01006 }
01007 }
01008
01009 if (_xis_legal_shackle (s, sinfo))
01010 return;
01011 iter = CXX_NEW (QUEUE_ITER<WN *> (s), &shackle_default_pool);
01012
01013
01014 while (iter->Step (&step)) {
01015 shackleQ2 = (QUEUE<WN *> *) WN_MAP_Get (shackle_shackle_map,
01016 step);
01017 shackleQ2->Get_Tail_Q();
01018 }
01019 }
01020 }
01021 }
01022 #ifndef _NEW_SYMTAB
01023 static QUEUE<SHACKLE_INFO*> *
01024 _xcreate_shackle_map_for_arrays_in_func(WN *main_snl,
01025 WN *func_nd)
01026 {
01027 QUEUE<SHACKLE_INFO *> *si;
01028 ST *st;
01029 TY_IDX ty;
01030 SHACKLE_INFO *sh;
01031 TYPE_ID type;
01032 SYMTAB_IDX symtab = Current_Symtab;
01033
01034 si = CXX_NEW (QUEUE<SHACKLE_INFO *> (&shackle_default_pool),
01035 &shackle_default_pool);
01036
01037
01038
01039
01040
01041 type = Find_Highest_Type_Of_Loop (main_snl);
01042 for (st = SYMTAB_symbols (symtab); NULL != st;
01043 st = ST_next (st)) {
01044 ty = Shackle_Is_Array_Type (ST_type (st));
01045 if (NULL != ty) {
01046 sh = CXX_NEW (SHACKLE_INFO (st, func_nd,
01047 &shackle_default_pool,
01048 type, FALSE),
01049 &shackle_default_pool);
01050 si->Add_Tail_Q (sh);
01051 }
01052 }
01053 return si;
01054 }
01055 #else
01056 static QUEUE<SHACKLE_INFO*> *
01057 _xcreate_shackle_map_for_arrays_in_func(WN *main_snl,
01058 WN *func_nd)
01059 {
01060 QUEUE<SHACKLE_INFO*> *si;
01061 TY_IDX ty;
01062 TYPE_ID type;
01063 ST *st;
01064 SHACKLE_INFO *sh;
01065 ST_TAB st_table;
01066 ST_ITER st_iter;
01067 UINT32 count;
01068 INT i;
01069
01070 si = CXX_NEW (QUEUE<SHACKLE_INFO *> (&shackle_default_pool),
01071 &shackle_default_pool);
01072 type = Find_Highest_Type_Of_Loop (main_snl);
01073
01074 FOREACH_SYMBOL (CURRENT_SYMTAB, st, i) {
01075 if (CLASS_UNK == ST_sym_class (st) ||
01076 CLASS_BLOCK == ST_sym_class (st) ||
01077 CLASS_COUNT == ST_sym_class (st))
01078 continue;
01079 ty = Shackle_Is_Array_Type (ST_type (st));
01080 if (ty != TY_IDX_ZERO) {
01081 if (shackle_debug_level > 0)
01082 fprintf(stdout, "Symbol: %s\n", ST_name (st));
01083 sh = CXX_NEW (SHACKLE_INFO (st, func_nd,
01084 &shackle_default_pool,
01085 type, FALSE),
01086 &shackle_default_pool);
01087 si->Add_Tail_Q (sh);
01088 }
01089 }
01090 FOREACH_SYMBOL (GLOBAL_SYMTAB, st, i) {
01091 if (CLASS_UNK == ST_sym_class (st) ||
01092 CLASS_BLOCK == ST_sym_class (st) ||
01093 CLASS_COUNT == ST_sym_class (st))
01094 continue;
01095 ty = Shackle_Is_Array_Type (ST_type (st));
01096 if (ty != TY_IDX_ZERO) {
01097 if (shackle_debug_level > 0)
01098 fprintf(stdout, "Symbol: %s\n", ST_name (st));
01099 sh = CXX_NEW (SHACKLE_INFO (st, func_nd,
01100 &shackle_default_pool,
01101 type, FALSE),
01102 &shackle_default_pool);
01103 si->Add_Tail_Q (sh);
01104 }
01105 }
01106 return si;
01107 }
01108 #endif
01109
01110 SHACKLE_INFO *
01111 Shackle_Info_For_Symbol(QUEUE<SHACKLE_INFO *> *shq,
01112 const ST *st)
01113 {
01114 QUEUE_ITER<SHACKLE_INFO*> iter(shq);
01115 SHACKLE_INFO *sh;
01116
01117 while (iter.Step(&sh)) {
01118 if (sh->Symbol() == st)
01119 return sh;
01120 }
01121 return NULL;
01122 }
01123
01124 static void
01125 Extend_Dep_Vectors(WN *top_level, INT32 extend_count)
01126 {
01127
01128
01129
01130 assert (0 != extend_count);
01131 extern ARRAY_DIRECTED_GRAPH16 *Array_Dependence_Graph;
01132 EINDEX16 e;
01133 ARRAY_DIRECTED_GRAPH16 *dg = Array_Dependence_Graph;
01134 VINDEX16 src, dst;
01135
01136 e = dg->Get_Edge();
01137 while (e) {
01138
01139 src = dg->Get_Source(e);
01140 dst = dg->Get_Sink(e);
01141 if (Is_Parent_Of (top_level, dg->Get_Wn (src)) &&
01142 Is_Parent_Of (top_level, dg->Get_Wn (dst))) {
01143 DEPV_ARRAY *d = dg->Depv_Array (e);
01144 INT32 num_vec = d->Num_Vec();
01145 INT32 num_dim = d->Num_Dim();
01146 INT32 num_unused_dim = d->Num_Unused_Dim();
01147 DEPV_ARRAY *newd =
01148 Create_DEPV_ARRAY (num_vec, num_dim + extend_count,
01149 num_unused_dim,
01150 dg->Pool());
01151 for (INT32 j = 0; j < d->Num_Vec(); j++) {
01152 DEPV *newv = newd->Depv (j);
01153 DEPV *oldv = d->Depv (j);
01154 INT32 i;
01155 for (i = 0; i < extend_count; i++)
01156 DEPV_Dep (newv, i) = DEP_SetDistance (0);
01157 for (i = 0; i < d->Num_Dim(); i++)
01158 DEPV_Dep (newv, i + extend_count) = DEPV_Dep (oldv, i);
01159 }
01160 Delete_DEPV_ARRAY (d, dg->Pool());
01161 dg->Set_Depv_Array (e, newd);
01162 }
01163 e = dg->Get_Next_Edge (e);
01164 }
01165 }
01166
01167 static WN**
01168 Create_Simple_Shackle_Loops(WN *main_body,
01169 QUEUE<WN *> *stmts,
01170 QUEUE<SHACKLE_INFO*> *shackle_info,
01171 INT32 shackle_depth)
01172 {
01173 QUEUE<WN *> *shackle_list;
01174 WN *stmt = stmts->Queue_First()->Qnode_Item();
01175 SHACKLE_INFO *sh;
01176 WN *top_level;
01177 OPCODE opc;
01178 WN *index_var, *start_exp, *end_exp, *do_step;
01179 WN *end_num_exp, *end_denom_exp;
01180 TYPE_ID index_type, rtype;
01181 WN *fake_unroll[2];
01182 WN *current_do, *prev_do = NULL;
01183 WN *if_to_insert, *prev_if_to_insert;
01184 WN *another_do;
01185 DEF_LIST *dl;
01186 INT32 added_loop_count = 0;
01187 WN *outermost_do;
01188 PROMPF_LINES *pl;
01189 INT64 linenum = WN_Get_Linenum (main_body);
01190
01191 if (Prompf_Info != NULL && Prompf_Info->Is_Enabled()) {
01192 pl = CXX_NEW (PROMPF_LINES (main_body, &PROMPF_pool),
01193 &PROMPF_pool);
01194 }
01195
01196 another_do = Find_Do_Loop (main_body);
01197 assert (NULL != another_do);
01198 TY_IDX high_level_type = WN_ty (WN_start (another_do));
01199 WN *dummy_do_load_op = NULL;
01200
01201 WN *parent_block = LWN_Get_Parent (main_body);
01202 shackle_list = (QUEUE<WN *> *) WN_MAP_Get (shackle_shackle_map,
01203 stmt);
01204 top_level = main_body;
01205 if (NULL == top_level)
01206 return NULL;
01207 QUEUE_ITER<WN *> iter (shackle_list);
01208 WN *step;
01209 WN **ret_val = CXX_NEW_ARRAY (WN *, shackle_depth,
01210 &shackle_default_pool);
01211
01212 while (iter.Step(&step)) {
01213 sh = Shackle_Info_For_Symbol (shackle_info,
01214 Identical_Array_Refbase (step,
01215 step));
01216 index_type = sh->Loop_Type();
01217 OPCODE load_opc =
01218 OPCODE_make_op (OPR_LDID, Promote_Type (index_type),
01219 index_type);
01220 OPCODE store_opc =
01221 OPCODE_make_op (OPR_STID, MTYPE_V, Promote_Type (index_type));
01222 for (INT32 i = 0; i < sh->Ndim(); i++) {
01223 if (sh->Is_Dim_Shackled (i)) {
01224 WN *do_index = sh->Loop ();
01225 dummy_do_load_op =
01226 WN_CreateLdid (load_opc, WN_offset (do_index),
01227 WN_st (do_index), high_level_type);
01228
01229
01230 WN *step_size = WN_CreateIntconst
01231 (OPCODE_make_op (OPR_INTCONST,
01232 Promote_Type (index_type), MTYPE_V),
01233 (INT64) 1);
01234 start_exp = WN_CreateIntconst
01235 (OPCODE_make_op (OPR_INTCONST,
01236 Promote_Type (index_type), MTYPE_V),
01237 (INT64) 0);
01238 if (sh->Is_Const_Upper (i))
01239 end_num_exp = WN_CreateIntconst
01240 (OPCODE_make_op (OPR_INTCONST,
01241 Promote_Type (index_type), MTYPE_V),
01242 (INT64) sh->Const_Upper (i));
01243 else {
01244 end_num_exp = sh->Expr_Upper (i);
01245 }
01246 WN *dup_lbnd;
01247 if (sh->Is_Const_Lower (i))
01248 dup_lbnd = WN_CreateIntconst
01249 (OPCODE_make_op (OPR_INTCONST,
01250 Promote_Type (index_type), MTYPE_V),
01251 (INT64) sh->Const_Lower(i));
01252 else {
01253 dup_lbnd = sh->Expr_Lower (i);
01254 }
01255 end_num_exp = LWN_CreateExp2
01256 (OPCODE_make_op (OPR_SUB, Promote_Type (index_type),
01257 MTYPE_V),
01258 end_num_exp, dup_lbnd);
01259 FmtAssert (sh->Shackle_Dim_Size (i) > 0,
01260 ("Size of shackle for this dimension is negative?"));
01261 end_denom_exp = WN_CreateIntconst
01262 (OPCODE_make_op (OPR_INTCONST,
01263 Promote_Type (index_type), MTYPE_V),
01264 (INT64) sh->Shackle_Dim_Size (i));
01265 end_exp = Sh_LWN_CreateDivfloor (Promote_Type (index_type),
01266 end_num_exp,
01267 end_denom_exp);
01268
01269
01270 WN *do_lbnd =
01271 LWN_CreateStid (store_opc, dummy_do_load_op, start_exp);
01272
01273 WN *step_kid_rhs = LWN_CreateLdid (load_opc, dummy_do_load_op);
01274 Du_Mgr->Add_Def_Use (do_lbnd, step_kid_rhs);
01275 WN *step_kid =
01276 LWN_CreateExp2
01277 (OPCODE_make_op (OPR_ADD, Promote_Type (index_type),
01278 MTYPE_V),
01279 step_size,
01280 step_kid_rhs);
01281 do_step = LWN_CreateStid
01282 (store_opc, dummy_do_load_op, step_kid);
01283 Du_Mgr->Add_Def_Use (do_step, step_kid_rhs);
01284
01285 rtype = OPCODE_rtype (WN_opcode (WN_end (another_do)));
01286 WN *do_ubnd_rhs = LWN_CreateLdid (load_opc, dummy_do_load_op);
01287 Du_Mgr->Add_Def_Use (do_step, do_ubnd_rhs);
01288 Du_Mgr->Add_Def_Use (do_lbnd, do_ubnd_rhs);
01289 WN *do_ubnd = LWN_CreateExp2
01290 (OPCODE_make_op (OPR_LE, rtype,
01291 Promote_Type (index_type)),
01292 do_ubnd_rhs,
01293 end_exp);
01294 current_do =
01295 LWN_CreateDO (do_index, do_lbnd, do_ubnd, do_step,
01296 WN_CreateBlock());
01297 ret_val[added_loop_count] = current_do;
01298 added_loop_count++;
01299 dl = Du_Mgr->Ud_Get_Def (step_kid_rhs);
01300 dl->Set_loop_stmt (current_do);
01301 dl = Du_Mgr->Ud_Get_Def (do_ubnd_rhs);
01302 dl->Set_loop_stmt (current_do);
01303 DO_LOOP_INFO *dli = CXX_NEW (DO_LOOP_INFO (&LNO_default_pool,
01304 NULL, NULL, NULL,
01305 FALSE, FALSE, FALSE, FALSE, FALSE,
01306 FALSE, FALSE, FALSE),
01307 &LNO_default_pool);
01308 Set_Do_Loop_Info (current_do, dli);
01309 sh->Set_Loop_Stmt (i, current_do);
01310 WN_Set_Linenum (current_do, linenum);
01311
01312 if (Prompf_Info != NULL && Prompf_Info->Is_Enabled()) {
01313 INT32 new_id = New_Construct_Id();
01314 WN_MAP32_Set (Prompf_Id_Map, current_do, new_id);
01315 WN_MAP32_Set (shackle_prompf_id_map, current_do,
01316 new_id);
01317 Prompf_Info->Outer_Shackle(new_id, pl,
01318 (char*) WB_Whirl_Symbol(current_do));
01319 }
01320
01321 WN *fake_unroll[2];
01322 WN *if_cond_lhs = LWN_Copy_Tree (start_exp);
01323 fake_unroll[0] = start_exp;
01324 fake_unroll[1] = if_cond_lhs;
01325 Unrolled_DU_Update (fake_unroll, 2, 0);
01326 WN *if_cond_rhs = LWN_Copy_Tree (end_num_exp);
01327 fake_unroll[0] = end_num_exp;
01328 fake_unroll[1] = if_cond_rhs;
01329 Unrolled_DU_Update (fake_unroll, 2, 0);
01330 WN *if_cond_to_insert = LWN_CreateExp2
01331 (OPCODE_make_op (OPR_LE, rtype, Promote_Type (index_type)),
01332 if_cond_lhs, if_cond_rhs);
01333 if_cond_to_insert =
01334 Simplify_If_Conditional (if_cond_to_insert);
01335 WN *if_to_insert = LWN_CreateIf (if_cond_to_insert,
01336 WN_CreateBlock(),
01337 WN_CreateBlock());
01338 IF_INFO *ii =
01339 CXX_NEW (IF_INFO (&LNO_default_pool, TRUE, FALSE),
01340 &LNO_default_pool);
01341 WN_MAP_Set (LNO_Info_Map, if_to_insert, (void *)ii);
01342 LWN_Insert_Block_After (WN_do_body (current_do), NULL,
01343 if_to_insert);
01344 if (prev_do) {
01345 WN *move_stmt;
01346 FmtAssert (prev_if_to_insert ==
01347 WN_first (WN_do_body (prev_do)),
01348 ("Mismatch in previous inserted pair"));
01349 FOR_CHILDREN (WN_then (prev_if_to_insert),
01350 child, ignCount) {
01351 move_stmt = LWN_Extract_From_Block (child);
01352 LWN_Insert_Block_Before(WN_then (if_to_insert),
01353 NULL, move_stmt);
01354 }
01355 END_CHILDREN;
01356 LWN_Insert_Block_Before (WN_then (prev_if_to_insert),
01357 NULL, current_do);
01358 }
01359 else {
01360 outermost_do = current_do;
01361 WN *move_stmt;
01362 Replace_WN (top_level, current_do);
01363 LWN_Insert_Block_Before (WN_then (if_to_insert),
01364 NULL, top_level);
01365 }
01366 prev_do = current_do;
01367 prev_if_to_insert = if_to_insert;
01368 LWN_Delete_Tree (dummy_do_load_op);
01369 }
01370 }
01371 }
01372 if (NULL != prev_do) {
01373 Reset_Do_Loop_Depths (outermost_do, 0);
01374 LWN_Parentize (parent_block);
01375 LNO_Build_Access (parent_block, &LNO_default_pool);
01376 Extend_Dep_Vectors(outermost_do, added_loop_count);
01377 }
01378 assert (added_loop_count == shackle_depth);
01379 return ret_val;
01380 }
01381
01382 static void
01383 Create_Shackle_If_Per_Stmt (WN *stmt,
01384 QUEUE<SHACKLE_INFO*> *shackle_info,
01385 WN **shackle_loop_info,
01386 INT32 shackling_depth)
01387 {
01388 QUEUE<WN*> *shackle_list =
01389 (QUEUE<WN *> *) WN_MAP_Get (shackle_shackle_map, stmt);
01390 INT32 stmt_depth =
01391 Num_Common_Loops (stmt, stmt);
01392 WN *step;
01393 QUEUE_ITER<WN *> iter (shackle_list);
01394 DOLOOP_STACK do_stack(&shackle_default_pool);
01395 INT32 added_loop_count = 0;
01396
01397 Build_Doloop_Stack (stmt, &do_stack);
01398 while (iter.Step (&step)) {
01399 SHACKLE_INFO *sh =
01400 Shackle_Info_For_Symbol (shackle_info,
01401 Identical_Array_Refbase (step, step));
01402 assert (sh->Ndim() == (WN_kid_count (step) >> 1));
01403 for (INT32 i = 0; i < sh->Ndim(); i++) {
01404 if (sh->Is_Dim_Shackled (i)) {
01405 WN *shackle_do = shackle_loop_info[added_loop_count];
01406 added_loop_count++;
01407 TYPE_ID index_type = sh->Loop_Type ();
01408 OPCODE load_opc =
01409 OPCODE_make_op (OPR_LDID, Promote_Type (index_type),
01410 index_type);
01411 WN *shackle_loop_var[2];
01412 WN *data_centric_ref[2];
01413 WN *fake_unroll[2];
01414 INT32 k;
01415 for (k = 0; k < 2; k++)
01416 shackle_loop_var[k] = LWN_CreateLdid (load_opc,
01417 WN_start (shackle_do));
01418 for (k = 0; k < 2; k++)
01419 data_centric_ref[k] =
01420 LWN_Copy_Tree (WN_kid (step, sh->Ndim() + i + 1));
01421 fake_unroll[0] = WN_kid (step, sh->Ndim() + i + 1);
01422 for (k = 0; k < 2; k++) {
01423 fake_unroll[1] = data_centric_ref[k];
01424 Unrolled_DU_Update (fake_unroll, 2, stmt_depth);
01425 }
01426
01427 for (k = 0; k < 2; k++) {
01428 Du_Mgr->Add_Def_Use (WN_start (shackle_do), shackle_loop_var[k]);
01429 Du_Mgr->Add_Def_Use (WN_step (shackle_do), shackle_loop_var[k]);
01430 DEF_LIST *dl = Du_Mgr->Ud_Get_Def (shackle_loop_var[k]);
01431 dl->Set_loop_stmt (shackle_do);
01432 }
01433 {
01434
01435 WN *add_one = WN_CreateIntconst
01436 (OPCODE_make_op (OPR_INTCONST,
01437 Promote_Type (index_type), MTYPE_V),
01438 (INT64) 1);
01439 shackle_loop_var[1] = WN_CreateExp2
01440 (OPCODE_make_op (OPR_ADD, Promote_Type (index_type),
01441 MTYPE_V),
01442 add_one, shackle_loop_var[1]);
01443 }
01444
01445 for (k = 0; k < 2; k++) {
01446 WN *shackle_mul = WN_CreateIntconst
01447 (OPCODE_make_op (OPR_INTCONST,
01448 Promote_Type (index_type), MTYPE_V),
01449 (INT64) sh->Shackle_Dim_Size (i));
01450 shackle_loop_var[k] = WN_CreateExp2
01451 (OPCODE_make_op (OPR_MPY,
01452 Promote_Type (index_type), MTYPE_V),
01453 shackle_loop_var[k], shackle_mul);
01454 }
01455
01456 TYPE_ID rtype = OPCODE_rtype (WN_opcode (WN_end (shackle_do)));
01457 WN *if_cond0 = LWN_CreateExp2
01458 (OPCODE_make_op (OPR_LE, rtype, Promote_Type (index_type)),
01459 shackle_loop_var[0], data_centric_ref[0]);
01460 WN *if_stmt0 = LWN_CreateIf (if_cond0,
01461 WN_CreateBlock(),
01462 WN_CreateBlock());
01463 Replace_WN (stmt, if_stmt0);
01464 LWN_Insert_Block_After (WN_then (if_stmt0), NULL, stmt);
01465 WN *if_cond1 = LWN_CreateExp2
01466 (OPCODE_make_op (OPR_GT, rtype, Promote_Type (index_type)),
01467 shackle_loop_var[1], data_centric_ref[1]);
01468 WN *if_stmt1 = LWN_CreateIf (if_cond1,
01469 WN_CreateBlock(),
01470 WN_CreateBlock());
01471 Replace_WN (if_stmt0, if_stmt1);
01472 LWN_Insert_Block_After (WN_then (if_stmt1), NULL, if_stmt0);
01473 IF_INFO *ii =
01474 CXX_NEW (IF_INFO (&LNO_default_pool, FALSE, FALSE),
01475 &LNO_default_pool);
01476 WN_MAP_Set (LNO_Info_Map, if_stmt0, (void *) ii);
01477 LNO_Build_If_Access (if_stmt0, &do_stack);
01478 ii =
01479 CXX_NEW (IF_INFO (&LNO_default_pool, FALSE, FALSE),
01480 &LNO_default_pool);
01481 WN_MAP_Set (LNO_Info_Map, if_stmt1, (void *) ii);
01482 LNO_Build_If_Access (if_stmt1, &do_stack);
01483 }
01484 }
01485 }
01486 assert (added_loop_count == shackling_depth);
01487 }
01488
01489 static void
01490 Create_Shackle_If_All_Stmts(WN *func_nd,
01491 QUEUE<WN *> *stmts,
01492 QUEUE<SHACKLE_INFO *> *shackle_info,
01493 WN **shackle_loop_info,
01494 INT32 shackle_depth)
01495 {
01496 QUEUE_ITER<WN *> iter(stmts);
01497 WN *step;
01498
01499 while (iter.Step (&step))
01500 Create_Shackle_If_Per_Stmt (step, shackle_info,
01501 shackle_loop_info,
01502 shackle_depth);
01503 LWN_Parentize (func_nd);
01504 }
01505
01506 static INT32
01507 shackling_depth(QUEUE<WN *> *shackle,
01508 QUEUE<SHACKLE_INFO *> *shq)
01509 {
01510
01511
01512 INT32 i, count = 0;
01513 QUEUE_ITER<WN *> iter(shackle);
01514 WN *wn;
01515 SHACKLE_INFO *sh;
01516 ST *st;
01517
01518 while (iter.Step (&wn)) {
01519 st = Identical_Array_Refbase (wn, wn);
01520 assert (NULL != st);
01521 sh = Shackle_Info_For_Symbol (shq, st);
01522 FmtAssert (NULL != sh, ("Shackling info cannot be NULL"));
01523 count += sh->Ndim_Shackled();
01524 }
01525 return count;
01526 }
01527
01528 static INT32
01529 Common_Shackling_Depth(QUEUE<WN *> *stmts,
01530 QUEUE<SHACKLE_INFO *> *shq)
01531 {
01532 INT32 count, retval;
01533 QUEUE_ITER<WN *> iter(stmts);
01534 WN *step;
01535
01536 count = 0;
01537 while (iter.Step(&step)) {
01538 QUEUE<WN *> *shackle =
01539 (QUEUE<WN *> *) WN_MAP_Get (shackle_shackle_map, step);
01540 retval = shackling_depth (shackle, shq);
01541 if (0 == count)
01542 count = retval;
01543 assert (count == retval);
01544 }
01545 return count;
01546 }
01547
01548 static BOOL
01549 _xdependence_is_preserved(WN *stmt1,
01550 WN *stmt2,
01551 WN *ref1,
01552 WN *ref2,
01553 BOOL stmt1_before_stmt2,
01554 QUEUE<SHACKLE_INFO*> *shq)
01555 {
01556
01557
01558
01559
01560
01561
01562
01563
01564
01565
01566
01567
01568
01569
01570
01571
01572
01573 WN *wn1, *wn2, *stmt;
01574 ST *st;
01575 TY_IDX ty;
01576 QUEUE<WN *> *shackle1, *shackle2;
01577 ACCESS_ARRAY *ar1, *ar2, *lb, *ub;
01578 ACCESS_VECTOR *v1, *v2;
01579 INT32 shackle_depth, i, j, k;
01580 INT32 nvars, depth1, depth2, count;
01581 INT32 common_depth;
01582 mINT32 *row;
01583 SYSTEM_OF_EQUATIONS **soe_lex_init, **soe_lex_final;
01584 SYSTEM_OF_EQUATIONS *soe_same_loc, *soe_data_shackle;
01585 SYSTEM_OF_EQUATIONS *soe_loop_bnds1, *soe_loop_bnds2;
01586 QUEUE_ITER<SHACKLE_INFO*> *iter;
01587 QUEUE_ITER<WN*> *wn_iter1, *wn_iter2;
01588 SHACKLE_INFO *sh;
01589 INT32 stmt_rhs_offset;
01590 LINEAR_CLAUSE *l1, *l2, *l3, *l4, *l5, *l6;
01591 LINEAR_CLAUSE *l11, *l12, *l13;
01592 DO_LOOP_INFO *dli;
01593 BOOL return_val;
01594
01595 st = Identical_Array_Refbase (ref1, ref2);
01596 if (NULL == st) {
01597
01598
01599 return TRUE;
01600 }
01601 MEM_POOL_Push (&shackle_default_pool);
01602 assert (NULL != st);
01603 ty = Shackle_Is_Array_Type (ST_type (st));
01604 if (ty == TY_IDX_ZERO) {
01605 MEM_POOL_Pop (&shackle_default_pool);
01606
01607 return FALSE;
01608 }
01609 assert (ty != TY_IDX_ZERO);
01610 shackle1 = (QUEUE<WN *> *) WN_MAP_Get (shackle_shackle_map,
01611 stmt1);
01612 shackle2 = (QUEUE<WN *> *) WN_MAP_Get (shackle_shackle_map,
01613 stmt2);
01614 ar1 = (ACCESS_ARRAY *) WN_MAP_Get (LNO_Info_Map, ref1);
01615 ar2 = (ACCESS_ARRAY *) WN_MAP_Get (LNO_Info_Map, ref2);
01616 assert (shackling_depth (shackle1, shq) ==
01617 shackling_depth (shackle2, shq));
01618 shackle_depth = shackling_depth (shackle1, shq);
01619 depth1 = Num_Common_Loops (stmt1, stmt1);
01620 depth2 = Num_Common_Loops (stmt2, stmt2);
01621 nvars = depth1 + depth2 + 2 * shackle_depth;
01622 row = CXX_NEW_ARRAY (mINT32, nvars, &shackle_default_pool);
01623 for (i = 0; i < nvars; i++)
01624 row[i] = 0;
01625
01626
01627 if (ar1->Num_Vec() != ar2->Num_Vec()) {
01628 MEM_POOL_Pop (&shackle_default_pool);
01629 return FALSE;
01630 }
01631 FmtAssert (ar1->Num_Vec() == ar2->Num_Vec(),
01632 ("Number of dimensions in references must be same!"));
01633 soe_same_loc =
01634 CXX_NEW (SYSTEM_OF_EQUATIONS (0, 0, nvars, &shackle_default_pool),
01635 &shackle_default_pool);
01636 for (i = 0; i < ar1->Num_Vec(); i++) {
01637 for (j = 0; j < depth1 + depth2; j++)
01638 row[j] = 0;
01639 v1 = ar1->Dim(i);
01640 v2 = ar2->Dim(i);
01641 assert (v1->Nest_Depth() == depth1);
01642 assert (v2->Nest_Depth() == depth2);
01643 for (j = 0; j < depth1; j++) {
01644 row[j] = v1->Loop_Coeff (j);
01645 }
01646 for (j = 0; j < depth2; j++) {
01647 row[j+depth1] = - v2->Loop_Coeff (j);
01648 }
01649 soe_same_loc->Add_Eq (row, v2->Const_Offset - v1->Const_Offset);
01650 }
01651
01652 for (i = 0; i < nvars; i++)
01653 row[i] = 0;
01654
01655 assert (shackle1->Queue_Length() == shackle2->Queue_Length());
01656 wn_iter1 = CXX_NEW (QUEUE_ITER<WN *> (shackle1),
01657 &shackle_default_pool);
01658 soe_data_shackle =
01659 CXX_NEW (SYSTEM_OF_EQUATIONS (0, 0, nvars, &shackle_default_pool),
01660 &shackle_default_pool);
01661
01662 count = depth1 + depth2;
01663 while (wn_iter1->Step(&wn1)) {
01664
01665
01666
01667 sh = Shackle_Info_For_Symbol (shq,
01668 Identical_Array_Refbase (wn1,
01669 wn1));
01670 assert (NULL != sh);
01671 ar1 = (ACCESS_ARRAY *) WN_MAP_Get (LNO_Info_Map, wn1);
01672
01673
01674 if (ar1->Num_Vec() != sh->Ndim()) {
01675 MEM_POOL_Pop (&shackle_default_pool);
01676 return FALSE;
01677 }
01678 assert (ar1->Num_Vec() == sh->Ndim());
01679 for (i = 0; i < sh->Ndim(); i++) {
01680 if (sh->Is_Dim_Shackled(i)) {
01681 v1 = ar1->Dim(i);
01682
01683 for (j = 0; j < depth1; j++) {
01684 row[j] = - v1->Loop_Coeff (j);
01685 }
01686 row[count] = sh->Shackle_Dim_Size (i);
01687 soe_data_shackle->Add_Le (row, v1->Const_Offset +
01688 sh->Shackle_Dim_Size (i));
01689 for (j = 0; j < depth1; j++) {
01690 row[j] = - row[j];
01691 }
01692 row[count] = - row[count];
01693 soe_data_shackle->Add_Le (row, -1 - v1->Const_Offset);
01694 row[count] = 0;
01695 count++;
01696 }
01697 }
01698 }
01699 for (i = 0; i < depth1; i++)
01700 row[i] = 0;
01701 assert ((count + shackle_depth) == nvars);
01702 wn_iter2 = CXX_NEW (QUEUE_ITER<WN *> (shackle2),
01703 &shackle_default_pool);
01704 while (wn_iter2->Step (&wn2)) {
01705
01706
01707
01708 sh = Shackle_Info_For_Symbol (shq,
01709 Identical_Array_Refbase (wn2,
01710 wn2));
01711 assert (NULL != sh);
01712 ar2 = (ACCESS_ARRAY *) WN_MAP_Get (LNO_Info_Map, wn2);
01713
01714
01715 if (ar2->Num_Vec() != sh->Ndim()) {
01716 MEM_POOL_Pop (&shackle_default_pool);
01717 return FALSE;
01718 }
01719 assert (ar2->Num_Vec() == sh->Ndim());
01720 for (i = 0; i < sh->Ndim(); i++) {
01721 if (sh->Is_Dim_Shackled(i)) {
01722 v2 = ar2->Dim (i);
01723
01724 for (j = 0; j < depth2; j++) {
01725 row[j+depth1] = - v2->Loop_Coeff (j);
01726 }
01727 row[count] = sh->Shackle_Dim_Size (i);
01728 soe_data_shackle->Add_Le (row, v2->Const_Offset +
01729 sh->Shackle_Dim_Size (i));
01730 for (j = 0; j < depth2; j++) {
01731 row[j+depth1] = - row[j+depth1];
01732 }
01733 row[count] = - row[count];
01734 soe_data_shackle->Add_Le (row, -1 - v2->Const_Offset);
01735 row[count] = 0;
01736 count++;
01737 }
01738 }
01739 }
01740 assert (count == nvars);
01741 if (shackle_debug_level > 0) {
01742 printf("First statement nested in %d loops\n", depth1);
01743 printf("Secnd statement nested in %d loops\n", depth2);
01744 printf("Shackle depth is %d\n", shackle_depth);
01745 printf("Total number of variables is %d\n", nvars);
01746 printf("Conditions expressing smae location:");
01747 soe_same_loc->Print(stdout);
01748 printf("Conditions expressing shackling:");
01749 soe_data_shackle->Print(stdout);
01750 }
01751
01752
01753 stmt_rhs_offset = (stmt1_before_stmt2) ? -1 : 0;
01754 common_depth = Num_Common_Loops (stmt1, stmt2);
01755 for (i = 0; i < nvars; i++)
01756 row[i] = 0;
01757 soe_lex_init = CXX_NEW_ARRAY (SYSTEM_OF_EQUATIONS *,
01758 common_depth,
01759 &shackle_default_pool);
01760 for (i = 0; i < common_depth; i++) {
01761 soe_lex_init[i] =
01762 CXX_NEW (SYSTEM_OF_EQUATIONS (0, 0, nvars,
01763 &shackle_default_pool),
01764 &shackle_default_pool);
01765 }
01766 for (i = 0; i < common_depth; i++) {
01767 for (j = 0; j < i; j++) {
01768 row[j] = 1;
01769 row[j+depth1] = -1;
01770 soe_lex_init[i]->Add_Eq (row, 0);
01771 row[j] = 0;
01772 row[j+depth1] = 0;
01773 }
01774 row[i] = -1;
01775 row[i+depth1] = 1;
01776 soe_lex_init[i]->Add_Le (row, stmt_rhs_offset);
01777 row[i] = 0;
01778 row[i+depth1] = 0;
01779 }
01780 l1 = CXX_NEW (LINEAR_CLAUSE (soe_lex_init, common_depth,
01781 &shackle_default_pool),
01782 &shackle_default_pool);
01783 if (shackle_debug_level > 0) {
01784 fprintf(stdout, "We'll now dump the initial lex conds\n");
01785 l1->Print(stdout);
01786 }
01787 soe_lex_final = CXX_NEW_ARRAY (SYSTEM_OF_EQUATIONS *,
01788 shackle_depth,
01789 &shackle_default_pool);
01790 for (i = 0; i < shackle_depth; i++) {
01791 soe_lex_final[i] =
01792 CXX_NEW (SYSTEM_OF_EQUATIONS (0, 0, nvars,
01793 &shackle_default_pool),
01794 &shackle_default_pool);
01795 }
01796
01797
01798 for (i = 0; i < shackle_depth; i++) {
01799 for (j = 0; j < i; j++) {
01800 row[j+depth1+depth2] = 1;
01801 row[j+depth1+depth2+shackle_depth] = -1;
01802 soe_lex_final[i]->Add_Eq (row, 0);
01803 row[j+depth1+depth2] = 0;
01804 row[j+depth1+depth2+shackle_depth] = 0;
01805 }
01806 row[i+depth1+depth2] = 1;
01807 row[i+depth1+depth2+shackle_depth] = -1;
01808 soe_lex_final[i]->Add_Le (row, -1);
01809 row[i+depth1+depth2] = 0;
01810 row[i+depth1+depth2+shackle_depth] = 0;
01811 }
01812 l2 = CXX_NEW (LINEAR_CLAUSE (soe_lex_final, shackle_depth,
01813 &shackle_default_pool),
01814 &shackle_default_pool);
01815 if (shackle_debug_level > 0) {
01816 fprintf(stdout, "We'll now dump the Final lex conds\n");
01817 l2->Print(stdout);
01818 }
01819 l3 = CXX_NEW (LINEAR_CLAUSE (soe_same_loc, &shackle_default_pool),
01820 &shackle_default_pool);
01821 l4 = CXX_NEW (LINEAR_CLAUSE (soe_data_shackle,
01822 &shackle_default_pool),
01823 &shackle_default_pool);
01824
01825 soe_loop_bnds1 =
01826 CXX_NEW (SYSTEM_OF_EQUATIONS (0, 0, nvars, &shackle_default_pool),
01827 &shackle_default_pool);
01828 count = depth1;
01829 stmt = stmt1;
01830 while (stmt != NULL) {
01831
01832 if (OPC_DO_LOOP == WN_opcode (stmt)) {
01833 dli = Get_Do_Loop_Info (stmt);
01834 assert (NULL != dli);
01835 lb = dli->LB;
01836 for (i = 0; i < lb->Num_Vec(); i++) {
01837 v1 = lb->Dim(i);
01838
01839
01840 if ((!v1->Contains_Lin_Symb()) &&
01841 (!v1->Contains_Non_Lin_Symb())) {
01842 for (j = 0; j < count; j++) {
01843 row[j] = v1->Loop_Coeff (j);
01844 }
01845 soe_loop_bnds1->Add_Le (row, v1->Const_Offset);
01846 }
01847 }
01848 count--;
01849 row[count] = 0;
01850 }
01851 stmt = LWN_Get_Parent (stmt);
01852 }
01853 assert (0 == count);
01854 count = depth1;
01855 stmt = stmt1;
01856 while (stmt != NULL) {
01857
01858 if (OPC_DO_LOOP == WN_opcode (stmt)) {
01859 dli = Get_Do_Loop_Info (stmt);
01860 assert (NULL != dli);
01861 ub = dli->UB;
01862 for (i = 0; i < ub->Num_Vec(); i++) {
01863 v1 = ub->Dim(i);
01864
01865
01866 if ((!v1->Contains_Lin_Symb()) &&
01867 (!v1->Contains_Non_Lin_Symb())) {
01868 for (j = 0; j < count; j++) {
01869 row[j] = v1->Loop_Coeff (j);
01870 }
01871 soe_loop_bnds1->Add_Le (row, v1->Const_Offset);
01872 }
01873 }
01874 count--;
01875 row[count] = 0;
01876 }
01877 stmt = LWN_Get_Parent (stmt);
01878 }
01879 assert (0 == count);
01880
01881 soe_loop_bnds2 =
01882 CXX_NEW (SYSTEM_OF_EQUATIONS (0, 0, nvars, &shackle_default_pool),
01883 &shackle_default_pool);
01884 count = depth2;
01885 stmt = stmt2;
01886 while (stmt != NULL) {
01887
01888 if (OPC_DO_LOOP == WN_opcode (stmt)) {
01889 dli = Get_Do_Loop_Info (stmt);
01890 assert (NULL != dli);
01891 lb = dli->LB;
01892 for (i = 0; i < lb->Num_Vec(); i++) {
01893 v2 = lb->Dim(i);
01894
01895
01896 if ((!v2->Contains_Lin_Symb()) &&
01897 (!v2->Contains_Non_Lin_Symb())) {
01898 for (j = 0; j < count; j++) {
01899 row[j+depth1] = v2->Loop_Coeff (j);
01900 }
01901 soe_loop_bnds2->Add_Le (row, v2->Const_Offset);
01902 }
01903 }
01904 count--;
01905 row[count+depth1] = 0;
01906 }
01907 stmt = LWN_Get_Parent (stmt);
01908 }
01909 assert (0 == count);
01910 count = depth2;
01911 stmt = stmt2;
01912 while (stmt != NULL) {
01913
01914 if (OPC_DO_LOOP == WN_opcode (stmt)) {
01915 dli = Get_Do_Loop_Info (stmt);
01916 assert (NULL != dli);
01917 ub = dli->UB;
01918 for (i = 0; i < ub->Num_Vec(); i++) {
01919 v2 = ub->Dim(i);
01920
01921
01922 if ((!v2->Contains_Lin_Symb()) &&
01923 (!v2->Contains_Non_Lin_Symb())) {
01924 for (j = 0; j < count; j++) {
01925 row[j+depth1] = v2->Loop_Coeff (j);
01926 }
01927 soe_loop_bnds2->Add_Le (row, v2->Const_Offset);
01928 }
01929 }
01930 count--;
01931 row[count+depth1] = 0;
01932 }
01933 stmt = LWN_Get_Parent (stmt);
01934 }
01935 assert (0 == count);
01936 if (shackle_debug_level > 0) {
01937 printf("Printing bounds for statement 1\n");
01938 soe_loop_bnds1->Print(stdout);
01939 printf("Print bounds for statement 2 \n");
01940 soe_loop_bnds2->Print(stdout);
01941 }
01942 l5 = CXX_NEW (LINEAR_CLAUSE (soe_loop_bnds1,
01943 &shackle_default_pool),
01944 &shackle_default_pool);
01945 l6 = CXX_NEW (LINEAR_CLAUSE (soe_loop_bnds2,
01946 &shackle_default_pool),
01947 &shackle_default_pool);
01948 l11 = combine_clauses (combine_clauses (l3, l4),
01949 combine_clauses (l5, l6));
01950 l12 = combine_clauses (l1, l2);
01951 l13 = combine_clauses (l11, l12);
01952 if (shackle_debug_level > 1) {
01953 fprintf(stdout, "Here is the big final mess\n");
01954 l13->Print (stdout);
01955 }
01956 return_val = !l13->Is_Consistent();
01957 MEM_POOL_Pop (&shackle_default_pool);
01958 return return_val;
01959 }
01960
01961 static BOOL
01962 _xis_legal_shackle(QUEUE<WN *> *stmts,
01963 QUEUE<SHACKLE_INFO*> *shq)
01964 {
01965 SYMBOL *newsyms;
01966 const INT32 bufsz = 128;
01967 char buf[bufsz];
01968 INT32 bufcnt, i;
01969 INT32 length = stmts->Queue_Length();
01970 QUEUE_ITER<WN *> iter1(stmts);
01971 QUEUE_ITER<WN *> *iter2;
01972 QUEUE_ITER<WN *> *iter_ref;
01973 WN *step1, *step2, *ref, *ref2;
01974 BOOL read_stmt_prior, result;
01975 QUEUE<WN *> *reflist1, *reflist2;
01976
01977 while (iter1.Step(&step1)) {
01978 reflist1 = (QUEUE<WN *> *) WN_MAP_Get (shackle_ref_map,
01979 step1);
01980 iter_ref = CXX_NEW (QUEUE_ITER<WN *> (reflist1),
01981 &shackle_default_pool);
01982 while (iter_ref->Step(&ref)) {
01983 iter2 = CXX_NEW (QUEUE_ITER<WN *> (stmts),
01984 &shackle_default_pool);
01985 read_stmt_prior = FALSE;
01986 while (iter2->Step(&step2)) {
01987 if (step2 == step1)
01988 read_stmt_prior = TRUE;
01989 reflist2 = (QUEUE<WN *> *) WN_MAP_Get (shackle_ref_map,
01990 step2);
01991 if (reflist2->Queue_Isempty())
01992 continue;
01993 ref2 = reflist2->Queue_First()->Qnode_Item();
01994 result = _xdependence_is_preserved (step1, step2, ref, ref2,
01995 read_stmt_prior, shq);
01996 if ((result) && (shackle_debug_level > 1))
01997 fprintf (stdout, "Dependence is preserved\n");
01998 else if (shackle_debug_level > 1)
01999 fprintf (stdout, "Dependence is violated- arrgh\n");
02000 if (FALSE == result)
02001 return FALSE;
02002 }
02003 }
02004 }
02005 return TRUE;
02006 }
02007
02008 static BOOL
02009 Contained_In_Loop(WN *wn)
02010 {
02011 WN *step = LWN_Get_Parent (wn);
02012 while (step) {
02013 if (OPC_DO_LOOP == WN_opcode (step))
02014 return TRUE;
02015 step = LWN_Get_Parent (step);
02016 }
02017 return FALSE;
02018 }
02019
02020 static void
02021 _xtest_dependence_is_preserved(QUEUE<WN *> *stmts,
02022 QUEUE<SHACKLE_INFO*> *shq)
02023 {
02024 WN *stmt1, *stmt2;
02025 WN *ref1, *ref2;
02026 QUEUE<WN *> *shackle_list1, *shackle_list2;
02027 BOOL result;
02028
02029 stmt1 = stmts->Queue_First()->Qnode_Item();
02030 stmt2 = stmts->Queue_First()->Qnode_Next()->Qnode_Item();
02031
02032 shackle_list1 = (QUEUE<WN *> *)
02033 WN_MAP_Get (shackle_shackle_map, stmt1);
02034 shackle_list2 = (QUEUE<WN *> *)
02035 WN_MAP_Get (shackle_shackle_map, stmt2);
02036 ref1 = shackle_list1->Queue_First()->Qnode_Item();
02037 ref2 = shackle_list2->Queue_First()->Qnode_Item();
02038 result =
02039 _xdependence_is_preserved (stmt1, stmt2, ref1, ref2, TRUE, shq);
02040 if (result)
02041 fprintf(stdout, "Dependence is preserved\n");
02042 else
02043 fprintf(stdout, "Dependence is violated\n");
02044 }
02045
02046 static BOOL
02047 Stmt_With_Only_Scalars(WN *stmt)
02048 {
02049 switch (WN_operator (stmt)) {
02050 case OPR_LDID:
02051 case OPR_STID:
02052 return TRUE;
02053 case OPR_ARRAY:
02054 case OPR_ILOAD:
02055 case OPR_MLOAD:
02056 case OPR_ISTORE:
02057 case OPR_MSTORE:
02058 return FALSE;
02059 default:
02060 FOR_CHILDREN (stmt, child, ignCount) {
02061 if (FALSE == Stmt_With_Only_Scalars (child))
02062 return FALSE;
02063 }
02064 END_CHILDREN;
02065 return TRUE;
02066 }
02067 }
02068
02069 static WN *
02070 Ldid_Comes_From_Loop(WN *wn)
02071 {
02072 FmtAssert (OPR_LDID == WN_operator (wn),
02073 ("Ldid_Comes_From_Loop called with non Ldid"));
02074 DU_MANAGER *du = Du_Mgr;
02075 DEF_LIST *def_list = du->Ud_Get_Def (wn);
02076 WN *parent;
02077 DEF_LIST_ITER iter(def_list);
02078 const DU_NODE *node = NULL;
02079
02080 for (node = iter.First(); !iter.Is_Empty(); node = iter.Next()) {
02081 WN *def = node->Wn();
02082 parent = LWN_Get_Parent (def);
02083
02084 if ((NULL == parent) || (OPC_DO_LOOP != WN_opcode (parent)))
02085 return NULL;
02086 }
02087 return parent;
02088 }
02089
02090 static WN *
02091 Enclosing_If_Or_Store (WN *wn)
02092 {
02093 if (NULL == wn)
02094 return NULL;
02095 else if (OPC_IF == WN_opcode (wn) ||
02096 OPCODE_is_store (WN_opcode (wn)))
02097 return wn;
02098 else
02099 return Enclosing_If_Or_Store (LWN_Get_Parent (wn));
02100 }
02101
02102 static WN *
02103 Enclosing_Store (WN *wn)
02104 {
02105 if (NULL == wn)
02106 return NULL;
02107 if (OPCODE_is_store (WN_opcode (wn)))
02108 return wn;
02109 else
02110 return Enclosing_Store (LWN_Get_Parent (wn));
02111 }
02112
02113 static BOOL
02114 Stid_Comes_From_Loop (WN *wn)
02115 {
02116 FmtAssert (OPR_STID == WN_operator (wn),
02117 ("Stid_Comes_From_Loop called with non Stid"));
02118 WN *parent = LWN_Get_Parent (wn);
02119 if (NULL == parent || (OPC_DO_LOOP != WN_opcode (parent)))
02120 return FALSE;
02121 return TRUE;
02122 }
02123
02124
02125
02126 static WN *
02127 Find_Unchained_Scalar(WN *root)
02128 {
02129 if (OPR_LDID == WN_operator (root)) {
02130 if (Shackle_Chain_Not_Visited(root)) {
02131 WN *frm_loop = Ldid_Comes_From_Loop (root);
02132 if (NULL == frm_loop) {
02133
02134 return root;
02135 } else {
02136
02137 return NULL;
02138 }
02139 } else
02140 return NULL;
02141 }
02142 else if (OPR_ARRAY == WN_operator (root) ||
02143 OPR_ILOAD == WN_operator (root) ||
02144 OPR_MLOAD == WN_operator (root))
02145 return NULL;
02146 else if (OPR_STID == WN_operator (root)) {
02147 if (Shackle_Chain_Not_Visited (root)) {
02148 BOOL frm_loop = Stid_Comes_From_Loop (root);
02149 if (FALSE == frm_loop) {
02150
02151 return root;
02152 } else {
02153
02154 return NULL;
02155 }
02156 } else
02157 return NULL;
02158 }
02159 FOR_CHILDREN (root, child, ignCount) {
02160 WN *result = Find_Unchained_Scalar (child);
02161 if (NULL != result)
02162 return result;
02163 }
02164 END_CHILDREN;
02165 return NULL;
02166 }
02167
02168 static WN *
02169 Find_Unchained_If_With_Scalar_Cond(WN *root)
02170 {
02171 if (OPC_IF == WN_opcode (root))
02172 if (Shackle_Chain_Not_Visited(root)) {
02173 WN *contained_scalars =
02174 Find_Unchained_Scalar (WN_if_test (root));
02175 if (NULL != contained_scalars) {
02176
02177 return root;
02178 } else {
02179
02180 }
02181 }
02182 FOR_CHILDREN (root, child, ignCount) {
02183 WN *result = Find_Unchained_If_With_Scalar_Cond (child);
02184 if (NULL != result)
02185 return result;
02186 }
02187 END_CHILDREN;
02188 return NULL;
02189 }
02190
02191 static WN *
02192 Find_Unchained_Store_With_Scalar(WN *root)
02193 {
02194 if (OPCODE_is_store (WN_opcode (root))) {
02195 if (Shackle_Chain_Not_Visited (root)) {
02196 WN *contained_scalars = Find_Unchained_Scalar (root);
02197 if (NULL != contained_scalars)
02198 return root;
02199 }
02200 }
02201 else {
02202 FOR_CHILDREN (root, child, ignCount) {
02203 WN *result = Find_Unchained_Store_With_Scalar (child);
02204 if (NULL != result)
02205 return result;
02206 }
02207 END_CHILDREN;
02208 }
02209 return NULL;
02210 }
02211
02212 static void
02213 Initialize_Shackle_Chain_Id_Map (QUEUE<WN *> *s)
02214 {
02215 QUEUE_ITER<WN *> iter (s);
02216 WN *stmt;
02217
02218 while (iter.Step (&stmt)) {
02219 WN_MAP32_Set (shackle_chain_id_map, stmt,
02220 shackle_chain_id_map_cnt);
02221 }
02222 }
02223
02224 static void
02225 Create_Chains_Of_Scalars(WN *top_level)
02226 {
02227 FmtAssert (OPC_DO_LOOP == WN_opcode (top_level),
02228 ("Non do loop being shackled"));
02229 WN *block = WN_do_body (top_level);
02230 FmtAssert (OPC_BLOCK == WN_opcode (block),
02231 ("Not a block as the statement list in a do?"));
02232 QUEUE<WN *> *work_q =
02233 CXX_NEW (QUEUE<WN *> (&shackle_default_pool),
02234 &shackle_default_pool);
02235 WN *stmt = Find_Unchained_If_With_Scalar_Cond (top_level);
02236 if (NULL == stmt)
02237 stmt = Find_Unchained_Store_With_Scalar (top_level);
02238 while (NULL != stmt) {
02239 shackle_chain_id_map_cnt++;
02240 WN *scalar;
02241 scalar = Find_Unchained_Scalar (stmt);
02242 while (NULL != scalar) {
02243 Shackle_Chain_Visited_Set (scalar);
02244 work_q->Add_Tail_Q (scalar);
02245 scalar = Find_Unchained_Scalar (stmt);
02246 }
02247 while (!work_q->Queue_Isempty()) {
02248 scalar = work_q->Get_Q();
02249 FmtAssert (NULL != scalar,
02250 ("Null scalar in Unchained if"));
02251 FmtAssert (OPR_LDID == WN_operator (scalar) ||
02252 OPR_STID == WN_operator (scalar),
02253 ("Scalar not an Stid or Ldid"));
02254 if (OPR_LDID == WN_operator (scalar)) {
02255 DU_MANAGER *du = Du_Mgr;
02256 DEF_LIST *def_list = du->Ud_Get_Def (scalar);
02257 DEF_LIST_ITER iter(def_list);
02258 const DU_NODE *node = NULL;
02259 for (node = iter.First(); !iter.Is_Empty();
02260 node = iter.Next()) {
02261 WN *def = node->Wn();
02262 WN *parent = Enclosing_If_Or_Store (def);
02263 if (NULL != parent)
02264 WN_MAP32_Set (shackle_chain_id_map, parent,
02265 shackle_chain_id_map_cnt);
02266 if (OPR_STID == WN_operator (def))
02267 work_q->Add_Tail_Q (def);
02268 }
02269 }
02270 else if (OPR_STID == WN_operator (scalar)) {
02271 Shackle_Chain_Visited_Set (scalar);
02272 DU_MANAGER *du = Du_Mgr;
02273 USE_LIST *use_list = du->Du_Get_Use (scalar);
02274 USE_LIST_ITER iter (use_list);
02275 const DU_NODE *node = NULL;
02276 for (node = iter.First(); !iter.Is_Empty();
02277 node = iter.Next()) {
02278 WN *use = node->Wn();
02279 WN *parent = Enclosing_If_Or_Store (use);
02280 if (NULL != parent)
02281 WN_MAP32_Set (shackle_chain_id_map, parent,
02282 shackle_chain_id_map_cnt);
02283 if (NULL != parent) {
02284 WN *nscalar = Find_Unchained_Scalar (parent);
02285 while (NULL != nscalar) {
02286 Shackle_Chain_Visited_Set (nscalar);
02287 work_q->Add_Tail_Q (nscalar);
02288 nscalar = Find_Unchained_Scalar (parent);
02289 }
02290 }
02291 }
02292 }
02293 }
02294 stmt = Find_Unchained_If_With_Scalar_Cond (top_level);
02295 if (NULL == stmt)
02296 stmt = Find_Unchained_Store_With_Scalar (top_level);
02297 }
02298 }
02299
02300
02301
02302
02303 static BOOL
02304 Is_Index_Expr_Shackleable(WN *wn)
02305 {
02306 if (OPR_ARRAY == WN_operator (wn))
02307 return FALSE;
02308 else if (OPR_LDID == WN_operator (wn))
02309 return (NULL != Ldid_Comes_From_Loop (wn));
02310 else {
02311 FOR_CHILDREN (wn, child, ignCount) {
02312 BOOL ret_val = Is_Index_Expr_Shackleable (child);
02313 if (FALSE == ret_val)
02314 return FALSE;
02315 }
02316 END_CHILDREN;
02317 return TRUE;
02318 }
02319 }
02320
02321 static BOOL
02322 Set_Dim_Shackleable(SHACKLE_INFO *sh, INT32 dim, WN *wn)
02323 {
02324 BOOL ret_val;
02325
02326 if (OPR_ARRAY == WN_operator (wn)) {
02327 ST *st = Identical_Array_Refbase (wn, wn);
02328 if (st == sh->Symbol()) {
02329 INT32 ndim = (WN_kid_count (wn) >> 1);
02330 if (dim >= ndim) {
02331 sh->Set_Reshaped (TRUE);
02332 return FALSE;
02333 }
02334 ret_val =
02335 Is_Index_Expr_Shackleable (WN_kid (wn, ndim + 1 + dim));
02336 if (FALSE == ret_val) {
02337 sh->Set_Dim_Shackled (dim, FALSE);
02338 return FALSE;
02339 } else
02340 return TRUE;
02341 } else
02342 return TRUE;
02343 }
02344 else {
02345 FOR_CHILDREN (wn, child, ignCount) {
02346 ret_val = Set_Dim_Shackleable (sh, dim, child);
02347 if (FALSE == ret_val)
02348 return FALSE;
02349 }
02350 END_CHILDREN;
02351 return TRUE;
02352 }
02353 }
02354
02355 static void
02356 Set_Shackleable(SHACKLE_INFO *sh, WN *main_snl)
02357 {
02358 INT32 ndim = sh->Ndim();
02359 for (INT32 i = 0; i < ndim; i++)
02360 Set_Dim_Shackleable (sh, i, main_snl);
02361 if (sh->Is_Reshaped()) {
02362 for (INT32 j = 0; j < ndim; j++)
02363 sh->Set_Dim_Shackled (j, FALSE);
02364 }
02365 }
02366
02367 static void
02368 Set_Shackleable(QUEUE<SHACKLE_INFO *> *shq, WN *main_snl)
02369 {
02370 QUEUE_ITER<SHACKLE_INFO *> iter (shq);
02371 SHACKLE_INFO *sh;
02372
02373 while (iter.Step (&sh))
02374 Set_Shackleable (sh, main_snl);
02375 }
02376
02377 static void
02378 Dump_Shackle_Info (SHACKLE_INFO *sh)
02379 {
02380 extern void dump_st(ST *);
02381
02382 fprintf(stdout, "Shackle_info for ");
02383 dump_st ((ST *) sh->Symbol());
02384 fprintf(stdout, "[");
02385 for (INT32 i = 0; i < sh->Ndim(); i++) {
02386 if (sh->Is_Dim_Shackled (i))
02387 fprintf(stdout, "{Sh %3d}", sh->Shackle_Dim_Size (i));
02388 else
02389 fprintf(stdout, "{No sh}");
02390 }
02391 fprintf(stdout, "]");
02392 fprintf(stdout, "\n");
02393 }
02394
02395 QUEUE<WN *> *
02396 Extract_Stmts_With_Chain_Id(QUEUE<WN *> *stmts,
02397 INT32 chain_id)
02398 {
02399 QUEUE<WN *> *result = CXX_NEW (QUEUE<WN *> (&shackle_default_pool),
02400 &shackle_default_pool);
02401 QUEUE_ITER<WN *> iter (stmts);
02402 WN *step;
02403
02404 while (iter.Step (&step)) {
02405 INT32 id = WN_MAP32_Get (shackle_chain_id_map, step);
02406 if (id == chain_id)
02407 result->Add_Tail_Q (step);
02408 }
02409 return result;
02410 }
02411
02412 static WN *
02413 Enclosing_Do_Loop_Of_Chain(QUEUE<WN *> *stmts)
02414 {
02415 if (stmts->Queue_Isempty())
02416 return NULL;
02417 WN *head = stmts->Queue_First()->Qnode_Item();
02418 INT32 chain_id = WN_MAP32_Get (shackle_chain_id_map, head);
02419 QUEUE_ITER<WN *> iter (stmts);
02420 WN *step;
02421 INT32 id;
02422 WN *do_loop = Enclosing_Do_Loop (head);
02423 if (NULL == do_loop)
02424 return NULL;
02425
02426 while (iter.Step (&step)) {
02427 id = WN_MAP32_Get (shackle_chain_id_map, step);
02428 FmtAssert (id == chain_id,
02429 ("Statements in the same chain have different ids!"));
02430 do_loop = LNO_Common_Loop (step, do_loop);
02431 if (NULL == do_loop)
02432 return NULL;
02433 }
02434 return do_loop;
02435 }
02436
02437 static BOOL
02438 Index_Derived_From_Parents_Of (WN *index_exp, WN *do_loop)
02439 {
02440 if (OPR_LDID == WN_operator (index_exp)) {
02441 WN *dup_loop = Ldid_Comes_From_Loop (index_exp);
02442 FmtAssert (NULL != dup_loop,
02443 ("Index expression must come from loop"));
02444 return Is_Parent_Of (dup_loop, do_loop);
02445 }
02446 else if (OPR_ARRAY == WN_operator (index_exp)) {
02447 FmtAssert (FALSE, ("Index exp cannot contain an array!"));
02448 return FALSE;
02449 }
02450 else {
02451 FOR_CHILDREN (index_exp, child, ignCount) {
02452 BOOL ret_val = Index_Derived_From_Parents_Of (child, do_loop);
02453 if (FALSE == ret_val)
02454 return FALSE;
02455 }
02456 END_CHILDREN;
02457 return TRUE;
02458 }
02459 }
02460
02461
02462
02463
02464 static void
02465 Shackleable_Refs_From_Stmt_In_Chain(QUEUE<SHACKLE_INFO*> *shq,
02466 WN *stmt,
02467 QUEUE<WN *> *result,
02468 WN *do_loop)
02469 {
02470 if (OPR_ARRAY == WN_operator (stmt)) {
02471 const ST *st = Identical_Array_Refbase (stmt, stmt);
02472 SHACKLE_INFO *sh = Shackle_Info_For_Symbol (shq, st);
02473 if (NULL == sh)
02474 return;
02475 INT32 ndim = (WN_kid_count (stmt) >> 1);
02476 BOOL ret_val = TRUE;
02477 for (INT32 i = 0; i < sh->Ndim(); i++) {
02478 if (sh->Is_Dim_Shackled (i)) {
02479 ret_val = ret_val &&
02480 Index_Derived_From_Parents_Of (WN_kid (stmt, ndim+1+i),
02481 do_loop);
02482 if (FALSE == ret_val)
02483 return;
02484 }
02485 }
02486 FmtAssert (TRUE == ret_val,
02487 ("Must be a shackleable references"));
02488 result->Add_Tail_Q (stmt);
02489 return;
02490 }
02491 else {
02492 FOR_CHILDREN (stmt, child, ignCount) {
02493 Shackleable_Refs_From_Stmt_In_Chain (shq, child,
02494 result, do_loop);
02495 }
02496 END_CHILDREN;
02497 }
02498 }
02499
02500 static QUEUE<WN *> *
02501 Shackleable_Refs_From_Chain (QUEUE<SHACKLE_INFO *> *shq,
02502 QUEUE<WN *> *stmtq)
02503 {
02504 if (stmtq->Queue_Isempty())
02505 return NULL;
02506 WN *head = stmtq->Queue_First()->Qnode_Item();
02507 INT32 id, chain_id = WN_MAP32_Get (shackle_chain_id_map, head);
02508 QUEUE<WN *> *result =
02509 CXX_NEW (QUEUE<WN *> (&shackle_default_pool),
02510 &shackle_default_pool);
02511 WN *do_loop = Enclosing_Do_Loop_Of_Chain (stmtq);
02512 QUEUE_ITER<WN *> iter (stmtq);
02513 WN *step;
02514
02515 while (iter.Step (&step)) {
02516 id = WN_MAP32_Get (shackle_chain_id_map, step);
02517 FmtAssert (id == chain_id,
02518 ("Statments in same chain with differented ids!"));
02519 Shackleable_Refs_From_Stmt_In_Chain (shq, step, result, do_loop);
02520 }
02521 return result;
02522 }
02523
02524
02525 static void
02526 Dump_Shackle_Info(QUEUE<SHACKLE_INFO *> *shq)
02527 {
02528 QUEUE_ITER<SHACKLE_INFO *> iter(shq);
02529 SHACKLE_INFO *sh;
02530
02531 while (iter.Step (&sh))
02532 Dump_Shackle_Info (sh);
02533 }
02534
02535 static void
02536 Dump_Shackle_Chain_Id_Map_Info(WN *func_nd, QUEUE<WN *> *s)
02537 {
02538 QUEUE_ITER<WN *> iter (s);
02539 WN *stmt;
02540
02541 Whirl2F_Init(func_nd);
02542 while (iter.Step (&stmt)) {
02543 Whirl2F_Emit(stdout, stmt);
02544 fprintf (stdout, ": %4d",
02545 WN_MAP32_Get (shackle_chain_id_map, stmt));
02546 fprintf(stdout, "\n");
02547 }
02548 }
02549
02550 static void
02551 Dump_Wn_Queue (WN *func_nd, QUEUE<WN *> *s)
02552 {
02553 if (s == NULL)
02554 return;
02555 QUEUE_ITER<WN *> iter (s);
02556 WN *step;
02557
02558 Whirl2F_Init (func_nd);
02559 fprintf(stdout, "{{");
02560 while (iter.Step (&step)) {
02561 fprintf(stdout, "[[");
02562 Whirl2F_Emit (stdout,
02563 ((OPR_ARRAY == WN_operator (step)) ?
02564 LWN_Get_Parent (step) : step));
02565 fprintf(stdout, "]]");
02566 }
02567 fprintf(stdout, "}}");
02568 }
02569
02570 static void
02571 Dump_Shackle_Map_Info (WN *func_nd, QUEUE<WN *> *s)
02572 {
02573 QUEUE_ITER<WN *> iter(s);
02574 WN *step;
02575
02576 Whirl2F_Init (func_nd);
02577 while (iter.Step(&step)) {
02578 QUEUE<WN *> *shackle =
02579 (QUEUE<WN *> *) WN_MAP_Get (shackle_shackle_map, step);
02580 Whirl2F_Emit (stdout, step);
02581 fprintf(stdout, "-----------------");
02582 Dump_Wn_Queue (func_nd, shackle);
02583 fprintf(stdout, "\n");
02584 }
02585 }
02586
02587 static void
02588 Shackleable_Refs_From_All_Chains(QUEUE<SHACKLE_INFO *> *shq,
02589 QUEUE<WN *> *stmtq)
02590 {
02591 shackle_chain_info =
02592 CXX_NEW_ARRAY (QUEUE<WN *> *,
02593 shackle_chain_id_map_cnt + 1,
02594 &shackle_default_pool);
02595 for (INT32 i = 1; i <= shackle_chain_id_map_cnt; i++) {
02596 QUEUE<WN *> *stmtq_chosen =
02597 Extract_Stmts_With_Chain_Id (stmtq, i);
02598 shackle_chain_info[i] =
02599 Shackleable_Refs_From_Chain (shq, stmtq_chosen);
02600
02601 }
02602 }
02603
02604 static WN*
02605 Exists_Same_Array_In_Queue (WN *array, QUEUE<WN *> *array_q)
02606 {
02607 if (NULL == array_q)
02608 return NULL;
02609
02610 QUEUE_ITER<WN *> iter(array_q);
02611 WN *step;
02612
02613 while (iter.Step (&step)) {
02614 if (NULL != Identical_Array_Refbase (step, array))
02615 return step;
02616 }
02617 return NULL;
02618 }
02619
02620 static BOOL
02621 Simple_Chain_Shackle_Case(QUEUE<WN *> *stmtq)
02622 {
02623 QUEUE<WN *> *unchained = Extract_Stmts_With_Chain_Id (stmtq, 0);
02624 if (unchained->Queue_Isempty())
02625 return FALSE;
02626 BOOL simple_chain_case = _xis_simple_shackle_case (unchained);
02627 if (!simple_chain_case)
02628 return FALSE;
02629 WN *array_ref = WN_kid1 (unchained->Queue_First()->Qnode_Item());
02630 WN **chain_ref_list =
02631 CXX_NEW_ARRAY (WN *, shackle_chain_id_map_cnt+1,
02632 &shackle_default_pool);
02633 for (INT32 i = 1; i <= shackle_chain_id_map_cnt; i++) {
02634 chain_ref_list[i] =
02635 Exists_Same_Array_In_Queue (array_ref, shackle_chain_info[i]);
02636 if (NULL == chain_ref_list[i])
02637 return FALSE;
02638 }
02639 QUEUE_ITER <WN *> iter(stmtq);
02640 WN *step;
02641
02642 while (iter.Step (&step)) {
02643 INT32 chain_id = WN_MAP32_Get (shackle_chain_id_map, step);
02644 QUEUE<WN *> *shackle_q =
02645 CXX_NEW (QUEUE<WN *> (&shackle_default_pool),
02646 &shackle_default_pool);
02647 FmtAssert (0 <= chain_id && chain_id <= shackle_chain_id_map_cnt,
02648 ("Invalid range for the id of the chain"));
02649 if (0 == chain_id)
02650 shackle_q->Add_Tail_Q (WN_kid1 (step));
02651 else
02652 shackle_q->Add_Tail_Q (chain_ref_list[chain_id]);
02653 WN_MAP_Set (shackle_shackle_map, step, (void *) shackle_q);
02654 }
02655 return TRUE;
02656 }
02657
02658 static BOOL
02659 Stored2Array_Assigned_Singly(WN *wn)
02660 {
02661 if (OPR_ISTORE != WN_operator (wn))
02662 return FALSE;
02663 WN *kid1 = WN_kid1 (wn);
02664 if (OPR_ARRAY != WN_operator (kid1))
02665 return FALSE;
02666 ARRAY_DIRECTED_GRAPH16 *dg = Array_Dependence_Graph;
02667 if (NULL == dg)
02668 return FALSE;
02669 VINDEX16 v = dg->Get_Vertex (wn);
02670 EINDEX16 e;
02671 if (0 == v)
02672 return FALSE;
02673
02674 if (!dg->Get_In_Edge (v) && !dg->Get_Out_Edge (v))
02675 return TRUE;
02676
02677 if (dg->Get_In_Edge (v)) {
02678 for (e = dg->Get_In_Edge (v); e != 0; e = dg->Get_Next_In_Edge(e))
02679 if (dg->Get_Source (e) == v)
02680 return FALSE;
02681 }
02682
02683 if (dg->Get_Out_Edge (v)) {
02684 for (e = dg->Get_Out_Edge (v); e != 0;
02685 e = dg->Get_Next_Out_Edge (e))
02686 if (dg->Get_Sink (e) == v)
02687 return FALSE;
02688 }
02689 return TRUE;
02690 }
02691
02692 static WN *
02693 Ref_To_Same_Array(WN *array, QUEUE<WN *> *refq)
02694 {
02695 QUEUE_ITER<WN *> iter (refq);
02696 WN *step;
02697
02698 while (iter.Step (&step)) {
02699 if (Identical_Array_Refbase (step, array))
02700 return step;
02701 }
02702 return NULL;
02703 }
02704
02705 static BOOL
02706 Scalar_Queue_Contains_Scalar(QUEUE<WN *> *lst,
02707 WN *scalar)
02708 {
02709 FmtAssert (OPR_LDID == WN_operator (scalar) ||
02710 OPR_STID == WN_operator (scalar),
02711 ("Scalar_Queue_Contains_Scalar called w/ non scalar"));
02712 QUEUE_ITER<WN *> iter(lst);
02713 WN *step;
02714
02715 while (iter.Step (&step)) {
02716 FmtAssert (OPR_LDID == WN_operator (step) ||
02717 OPR_STID == WN_operator (step),
02718 ("Scalar queue contains non scalars!"));
02719
02720 if (WN_st (step) == WN_st (scalar) &&
02721 WN_offset (step) == WN_offset (scalar))
02722 return TRUE;
02723 }
02724 return FALSE;
02725 }
02726
02727
02728 static BOOL
02729 Is_Nonloop_Scalar (WN *wn)
02730 {
02731 FmtAssert (OPR_LDID == WN_operator (wn) ||
02732 OPR_STID == WN_operator (wn),
02733 ("Is_Nonloop_Scalar called with non LD/STid"));
02734 if (OPR_STID == WN_operator (wn))
02735 return !Stid_Comes_From_Loop (wn);
02736 else {
02737 if (Ldid_Comes_From_Loop (wn))
02738 return FALSE;
02739 else if (NULL != LWN_Get_Parent (wn) &&
02740 OPR_ARRAY == WN_operator (LWN_Get_Parent (wn)) &&
02741 wn == WN_kid0 (LWN_Get_Parent (wn)))
02742 return FALSE;
02743 else
02744 return TRUE;
02745 }
02746 }
02747
02748 static void
02749 Gather_Nonloop_Scalars_In_Wn(QUEUE<WN *> *lst,
02750 WN *wn)
02751 {
02752 if (NULL == wn)
02753 return;
02754 else if (OPR_LDID == WN_operator (wn) ||
02755 OPR_STID == WN_operator (wn)) {
02756 if (!Scalar_Queue_Contains_Scalar (lst, wn) &&
02757 Is_Nonloop_Scalar (wn))
02758 lst->Add_Tail_Q (wn);
02759 return;
02760 }
02761 else {
02762 FOR_CHILDREN (wn, child, ignCount) {
02763 Gather_Nonloop_Scalars_In_Wn (lst, child);
02764 }
02765 END_CHILDREN;
02766 }
02767 }
02768
02769
02770 static BOOL
02771 Shackle_Scalars_Privatizable (WN *loop, QUEUE<WN *> *scq)
02772 {
02773 QUEUE_ITER<WN *> iter1(scq);
02774 WN *step1;
02775 DU_MANAGER *du_mgr = Du_Mgr;
02776
02777 while (iter1.Step (&step1))
02778 if (SE_EASY != Scalar_Expandable (step1, loop, du_mgr))
02779 return FALSE;
02780 return TRUE;
02781 }
02782
02783 static void
02784 Shackle_Scalars_Do_Privatize(WN *loop, QUEUE<WN *> *scq)
02785 {
02786 QUEUE<WN *> *old_stmts = gather_stmts_in_func (loop);
02787 QUEUE_ITER<WN *> old_iter (old_stmts);
02788 WN *old_step;
02789 INT32 count = old_stmts->Queue_Length();
02790 QUEUE<WN *> **shackle = CXX_NEW_ARRAY (QUEUE<WN *> *,
02791 count,
02792 &shackle_default_pool);
02793 count = 0;
02794 while (old_iter.Step (&old_step)) {
02795 shackle[count] = (QUEUE<WN *> *)
02796 WN_MAP_Get (shackle_shackle_map, old_step);
02797 count++;
02798 }
02799 FmtAssert (count == old_stmts->Queue_Length(),
02800 ("Queue length cannot change!"));
02801
02802 QUEUE_ITER<WN *> iter2(scq);
02803 WN *step2;
02804
02805 while (iter2.Step (&step2)) {
02806 FmtAssert (OPR_LDID == WN_operator (step2) ||
02807 OPR_STID == WN_operator (step2),
02808 ("Scalar queue contains non scalars!"));
02809 INT32 dummy[1] = {0};
02810 SYMBOL sym(step2);
02811 Scalar_Expand (loop, loop, step2, sym, &loop, dummy,
02812 1, TRUE, FALSE, FALSE, NULL);
02813 }
02814 QUEUE<WN *> *new_stmts = gather_stmts_in_func (loop);
02815 QUEUE_ITER<WN *> new_iter (new_stmts);
02816 WN *new_step;
02817 count = 0;
02818 while (new_iter.Step (&new_step)) {
02819 WN_MAP_Set (shackle_shackle_map, new_step,
02820 (void *) shackle[count]);
02821 count++;
02822 }
02823 FmtAssert (count == new_stmts->Queue_Length(),
02824 ("New statements Introduced!"));
02825 return;
02826 }
02827
02828 static QUEUE<WN *> *
02829 Create_Alternate_Simple_Chain_Shackle(QUEUE<WN *> *sq)
02830 {
02831 QUEUE_ITER<WN *> iter (sq);
02832 WN *step;
02833 QUEUE <WN *> *result;
02834
02835 result = CXX_NEW (QUEUE<WN *>(&shackle_default_pool),
02836 &shackle_default_pool);
02837
02838 while (iter.Step (&step)) {
02839 QUEUE<WN *> *old = (QUEUE<WN *> *)
02840 WN_MAP_Get (shackle_shackle_map, step);
02841 INT32 chain_id = WN_MAP32_Get (shackle_chain_id_map, step);
02842 QUEUE<WN *> *ref_array = (QUEUE<WN *> *)
02843 WN_MAP_Get (shackle_ref_map, step);
02844 if (0 != chain_id &&
02845 NULL != ref_array &&
02846 !ref_array->Queue_Isempty()) {
02847 WN *old_array = old->Queue_First()->Qnode_Item();
02848 WN *alternate = Ref_To_Same_Array (old_array, ref_array);
02849 if (NULL != alternate) {
02850 QUEUE<WN *> *newref =
02851 CXX_NEW (QUEUE<WN *> (&shackle_default_pool),
02852 &shackle_default_pool);
02853 newref->Add_Tail_Q (alternate);
02854 WN_MAP_Set (shackle_shackle_map, step, (void *) newref);
02855 Gather_Nonloop_Scalars_In_Wn (result, alternate);
02856 }
02857 }
02858 }
02859 return result;
02860 }
02861
02862 static BOOL
02863 SNL_Contains_Ge2_Do_Loops(WN *main_snl)
02864 {
02865 if (OPC_DO_LOOP != WN_opcode (main_snl))
02866 return FALSE;
02867 INT32 do_children_count = 0;
02868 FOR_CHILDREN (WN_do_body (main_snl), child, ignCount) {
02869 if (OPC_DO_LOOP == WN_opcode (child))
02870 do_children_count++;
02871 }
02872 END_CHILDREN;
02873 return (do_children_count >= 2);
02874 }
02875
02876 #ifdef KEY
02877
02878 static BOOL _xfunc_has_vectorizable_loop (WN* func_nd)
02879 {
02880 QUEUE_WKLIST_ITER<WN *> wklist(func_nd, &shackle_default_pool);
02881 WN * wk_item;
02882
02883 while (wklist.Step(&wk_item)) {
02884 if (OPC_DO_LOOP == WN_opcode (wk_item)) {
02885 DO_LOOP_INFO* dli = Get_Do_Loop_Info(wk_item);
02886 if (dli->Vectorizable)
02887 return TRUE;
02888 wklist.Wklist_Queue()->Add_Tail_Q (WN_do_body (wk_item));
02889 } else {
02890 FOR_CHILDREN (wk_item, child, ignCount) {
02891 assert (child != (WN *) NULL);
02892 wklist.Wklist_Queue()->Add_Tail_Q (child);
02893 }
02894 END_CHILDREN;
02895 }
02896 }
02897 return FALSE;
02898 }
02899 #endif
02900 static BOOL
02901 Per_SNL_Shackle_Phase(WN *main_snl,
02902 WN *func_nd)
02903 {
02904
02905 QUEUE<WN *> *s;
02906 QUEUE<SHACKLE_INFO*> *shackle_info;
02907 BOOL shackle_legal;
02908 INT32 shackling_depth;
02909 WN **shackle_loops_info;
02910
02911 if (OPC_DO_LOOP != WN_opcode (main_snl))
02912 return FALSE;
02913 if (!SNL_Contains_Ge2_Do_Loops (main_snl))
02914 return FALSE;
02915 DO_LOOP_INFO *dli = Get_Do_Loop_Info (main_snl);
02916
02917
02918 if (dli->Cannot_Block || dli->Auto_Parallelized ||
02919 dli->Is_Outer_Lego_Tile || dli->Is_Inner_Lego_Tile ||
02920 dli->Is_Processor_Tile || dli->Is_Doacross ||
02921 dli->Suggested_Parallel)
02922 return FALSE;
02923
02924 s = gather_stmts_in_func (main_snl);
02925 Shackle_Prompf_Map_Initialize (main_snl);
02926 shackle_chain_id_map_cnt = 0;
02927 if (shackle_debug_level > 0)
02928 printf("The number of statements is %d\n", s->Queue_Length());
02929 #ifdef KEY
02930
02931
02932
02933
02934
02935
02936
02937
02938
02939
02940 if ( LNO_Run_Simd > 0 &&
02941 LNO_Simd_Avoid_Fusion ) {
02942 if (_xfunc_has_vectorizable_loop (main_snl)) {
02943 if (shackle_debug_level > 0)
02944 printf("Vectorizable loop(s) prevent function from being shackled.\n");
02945 return FALSE;
02946 }
02947 }
02948 #endif
02949
02950
02951 if (TRUE == _xfunc_has_stmts2prevent_shackle (s)) {
02952 if (shackle_debug_level > 0)
02953 printf("Bad statements prevent function from being shackled\n");
02954 return FALSE;
02955 }
02956 if (TRUE == _xis_simple_shackle_case (s)) {
02957 if (shackle_debug_level > 0)
02958 printf("Simple case of shackling\n");
02959 Initialize_Shackle_Chain_Id_Map (s);
02960 Form_Statement_Refs(s);
02961
02962 _xcreate_simple_basic_shackle(s);
02963 shackle_info =
02964 _xcreate_shackle_map_for_arrays_in_func(main_snl, func_nd);
02965 Set_Shackleable (shackle_info, main_snl);
02966
02967 if (shackle_debug_level > 0)
02968 printf("Number of arrays to be shackled: %d\n",
02969 shackle_info->Queue_Length());
02970
02971 if (0 == shackle_info->Queue_Length())
02972 return FALSE;
02973 if (!Appropriate_Shackle_Size_Set (main_snl, shackle_info))
02974 return FALSE;
02975 shackle_legal = _xis_legal_shackle (s, shackle_info);
02976 if (!shackle_legal)
02977 return FALSE;
02978 if (Get_Trace(TP_LNOPT2, TT_SHACKLE_ONLY))
02979 Augment_Simple_Basic_Shackle (s, shackle_info);
02980
02981 if (!Reuse_Exists_In_Loop (main_snl, shackle_info))
02982 return FALSE;
02983 shackling_depth = Common_Shackling_Depth (s, shackle_info);
02984 if (0 == shackling_depth)
02985 return FALSE;
02986 shackle_loops_info = Create_Simple_Shackle_Loops (main_snl, s,
02987 shackle_info,
02988 shackling_depth);
02989 Create_Shackle_If_All_Stmts (main_snl, s, shackle_info,
02990 shackle_loops_info,
02991 shackling_depth);
02992 return TRUE;
02993 }
02994 else {
02995 if (shackle_debug_level > 0)
02996 printf("Not a simple case of shackling\n");
02997 Initialize_Shackle_Chain_Id_Map (s);
02998 Create_Chains_Of_Scalars(main_snl);
02999
03000 shackle_info =
03001 _xcreate_shackle_map_for_arrays_in_func(main_snl, func_nd);
03002 if (0 == shackle_info->Queue_Length())
03003 return FALSE;
03004 Set_Shackleable (shackle_info, main_snl);
03005
03006 Shackleable_Refs_From_All_Chains (shackle_info, s);
03007 if (Simple_Chain_Shackle_Case(s)) {
03008
03009 Form_Statement_Refs(s);
03010 if (!Appropriate_Shackle_Size_Set (main_snl, shackle_info))
03011 return FALSE;
03012 shackle_legal = _xis_legal_shackle (s, shackle_info);
03013 if (!shackle_legal) {
03014 QUEUE<WN *> *privatize_alternate =
03015 Create_Alternate_Simple_Chain_Shackle(s);
03016 BOOL alternate_shackle =
03017 Shackle_Scalars_Privatizable (main_snl, privatize_alternate);
03018 if (!alternate_shackle)
03019 return FALSE;
03020
03021 if (!Appropriate_Shackle_Size_Set (main_snl, shackle_info))
03022 return FALSE;
03023 shackle_legal = _xis_legal_shackle (s, shackle_info);
03024 if (!shackle_legal) {
03025 if (shackle_debug_level > 0)
03026 fprintf(stdout, "Illegal shackling\n");
03027 return FALSE;
03028 }
03029 else {
03030 if (shackle_debug_level > 0)
03031 fprintf(stdout, "Alternate legal shackling\n");
03032 Shackle_Scalars_Do_Privatize (main_snl, privatize_alternate);
03033 s = gather_stmts_in_func (main_snl);
03034 }
03035 } else {
03036 if (shackle_debug_level > 0)
03037 fprintf(stdout, "Legal shackling");
03038 }
03039 if (!Reuse_Exists_In_Loop (main_snl, shackle_info))
03040 return FALSE;
03041 shackling_depth = Common_Shackling_Depth (s, shackle_info);
03042 if (0 == shackling_depth)
03043 return FALSE;
03044 shackle_loops_info =
03045 Create_Simple_Shackle_Loops (main_snl, s, shackle_info,
03046 shackling_depth);
03047 Create_Shackle_If_All_Stmts (main_snl, s, shackle_info,
03048 shackle_loops_info,
03049 shackling_depth);
03050 return TRUE;
03051 }
03052 else
03053 return FALSE;
03054 }
03055 }
03056
03057 void
03058 SHACKLE_Phase (WN *func_nd)
03059 {
03060 BOOL func_shackled = FALSE;
03061
03062
03063 if (!LNO_Shackle && !Get_Trace(TP_LNOPT2, TT_SHACKLE_ONLY))
03064 return;
03065 if (Get_Trace(TP_LNOPT2, TT_TILE_ONLY))
03066 return;
03067
03068 if (Get_Trace(TP_LNOPT2, TT_SHACKLE_DEBUG))
03069 shackle_debug_level = 1;
03070 else
03071 shackle_debug_level = 0;
03072
03073 if (shackle_debug_level > 0) {
03074 printf("Shackling started\n");
03075 }
03076
03077 MEM_POOL_Initialize (&shackle_default_pool, "shackle_default_pool", FALSE);
03078 MEM_POOL_Initialize (&shackle_map_pool, "shackle_map_pool", FALSE);
03079 MEM_POOL_Push (&shackle_default_pool);
03080 Shackle_Mem_Initialize (&shackle_default_pool);
03081 shackle_ref_map = WN_MAP_Create (&shackle_map_pool);
03082 shackle_shackle_map = WN_MAP_Create (&shackle_map_pool);
03083 shackle_prompf_id_map = WN_MAP32_Create (&shackle_map_pool);
03084 shackle_chain_map = WN_MAP32_Create (&shackle_map_pool);
03085 shackle_chain_id_map = WN_MAP32_Create (&shackle_map_pool);
03086 FIZ_FUSE_INFO *ffi =
03087 CXX_NEW (FIZ_FUSE_INFO (&shackle_default_pool),
03088 &shackle_default_pool);
03089 ffi->Build(func_nd);
03090 for (INT32 i = 0; i < ffi->Num_Snl(); i++) {
03091 if (ffi->Get_Type(i) != Invalid) {
03092 WN *loop = ffi->Get_Wn (i);
03093
03094 if (Contained_In_Loop (loop))
03095 continue;
03096 if (Per_SNL_Shackle_Phase (ffi->Get_Wn (i), func_nd))
03097 func_shackled = TRUE;
03098 }
03099 }
03100 if (func_shackled) {
03101 shackle_if_init(&shackle_default_pool);
03102 analyze_stmts_in_func_for_if (func_nd);
03103 LWN_Parentize (func_nd);
03104 Convert_Do_Loops_Conditionals (func_nd);
03105 shackle_if_finalize();
03106 LWN_Parentize (func_nd);
03107 Shackle_Postprocess_Do_Loop_Bounds(func_nd);
03108 }
03109 WN_MAP_Delete (shackle_ref_map);
03110 WN_MAP_Delete (shackle_shackle_map);
03111 WN_MAP_Delete (shackle_prompf_id_map);
03112 WN_MAP_Delete (shackle_chain_map);
03113 WN_MAP_Delete (shackle_chain_id_map);
03114 MEM_POOL_Pop (&shackle_default_pool);
03115 MEM_POOL_Delete (&shackle_default_pool);
03116 MEM_POOL_Delete (&shackle_map_pool);
03117 }