00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075 #define __STDC_LIMIT_MACROS
00076 #include <stdint.h>
00077 #ifdef USE_PCH
00078 #include "lno_pch.h"
00079 #endif // USE_PCH
00080 #pragma hdrstop
00081
00082 static const char *source_file = __FILE__;
00083 static const char *rcs_id = "$Source: ../../be/lno/SCCS/s.can.cxx $ $Revision: 1.25 $";
00084
00085 #include "call_info.h"
00086 #include "lnopt_main.h"
00087 #include "lnoutils.h"
00088 #include "lwn_util.h"
00089 #include "opt_alias_interface.h"
00090 #include "opt_du.h"
00091 #include "config_targ.h"
00092 #include "targ_const.h"
00093 #include "targ_sim.h"
00094 #include "wn_simp.h"
00095 #include "reverse.h"
00096 #include "errors.h"
00097 #include "erbe.h"
00098 #include "snl_utils.h"
00099 #include "lego_util.h"
00100 #include "config.h"
00101 #include "be_util.h"
00102
00103 extern BOOL Run_autopar_save;
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126 typedef STACK<WN *> STACK_OF_WN;
00127 typedef STACK<DO_LOOP_INFO *> DLI_STACK;
00128 typedef STACK<IF_INFO *> II_STACK;
00129 static void Mark_Code(WN *, WN *, DOLOOP_STACK *,DLI_STACK *, II_STACK *,
00130 STACK_OF_WN *, HASH_TABLE<INT, WN*> *,
00131 mUINT8 depth, INT *inner_depth,
00132 BOOL promote_pointers, BOOL inside_bound,
00133 BOOL strict_limit=TRUE);
00134 static void Dismantle_Do(WN *);
00135 static void Dismantle_Dos(WN *, BOOL);
00136 static BOOL did_dismantle;
00137 static BOOL has_dos;
00138 static INT64 Find_Average(ACCESS_VECTOR *av, BOOL *know_val,
00139 DOLOOP_STACK *do_stack);
00140 static void Copy_Loads_In_Bound(WN *do_loop, WN *tmp, BOOL is_start);
00141 static void Promote_Pointer(WN *wn, INT kid_num, INT load_size);
00142 #ifdef KEY
00143
00144 static void Fold_Array(WN *wn, INT kid_num);
00145 #endif
00146 static void Fold_Base(WN *array);
00147 static void Fold_Offset(WN *wn, WN *array);
00148 static void Fold_Intconst(WN *ld_st, WN *intconst, BOOL negate);
00149 static void Enter_Label_Goto_Hash(WN *func_nd,
00150 HASH_TABLE<INT32, WN*> *label_hash,
00151 HASH_TABLE<INT32, WN*> *goto_hash);
00152 static void Delete_Unused_Labels(HASH_TABLE<INT32, WN*> *label_hash,
00153 HASH_TABLE<INT32, WN*> *goto_hash);
00154
00155 static WN *Convert_Alloca_To_Intrinsic (WN *wn);
00156 static WN *Convert_Dealloca_To_Intrinsic (WN *wn);
00157 extern WN *Convert_Intrinsic_To_Alloca_Dealloca (WN *wn);
00158
00159 static INT64 constval;
00160
00161 extern BOOL Mark_Code(WN *func_nd,
00162 BOOL promote_pointers,
00163 BOOL strict_limit)
00164 {
00165 Is_True(WN_opcode(func_nd) == OPC_FUNC_ENTRY,
00166 ("non func_entry in Mark_Code"));
00167 INT inner_depth=0;
00168 did_dismantle=FALSE;
00169 has_dos = FALSE;
00170 extern BOOL PU_has_manual_prefetch;
00171 PU_has_manual_prefetch = FALSE;
00172 MEM_POOL_Push(&LNO_local_pool);
00173 {
00174 DLI_STACK *dlistack = CXX_NEW(DLI_STACK(&LNO_local_pool),&LNO_local_pool);
00175 DOLOOP_STACK *stack=CXX_NEW(DOLOOP_STACK(&LNO_local_pool),&LNO_local_pool);
00176
00177 II_STACK *if_stack = CXX_NEW(II_STACK(&LNO_local_pool),&LNO_local_pool);
00178 STACK_OF_WN *label_stack =
00179 CXX_NEW(STACK_OF_WN(&LNO_local_pool),&LNO_local_pool);
00180 HASH_TABLE<INT32, WN*> label_hash(50,&LNO_local_pool);
00181 HASH_TABLE<INT32, WN*> goto_hash(50,&LNO_local_pool);
00182 Enter_Label_Goto_Hash(func_nd,&label_hash, &goto_hash);
00183 Mark_Code(func_nd,func_nd,stack,dlistack,if_stack,label_stack,&label_hash,
00184 0,&inner_depth, promote_pointers,FALSE,strict_limit);
00185 Delete_Unused_Labels (&label_hash, &goto_hash);
00186 WN_Simplify_Tree(func_nd);
00187 if (did_dismantle) Remark_Depth(func_nd,0);
00188 }
00189 MEM_POOL_Pop(&LNO_local_pool);
00190 return has_dos;
00191 }
00192
00193 static void Move_To_PU_Pragma_List(WN* pragma_wn, WN* func_nd);
00194 static void Error_Check_MP_Pragmas (WN* wn);
00195 static void Mark_Concurrent_Call(WN *wn);
00196
00197
00198
00199 static void Patch_Loop_Statement_Expression(WN* wn_exp,
00200 WN* wn_loop)
00201 {
00202 DEF_LIST* def_list = Du_Mgr->Ud_Get_Def(wn_exp);
00203 if (def_list != NULL && SYMBOL(wn_exp) != SYMBOL(WN_index(wn_loop))
00204 && def_list->Loop_stmt() == wn_loop) {
00205 WN* wn_enclosing_loop = Enclosing_Proper_Do_Loop(wn_exp);
00206 def_list->Set_loop_stmt(wn_enclosing_loop);
00207 DEF_LIST_ITER iter(def_list);
00208 const DU_NODE* node = NULL;
00209 const DU_NODE* nnext = NULL;
00210 for (node = iter.First(); !iter.Is_Empty(); node = nnext) {
00211 nnext = iter.Next();
00212 WN* wn_def = node->Wn();
00213 if (Wn_Is_Inside(wn_def, wn_loop))
00214 Du_Mgr->Delete_Def_Use(wn_def, wn_exp);
00215 }
00216 }
00217 for (INT i = 0; i < WN_kid_count(wn_exp); i++)
00218 Patch_Loop_Statement_Expression(WN_kid(wn_exp, i), wn_loop);
00219 }
00220
00221 static void Patch_Loop_Statements(WN* wn_loop)
00222 {
00223 Patch_Loop_Statement_Expression(WN_start(wn_loop), wn_loop);
00224 Patch_Loop_Statement_Expression(WN_end(wn_loop), wn_loop);
00225 Patch_Loop_Statement_Expression(WN_step(wn_loop), wn_loop);
00226 }
00227
00228 static INT Loop_Depth_Limit(BOOL strict_limit)
00229 {
00230 INT upper_limit = LNO_MAX_DO_LOOP_DEPTH - 1;
00231 if (strict_limit)
00232 upper_limit = MIN(LNO_MAX_DO_LOOP_DEPTH - 1, LNO_Max_Do_Loop_Depth_Strict);
00233 return upper_limit;
00234 }
00235
00236 static INT Nest_Total(WN* wn_region)
00237 {
00238 WN* wn_first = WN_first(WN_region_pragmas(wn_region));
00239 for (WN* wn = wn_first; wn != NULL; wn = WN_next(wn)) {
00240 if (WN_opcode(wn) == OPC_PRAGMA) {
00241 switch (WN_pragma(wn)) {
00242 case WN_PRAGMA_PDO_BEGIN:
00243 case WN_PRAGMA_DOACROSS:
00244 case WN_PRAGMA_PARALLEL_DO:
00245 return WN_pragma_arg2(wn);
00246 }
00247 }
00248 }
00249 return -1;
00250 }
00251
00252
00253
00254
00255
00256
00257
00258 static void Dismantle_Nested_Region(WN* wn_region)
00259 {
00260 WN* wnn = NULL;
00261 WN* wn_after = wn_region;
00262 WN* wn_first = WN_first(WN_region_body(wn_region));
00263 for (WN* wn = wn_first; wn != NULL; wn = wnn) {
00264 wnn = WN_next(wn);
00265 LWN_Extract_From_Block(wn);
00266 LWN_Insert_Block_After(LWN_Get_Parent(wn_region), wn_after, wn);
00267 wn_after = wn;
00268 }
00269 LWN_Extract_From_Block(wn_region);
00270 LWN_Delete_Tree(wn_region);
00271 }
00272
00273
00274
00275
00276
00277
00278
00279 static WN* Dismantle_Nested_Doacross(WN* wn_region,
00280 INT tile_count)
00281 {
00282 WN* wn_start = WN_first(WN_region_body(wn_region));
00283 WN* wn = 0;
00284 for (wn = wn_start; wn != NULL; wn = WN_next(wn))
00285 if (WN_operator(wn) == OPR_DO_LOOP)
00286 break;
00287 FmtAssert(wn != NULL, ("Dismantle_Nested_Doacross: Could not find DO"));
00288 WN* wn_outer_loop = wn;
00289 WN* wn_inner_loop = SNL_Get_Inner_Snl_Loop(wn_outer_loop, tile_count);
00290 wn_start = wn_inner_loop;
00291 INT i;
00292 for (i = 0; i < tile_count; i++) {
00293 WN* wn = 0;
00294 for (wn = wn_start; wn != NULL; wn = LWN_Get_Parent(wn))
00295 if (WN_opcode(wn) == OPC_REGION)
00296 break;
00297 WN* wn_region = wn;
00298 FmtAssert(wn_region != NULL, ("Could not find enclosing region"));
00299 wn_start = LWN_Get_Parent(wn_region);
00300 Dismantle_Nested_Region(wn_region);
00301 }
00302 ErrMsgSrcpos(EC_LNO_Generic, WN_Get_Linenum(wn_outer_loop),
00303 "Nested Do Across Loop is Too Deep, Directive Ignored\n");
00304 return wn_outer_loop;
00305 }
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318 static void Mark_Code(WN *wn, WN *func_nd, DOLOOP_STACK *stack,
00319 DLI_STACK *dlistack, II_STACK *if_stack,
00320 STACK_OF_WN *label_stack,
00321 HASH_TABLE<INT32,WN*> *label_hash,
00322 mUINT8 depth,INT *inner_depth,
00323 BOOL promote_pointers, BOOL inside_bound,
00324 BOOL strict_limit)
00325 {
00326 WN *kid;
00327 DO_LOOP_INFO *dli;
00328
00329 Is_True(wn,("Null wn in Mark_Code"));
00330
00331 OPCODE opcode = WN_opcode(wn);
00332
00333 if (opcode == OPC_BLOCK) {
00334
00335 *inner_depth=0;
00336 UINT8 tmp=0;
00337 kid = WN_last (wn);
00338 while (kid) {
00339 if (!LNO_Ignore_Pragmas &&
00340 WN_operator(kid) == OPR_PRAGMA) {
00341 if ((WN_pragma(kid) == WN_PRAGMA_PREFETCH) ||
00342 (WN_pragma(kid) == WN_PRAGMA_PREFETCH_MANUAL) ||
00343 (WN_pragma(kid) == WN_PRAGMA_PREFETCH_REF_DISABLE)) {
00344 WN* prev_kid = WN_prev(kid);
00345 Move_To_PU_Pragma_List (kid, func_nd);
00346 kid = prev_kid;
00347 continue;
00348 }
00349 if (WN_pragma(kid) == WN_PRAGMA_PREFETCH_REF) {
00350 extern BOOL PU_has_manual_prefetch;
00351 PU_has_manual_prefetch = TRUE;
00352 WN* pf_wn = WN_next(kid);
00353 FmtAssert (pf_wn && (WN_opcode(pf_wn) == OPC_PREFETCH),
00354 ("FE Error: pragma prefetch_ref not followed by prefetch\n"));
00355 WN_pf_set_confidence(pf_wn, 3);
00356 }
00357 }
00358 WN *prev_kid = WN_prev(kid);
00359 Mark_Code(kid,func_nd,stack,dlistack,if_stack,label_stack,label_hash,
00360 depth,inner_depth,promote_pointers,inside_bound,strict_limit);
00361 tmp = MAX(tmp,*inner_depth);
00362 kid = prev_kid;
00363 }
00364 *inner_depth = tmp;
00365 return;
00366 }
00367
00368 if (!LNO_Ignore_Pragmas &&
00369 WN_operator(wn) == OPR_PRAGMA) {
00370 if (WN_pragma(wn) == WN_PRAGMA_KAP_ASSERT_PERMUTATION) {
00371 ST *st = WN_st(wn);
00372 if (Permutation_Arrays->Elements() > 50) {
00373 ErrMsgSrcpos(EC_LNO_Generic,WN_Get_Linenum(wn),
00374 "Two many permuatation directives. Extra one ignored.");
00375 } else {
00376 BOOL found = FALSE;
00377 for (INT i=0; i<Permutation_Arrays->Elements() && !found; i++) {
00378 ST *tmp = Permutation_Arrays->Bottom_nth(i)._st;
00379 if (tmp == st) {
00380 found = TRUE;
00381 }
00382 }
00383 if (!found) Permutation_Arrays->Push(PERMUTATION_DESCRIPTOR(st));
00384 }
00385 } else if (WN_pragma(wn) == WN_PRAGMA_KAP_OPTIMIZE) {
00386 if (WN_pragma_arg1(wn) == 0) {
00387 Run_autopar = FALSE;
00388 }
00389 } else if (WN_pragma(wn) == WN_PRAGMA_KAP_CONCURRENTIZE) {
00390 if (Run_autopar_save)
00391 Run_autopar = TRUE;
00392 } else if (WN_pragma(wn) == WN_PRAGMA_KAP_NOCONCURRENTIZE) {
00393 Run_autopar = FALSE;
00394 } else if (WN_pragma(wn) == WN_PRAGMA_KAP_ROUNDOFF) {
00395 if (WN_pragma_arg1(wn) <= 1) {
00396 Roundoff_Level = ROUNDOFF_NONE;
00397 }
00398 }
00399 }
00400
00401
00402 OPERATOR oper = OPCODE_operator(opcode);
00403 if (opcode == OPC_DO_LOOP) {
00404 label_stack = CXX_NEW(STACK_OF_WN(&LNO_local_pool),&LNO_local_pool);
00405 has_dos = TRUE;
00406 dli = (DO_LOOP_INFO *) WN_MAP_Get(LNO_Info_Map,wn);
00407 if (!dli) {
00408 dli = (DO_LOOP_INFO *)
00409 CXX_NEW(DO_LOOP_INFO(&LNO_default_pool,NULL,NULL,NULL,FALSE,FALSE,FALSE,
00410 FALSE,FALSE,FALSE,FALSE,TRUE), &LNO_default_pool);
00411 dli->Depth = depth;
00412 dli->Is_Backward = Do_Loop_Is_Backward(wn);
00413 WN_MAP_Set(LNO_Info_Map,wn,(void *)dli);
00414 } else {
00415 dli->Has_Calls=FALSE;
00416 dli->Has_Unsummarized_Calls=FALSE;
00417 dli->Has_Gotos_This_Level=FALSE;
00418 dli->Has_Exits=FALSE;
00419 dli->Is_Inner=TRUE;
00420 }
00421 WN* wn_region = LWN_Get_Parent(LWN_Get_Parent(wn));
00422 if (Is_Mp_Region(wn_region)) {
00423 Contains_MP = TRUE;
00424 Patch_Loop_Statements(wn);
00425 WN* wn_first_pragma = WN_first(WN_region_pragmas(wn_region));
00426 FmtAssert(WN_opcode(wn_first_pragma) == OPC_PRAGMA,
00427 ("Found a non-pragma as first statement in MP pragma region"));
00428 while (wn_first_pragma) {
00429 if (WN_opcode(wn_first_pragma) == OPC_PRAGMA &&
00430 (WN_pragma(wn_first_pragma) == WN_PRAGMA_DOACROSS ||
00431 WN_pragma(wn_first_pragma) == WN_PRAGMA_PDO_BEGIN ||
00432 WN_pragma(wn_first_pragma) == WN_PRAGMA_PARALLEL_DO))
00433 break;
00434 wn_first_pragma = WN_next(wn_first_pragma);
00435 }
00436 if (wn_first_pragma &&
00437 (WN_pragma(wn_first_pragma) == WN_PRAGMA_DOACROSS ||
00438 WN_pragma(wn_first_pragma) == WN_PRAGMA_PDO_BEGIN ||
00439 WN_pragma(wn_first_pragma) == WN_PRAGMA_PARALLEL_DO)) {
00440 Error_Check_MP_Pragmas (wn_first_pragma);
00441 if (dli->Mp_Info == NULL)
00442 dli->Mp_Info = CXX_NEW(MP_INFO(WN_region_pragmas(wn_region)),
00443 &LNO_default_pool);
00444 }
00445 }
00446 depth++;
00447 INT i;
00448 for (i=0; i<dlistack->Elements(); i++) {
00449 dlistack->Bottom_nth(i)->Is_Inner = FALSE;
00450 }
00451 for (i=0; i<if_stack->Elements(); i++) {
00452 if_stack->Bottom_nth(i)->Contains_Do_Loops = TRUE;
00453 }
00454 stack->Push(wn);
00455 dlistack->Push(dli);
00456 } else if (opcode == OPC_REGION) {
00457 if (Is_Mp_Region(wn) && Nest_Total(wn) > Loop_Depth_Limit(strict_limit)) {
00458 wn = Dismantle_Nested_Doacross(wn, Nest_Total(wn));
00459 Mark_Code(wn ,func_nd, stack, dlistack,if_stack, label_stack, label_hash,
00460 depth, inner_depth, promote_pointers, inside_bound, strict_limit);
00461 return;
00462 }
00463 if (Is_Mp_Region(wn))
00464 Contains_MP = TRUE;
00465 for (INT i=0; i<if_stack->Elements(); i++) {
00466 if_stack->Bottom_nth(i)->Contains_Regions = TRUE;
00467 }
00468 REGION_INFO* rgi = NULL;
00469 WN* wn_first = WN_first(WN_region_pragmas(wn));
00470 if (wn_first != NULL && WN_opcode(wn_first) == OPC_PRAGMA
00471 && WN_pragma(wn_first) == WN_PRAGMA_PARALLEL_BEGIN) {
00472 rgi = (REGION_INFO *) CXX_NEW(REGION_INFO(FALSE), &LNO_default_pool);
00473 WN_MAP_Set(LNO_Info_Map, wn, (void *) rgi);
00474 }
00475
00476
00477
00478
00479
00480 if (WN_region_is_EH(wn)) {
00481 WN *pwn = LWN_Get_Parent(wn);
00482 while (pwn) {
00483 if (WN_opcode(pwn) == OPC_DO_LOOP) {
00484 DO_LOOP_INFO *dli = Get_Do_Loop_Info(pwn);
00485 if (dli && dli->Mp_Info) {
00486
00487 dli->Mp_Info->Disable_Plowering();
00488 }
00489 }
00490 pwn = LWN_Get_Parent(pwn);
00491 }
00492 }
00493 } else if (opcode == OPC_IF) {
00494 IF_INFO *ii = (IF_INFO *) WN_MAP_Get(LNO_Info_Map,wn);
00495 if (!ii) {
00496 ii = CXX_NEW(IF_INFO(&LNO_default_pool,FALSE,FALSE),&LNO_default_pool);
00497 WN_MAP_Set(LNO_Info_Map,wn,(void *)ii);
00498 } else {
00499 ii->Contains_Do_Loops = FALSE;
00500 ii->Contains_Regions = FALSE;
00501 }
00502 if_stack->Push(ii);
00503 } else if (OPCODE_is_call(opcode)) {
00504 if (!Has_Call_Info(wn)) {
00505 for (INT i=0; i<dlistack->Elements()-inside_bound; i++) {
00506 dlistack->Bottom_nth(i)->Has_Unsummarized_Calls = TRUE;
00507 }
00508 }
00509 for (INT i=0; i<dlistack->Elements()-inside_bound; i++) {
00510 dlistack->Bottom_nth(i)->Has_Calls = TRUE;
00511 }
00512 #ifdef KEY //bug 14284 : determine whether loop has calls to nested functions
00513 ST *st = WN_has_sym(wn) ? WN_st(wn) : NULL;
00514 if(st != NULL) {
00515 PU &pu = Pu_Table[ST_pu(st)];
00516 if(PU_is_nested_func(pu)){
00517 for (INT i=0; i<dlistack->Elements()-inside_bound; i++) {
00518 dlistack->Bottom_nth(i)->Has_Nested_Calls = TRUE;
00519 }
00520 }
00521 }
00522 #endif
00523 } else if (OPCODE_operator(opcode) == OPR_ALLOCA ||
00524 OPCODE_operator(opcode) == OPR_DEALLOCA) {
00525
00526
00527
00528
00529
00530
00531
00532
00533 FmtAssert (Alloca_Dealloca_On,
00534 ("Saw an ALLOCA/DEALLOCA, but Alloca_Dealloca_On is false"));
00535
00536 WN *new_wn = ((OPCODE_operator(opcode) == OPR_ALLOCA) ?
00537 Convert_Alloca_To_Intrinsic (wn) :
00538 Convert_Dealloca_To_Intrinsic (wn));
00539 if (new_wn) {
00540 wn = new_wn;
00541 Mark_Code(wn,func_nd,stack,dlistack,if_stack,label_stack,label_hash,
00542 depth,inner_depth,promote_pointers,inside_bound,strict_limit);
00543 }
00544 } else if (opcode == OPC_IO ||
00545 (oper==OPR_FORWARD_BARRIER) || (oper==OPR_BACKWARD_BARRIER)) {
00546 if (!Array_Dependence_Graph || !Array_Dependence_Graph->Get_Vertex(wn)) {
00547 for (INT i=0; i<dlistack->Elements()-inside_bound; i++) {
00548 dlistack->Bottom_nth(i)->Has_Calls = TRUE;
00549 dlistack->Bottom_nth(i)->Has_Unsummarized_Calls = TRUE;
00550 dlistack->Bottom_nth(i)->Has_Bad_Mem = TRUE;
00551 dlistack->Bottom_nth(i)->Has_Barriers = TRUE;
00552 }
00553 }
00554 } else if (OPCODE_is_load(opcode) || OPCODE_is_store(opcode)) {
00555
00556
00557
00558 if ((oper != OPR_LDID) && (oper != OPR_STID)) {
00559 if (!Array_Dependence_Graph || !Array_Dependence_Graph->Get_Vertex(wn)) {
00560 for (INT i=0; i<dlistack->Elements()-inside_bound; i++) {
00561 dlistack->Bottom_nth(i)->Has_Bad_Mem = TRUE;
00562 }
00563 }
00564 if (promote_pointers && dlistack->Elements()) {
00565 if ((oper == OPR_ILOAD) &&
00566 WN_operator(WN_kid0(wn)) != OPR_ARRAY) {
00567 Promote_Pointer(wn,0,0);
00568 } else if ((oper == OPR_ISTORE) &&
00569 WN_operator(WN_kid1(wn)) != OPR_ARRAY) {
00570 Promote_Pointer(wn,1,0);
00571 }
00572 }
00573 #ifdef KEY
00574
00575 if (dlistack->Elements()) {
00576 if ((oper == OPR_ILOAD) &&
00577 (WN_operator(WN_kid0(wn)) == OPR_ARRAY)) {
00578 Fold_Array(wn,0);
00579 } else if ((oper == OPR_ISTORE) &&
00580 (WN_operator(WN_kid1(wn)) == OPR_ARRAY)) {
00581 Fold_Array(wn,1);
00582 }
00583 }
00584 #endif
00585 }
00586 } else if (opcode == OPC_LABEL) {
00587 label_stack->Push(wn);
00588 } else if (opcode == OPC_IO_ITEM &&
00589 (WN_io_item(wn) == IOC_END || WN_io_item(wn) == IOC_ERR ||
00590 WN_io_item(wn) == IOC_EOR)) {
00591
00592
00593 for (INT i=0; i<dlistack->Elements()-inside_bound; i++) {
00594 dlistack->Bottom_nth(i)->Has_Gotos = TRUE;
00595 dlistack->Bottom_nth(i)->Has_Gotos_This_Level = TRUE;
00596 dlistack->Bottom_nth(i)->Has_Exits = TRUE;
00597 }
00598 } else if (OPCODE_is_non_scf(opcode) ||
00599 (opcode == OPC_DO_WHILE) ||
00600 (opcode == OPC_WHILE_DO) ||
00601 (opcode == OPC_COMPGOTO) ) {
00602 if (opcode == OPC_GOTO || opcode == OPC_TRUEBR || opcode == OPC_FALSEBR) {
00603 for (INT i=0; i<dlistack->Elements()-inside_bound; i++) {
00604 dlistack->Bottom_nth(i)->Has_Gotos = TRUE;
00605 }
00606 #ifndef KEY
00607 for (INT i=0; i<dlistack->Elements()-inside_bound-1; i++) {
00608 dlistack->Bottom_nth(i)->Has_Conditional = TRUE;
00609 }
00610 #endif
00611
00612 WN *label = label_hash->Find(WN_label_number(wn));
00613 FmtAssert (label, ("goto to non-existant label"));
00614 MEM_POOL_Push(&LNO_local_pool);
00615 {
00616 DOLOOP_STACK label_loops(&LNO_local_pool);
00617 Build_Doloop_Stack(label,&label_loops);
00618 if (label_loops.Elements()) {
00619 Get_Do_Loop_Info(label_loops.Top_nth(0))->Has_Gotos_This_Level = TRUE;
00620 }
00621 INT i=0;
00622 INT min = MIN(stack->Elements(),label_loops.Elements());
00623 #ifndef KEY
00624 if (stack->Elements() > 0 && stack->Elements() <= label_loops.Elements()) {
00625 dlistack->Top_nth(0)->Has_Gotos = TRUE;
00626 dlistack->Top_nth(0)->Has_Conditional = TRUE;
00627 }
00628 #endif
00629 while (i<min &&
00630 (stack->Bottom_nth(i) == label_loops.Bottom_nth(i))) i++;
00631 for (i=i; i<dlistack->Elements()-inside_bound; i++) {
00632 dlistack->Bottom_nth(i)->Has_Exits = TRUE;
00633 }
00634 }
00635 MEM_POOL_Pop(&LNO_local_pool);
00636 } else if (opcode == OPC_DO_WHILE || opcode == OPC_WHILE_DO) {
00637 for (INT i=0; i<dlistack->Elements()-inside_bound; i++) {
00638 dlistack->Bottom_nth(i)->Has_Gotos = TRUE;
00639 #ifndef KEY
00640 dlistack->Bottom_nth(i)->Has_Conditional = TRUE;
00641 #endif
00642 }
00643 }
00644 #ifndef KEY
00645 else if (opcode == OPC_RETURN){
00646 for (INT i=0; i<dlistack->Elements()-inside_bound; i++) {
00647 dlistack->Bottom_nth(i)->Has_Exits = TRUE;
00648 }
00649 }
00650 #endif
00651 else {
00652 for (INT i=0; i<dlistack->Elements()-inside_bound; i++) {
00653 dlistack->Bottom_nth(i)->Has_Gotos = TRUE;
00654 #ifndef KEY
00655 dlistack->Bottom_nth(i)->Has_Conditional = TRUE;
00656 #endif
00657 dlistack->Bottom_nth(i)->Has_Gotos_This_Level = TRUE;
00658 dlistack->Bottom_nth(i)->Has_Exits = TRUE;
00659 }
00660 }
00661 }
00662
00663
00664 UINT8 tmp=0;
00665 for (INT kidno=0; kidno<WN_kid_count(wn); kidno++) {
00666 kid = WN_kid(wn,kidno);
00667 if ((WN_operator(kid) == OPR_LDID) &&
00668 (Wn_Is_Intconst(kid,&constval))) {
00669 WN_kid(wn,kidno) = LWN_Make_Icon(WN_rtype(kid),constval);
00670 LWN_Set_Parent(WN_kid(wn,kidno),wn);
00671 LWN_Delete_Tree(kid);
00672 } else {
00673 BOOL ib = inside_bound;
00674 if (opcode == OPC_DO_LOOP) {
00675 if (kid == WN_do_body(wn)) {
00676 ib = 0;
00677 } else {
00678 ib = 1;
00679 }
00680 }
00681 Mark_Code(kid,func_nd, stack,dlistack,if_stack,label_stack,label_hash,
00682 depth, inner_depth, promote_pointers,ib,strict_limit);
00683 tmp = MAX(tmp,*inner_depth);
00684 }
00685 }
00686 *inner_depth=tmp;
00687
00688
00689
00690 if (opcode == OPC_DO_LOOP) {
00691 (*inner_depth)++;
00692 if ((*inner_depth) > Loop_Depth_Limit(strict_limit)) {
00693 Dismantle_Dos(wn, strict_limit);
00694 } else {
00695 if (!dlistack->Top_nth(0)->Has_Gotos) {
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706 }
00707
00708
00709
00710 }
00711 stack->Pop();
00712 dlistack->Pop();
00713 depth--;
00714 CXX_DELETE(label_stack,&LNO_local_pool);
00715 } else if (opcode == OPC_IF) {
00716 if_stack->Pop();
00717 } else if (opcode == OPC_PRAGMA) {
00718
00719 if (!LNO_Ignore_Pragmas &&
00720 ((WN_pragma(wn) == WN_PRAGMA_IVDEP) ||
00721 (WN_pragma(wn) == WN_PRAGMA_CRI_CNCALL) ||
00722 (WN_pragma(wn) == WN_PRAGMA_NORECURRENCE) ||
00723 ((WN_pragma(wn) == WN_PRAGMA_KAP_ASSERT_DO) &&
00724 (WN_pragma_arg1(wn) == ASSERT_DO_CONCURRENT)) ||
00725 (WN_pragma(wn) == WN_PRAGMA_KAP_ASSERT_CONCURRENT_CALL))) {
00726 WN *tmp = WN_next(wn);
00727 WN *do_after_pragma = NULL;
00728 BOOL done=FALSE;
00729 while (!done) {
00730 if (!tmp) {
00731 done = TRUE;
00732 } else {
00733 OPCODE opcode = WN_opcode(tmp);
00734 if (OPCODE_is_scf(opcode)) {
00735 if (opcode == OPC_DO_LOOP) {
00736 done = TRUE;
00737 do_after_pragma = tmp;
00738 } else if (Is_Mp_Region(tmp)) {
00739 tmp = WN_first(WN_region_body(tmp));
00740 } else {
00741 done = TRUE;
00742 }
00743 } else {
00744 tmp = WN_next(tmp);
00745 }
00746 }
00747 }
00748 if (do_after_pragma) {
00749 DO_LOOP_INFO *dli = Get_Do_Loop_Info(do_after_pragma);
00750 if (WN_pragma(wn) == WN_PRAGMA_IVDEP) {
00751 if (!dli->Is_Inner) {
00752 ErrMsgSrcpos(EC_LNO_Generic,WN_Get_Linenum(wn),
00753 "IVDEP on non-inner loop ignored");
00754 } else {
00755 dli->Is_Ivdep = TRUE;
00756 LWN_Delete_From_Block(LWN_Get_Parent(wn),wn);
00757 }
00758 } else if ((WN_pragma(wn) == WN_PRAGMA_KAP_ASSERT_DO) &&
00759 (WN_pragma_arg1(wn) == ASSERT_DO_CONCURRENT)) {
00760 dli->Concurrent_Directive = TRUE;
00761 dli->Pragma_Prefer_Concurrentize = TRUE;
00762 LWN_Delete_From_Block(LWN_Get_Parent(wn),wn);
00763 } else if (WN_pragma(wn) == WN_PRAGMA_NORECURRENCE) {
00764 dli->Concurrent_Directive = TRUE;
00765 LWN_Delete_From_Block(LWN_Get_Parent(wn),wn);
00766 } else if ((WN_pragma(wn) == WN_PRAGMA_CRI_CNCALL) ||
00767 (WN_pragma(wn) == WN_PRAGMA_KAP_ASSERT_CONCURRENT_CALL)) {
00768 dli->Is_Concurrent_Call = TRUE;
00769 LWN_Delete_From_Block(LWN_Get_Parent(wn),wn);
00770 if (!dli->Is_Inner) {
00771 Mark_Concurrent_Call(WN_do_body(do_after_pragma));
00772 }
00773 }
00774 } else {
00775 ErrMsgSrcpos(EC_LNO_Generic,WN_Get_Linenum(wn),
00776 "DO loop corresponding to pragma not found");
00777 }
00778 }
00779 } else if (OPCODE_operator(opcode) == OPR_ARRAY) {
00780 Fold_Base(wn);
00781 }
00782 }
00783
00784
00785 static void Mark_Concurrent_Call(WN *wn)
00786 {
00787 OPCODE opc = WN_opcode(wn);
00788 if (opc == OPC_BLOCK) {
00789 WN *kid = WN_first (wn);
00790 while (kid) {
00791 Mark_Concurrent_Call(kid);
00792 kid = WN_next(kid);
00793 }
00794 return;
00795 }
00796 if (opc == OPC_DO_LOOP) {
00797 DO_LOOP_INFO *dli = Get_Do_Loop_Info(wn);
00798 dli->Is_Concurrent_Call = TRUE;
00799 }
00800 if (OPCODE_is_scf(opc)) {
00801 for (INT kidno=0; kidno<WN_kid_count(wn); kidno++) {
00802 Mark_Concurrent_Call(WN_kid(wn,kidno));
00803 }
00804 }
00805 }
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820 static void Error_Check_MP_Pragmas (WN* wn) {
00821 if (WN_pragma(wn) != WN_PRAGMA_DOACROSS &&
00822 WN_pragma(wn) != WN_PRAGMA_PDO_BEGIN &&
00823 WN_pragma(wn) != WN_PRAGMA_PARALLEL_DO) {
00824 DevWarn ("Error_Check_MP_Pragmas -- expected doacross/pdo/parallel-do\n");
00825 return;
00826 }
00827
00828 INT nest_total = WN_pragma_arg2(wn);
00829 if (nest_total > 1) {
00830
00831 WN* pwn = WN_first(LWN_Get_Parent(wn));
00832 WN *onto_wn = NULL, *aff_wn = NULL;
00833
00834
00835 while (pwn) {
00836 if (WN_opcode(pwn) == OPC_PRAGMA) {
00837 if (WN_pragma(pwn) == WN_PRAGMA_MPSCHEDTYPE &&
00838 (WN_pragma_arg1(pwn) == WN_PRAGMA_SCHEDTYPE_DYNAMIC ||
00839 WN_pragma_arg1(pwn) == WN_PRAGMA_SCHEDTYPE_GSS ||
00840 WN_pragma_arg1(pwn) == WN_PRAGMA_SCHEDTYPE_RUNTIME)) {
00841
00842 ErrMsgSrcpos(EC_LNO_Bad_Pragma_String, WN_Get_Linenum(pwn),
00843 WN_pragmas[WN_pragma(pwn)].name,
00844 "currently not supported with nested parallelism (ignoring).");
00845 WN_pragma_arg1(pwn) = WN_PRAGMA_SCHEDTYPE_SIMPLE;
00846 }
00847 }
00848 if (WN_opcode(pwn) == OPC_XPRAGMA) {
00849 if (!onto_wn && WN_pragma(pwn) == WN_PRAGMA_ONTO) onto_wn = pwn;
00850 if (!aff_wn && WN_pragma(pwn) == WN_PRAGMA_AFFINITY) aff_wn = pwn;
00851 }
00852 pwn = WN_next(pwn);
00853 }
00854
00855
00856 if (onto_wn && aff_wn) {
00857 ErrMsgSrcpos(EC_LNO_Bad_Pragma_String, WN_Get_Linenum(onto_wn),
00858 WN_pragmas[WN_pragma(onto_wn)].name,
00859 "not allowed with affinity (ignoring).");
00860
00861 while (onto_wn &&
00862 WN_opcode(onto_wn) == OPC_XPRAGMA &&
00863 WN_pragma(onto_wn) == WN_PRAGMA_ONTO) {
00864 WN* tmp = WN_next(onto_wn);
00865 LWN_Delete_Tree_From_Block (onto_wn);
00866 onto_wn = tmp;
00867 }
00868 }
00869
00870
00871 if (aff_wn) {
00872 WN* tmp_wn = aff_wn;
00873 while (tmp_wn &&
00874 WN_opcode(tmp_wn) == OPC_XPRAGMA &&
00875 WN_pragma(tmp_wn) == WN_PRAGMA_AFFINITY) {
00876 tmp_wn = WN_next(tmp_wn);
00877 }
00878 Is_True (tmp_wn && WN_opcode(tmp_wn) == OPC_XPRAGMA &&
00879 (WN_pragma(tmp_wn) == WN_PRAGMA_DATA_AFFINITY ||
00880 WN_pragma(tmp_wn) == WN_PRAGMA_THREAD_AFFINITY),
00881 ("Must have either data or thread affinity\n"));
00882
00883 if (WN_pragma(tmp_wn) == WN_PRAGMA_THREAD_AFFINITY) {
00884 ErrMsgSrcpos(EC_LNO_Bad_Pragma_String, WN_Get_Linenum(tmp_wn),
00885 WN_pragmas[WN_pragma(tmp_wn)].name,
00886 "not supported with nested parallelism (ignoring).");
00887
00888 while (aff_wn &&
00889 WN_opcode(aff_wn) == OPC_XPRAGMA &&
00890 (WN_pragma(aff_wn) == WN_PRAGMA_AFFINITY ||
00891 WN_pragma(aff_wn) == WN_PRAGMA_THREAD_AFFINITY)) {
00892 WN* tmp = WN_next(aff_wn);
00893 LWN_Delete_Tree_From_Block(aff_wn);
00894 aff_wn = tmp;
00895 }
00896
00897 WN* do_wn=WN_first(WN_region_body(LWN_Get_Parent(LWN_Get_Parent(wn))));
00898 while (do_wn) {
00899 if (WN_operator(do_wn) == OPR_DO_LOOP) break;
00900 do_wn = WN_next(do_wn);
00901 }
00902 Is_True (do_wn, ("Missing parallel do loop\n"));
00903
00904 INT i;
00905 for (i=1; i<nest_total; i++) {
00906 do_wn = WN_first(WN_do_body(do_wn));
00907 while (do_wn && (WN_operator(do_wn) != OPR_REGION)) {
00908 do_wn = WN_next(do_wn);
00909 }
00910 FmtAssert (do_wn,
00911 ("nested-doacross: cannot find nested region %d\n", i));
00912 do_wn = WN_first(WN_region_body(do_wn));
00913 while (do_wn && (WN_operator(do_wn) != OPR_DO_LOOP)) {
00914 do_wn = WN_next(do_wn);
00915 }
00916 FmtAssert(do_wn,
00917 ("nested-doacross: missing doloop in MP region %d\n",i));
00918 }
00919
00920
00921
00922 do_wn = WN_first(WN_do_body(do_wn));
00923 while (do_wn &&
00924 WN_opcode(do_wn) == OPC_XPRAGMA &&
00925 (WN_pragma(do_wn) == WN_PRAGMA_AFFINITY ||
00926 WN_pragma(do_wn) == WN_PRAGMA_THREAD_AFFINITY)) {
00927 WN* tmp = WN_next(do_wn);
00928 LWN_Delete_Tree_From_Block(do_wn);
00929 do_wn = tmp;
00930 }
00931 }
00932 }
00933 }
00934 }
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944 static void Move_To_PU_Pragma_List (WN* pragma_wn, WN* func_nd) {
00945 WN* copy_wn = LWN_Copy_Tree (pragma_wn);
00946 LWN_Delete_From_Block (NULL, pragma_wn);
00947 WN* plist_wn = WN_func_pragmas(func_nd);
00948 Is_True (WN_opcode(plist_wn) == OPC_BLOCK,
00949 ("Body of PU is not a block"));
00950 LWN_Insert_Block_Before (plist_wn, NULL, copy_wn);
00951 }
00952
00953
00954
00955 void DO_LOOP_INFO::Set_Est_Num_Iterations(DOLOOP_STACK *do_stack)
00956 {
00957 Num_Iterations_Symbolic = FALSE;
00958 ACCESS_VECTOR *svec = Step;
00959 if (svec->Too_Messy || !svec->Is_Const() || (svec->Const_Offset == 0)) {
00960 Est_Num_Iterations = LNO_Num_Iters;
00961 Num_Iterations_Symbolic = TRUE;
00962 return;
00963 }
00964 INT64 step = svec->Const_Offset;
00965 ACCESS_ARRAY *la, *ua;
00966 if (step > 0) {
00967 la = LB;
00968 ua = UB;
00969 } else {
00970 la = UB;
00971 ua = LB;
00972 step = -step;
00973 }
00974
00975 #ifndef KEY
00976 if (la->Too_Messy || ua->Too_Messy) {
00977 #else
00978
00979 if (la->Too_Messy || ua->Too_Messy ||
00980 !la->Dim(0)->Has_Loop_Coeff() ||
00981 !ua->Dim(0)->Has_Loop_Coeff()) {
00982 #endif
00983 Est_Num_Iterations = LNO_Num_Iters;
00984 if (Est_Max_Iterations_Index >= 0 &&
00985 Est_Max_Iterations_Index < Est_Num_Iterations) {
00986 Est_Num_Iterations = Est_Max_Iterations_Index;
00987 Num_Iterations_Symbolic = FALSE;
00988 } else {
00989 Num_Iterations_Symbolic = TRUE;
00990 }
00991 return;
00992 }
00993
00994 INT64 low,up,r;
00995 BOOL know_val;
00996
00997 MEM_POOL_Push(&LNO_local_pool);
00998
00999
01000 INT num_dim = la->Dim(0)->Nest_Depth();
01001 if ((la->Num_Vec() == 1) && (ua->Num_Vec() == 1) &&
01002 (!la->Dim(0)->Too_Messy) && (!ua->Dim(0)->Too_Messy) &&
01003 (abs(la->Dim(0)->Loop_Coeff(num_dim-1)) == 1) &&
01004 (abs(ua->Dim(0)->Loop_Coeff(num_dim-1)) == 1)) {
01005 ACCESS_VECTOR *range = Add(ua->Dim(0),la->Dim(0),&LNO_local_pool);
01006 range->Negate_Me();
01007 range->Const_Offset = -range->Const_Offset;
01008 r = Find_Average(range,&know_val,do_stack);
01009 if (!know_val) {
01010 Est_Num_Iterations = LNO_Num_Iters;
01011 if (Est_Max_Iterations_Index >= 0 &&
01012 Est_Max_Iterations_Index < Est_Num_Iterations) {
01013 Est_Num_Iterations = Est_Max_Iterations_Index;
01014 Num_Iterations_Symbolic = FALSE;
01015 } else {
01016 Num_Iterations_Symbolic = TRUE;
01017 }
01018 } else {
01019 Est_Num_Iterations = (r + 1) / step;
01020 }
01021 if (Est_Num_Iterations < 0)
01022 Est_Num_Iterations = 1;
01023 MEM_POOL_Pop(&LNO_local_pool);
01024 return;
01025 }
01026
01027
01028
01029
01030
01031
01032
01033 BOOL seen_symb = FALSE;
01034
01035 low = INT64_MIN;
01036 up = INT64_MAX;
01037 ACCESS_VECTOR *lb = la->Dim(0)->Convert_Bound_To_Exp(&LNO_local_pool);
01038 INT64 this_low;
01039 if (la->Dim(0)->Loop_Coeff(num_dim-1)) {
01040 this_low = Find_Average(lb,&know_val,do_stack)/
01041 abs(la->Dim(0)->Loop_Coeff(num_dim-1));
01042 }
01043 else {
01044 this_low = Find_Average(lb,&know_val,do_stack)/1;
01045 }
01046 if (!know_val) {
01047 seen_symb = TRUE;
01048 Num_Iterations_Symbolic = TRUE;
01049 } else {
01050 low = this_low;
01051 }
01052 INT i;
01053 for (i=1; i<la->Num_Vec(); i++) {
01054 lb = la->Dim(i)->Convert_Bound_To_Exp(&LNO_local_pool);
01055 if (la->Dim(0)->Loop_Coeff(num_dim-1)) {
01056 this_low = Find_Average(lb,&know_val,do_stack)/
01057 abs(la->Dim(0)->Loop_Coeff(num_dim-1));
01058 } else {
01059 this_low = Find_Average(lb,&know_val,do_stack)/1;
01060 }
01061 if (!know_val) {
01062 seen_symb = TRUE;
01063 Num_Iterations_Symbolic = TRUE;
01064 } else {
01065 low = MAX(low,this_low);
01066 }
01067 }
01068
01069 if (ua->Dim(0)->Too_Messy) {
01070 Est_Num_Iterations = LNO_Num_Iters;
01071 if (Est_Max_Iterations_Index >= 0 &&
01072 Est_Max_Iterations_Index < Est_Num_Iterations) {
01073 Est_Num_Iterations = Est_Max_Iterations_Index;
01074 Num_Iterations_Symbolic = FALSE;
01075 } else {
01076 Num_Iterations_Symbolic = TRUE;
01077 }
01078 MEM_POOL_Pop(&LNO_local_pool);
01079 return;
01080 }
01081 ACCESS_VECTOR *ub = ua->Dim(0)->Convert_Bound_To_Exp(&LNO_local_pool);
01082 INT64 this_up = Find_Average(ub,&know_val,do_stack)/
01083 abs(ua->Dim(0)->Loop_Coeff(num_dim-1));
01084 if (!know_val) {
01085 seen_symb = TRUE;
01086 Num_Iterations_Symbolic = TRUE;
01087 } else {
01088 up = this_up;
01089 }
01090 for (i=1; i<ua->Num_Vec(); i++) {
01091 ub = ua->Dim(i)->Convert_Bound_To_Exp(&LNO_local_pool);
01092 this_up = Find_Average(ub,&know_val,do_stack)/
01093 abs(ua->Dim(0)->Loop_Coeff(num_dim-1));
01094 if (!know_val) {
01095 seen_symb = TRUE;
01096 Num_Iterations_Symbolic = TRUE;
01097 } else {
01098 up = MIN(up,this_up);
01099 }
01100 }
01101
01102 if (seen_symb) {
01103 Num_Iterations_Symbolic = TRUE;
01104 if ((up != INT64_MAX) && (low != INT64_MIN)) {
01105 Est_Num_Iterations = MIN(LNO_Num_Iters,(up - low + 1) / step);
01106 } else {
01107 Est_Num_Iterations = LNO_Num_Iters;
01108 }
01109 if (Est_Max_Iterations_Index >= 0 &&
01110 Est_Max_Iterations_Index < Est_Num_Iterations) {
01111 Est_Num_Iterations = Est_Max_Iterations_Index;
01112 Num_Iterations_Symbolic = FALSE;
01113 }
01114 } else {
01115 Est_Num_Iterations = (up - low + 1) / step;
01116 }
01117 if (Est_Num_Iterations < 0)
01118 Est_Num_Iterations = 1;
01119 MEM_POOL_Pop(&LNO_local_pool);
01120 }
01121
01122
01123
01124
01125 static INT64 Find_Average(ACCESS_VECTOR *av, BOOL *know_val,
01126 DOLOOP_STACK *do_stack)
01127 {
01128 if (av->Too_Messy || av->Contains_Lin_Symb() ||
01129 av->Contains_Non_Lin_Symb()) {
01130 *know_val = FALSE;
01131 return 0;
01132 }
01133
01134 INT64 result = av->Const_Offset;
01135 if (av->Has_Loop_Coeff()) {
01136 for (INT i = 0; i<av->Nest_Depth(); i++) {
01137 if (av->Loop_Coeff(i)) {
01138 INT64 up,low;
01139 BOOL know_bound;
01140
01141 DO_LOOP_INFO *dli =
01142 (DO_LOOP_INFO *) WN_MAP_Get(LNO_Info_Map,do_stack->Bottom_nth(i));
01143 ACCESS_VECTOR *step = dli->Step;
01144 if (!step->Is_Const()) {
01145 *know_val = FALSE;
01146 return 0;
01147 }
01148
01149 ACCESS_ARRAY *la,*ua;
01150 if (step->Const_Offset > 0) {
01151 la = dli->LB;
01152 ua = dli->UB;
01153 } else {
01154 la = dli->UB;
01155 ua = dli->LB;
01156 }
01157
01158 if (la->Too_Messy || ua->Too_Messy) {
01159 *know_val = FALSE;
01160 return(0);
01161 }
01162 ACCESS_VECTOR *lb = la->Dim(0)->Convert_Bound_To_Exp(&LNO_local_pool);
01163 if (lb->Too_Messy) {
01164 *know_val = FALSE;
01165 return(0);
01166 }
01167 low = Find_Average(lb,&know_bound,do_stack) /
01168 abs(la->Dim(0)->Loop_Coeff(la->Dim(0)->Nest_Depth()-1));
01169 if (!know_bound) {
01170 *know_val = FALSE;
01171 return(0);
01172 }
01173 INT b;
01174 for (b=1; b<la->Num_Vec(); b++) {
01175 lb = la->Dim(b)->Convert_Bound_To_Exp(&LNO_local_pool);
01176 INT tmp = Find_Average(lb,&know_bound,do_stack)/
01177 abs(la->Dim(b)->Loop_Coeff(la->Dim(b)->Nest_Depth()-1));
01178 low = MAX(low, tmp);
01179 if (!know_bound) {
01180 *know_val = FALSE;
01181 return(0);
01182 }
01183 }
01184
01185 ACCESS_VECTOR *ub = ua->Dim(0)->Convert_Bound_To_Exp(&LNO_local_pool);
01186 if (ub->Too_Messy) {
01187 *know_val = FALSE;
01188 return(0);
01189 }
01190 up = Find_Average(ub,&know_bound,do_stack) /
01191 abs(ua->Dim(0)->Loop_Coeff(ua->Dim(0)->Nest_Depth()-1));
01192 if (!know_bound) {
01193 *know_val = FALSE;
01194 return(0);
01195 }
01196 for (b=1; b<ua->Num_Vec(); b++) {
01197 ub = ua->Dim(b)->Convert_Bound_To_Exp(&LNO_local_pool);
01198 INT tmp = Find_Average(ub,&know_bound,do_stack)/
01199 abs(ua->Dim(b)->Loop_Coeff(ua->Dim(b)->Nest_Depth()-1));
01200 up = MIN(up,tmp);
01201 if (!know_bound) {
01202 *know_val = FALSE;
01203 return(0);
01204 }
01205 }
01206
01207 result = result + av->Loop_Coeff(i) * (low + up)/2;
01208 }
01209 }
01210 }
01211 *know_val = TRUE;
01212 return (result);
01213 }
01214
01215
01216
01217 static void Dismantle_Do_Fix_Loop_Stmt(WN *loop, WN *wn)
01218 {
01219 DEF_LIST *dl = Du_Mgr->Ud_Get_Def(wn);
01220 if (dl && (dl->Loop_stmt() == loop)) {
01221 dl->Set_loop_stmt(NULL);
01222 }
01223 if (WN_opcode(wn) == OPC_BLOCK) {
01224 WN *kid = WN_first (wn);
01225 while (kid) {
01226 Dismantle_Do_Fix_Loop_Stmt(loop,kid);
01227 kid = WN_next(kid);
01228 }
01229 } else {
01230 for (INT kidno=0; kidno<WN_kid_count(wn); kidno++) {
01231 WN *kid = WN_kid(wn,kidno);
01232 Dismantle_Do_Fix_Loop_Stmt(loop,kid);
01233 }
01234 }
01235 }
01236
01237
01238 static void Dismantle_Do(WN *wn)
01239 {
01240 did_dismantle = TRUE;
01241 Dismantle_Do_Fix_Loop_Stmt(wn,wn);
01242 WN *whiledo = LWN_CreateWhileDo(WN_end(wn),WN_do_body(wn));
01243 LWN_Insert_Block_Before(LWN_Get_Parent(wn),wn,whiledo);
01244 LWN_Insert_Block_Before(LWN_Get_Parent(wn),whiledo,WN_start(wn));
01245 LWN_Insert_Block_Before(WN_while_body(whiledo),NULL,WN_step(wn));
01246 CXX_DELETE(Get_Do_Loop_Info(wn), &LNO_default_pool);
01247 LWN_Delete_From_Block(LWN_Get_Parent(wn),wn);
01248 }
01249
01250
01251
01252
01253
01254
01255 static void Dismantle_Do_Walk(WN* wn_loop,
01256 DOLOOP_STACK* st_loops,
01257 DOLOOP_STACK* st_dismantle,
01258 BOOL strict_limit)
01259 {
01260 if (WN_opcode(wn_loop) == OPC_DO_LOOP) {
01261 DO_LOOP_INFO* dli = Get_Do_Loop_Info(wn_loop);
01262 if (Do_Depth(wn_loop) >= Loop_Depth_Limit(strict_limit)) {
01263 INT i;
01264 for (i = 0; i < st_loops->Elements(); i++) {
01265 WN* wn_candidate = st_loops->Bottom_nth(i);
01266 DO_LOOP_INFO* dli_candidate = Get_Do_Loop_Info(wn_candidate);
01267 if (dli_candidate->Mp_Info == NULL) {
01268 INT j;
01269 for (j = 0; j < st_dismantle->Elements(); j++)
01270 if (st_dismantle->Bottom_nth(j) == wn_candidate)
01271 break;
01272 if (j == st_dismantle->Elements())
01273 st_dismantle->Push(wn_candidate);
01274 break;
01275 }
01276 }
01277 if (i > 0 && i == st_loops->Elements())
01278 st_dismantle->Push(st_loops->Bottom_nth(0));
01279 } else {
01280 st_loops->Push(wn_loop);
01281 for (WN* wn = WN_first(WN_do_body(wn_loop)); wn != NULL; wn = WN_next(wn))
01282 Dismantle_Do_Walk(wn, st_loops, st_dismantle, strict_limit);
01283 st_loops->Pop();
01284 }
01285 } else if (WN_opcode(wn_loop) == OPC_BLOCK) {
01286 for (WN* wn = WN_first(wn_loop); wn != NULL; wn = WN_next(wn))
01287 Dismantle_Do_Walk(wn, st_loops, st_dismantle, strict_limit);
01288 } else {
01289 for (INT i = 0; i < WN_kid_count(wn_loop); i++)
01290 Dismantle_Do_Walk(WN_kid(wn_loop, i), st_loops, st_dismantle,
01291 strict_limit);
01292 }
01293 }
01294
01295 static void Dismantle_Dos(WN* wn_loop,
01296 BOOL strict_limit)
01297 {
01298 FmtAssert(strict_limit,
01299 ("Dismantle_Dos: Should not need to dismantle dos in this case"));
01300 if (!Contains_MP) {
01301 Dismantle_Do(wn_loop);
01302 return;
01303 }
01304 DOLOOP_STACK st_loops(&LNO_local_pool);
01305 DOLOOP_STACK st_dismantle(&LNO_local_pool);
01306 Dismantle_Do_Walk(wn_loop, &st_loops, &st_dismantle, strict_limit);
01307 for (INT i = 0; i < st_dismantle.Elements(); i++)
01308 Dismantle_Do(st_dismantle.Bottom_nth(i));
01309 }
01310
01311
01312
01313 static void Remark_Depth(WN *wn, DLI_STACK *do_stack,mUINT8 depth)
01314 {
01315 WN *kid;
01316 DO_LOOP_INFO *dli;
01317
01318 Is_True(wn,("Null wn in Remark_Depth"));
01319
01320 OPCODE opcode = WN_opcode(wn);
01321
01322 if (opcode == OPC_BLOCK) {
01323 kid = WN_first (wn);
01324 while (kid) {
01325 Remark_Depth(kid,do_stack,depth);
01326 kid = WN_next(kid);
01327 }
01328 return;
01329 }
01330
01331 if (opcode == OPC_DO_LOOP) {
01332 dli = (DO_LOOP_INFO *) WN_MAP_Get(LNO_Info_Map,wn);
01333 Is_True(dli,("no mapping in Remark_Depth"));
01334 dli->Depth = depth;
01335 depth++;
01336 do_stack->Push(dli);
01337 }
01338
01339 for (INT kidno=0; kidno<WN_kid_count(wn); kidno++) {
01340 kid = WN_kid(wn,kidno);
01341 Remark_Depth(kid,do_stack,depth);
01342 }
01343
01344 if (opcode == OPC_DO_LOOP) {
01345 do_stack->Pop();
01346 depth--;
01347 }
01348 }
01349
01350
01351 static void Copy_Loads_In_Bound(WN *do_loop, WN *wn, BOOL is_start)
01352 {
01353 OPCODE opcode = WN_opcode(wn);
01354 if (OPCODE_is_load(opcode) && (OPCODE_operator(opcode) != OPR_LDID)) {
01355 WN *parent = LWN_Get_Parent(wn);
01356 TYPE_ID type = OPCODE_rtype(opcode);
01357 ST *preg_st = MTYPE_To_PREG(type);
01358 OPCODE ldid_opc = OPCODE_make_op(OPR_LDID,Promote_Type(type),type);
01359 OPCODE stid_opc = OPCODE_make_op(OPR_STID,MTYPE_V,type);
01360 WN_OFFSET preg_num;
01361 #ifdef _NEW_SYMTAB
01362 if (is_start) {
01363 preg_num = Create_Preg(type, "lb");
01364 } else {
01365 preg_num = Create_Preg(type, "ub");
01366 }
01367 #else
01368 if (is_start) {
01369 preg_num = Create_Preg(type, "lb",NULL);
01370 } else {
01371 preg_num = Create_Preg(type, "ub",NULL);
01372 }
01373 #endif
01374 WN *ldid = WN_CreateLdid(ldid_opc,preg_num,preg_st,Be_Type_Tbl(type));
01375 LWN_Set_Parent(ldid,parent);
01376 Create_alias(Alias_Mgr,ldid);
01377 WN *stid = LWN_CreateStid(stid_opc,preg_num,preg_st,
01378 Be_Type_Tbl(type),wn);
01379 Create_alias(Alias_Mgr,stid);
01380 LWN_Copy_Linenumber(do_loop,stid);
01381 LWN_Insert_Block_Before(LWN_Get_Parent(do_loop),do_loop,stid);
01382
01383 INT kidno = 0;
01384 while (WN_kid(parent,kidno) != wn) kidno++;
01385
01386 WN_kid(parent,kidno) = ldid;
01387 Du_Mgr->Add_Def_Use(stid,ldid);
01388 } else {
01389 for (INT kidno=0; kidno<WN_kid_count(wn); kidno++) {
01390 Copy_Loads_In_Bound(do_loop,WN_kid(wn,kidno),is_start);
01391 }
01392 }
01393 }
01394
01395
01396
01397 #ifdef KEY
01398
01399
01400
01401 static WN *
01402 Find_Term_Coeff(WN *wn) {
01403 if (WN_operator(wn) == OPR_MPY) {
01404 WN *coeff = Find_Term_Coeff(WN_kid0(wn));
01405 if (coeff != NULL) {
01406 return coeff;
01407 }
01408 coeff = Find_Term_Coeff(WN_kid1(wn));
01409 return coeff;
01410 }
01411
01412 if (WN_operator(wn) == OPR_INTCONST) {
01413 return wn;
01414 }
01415
01416 return NULL;
01417 }
01418 #endif
01419
01420
01421
01422
01423
01424
01425
01426
01427
01428
01429
01430
01431
01432
01433
01434
01435
01436
01437
01438
01439 static void Promote_Pointer(WN *wn, INT kid_num, INT load_size)
01440 {
01441 OPCODE opcode = WN_opcode(wn);
01442 WN *addr;
01443 INT addr_num = kid_num;
01444 addr = WN_kid(wn,addr_num);
01445 OPERATOR addr_oper = WN_operator(addr);
01446 WN *mult, *base, *index;
01447 INT kid_that_is_base;
01448 INT kid_that_is_mult, kid_that_is_index;
01449
01450
01451 if (!load_size) {
01452 if (OPCODE_is_load(opcode) || OPCODE_is_store(opcode)) {
01453 switch (OPCODE_desc(opcode)) {
01454 case MTYPE_I1 : case MTYPE_U1: load_size=1; break;
01455 case MTYPE_I2 : case MTYPE_U2: load_size =2; break;
01456 case MTYPE_I4 : case MTYPE_U4: case MTYPE_F4: load_size=4; break;
01457 case MTYPE_I8 : case MTYPE_U8: case MTYPE_F8: case MTYPE_C4:
01458 load_size = 8; break;
01459 #ifdef TARG_IA64
01460 case MTYPE_F10: load_size = 16; break;
01461 #endif
01462 case MTYPE_C8 : case MTYPE_FQ:
01463 load_size = 16; break;
01464 #if defined(TARG_IA64)
01465 case MTYPE_C10:
01466 #endif
01467 case MTYPE_CQ :
01468 load_size = 32; break;
01469 default: return;
01470 }
01471 } else {
01472 return;
01473 }
01474 }
01475
01476
01477 if (OPCODE_is_load(opcode) || OPCODE_is_store(opcode)) {
01478 if ((addr_oper == OPR_LDID) || (addr_oper == OPR_LDA)) {
01479 OPCODE op_array = OPCODE_make_op(OPR_ARRAY,Pointer_type, MTYPE_V);
01480 WN *array = WN_Create(op_array,3);
01481 WN_element_size(array) = abs(load_size);
01482 WN_array_base(array) = addr;
01483 LWN_Set_Parent(addr,array);
01484 WN_array_index(array,0) = WN_CreateIntconst(OPC_I4INTCONST,0);
01485 LWN_Set_Parent(WN_array_index(array,0),array);
01486 WN_array_dim(array,0) = WN_CreateIntconst(OPC_I4INTCONST,0);
01487 LWN_Set_Parent(WN_array_dim(array,0),array);
01488 WN_kid(wn,addr_num) = array;
01489 LWN_Set_Parent(array,wn);
01490 Fold_Offset(wn,array);
01491 return;
01492 }
01493 }
01494
01495
01496 BOOL char_canon = FALSE;
01497 if ((OPCODE_desc(opcode) == MTYPE_I1) || OPCODE_desc(opcode) == MTYPE_U1) {
01498 if ((addr_oper == OPR_ADD) || (addr_oper == OPR_SUB)) {
01499 OPERATOR kid0 = WN_operator(WN_kid0(addr));
01500 OPERATOR kid1 = WN_operator(WN_kid1(addr));
01501 if ((kid0 != OPR_MPY) && (kid1 != OPR_MPY)) {
01502
01503
01504 BOOL simp_state_save = WN_Simplifier_Enable(FALSE);
01505 if (((kid0 == OPR_LDID) || (kid0 == OPR_LDA)) ||
01506 ((kid1 != OPR_LDID) && (kid1 != OPR_LDA))) {
01507 TYPE_ID rtype = WN_rtype(WN_kid1(addr));
01508 WN *multiply = LWN_CreateExp2( OPCODE_make_op(OPR_MPY,rtype, MTYPE_V),
01509 LWN_Make_Icon(rtype,1),WN_kid1(addr));
01510 WN_kid1(addr) = multiply;
01511 LWN_Set_Parent(multiply,addr);
01512 } else {
01513 TYPE_ID rtype = WN_rtype(WN_kid0(addr));
01514 BOOL simp_state_save = WN_Simplifier_Enable(FALSE);
01515 WN *multiply = LWN_CreateExp2( OPCODE_make_op(OPR_MPY,rtype, MTYPE_V),
01516 LWN_Make_Icon(rtype,1),WN_kid0(addr));
01517 WN_kid0(addr) = multiply;
01518 LWN_Set_Parent(multiply,addr);
01519 }
01520 WN_Simplifier_Enable(simp_state_save);
01521 char_canon = TRUE;
01522 }
01523 }
01524 }
01525
01526
01527
01528 if (OPCODE_is_load(opcode) || OPCODE_is_store(opcode)) {
01529 if ((addr_oper == OPR_ADD) || (addr_oper == OPR_SUB)) {
01530 if (WN_operator(WN_kid0(addr)) == OPR_INTCONST) {
01531 Fold_Intconst(wn,WN_kid0(addr),FALSE);
01532 addr = WN_kid(wn,addr_num);
01533 addr_oper = WN_operator(addr);
01534 } else if (WN_operator(WN_kid1(addr)) == OPR_INTCONST) {
01535 if (addr_oper == OPR_ADD) {
01536 Fold_Intconst(wn,WN_kid1(addr),FALSE);
01537 } else {
01538 Fold_Intconst(wn,WN_kid1(addr),TRUE);
01539 }
01540 addr = WN_kid(wn,addr_num);
01541 addr_oper = WN_operator(addr);
01542 }
01543 }
01544 }
01545
01546
01547 #ifdef KEY // Bug 2565
01548 if (
01549 #ifdef TARG_X8664
01550 Is_Target_64bit() &&
01551 #endif
01552 (addr_oper == OPR_ADD || addr_oper == OPR_SUB)) {
01553
01554
01555
01556
01557
01558
01559
01560
01561
01562
01563
01564
01565
01566
01567
01568
01569
01570 if (WN_operator(WN_kid0(addr)) == OPR_CVT &&
01571 WN_operator(WN_kid0(WN_kid0(addr))) == OPR_MPY) {
01572 WN* mpy = WN_kid0(WN_kid0(addr));
01573 BOOL const_mpy = FALSE;
01574 INT kid = -1;
01575 if (WN_operator(WN_kid0(mpy)) == OPR_INTCONST &&
01576 (WN_const_val(WN_kid0(mpy)) == 2 ||
01577 WN_const_val(WN_kid0(mpy)) == 4 ||
01578 WN_const_val(WN_kid0(mpy)) == 8)) {
01579 kid = 0;
01580 const_mpy = TRUE;
01581 }
01582 else if (WN_operator(WN_kid1(mpy)) == OPR_INTCONST &&
01583 (WN_const_val(WN_kid1(mpy)) == 2 ||
01584 WN_const_val(WN_kid1(mpy)) == 4 ||
01585 WN_const_val(WN_kid1(mpy)) == 8)) {
01586 kid = 1;
01587 const_mpy = TRUE;
01588 }
01589 if (kid != -1 && WN_operator(WN_kid(mpy, (kid + 1)%2)) != OPR_LDID)
01590 const_mpy = FALSE;
01591 if (const_mpy) {
01592 INT val = WN_const_val(WN_kid(mpy, kid));
01593 WN* cvt = WN_kid0(addr);
01594 BOOL simp_state_save = WN_Simplifier_Enable(FALSE);
01595 TYPE_ID cvt_rtype = WN_rtype(cvt);
01596 TYPE_ID cvt_desc = WN_desc(cvt);
01597 if (MTYPE_is_unsigned(cvt_rtype))
01598 cvt_rtype = MTYPE_complement(cvt_rtype);
01599 if (MTYPE_is_unsigned(cvt_desc))
01600 cvt_rtype = MTYPE_complement(cvt_desc);
01601 WN* ldid = WN_kid(mpy, (kid+1)%2);
01602 WN_set_rtype(ldid, cvt_rtype);
01603 WN_set_desc(ldid, cvt_desc);
01604 WN* multiply = LWN_CreateExp2( OPCODE_make_op(OPR_MPY,cvt_rtype,
01605 MTYPE_V),
01606 LWN_Make_Icon(cvt_rtype,val),ldid);
01607 WN_kid0(addr) = multiply;
01608 LWN_Set_Parent(multiply,addr);
01609 WN_Simplifier_Enable(simp_state_save);
01610 }
01611 } else if (WN_operator(WN_kid1(addr)) == OPR_CVT &&
01612 WN_operator(WN_kid0(WN_kid1(addr))) == OPR_MPY) {
01613 WN* mpy = WN_kid0(WN_kid1(addr));
01614 BOOL const_mpy = FALSE;
01615 INT kid = -1;
01616 if (WN_operator(WN_kid0(mpy)) == OPR_INTCONST &&
01617 (WN_const_val(WN_kid0(mpy)) == 2 ||
01618 WN_const_val(WN_kid0(mpy)) == 4 ||
01619 WN_const_val(WN_kid0(mpy)) == 8)) {
01620 kid = 0;
01621 const_mpy = TRUE;
01622 }
01623 else if (WN_operator(WN_kid1(mpy)) == OPR_INTCONST &&
01624 (WN_const_val(WN_kid1(mpy)) == 2 ||
01625 WN_const_val(WN_kid1(mpy)) == 4 ||
01626 WN_const_val(WN_kid1(mpy)) == 8)) {
01627 kid = 1;
01628 const_mpy = TRUE;
01629 }
01630 if (kid != -1 && WN_operator(WN_kid(mpy, (kid + 1)%2)) != OPR_LDID)
01631 const_mpy = FALSE;
01632 if (const_mpy) {
01633 INT val = WN_const_val(WN_kid(mpy, kid));
01634 WN* cvt = WN_kid1(addr);
01635 BOOL simp_state_save = WN_Simplifier_Enable(FALSE);
01636 TYPE_ID cvt_rtype = WN_rtype(cvt);
01637 TYPE_ID cvt_desc = WN_desc(cvt);
01638 if (!MTYPE_is_unsigned(cvt_rtype))
01639 cvt_rtype = MTYPE_complement(cvt_rtype);
01640 if (!MTYPE_is_unsigned(cvt_desc))
01641 cvt_rtype = MTYPE_complement(cvt_desc);
01642 WN* ldid = WN_kid(mpy, (kid+1)%2);
01643 WN_set_rtype(ldid, cvt_rtype);
01644 WN_set_desc(ldid, cvt_desc);
01645 WN* multiply = LWN_CreateExp2( OPCODE_make_op(OPR_MPY,cvt_rtype,
01646 MTYPE_V),
01647 LWN_Make_Icon(cvt_rtype,val),ldid);
01648 WN_kid1(addr) = multiply;
01649 LWN_Set_Parent(multiply,addr);
01650 WN_Simplifier_Enable(simp_state_save);
01651 }
01652 }
01653 }
01654 #endif
01655 if (addr_oper == OPR_ADD) {
01656 if (WN_operator(WN_kid0(addr)) == OPR_MPY) {
01657 mult = WN_kid0(addr);
01658 base = WN_kid1(addr);
01659 kid_that_is_mult = 0;
01660 kid_that_is_base = 1;
01661 } else if (WN_operator(WN_kid1(addr)) == OPR_MPY) {
01662 mult = WN_kid1(addr);
01663 base = WN_kid0(addr);
01664 kid_that_is_mult = 1;
01665 kid_that_is_base = 0;
01666 } else {
01667 if (char_canon) WN_Simplify_Tree(wn);
01668 return;
01669 }
01670 } else if (addr_oper == OPR_SUB) {
01671 if (WN_operator(WN_kid1(addr)) == OPR_MPY) {
01672 mult = WN_kid1(addr);
01673 base = WN_kid0(addr);
01674 kid_that_is_mult = 1;
01675 kid_that_is_base = 0;
01676 } else {
01677 if (char_canon) WN_Simplify_Tree(wn);
01678 return;
01679 }
01680 } else {
01681 if (char_canon) WN_Simplify_Tree(wn);
01682 return;
01683 }
01684
01685
01686
01687 OPERATOR base_oper = WN_operator(base);
01688 if ((base_oper == OPR_ADD) || (base_oper == OPR_SUB)) {
01689 Promote_Pointer(addr,kid_that_is_base,load_size);
01690 base = WN_kid(addr,kid_that_is_base);
01691 base_oper = WN_operator(base);
01692 }
01693
01694
01695 #ifndef KEY
01696 WN *intconst, *index_expr;
01697 INT64 val;
01698 if (WN_operator(WN_kid0(mult)) == OPR_INTCONST) {
01699 intconst = WN_kid0(mult);
01700 index_expr = WN_kid1(mult);
01701 } else if (WN_operator(WN_kid1(mult)) == OPR_INTCONST) {
01702 intconst = WN_kid1(mult);
01703 index_expr = WN_kid0(mult);
01704 } else {
01705 if (char_canon) WN_Simplify_Tree(wn);
01706 return;
01707 }
01708
01709 val = WN_const_val(intconst);
01710 if (abs(val) >= INT32_MAX) return;
01711
01712
01713 if ((abs(val) % load_size) != 0) {
01714 if (char_canon) WN_Simplify_Tree(wn);
01715 return;
01716 }
01717 #else
01718
01719
01720
01721 int reassoc_idx = 0;
01722 WN *index_expr = WN_kid1(mult);
01723
01724
01725 if (WN_operator(WN_kid0(mult)) == OPR_INTCONST &&
01726 WN_operator(WN_kid1(mult)) == OPR_INTCONST &&
01727 WN_const_val(WN_kid0(mult)) == 1) {
01728 reassoc_idx = 1;
01729 index_expr = WN_kid0(mult);
01730 FmtAssert(MTYPE_byte_size(WN_desc(wn)) == 1, ("Handle this case"));
01731 }
01732 WN *intconst = Find_Term_Coeff(index_expr);
01733 if (intconst == NULL) {
01734 reassoc_idx = 1;
01735 index_expr = WN_kid0(mult);
01736 intconst = Find_Term_Coeff(index_expr);
01737 if (intconst == NULL) {
01738 if (char_canon) WN_Simplify_Tree(wn);
01739 return;
01740 }
01741 }
01742
01743 INT64 val = WN_const_val(intconst);
01744 if (abs(val) >= INT32_MAX ||
01745 (abs(val) % load_size) != 0) {
01746 if (char_canon) WN_Simplify_Tree(wn);
01747 return;
01748 }
01749
01750
01751
01752 WN *intconst_parent = LWN_Get_Parent(intconst);
01753 Is_True(intconst_parent != NULL, ("Missing parent"));
01754
01755 INT intconst_idx;
01756 for (intconst_idx = 0; intconst_idx < WN_kid_count(intconst_parent); intconst_idx++) {
01757 if (WN_kid(intconst_parent, intconst_idx) == intconst) {
01758 break;
01759 }
01760 }
01761 Is_True(intconst_idx < WN_kid_count(intconst_parent),
01762 ("Can't find the intconst node in its parent"));
01763
01764 if (intconst_parent != mult) {
01765
01766
01767 WN *reassoc_expr = WN_kid(mult, reassoc_idx);
01768 WN_kid(intconst_parent, intconst_idx) = reassoc_expr;
01769 LWN_Set_Parent(reassoc_expr, intconst_parent);
01770 WN_kid(mult, reassoc_idx) = intconst;
01771 LWN_Set_Parent(intconst, mult);
01772
01773
01774 Is_True(WN_operator(intconst_parent) == OPR_MPY,
01775 ("Expected MPY operator not %s", OPERATOR_name(WN_operator(intconst_parent))));
01776 } else {
01777
01778
01779 index_expr = WN_kid(mult, reassoc_idx);
01780 }
01781 #endif // KEY
01782
01783 if (base_oper == OPR_ARRAY) {
01784
01785 if (WN_kid_count(base) != 3) {
01786 if (char_canon) WN_Simplify_Tree(wn);
01787 return;
01788 }
01789 #ifdef KEY
01790
01791 if (val == 0) {
01792 if (char_canon) WN_Simplify_Tree(wn);
01793 return;
01794 }
01795 #endif
01796 if ((WN_element_size(base) % val) != 0) {
01797 if (val % WN_element_size(base) == 0) {
01798 OPCODE index_op = WN_opcode(index_expr);
01799 OPCODE mpy_op = OPCODE_make_op(OPR_MPY,OPCODE_rtype(index_op),MTYPE_V);
01800 index_expr = LWN_CreateExp2(mpy_op,
01801 LWN_Make_Icon(OPCODE_rtype(index_op),
01802 val / WN_element_size(base)),
01803 index_expr);
01804 for (INT i=0; i<WN_kid_count(index_expr); i++) {
01805 LWN_Set_Parent(WN_kid(index_expr,i),index_expr);
01806 }
01807 val = WN_element_size(base);
01808 } else {
01809 if (char_canon) WN_Simplify_Tree(wn);
01810 return;
01811 }
01812 }
01813 #ifndef KEY
01814 } else if ((base_oper != OPR_LDID) && (base_oper != OPR_LDA)) {
01815 #else
01816
01817
01818
01819 } else if ((base_oper != OPR_LDID) && (base_oper != OPR_LDA) &&
01820 (base_oper != OPR_ILOAD)) {
01821 #endif
01822 if (char_canon) WN_Simplify_Tree(wn);
01823 return;
01824 }
01825 #ifdef KEY
01826
01827 if (base_oper == OPR_ILOAD &&
01828 WN_operator(WN_kid0(base)) != OPR_LDID) {
01829 if (char_canon) WN_Simplify_Tree(wn);
01830 return;
01831 }
01832 #endif
01833
01834
01835
01836 WN *array;
01837
01838 if (base_oper == OPR_ARRAY) {
01839 array = base;
01840 INT64 ratio = abs(WN_element_size(array) / val);
01841 WN_kid(wn,addr_num) = array;
01842 LWN_Set_Parent(array,wn);
01843
01844 WN *array_index;
01845 if (ratio == 1) {
01846 array_index = WN_array_index(array,0);
01847 WN_Delete(intconst);
01848 WN_Delete(mult);
01849 } else {
01850
01851 WN_kid0(mult) = intconst;
01852 WN_const_val(intconst) = ratio;
01853 WN_kid1(mult) = WN_array_index(array,0);
01854 LWN_Set_Parent(WN_array_index(array,0),mult);
01855 array_index = mult;
01856 }
01857 WN_element_size(array) = abs(val);
01858
01859 WN_kid(addr,kid_that_is_base) = array_index;
01860 LWN_Set_Parent(array_index,addr);
01861
01862 WN_array_index(array,0) = addr;
01863 LWN_Set_Parent(addr,array);
01864
01865 if (val < 0) {
01866 OPCODE index_op = WN_opcode(index_expr);
01867 #ifndef KEY
01868 index_expr = LWN_CreateExp1(OPCODE_make_op(OPR_NEG,OPCODE_rtype(index_op),
01869 MTYPE_V),index_expr);
01870 #else
01871
01872
01873 if (MTYPE_is_signed(OPCODE_rtype(index_op)))
01874 index_expr = LWN_CreateExp1(OPCODE_make_op(OPR_NEG,
01875 OPCODE_rtype(index_op),
01876 MTYPE_V),index_expr);
01877 else
01878 index_expr = LWN_CreateExp1(OPCODE_make_op(OPR_NEG,
01879 MTYPE_complement(OPCODE_rtype(index_op)),
01880 MTYPE_V),index_expr);
01881 #endif
01882 }
01883 WN_kid(addr,kid_that_is_mult) = index_expr;
01884 LWN_Set_Parent(index_expr,addr);
01885
01886 } else {
01887
01888 BOOL negate;
01889 if (addr_oper == OPR_SUB) {
01890 negate = (val > 0);
01891 } else {
01892 negate = (val < 0);
01893 }
01894 #ifdef KEY
01895
01896
01897
01898
01899
01900
01901
01902
01903
01904
01905
01906
01907
01908
01909
01910
01911
01912
01913 if (MTYPE_byte_size(WN_rtype(index_expr)) == 4 && val > INT32_MAX ||
01914 MTYPE_byte_size(WN_rtype(index_expr)) == 8 && val > INT64_MAX)
01915 negate = TRUE;
01916 #endif
01917
01918 WN *new_index = index_expr;
01919 if (negate) {
01920 OPCODE index_op = WN_opcode(index_expr);
01921 #ifndef KEY
01922 new_index = LWN_CreateExp1(OPCODE_make_op(OPR_NEG,OPCODE_rtype(index_op),
01923 MTYPE_V),index_expr);
01924 #else
01925
01926
01927 if (MTYPE_is_signed(OPCODE_rtype(index_op)))
01928 new_index = LWN_CreateExp1(OPCODE_make_op(OPR_NEG,
01929 OPCODE_rtype(index_op),
01930 MTYPE_V), index_expr);
01931 else
01932 new_index = LWN_CreateExp1(OPCODE_make_op(OPR_NEG,
01933 MTYPE_complement(OPCODE_rtype(index_op)),
01934 MTYPE_V), index_expr);
01935 #endif
01936 }
01937
01938 #ifndef KEY
01939 WN_const_val(intconst) = 0;
01940
01941 #else
01942
01943
01944
01945 intconst = WN_CreateIntconst(OPCODE_make_op(OPR_INTCONST,
01946 Pointer_type, MTYPE_V), 0);
01947 #endif
01948 OPCODE op_array = OPCODE_make_op(OPR_ARRAY,Pointer_type, MTYPE_V);
01949 array = WN_Create(op_array,3);
01950 WN_element_size(array) = abs(val);
01951 WN_array_base(array) = base;
01952 LWN_Set_Parent(base,array);
01953 WN_array_index(array,0) = new_index;
01954 LWN_Set_Parent(new_index,array);
01955 WN_array_dim(array,0) = intconst;
01956 LWN_Set_Parent(intconst,array);
01957
01958 WN_kid(wn,addr_num) = array;
01959 LWN_Set_Parent(array,wn);
01960
01961 WN_Delete(addr);
01962 WN_Delete(mult);
01963 }
01964
01965 if (OPCODE_is_load(opcode) || OPCODE_is_store(opcode)) {
01966 Fold_Offset(wn,array);
01967 }
01968
01969 return;
01970 }
01971
01972 #ifdef KEY
01973
01974
01975
01976
01977
01978 static void Fold_Array (WN *wn, INT kid_num) {
01979 OPCODE opcode = WN_opcode(wn);
01980 WN *addr = WN_kid(wn,kid_num);
01981
01982 if (WN_operator(addr) != OPR_ARRAY)
01983 return;
01984
01985 while (WN_operator(WN_array_base(addr))==OPR_ARRAY) {
01986
01987
01988 WN *addr_sub = WN_array_base(addr);
01989 INT num_dim_sub = WN_num_dim(addr_sub);
01990 INT num_dim = WN_num_dim(addr);
01991
01992
01993
01994
01995
01996 for (INT dim_sub =0; dim_sub < num_dim_sub; dim_sub++) {
01997 WN *wn_dim_sub = WN_array_dim(addr_sub,dim_sub);
01998 if (WN_operator(wn_dim_sub)!=OPR_INTCONST ||
01999 WN_const_val(wn_dim_sub)<=0)
02000 return;
02001 }
02002
02003 WN_ESIZE addr_size = WN_element_size(addr);
02004 WN_ESIZE addr_sub_el_size = WN_element_size(addr_sub);
02005
02006 if (addr_size<=0 || addr_sub_el_size<=0)
02007 return;
02008
02009 for (INT dim = 0; dim < num_dim; dim++) {
02010 WN *wn_dim = WN_array_dim(addr,dim);
02011 if (WN_operator(wn_dim)!=OPR_INTCONST ||
02012 WN_const_val(wn_dim)<=0)
02013 return;
02014 addr_size*=WN_const_val(wn_dim);
02015 }
02016
02017 if (addr_size!=addr_sub_el_size)
02018 return;
02019
02020
02021
02022 INT num_dim_new = num_dim + num_dim_sub;
02023
02024 OPCODE op_array = OPCODE_make_op(OPR_ARRAY,Pointer_type, MTYPE_V);
02025 WN *addr_new = WN_Create(op_array,num_dim_new*2+1);
02026
02027 LWN_Set_Parent(addr_new,wn);
02028 WN_kid(wn,kid_num) = addr_new;
02029
02030 WN_element_size(addr_new) = WN_element_size(addr);
02031
02032
02033
02034 WN_array_base(addr_new) = WN_array_base(addr_sub);
02035 LWN_Set_Parent(WN_array_base(addr_new),addr_new);
02036
02037 INT index_new = 0;
02038 for (INT index_sub = 0; index_sub < num_dim_sub; index_sub++) {
02039 WN_array_index(addr_new,index_new) = WN_array_index(addr_sub,index_sub);
02040 LWN_Set_Parent(WN_array_index(addr_new,index_new),addr_new);
02041 index_new++;
02042 }
02043 for (INT index = 0; index < num_dim; index++) {
02044 WN_array_index(addr_new,index_new) = WN_array_index(addr,index);
02045 LWN_Set_Parent(WN_array_index(addr_new,index_new),addr_new);
02046 index_new++;
02047 }
02048
02049 INT dim_new = 0;
02050 for (INT dim_sub = 0; dim_sub < num_dim_sub; dim_sub++) {
02051 WN_array_dim(addr_new,dim_new) = WN_array_dim(addr_sub,dim_sub);
02052 LWN_Set_Parent(WN_array_index(addr_new,dim_new),addr_new);
02053 dim_new++;
02054 }
02055 for (INT dim = 0; dim < num_dim; dim++) {
02056 WN_array_dim(addr_new,dim_new) = WN_array_dim(addr,dim);
02057 LWN_Set_Parent(WN_array_index(addr_new,dim_new),addr_new);
02058 dim_new++;
02059 }
02060
02061
02062 WN_Delete(addr);
02063 WN_Delete(addr_sub);
02064
02065 addr = addr_new;
02066 }
02067 return;
02068 }
02069 #endif
02070
02071
02072 static void Fold_Offset(WN *wn, WN *array)
02073 {
02074 #ifdef KEY
02075 if (WN_element_size(array) == 0)
02076 return;
02077 #endif
02078 if (WN_offset(wn) && ((abs(WN_offset(wn)) % WN_element_size(array)) == 0)) {
02079 TYPE_ID rtype;
02080
02081
02082 if ((Pointer_type == MTYPE_A4 || Pointer_type == MTYPE_U4) &&
02083
02084 (WN_offset(wn) <= INT32_MAX) &&
02085 (WN_offset(wn) >= INT32_MIN)) {
02086 rtype = MTYPE_I4;
02087 } else {
02088 rtype = MTYPE_I8;
02089 }
02090 OPCODE add_op = OPCODE_make_op(OPR_ADD,rtype, MTYPE_V);
02091 WN_array_index(array,0) = LWN_CreateExp2(add_op,WN_array_index(array,0),
02092 LWN_Make_Icon(rtype,WN_offset(wn)/WN_element_size(array)));
02093 LWN_Set_Parent(WN_array_index(array,0),array);
02094 WN_offset(wn) = 0;
02095 }
02096 }
02097
02098
02099
02100 static void Fold_Intconst(WN *ld_st, WN *intconst, BOOL negate)
02101 {
02102 INT64 result;
02103 if (negate) {
02104 result = WN_offset(ld_st) - WN_const_val(intconst);
02105 } else {
02106 result = WN_offset(ld_st) + WN_const_val(intconst);
02107 }
02108 if ((result <= INT32_MAX) && (result >= INT32_MIN)) {
02109 WN_offset(ld_st) = result;
02110 WN_const_val(intconst) = 0;
02111 WN_Simplify_Tree(ld_st);
02112 }
02113 }
02114
02115
02116
02117
02118 static BOOL Compatible_Type(MTYPE add, MTYPE index)
02119 {
02120 if (add == index) return TRUE;
02121 if (add == MTYPE_U4 && index == MTYPE_I4) return TRUE;
02122 if (add == MTYPE_U8 && index == MTYPE_I8) return TRUE;
02123 return FALSE;
02124 }
02125
02126
02127
02128
02129
02130 static void Fold_Base(WN *array)
02131 {
02132 if (WN_kid_count(array) != 3) return;
02133 #ifdef KEY
02134
02135 if (WN_element_size(array) < 0) return;
02136 #endif
02137 WN *base = WN_array_base(array);
02138 OPERATOR oper = WN_operator(base);
02139 if (oper != OPR_ADD && (oper != OPR_SUB)) {
02140 return;
02141 }
02142 WN *kid0 = WN_kid0(base);
02143 OPCODE kid0o = WN_opcode(kid0);
02144 WN *kid1 = WN_kid1(base);
02145 OPCODE kid1o = WN_opcode(kid1);
02146
02147 WN *index = WN_array_index(array,0);
02148 TYPE_ID index_type = WN_rtype(index);
02149 TYPE_ID add_type = WN_rtype(base);
02150 if (!Compatible_Type(add_type,index_type)) return;
02151
02152
02153 BOOL simp_state_save = WN_Simplifier_Enable(FALSE);
02154
02155
02156 if (OPCODE_operator(kid0o) == OPR_INTCONST && (oper == OPR_ADD)) {
02157 if (abs(WN_const_val(kid0)) < INT32_MAX) {
02158 if (abs(WN_const_val(kid0)) % WN_element_size(array) == 0) {
02159 if (OPCODE_rtype(kid0o) == add_type) {
02160 OPCODE add_op = OPCODE_make_op(OPR_ADD,add_type,MTYPE_V);
02161 WN_array_index(array,0) = LWN_CreateExp2(add_op,WN_array_index(array,0),
02162 LWN_Make_Icon(add_type,WN_const_val(kid0)/WN_element_size(array)));
02163 LWN_Set_Parent(WN_array_index(array,0), array);
02164 WN_Delete(kid0);
02165 WN_Delete(base);
02166 WN_array_base(array) = kid1;
02167 LWN_Set_Parent(kid1,array);
02168
02169
02170 WN_array_dim(array, 0) =
02171 LWN_Make_Icon(WN_rtype(WN_array_dim(array, 0)), 0);
02172 LWN_Set_Parent(WN_array_dim(array, 0), array);
02173
02174 Fold_Base(array);
02175 WN_Simplifier_Enable(simp_state_save);
02176 return;
02177 }
02178 }
02179 }
02180 } else if (OPCODE_operator(kid1o) == OPR_INTCONST) {
02181 if (abs(WN_const_val(kid1)) < INT32_MAX) {
02182 if (abs(WN_const_val(kid1)) % WN_element_size(array) == 0) {
02183 if (OPCODE_rtype(kid1o) == add_type) {
02184 OPCODE add_op = OPCODE_make_op(oper,add_type,MTYPE_V);
02185 WN_array_index(array,0) = LWN_CreateExp2(add_op,WN_array_index(array,0),
02186 LWN_Make_Icon(add_type,WN_const_val(kid1)/WN_element_size(array)));
02187 LWN_Set_Parent(WN_array_index(array,0), array);
02188 WN_Delete(kid1);
02189 WN_Delete(base);
02190 WN_array_base(array) = kid0;
02191 LWN_Set_Parent(kid0,array);
02192
02193
02194 WN_array_dim(array, 0) =
02195 LWN_Make_Icon(WN_rtype(WN_array_dim(array, 0)), 0);
02196 LWN_Set_Parent(WN_array_dim(array, 0), array);
02197
02198 Fold_Base(array);
02199 WN_Simplifier_Enable(simp_state_save);
02200 return;
02201 }
02202 }
02203 }
02204
02205
02206 } else if (OPCODE_operator(kid0o) == OPR_MPY && (oper == OPR_ADD)) {
02207 WN *mult_kid0 = WN_kid0(kid0);
02208 WN *mult_kid1 = WN_kid1(kid0);
02209 WN *mult_kid = NULL;
02210 if (WN_operator(mult_kid0) == OPR_INTCONST) {
02211 mult_kid = mult_kid0;
02212 } else if (WN_operator(mult_kid1) == OPR_INTCONST) {
02213 mult_kid = mult_kid1;
02214 }
02215 if (mult_kid) {
02216 if (abs(WN_const_val(mult_kid)) < INT32_MAX) {
02217 if (abs(WN_const_val(mult_kid)) % WN_element_size(array) == 0) {
02218 if (WN_rtype(kid0) == add_type) {
02219 OPCODE add_op = OPCODE_make_op(OPR_ADD,add_type,MTYPE_V);
02220 WN_array_index(array,0) = LWN_CreateExp2(add_op,WN_array_index(array,0),kid0);
02221 WN_const_val(mult_kid) = WN_const_val(mult_kid) / WN_element_size(array);
02222 LWN_Set_Parent(WN_array_index(array,0), array);
02223 WN_Delete(base);
02224 WN_array_base(array) = kid1;
02225 LWN_Set_Parent(kid1,array);
02226
02227
02228 WN_array_dim(array, 0) =
02229 LWN_Make_Icon(WN_rtype(WN_array_dim(array, 0)), 0);
02230 LWN_Set_Parent(WN_array_dim(array, 0), array);
02231
02232 Fold_Base(array);
02233 WN_Simplifier_Enable(simp_state_save);
02234 return;
02235 }
02236 }
02237 }
02238 }
02239 } else if (OPCODE_operator(kid1o) == OPR_MPY) {
02240 WN *mult_kid0 = WN_kid0(kid1);
02241 WN *mult_kid1 = WN_kid1(kid1);
02242 WN *mult_kid = NULL;
02243 if (WN_operator(mult_kid0) == OPR_INTCONST) {
02244 mult_kid = mult_kid0;
02245 } else if (WN_operator(mult_kid1) == OPR_INTCONST) {
02246 mult_kid = mult_kid1;
02247 }
02248 if (mult_kid) {
02249 if (abs(WN_const_val(mult_kid)) < INT32_MAX) {
02250 if (abs(WN_const_val(mult_kid)) % WN_element_size(array) == 0) {
02251 if (WN_rtype(kid1) == add_type) {
02252 OPCODE add_op = OPCODE_make_op(oper,add_type,MTYPE_V);
02253 WN_array_index(array,0) = LWN_CreateExp2(add_op,WN_array_index(array,0),kid1);
02254 WN_const_val(mult_kid) = WN_const_val(mult_kid) / WN_element_size(array);
02255 LWN_Set_Parent(WN_array_index(array,0), array);
02256 WN_Delete(base);
02257 WN_array_base(array) = kid0;
02258 LWN_Set_Parent(kid0,array);
02259
02260
02261 WN_array_dim(array, 0) =
02262 LWN_Make_Icon(WN_rtype(WN_array_dim(array, 0)), 0);
02263 LWN_Set_Parent(WN_array_dim(array, 0), array);
02264
02265 Fold_Base(array);
02266 WN_Simplifier_Enable(simp_state_save);
02267 return;
02268 }
02269 }
02270 }
02271 }
02272 }
02273 WN_Simplifier_Enable(simp_state_save);
02274 }
02275
02276 static void Enter_Label_Goto_Hash(WN *wn,
02277 HASH_TABLE<INT32, WN*> *label_hash,
02278 HASH_TABLE<INT32, WN*> *goto_hash)
02279 {
02280 OPERATOR oper = WN_operator(wn);
02281
02282 if (oper == OPR_BLOCK) {
02283 WN *kid = WN_first (wn);
02284 while (kid) {
02285 Enter_Label_Goto_Hash(kid,label_hash,goto_hash);
02286 kid = WN_next(kid);
02287 }
02288 } else if (oper == OPR_LABEL) {
02289 label_hash->Enter(WN_label_number(wn),wn);
02290 } else if (oper == OPR_GOTO ||
02291 oper == OPR_TRUEBR ||
02292 oper == OPR_FALSEBR ||
02293 oper == OPR_REGION_EXIT) {
02294 goto_hash->Enter(WN_label_number(wn),wn);
02295 } else {
02296 for (INT kidno=0; kidno<WN_kid_count(wn); kidno++) {
02297 Enter_Label_Goto_Hash(WN_kid(wn,kidno),label_hash,goto_hash);
02298 }
02299 }
02300 }
02301
02302 static void Delete_Unused_Labels (HASH_TABLE<INT32, WN*> *label_hash,
02303 HASH_TABLE<INT32, WN*> *goto_hash) {
02304
02305 HASH_TABLE_ITER<INT32, WN*> iter (label_hash);
02306 INT32 label;
02307 WN *wn;
02308
02309 while (iter.Step (&label, &wn)) {
02310 #ifdef KEY
02311 if (!LABEL_addr_saved(label) &&
02312 LABEL_kind(Label_Table[label]) != LKIND_BEGIN_HANDLER) {
02313 #else
02314 if (!LABEL_addr_saved(label)) {
02315 #endif
02316 WN* goto_wn = goto_hash->Find(label);
02317 if (goto_wn == NULL) {
02318
02319 LWN_Delete_Tree(wn);
02320 }
02321 }
02322 }
02323 }
02324
02325
02326
02327
02328
02329
02330
02331 static WN *Convert_Alloca_To_Intrinsic (WN *wn) {
02332 WN *stmt_wn = LWN_Get_Parent(wn);
02333
02334 while (1) {
02335 if (WN_opcode(stmt_wn) == OPC_IO) {
02336
02337
02338
02339 return NULL;
02340 }
02341
02342 if (OPERATOR_is_stmt(WN_operator(stmt_wn)) &&
02343 (WN_opcode(LWN_Get_Parent(stmt_wn)) == OPC_BLOCK)) {
02344 break;
02345 }
02346 stmt_wn = LWN_Get_Parent(stmt_wn);
02347 }
02348
02349 BOOL alloca_zero = FALSE;
02350 WN *sz = WN_kid0(wn);
02351 if (WN_operator(sz) == OPR_INTCONST && WN_const_val(sz) == 0) {
02352 alloca_zero = TRUE;
02353 }
02354
02355 WN *iwn;
02356 OPCODE op = OPCODE_make_op(OPR_INTRINSIC_CALL, Pointer_type, MTYPE_V);
02357 if (alloca_zero) {
02358
02359 iwn = WN_Create(op, 0);
02360 WN_intrinsic(iwn) = (Pointer_Size == 8 ?
02361 INTRN_U8READSTACKPOINTER :
02362 INTRN_U4READSTACKPOINTER);
02363 }
02364 else {
02365
02366 iwn = WN_Create(op, 1);
02367 WN_intrinsic(iwn) = (Pointer_Size == 8 ? INTRN_U8I8ALLOCA :
02368 INTRN_U4I4ALLOCA);
02369 WN* parm_wn = WN_CreateParm (MTYPE_U8, sz, Be_Type_Tbl(MTYPE_U8),
02370 WN_PARM_BY_VALUE);
02371 LWN_Set_Parent(sz, parm_wn);
02372 WN_kid0(wn) = NULL;
02373 WN_kid0(iwn) = parm_wn;
02374 LWN_Set_Parent(parm_wn, iwn);
02375 }
02376
02377 LWN_Insert_Block_Before(LWN_Get_Parent(stmt_wn), stmt_wn, iwn);
02378 LWN_Copy_Linenumber(stmt_wn, iwn);
02379 LWN_Copy_Frequency_Tree(iwn, stmt_wn);
02380
02381 PREG_NUM rreg1, rreg2;
02382 ST* rst = Find_Return_Registers(Pointer_type, &rreg1, &rreg2);
02383 WN *rreg = WN_CreateLdid (OPCODE_make_op(OPR_LDID, Pointer_type,
02384 Pointer_type),
02385 rreg1, rst,
02386 OPCODE_rtype(WN_opcode(wn)));
02387 Create_alias(Alias_Mgr, rreg);
02388 Du_Mgr->Add_Def_Use (iwn, rreg);
02389
02390 WN *pwn = LWN_Get_Parent(wn);
02391 INT i;
02392 for (i=0; i<WN_kid_count(pwn); i++) {
02393 if (WN_kid(pwn,i) == wn) break;
02394 }
02395
02396 WN_kid(pwn,i) = rreg;
02397 LWN_Set_Parent(rreg, pwn);
02398 LWN_Delete_Tree(wn);
02399 return iwn;
02400 }
02401
02402
02403
02404
02405
02406
02407
02408 static WN *Convert_Dealloca_To_Intrinsic (WN *wn) {
02409
02410 OPCODE icallop = OPCODE_make_op(OPR_INTRINSIC_CALL, MTYPE_V,
02411 MTYPE_V);
02412 WN *iwn = WN_Create(icallop, WN_kid_count(wn));
02413 WN_intrinsic(iwn) = (Pointer_Size == 8 ?
02414 INTRN_U8I8SETSTACKPOINTER :
02415 INTRN_U4I4SETSTACKPOINTER);
02416 for (INT i=0; i<WN_kid_count(wn); i++) {
02417 WN *parm_wn = WN_CreateParm(Pointer_type, WN_kid(wn,i),
02418 Be_Type_Tbl(Pointer_type),
02419 WN_PARM_BY_VALUE);
02420 LWN_Set_Parent(WN_kid(wn,i), parm_wn);
02421 WN_kid(iwn, i) = parm_wn;
02422 LWN_Set_Parent(parm_wn, iwn);
02423 WN_kid(wn,i) = NULL;
02424 }
02425 LWN_Insert_Block_Before (LWN_Get_Parent(wn), wn, iwn);
02426 LWN_Copy_Linenumber(wn, iwn);
02427 LWN_Copy_Frequency_Tree(iwn, wn);
02428
02429 LWN_Delete_Tree(wn);
02430 return iwn;
02431 }
02432
02433
02434
02435
02436
02437
02438
02439 static WN *Find_RReg_Ldid (WN *wn, INT *idx) {
02440 if (wn == NULL) return wn;
02441
02442 if (WN_operator(wn) == OPR_LDID &&
02443 ST_class(WN_st(wn)) == CLASS_PREG &&
02444 WN_offset(wn) == First_Int_Preg_Return_Offset) {
02445 *idx = -1;
02446 return wn;
02447 }
02448
02449 for (INT i=0; i<WN_kid_count(wn); i++) {
02450 WN *tmp = Find_RReg_Ldid(WN_kid(wn,i), idx);
02451 if (tmp) {
02452 if (*idx == -1) *idx = i;
02453 return tmp;
02454 }
02455 }
02456 return NULL;
02457 }
02458
02459
02460
02461
02462
02463
02464
02465
02466
02467
02468 extern WN *Convert_Intrinsic_To_Alloca_Dealloca (WN *wn) {
02469
02470 if (wn == NULL) return wn;
02471
02472 if (WN_opcode(wn) == OPC_BLOCK) {
02473 WN *kid = WN_first(wn);
02474 while (kid) {
02475 kid = Convert_Intrinsic_To_Alloca_Dealloca(kid);
02476 kid = WN_next(kid);
02477 }
02478 return wn;
02479 }
02480
02481 if (WN_opcode(wn) == OPC_IO) {
02482
02483
02484 return wn;
02485 }
02486
02487 if (WN_operator(wn) != OPR_INTRINSIC_CALL) {
02488 for (INT i=0; i<WN_kid_count(wn); i++) {
02489 Convert_Intrinsic_To_Alloca_Dealloca(WN_kid(wn,i));
02490 }
02491 return wn;
02492 }
02493
02494 WN *ret_wn = wn;
02495
02496 switch (WN_intrinsic(wn)) {
02497
02498 case INTRN_U8READSTACKPOINTER:
02499 case INTRN_U4READSTACKPOINTER:
02500
02501 wn = WN_next(wn);
02502 ret_wn = wn;
02503 LWN_Delete_Tree(WN_prev(wn));
02504
02505 INT idx;
02506 wn = Find_RReg_Ldid (wn, &idx);
02507 FmtAssert (wn, ("Could not find return-value from intrinsic"));
02508
02509 WN_kid (LWN_Get_Parent(wn),idx) =
02510 WN_CreateAlloca(WN_CreateIntconst(OPC_I4INTCONST,0));
02511 LWN_Parentize(LWN_Get_Parent(wn));
02512 LWN_Set_Parent(wn,NULL);
02513 LWN_Delete_Tree(wn);
02514
02515 break;
02516
02517 case INTRN_U8I8ALLOCA:
02518 case INTRN_U4I4ALLOCA: {
02519
02520 WN *sz = WN_kid0(WN_kid0(wn));
02521 LWN_Set_Parent(WN_kid0(WN_kid0(wn)), NULL);
02522 WN_kid0(WN_kid0(wn)) = NULL;
02523 wn = WN_next(wn);
02524 ret_wn = wn;
02525 LWN_Delete_Tree(WN_prev(wn));
02526
02527 wn = Find_RReg_Ldid (wn, &idx);
02528 FmtAssert (wn, ("Could not find return-value from intrinsic"));
02529
02530 WN_kid (LWN_Get_Parent(wn),idx) = WN_CreateAlloca(sz);
02531 LWN_Parentize(LWN_Get_Parent(wn));
02532 LWN_Set_Parent(wn,NULL);
02533 LWN_Delete_Tree(wn);
02534 }
02535 break;
02536
02537 case INTRN_U8I8SETSTACKPOINTER:
02538 case INTRN_U4I4SETSTACKPOINTER:
02539
02540 WN *dwn = WN_CreateDealloca(WN_kid_count(wn));
02541 for (INT i=0; i<WN_kid_count(wn); i++) {
02542 WN_kid(dwn,i) = WN_kid0(WN_kid(wn,i));
02543 WN_kid0(WN_kid(wn,i)) = NULL;
02544 }
02545 LWN_Parentize(dwn);
02546 LWN_Insert_Block_Before (LWN_Get_Parent(wn), wn, dwn);
02547 LWN_Delete_Tree(wn);
02548 ret_wn = dwn;
02549 break;
02550 }
02551 return ret_wn;
02552 }