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 #ifdef USE_PCH
00063 #include "lno_pch.h"
00064 #endif // USE_PCH
00065 #pragma hdrstop
00066
00067 static const char *source_file = __FILE__;
00068
00069 #ifdef _KEEP_RCS_ID
00070 static char *rcs_id = "$Source: /home/bos/bk/kpro64-pending/be/lno/SCCS/s.al_ref.cxx $ $Revision: 1.5 $";
00071 #endif
00072
00073 #include <sys/types.h>
00074 #include <ctype.h>
00075 #include <limits.h>
00076 #include <alloca.h>
00077
00078 #include "pu_info.h"
00079 #include "lnopt_main.h"
00080 #include "config_targ.h"
00081 #include "erbe.h"
00082 #include "lnoutils.h"
00083 #include "lwn_util.h"
00084 #include "snl_utils.h"
00085 #include "lego_pragma.h"
00086 #include "lego_util.h"
00087 #include "lego_opts.h"
00088 #include "array_lower.h"
00089 #include "al_loop.h"
00090 #include "al_ref.h"
00091 #include "move.h"
00092
00093
00094
00095
00096
00097 extern mBOOL Single_Loop_Coeff(ACCESS_VECTOR *av, INT64 *stride, INT64 *offset,
00098 mINT32 *depth);
00099
00100 extern void Try_Hoist_Expression (WN* expr_wn);
00101
00102
00103
00104
00105
00106 static WN *Get_Call_Parent(WN *curr_nd);
00107 static TY_IDX Get_Callee_TY(WN *call_nd, ST *array_st);
00108 static INT Find_Param_Num(WN *array_param, WN *call_nd);
00109 static void Fixup_DU_Under_IO (WN* ref, WN* io_wn);
00110 static WN* Get_IO_Parent (WN* ref);
00111 static void Hoist_Reshaped_Reference (WN* array_wn);
00112 static WN* Lower_Reshaped_Reference (WN* array_wn);
00113
00114
00115
00116
00117
00118
00119 ARRAY_LOWER_REF::ARRAY_LOWER_REF(WN *array_ref,
00120 DISTR_ARRAY *dact,
00121 ARRAY_LOWER_LOOP *parent_loop,
00122 mBOOL is_param )
00123 {
00124 if (is_param) {
00125 Is_True(array_ref &&
00126 ((WN_operator(array_ref) == OPR_LDA) ||
00127 (WN_operator(array_ref) == OPR_LDID)),
00128 ("ARRAY_LOWER_REF constuctor: bad array_ref for array param\n"));
00129 } else {
00130 Is_True(array_ref && (WN_operator(array_ref) == OPR_ARRAY),
00131 ("ARRAY_LOWER_REF constructor: bad array_ref for array expr\n"));
00132 }
00133
00134 Is_True(dact, ("ARRAY_LOWER_REF constructor: dact is NULL\n"));
00135 Is_True(parent_loop, ("ARRAY_LOWER_REF constructor: parent_loop is NULL\n"));
00136
00137 _array_ref = array_ref;
00138 _dact = dact;
00139 _parent_loop = parent_loop;
00140 _is_param = is_param;
00141 }
00142
00143
00144 ARRAY_LOWER_REF::~ARRAY_LOWER_REF(void)
00145 { }
00146
00147
00148 void
00149 ARRAY_LOWER_REF::Lower_Ref(void)
00150 {
00151 if (Is_Param()) Lower_Array_Param();
00152 else Lower_Array_Expr();
00153 }
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163 ARRAY_LOWER_LOOP
00164 *ARRAY_LOWER_REF::Get_Ref_Loop(INT dim,
00165 INT64 *ref_stride,
00166 INT64 *ref_offset)
00167 {
00168 ACCESS_ARRAY *aa = (ACCESS_ARRAY *) WN_MAP_Get(LNO_Info_Map, Array_Ref());
00169 if (aa == NULL) {
00170 DevWarn ("Get_Ref_Loop: No ACCESS_ARRAY for ref\n");
00171 return NULL;
00172 }
00173 ACCESS_VECTOR *av = aa->Dim(dim);
00174
00175
00176
00177
00178 *ref_offset = 0;
00179 *ref_stride = 0;
00180 mINT32 ref_depth;
00181 if (!Single_Loop_Coeff(av, ref_stride, ref_offset, &ref_depth))
00182 return NULL;
00183
00184
00185
00186
00187 ARRAY_LOWER_LOOP *ref_loop =
00188 Parent_Loop()->Get_Ancestor(av->Nest_Depth() - ref_depth - 1);
00189 Is_True(ref_loop,
00190 ("Get_Ref_Loop: Ref loop not found at depth %d\n", ref_depth));
00191
00192 DO_LOOP_INFO *loop_info = Get_Do_Loop_Info(ref_loop->Doloop());
00193 Is_True(loop_info->Depth == ref_depth,
00194 ("Get_Ref_Loop: Mismatch in loop depths\n"));
00195
00196 return ref_loop;
00197 }
00198
00199
00200
00201
00202
00203
00204
00205
00206 static WN* Get_IO_Parent (WN* ref) {
00207 WN* parent = LWN_Get_Parent(ref);
00208 while (parent) {
00209 if (WN_operator(parent) == OPR_IO) return parent;
00210 if (OPCODE_is_stmt(WN_opcode(parent))) return NULL;
00211 parent = LWN_Get_Parent(parent);
00212 }
00213 return NULL;
00214 }
00215
00216
00217
00218
00219
00220
00221
00222 static void Fixup_DU_Under_IO (WN* ref, WN* io_wn) {
00223 USE_LIST* use_list = Du_Mgr->Du_Get_Use(ref);
00224 USE_LIST_ITER use_iter(use_list);
00225 DU_NODE* node;
00226
00227
00228 for (node = use_iter.First(); !use_iter.Is_Empty();
00229 node = use_iter.Next()) {
00230 WN* uwn = node->Wn();
00231 Du_Mgr->Delete_Def_Use (ref, uwn);
00232 Du_Mgr->Add_Def_Use (io_wn, uwn);
00233 }
00234
00235 DEF_LIST* def_list = Du_Mgr->Ud_Get_Def(ref);
00236 DEF_LIST_ITER def_iter(def_list);
00237
00238
00239 for (node = def_iter.First(); !def_iter.Is_Empty();
00240 node = def_iter.Next()) {
00241 WN* dwn = node->Wn();
00242 Du_Mgr->Delete_Def_Use (dwn, ref);
00243 Du_Mgr->Add_Def_Use (dwn, io_wn);
00244 }
00245
00246
00247 for (INT i=0; i<WN_kid_count(ref); i++)
00248 Fixup_DU_Under_IO (WN_kid(ref, i), io_wn);
00249 }
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259 void
00260 ARRAY_LOWER_REF::Lower_Array_Expr(void)
00261 {
00262 TYPE_ID type;
00263 OPCODE op;
00264
00265 DISTR_INFO *dinfo = Dact()->Dinfo();
00266
00267
00268
00269
00270 INT i;
00271 INT num_block = 0;
00272 INT num_cyclic = 0;
00273 INT num_blkcyc = 0;
00274 INT num_star = 0;
00275 INT num_dim = dinfo->Num_Dim();
00276
00277 for (i = 0; i < num_dim; i++) {
00278 switch (Dact()->Dims()[i].Distr_Type()) {
00279 case DISTRIBUTE_BLOCK:
00280 num_block++;
00281 break;
00282 case DISTRIBUTE_STAR:
00283 num_star++;
00284 break;
00285 case DISTRIBUTE_CYCLIC_CONST:
00286 if (Dact()->Dims()[i].Chunk_Const_Val() == 1) num_cyclic++;
00287 else num_blkcyc++;
00288 break;
00289 case DISTRIBUTE_CYCLIC_EXPR:
00290 num_blkcyc++;
00291 break;
00292 }
00293 }
00294
00295 INT num_distr = num_block + num_cyclic + num_blkcyc;
00296 INT num_local = num_distr + num_blkcyc + num_star;
00297
00298 if (num_distr == 0) return;
00299
00300
00301
00302
00303 op = OPCODE_make_op(OPR_ARRAY, Pointer_type, MTYPE_V);
00304 WN *distr_addr = WN_Create(op, 2*num_distr + 1);
00305 WN *local_addr = WN_Create(op, 2*num_local + 1);
00306
00307 INT curr_local = 0;
00308 INT curr_distr = 0;
00309 for (i = 0; i < num_dim; i++) {
00310 switch (Dact()->Dims()[i].Distr_Type()) {
00311
00312
00313
00314 case DISTRIBUTE_BLOCK: {
00315 Create_Block_Dim(i, distr_addr, local_addr, &curr_distr, &curr_local);
00316 break;
00317 }
00318
00319
00320
00321 case DISTRIBUTE_STAR: {
00322 Create_Star_Dim(i, local_addr, &curr_local);
00323 break;
00324 }
00325
00326 case DISTRIBUTE_CYCLIC_CONST: {
00327 if (Dact()->Dims()[i].Chunk_Const_Val() == 1) {
00328
00329
00330
00331 Create_Cyclic_Dim(i, distr_addr, local_addr, &curr_distr, &curr_local);
00332 } else {
00333
00334
00335
00336 TYPE_ID type =
00337 WN_rtype(WN_array_index(Array_Ref(), i));
00338 WN *chunk_nd =
00339 LWN_Make_Icon(type, Dact()->Dims()[i].Chunk_Const_Val());
00340
00341 Create_Blkcyc_Dim(i, distr_addr, local_addr, &curr_distr,
00342 &curr_local, chunk_nd);
00343 }
00344 break;
00345 }
00346
00347
00348
00349 case DISTRIBUTE_CYCLIC_EXPR: {
00350 WN *chunk_nd = Dact()->Chunksize (i);
00351 Create_Blkcyc_Dim(i, distr_addr, local_addr, &curr_distr,
00352 &curr_local, chunk_nd);
00353 }
00354 }
00355 }
00356
00357
00358
00359
00360 ST *array_st = dinfo->Array_ST();
00361 TY_IDX distr_ty_idx = ST_type(array_st);
00362 Is_True((TY_kind(distr_ty_idx) == KIND_POINTER) &&
00363 (TY_ptr_as_array(distr_ty_idx)),
00364 ("Lower_Array_Expr: Bad type for reshaped array %s\n", ST_name(array_st)));
00365
00366 TY_IDX local_ty_idx = TY_pointed(distr_ty_idx);
00367 Is_True((TY_kind(local_ty_idx) == KIND_POINTER) &&
00368 (TY_ptr_as_array(local_ty_idx)),
00369 ("Lower_Array_Expr: Bad type for reshaped array %s\n", ST_name(array_st)));
00370
00371 op = OPCODE_make_op(OPR_LDID, Pointer_type, Pointer_type);
00372 WN *distr_array_base = dinfo->Load_Distr_Array ();
00373 WN_array_base(distr_addr) = distr_array_base;
00374
00375
00376
00377 Du_Mgr->Ud_Get_Def(distr_array_base)->Set_loop_stmt(NULL);
00378
00379 LWN_Set_Parent(distr_array_base, distr_addr);
00380
00381 op = OPCODE_make_op(OPR_ILOAD, Pointer_type, Pointer_type);
00382 WN_array_base(local_addr) = LWN_CreateIload(op, 0, local_ty_idx,
00383 distr_ty_idx, distr_addr);
00384
00385
00386
00387 WN* array_ptr_alias_wn = dinfo->Get_Array_Ptr_Alias_WN();
00388 if (array_ptr_alias_wn)
00389 Copy_alias_info (Alias_Mgr, array_ptr_alias_wn, WN_array_base(local_addr));
00390 else {
00391 Create_unique_pointer_alias (Alias_Mgr, array_st, NULL,
00392 WN_array_base(local_addr));
00393 WN* copy_wn = LWN_Copy_Tree (WN_array_base(local_addr));
00394 Copy_alias_info (Alias_Mgr, WN_array_base(local_addr), copy_wn);
00395 dinfo->Set_Array_Ptr_Alias_WN (copy_wn);
00396 }
00397 LWN_Set_Parent(WN_array_base(local_addr), local_addr);
00398
00399 WN_element_size(distr_addr) = Pointer_Size;
00400 WN_element_size(local_addr) = TY_size(TY_pointed(local_ty_idx));
00401
00402 Replace_WN(_array_ref, local_addr);
00403 LWN_Delete_Tree(_array_ref);
00404 _array_ref = local_addr;
00405
00406 if (LNO_enabled && !Get_Trace(TP_LNOPT2, TT_LEGO_DISABLE_HOIST)) {
00407
00408
00409
00410 DOLOOP_STACK do_stack(LEGO_pool);
00411 Build_Doloop_Stack(LWN_Get_Parent(distr_addr), &do_stack);
00412 LNO_Build_Access(distr_addr, &do_stack, LEGO_pool);
00413 LNO_Build_Access(local_addr, &do_stack, LEGO_pool);
00414
00415 local_addr = Lower_Reshaped_Reference (local_addr);
00416 distr_addr = WN_kid0(WN_array_base(local_addr));
00417
00418
00419
00420 Build_Doloop_Stack(LWN_Get_Parent(distr_addr), &do_stack);
00421 LNO_Build_Access(distr_addr, &do_stack, LEGO_pool);
00422 LNO_Build_Access(local_addr, &do_stack, LEGO_pool);
00423
00424 Hoist_Reshaped_Reference (local_addr);
00425 _array_ref = local_addr;
00426 }
00427
00428
00429
00430 DOLOOP_STACK do_stack(LEGO_pool);
00431 Build_Doloop_Stack(LWN_Get_Parent(distr_addr), &do_stack);
00432 LNO_Build_Access(distr_addr, &do_stack, LEGO_pool);
00433 LNO_Build_Access(local_addr, &do_stack, LEGO_pool);
00434
00435 {
00436
00437 WN* io_wn = Get_IO_Parent(_array_ref);
00438 if (io_wn) Fixup_DU_Under_IO (_array_ref, io_wn);
00439 }
00440 }
00441
00442
00443
00444
00445
00446 void ARRAY_LOWER_REF::Lower_Array_Param(void)
00447 {
00448 INT i;
00449 DISTR_INFO *dinfo = Dact()->Dinfo();
00450
00451 WN *call_nd = Get_Call_Parent(Array_Ref());
00452 Is_True(call_nd, ("Lower_Array_Param: No call parent for array param\n"));
00453
00454 ST *array_st = dinfo->Array_ST();
00455 TY_IDX distr_ty = ST_type(array_st);
00456
00457 OPCODE op = OPCODE_make_op(OPR_LDID, Pointer_type, Pointer_type);
00458 WN *distr_array_base = dinfo->Load_Distr_Array();
00459
00460
00461
00462 TY_IDX callee_ty = Get_Callee_TY(call_nd, array_st);
00463 INT param_num = Find_Param_Num(Array_Ref(), call_nd);
00464 Is_True(param_num >= 0, ("Lower_Array_Param: Bad parameter number\n"));
00465
00466 if (callee_ty) {
00467 #ifdef _NEW_SYMTAB
00468 TYLIST_IDX curr_ty = TY_parms(callee_ty);
00469 #else
00470 struct tylist *curr_ty = FTI_parms(TY_ftinfo(callee_ty));
00471 #endif
00472 if (curr_ty) {
00473 for (i = 0; i < param_num; i++) {
00474 curr_ty = TYLIST_next(curr_ty);
00475
00476
00477 if (curr_ty == TY_IDX_ZERO) break;
00478 }
00479 #ifdef _NEW_SYMTAB
00480 Set_TYLIST_type(curr_ty,distr_ty);
00481 #else
00482 if (curr_ty) TYLIST_item(curr_ty) = distr_ty;
00483 #endif
00484 }
00485 else if (WN_operator(call_nd) == OPR_ICALL) {
00486 ErrMsgSrcpos(EC_LNO_Generic, WN_Get_Linenum(call_nd),
00487 "Reshaped array passed to function pointer\n");
00488 }
00489 }
00490
00491
00492
00493 WN* parm_wn = LWN_Get_Parent(Array_Ref());
00494 FmtAssert (parm_wn && (WN_operator(parm_wn) == OPR_PARM),
00495 ("Parent of actual should be OPR_PARM"));
00496 WN_set_ty(parm_wn, distr_ty);
00497
00498
00499
00500
00501 Du_Mgr->Ud_Get_Def(distr_array_base)->Set_loop_stmt(NULL);
00502
00503 Replace_WN(_array_ref, distr_array_base);
00504 LWN_Delete_Tree(_array_ref);
00505 _array_ref = distr_array_base;
00506 }
00507
00508
00509
00510
00511
00512 void
00513 ARRAY_LOWER_REF::Create_Block_Dim(INT dim,
00514 WN *distr_addr,
00515 WN *local_addr,
00516 INT *curr_distr,
00517 INT *curr_local)
00518 {
00519 if (!disable_divmod_opts && Is_Block_Dim_Local(dim)) {
00520 Create_Local_Block_Dim(dim, distr_addr, local_addr,
00521 curr_distr, curr_local);
00522 } else {
00523 Create_Remote_Block_Dim(dim, distr_addr, local_addr,
00524 curr_distr, curr_local);
00525 }
00526 }
00527
00528
00529
00530
00531
00532 mBOOL
00533 ARRAY_LOWER_REF::Is_Block_Dim_Local(INT dim)
00534 {
00535 INT64 ref_stride;
00536 INT64 ref_offset;
00537
00538 if (!disable_rr_maps) {
00539 RR_INFO* rri = Get_RR_Map(Array_Ref());
00540 if (rri && rri->Dim(dim)->Do_Loop()) return TRUE;
00541 return FALSE;
00542 }
00543
00544 ARRAY_LOWER_LOOP *ref_loop = Get_Ref_Loop(dim, &ref_stride, &ref_offset);
00545 if (!ref_loop) return FALSE;
00546
00547 LEGO_INFO *lego_info = ref_loop->Get_Lego_Info();
00548 if (!lego_info || lego_info->Is_Too_Messy()) return FALSE;
00549
00550 SYMBOL *affinity_array = lego_info->Array();
00551 DISTR_ARRAY *affinity_dact = Lookup_DACT(affinity_array->St());
00552
00553
00554
00555
00556 if (Dact()->DACT_Equiv(affinity_dact, dim, lego_info->Dim_Num())) {
00557
00558 if (ref_stride != lego_info->Stride()) return FALSE;
00559
00560 INT64 step = lego_info->Get_Local_Step(ref_loop->Doloop());
00561 if (step <= 0) return FALSE;
00562
00563 ref_offset -= lego_info->Offset();
00564 if (ref_offset >= 0) {
00565 return (INT64(lego_info->Back_Peel()) >= (ref_offset - (step - 1)));
00566 } else {
00567 return (INT64(lego_info->Front_Peel()) >= -ref_offset);
00568 }
00569 }
00570
00571 return FALSE;
00572 }
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587 void
00588 ARRAY_LOWER_REF::Create_Local_Block_Dim(INT dim,
00589 WN *distr_addr,
00590 WN *local_addr,
00591 INT *curr_distr,
00592 INT *curr_local)
00593 {
00594
00595 if (!disable_rr_maps) {
00596 RR_INFO* rri = Get_RR_Map (_array_ref);
00597 Is_True (rri, ("Missing RR-Map"));
00598 RR_DIM* rrdim = rri->Dim(dim);
00599 Is_True (rrdim, ("Missing RR-Map"));
00600
00601 DISTR_INFO *dinfo = Dact()->Dinfo();
00602
00603
00604
00605 WN *bound = dinfo->Numprocs(dim);
00606 WN* proc_wn = rrdim->Do_Loop();
00607 SYMBOL sym (WN_start(proc_wn));
00608 WN* index = AWN_LdidSym(&sym);
00609 printf ("Hey -- set DU info\n");
00610
00611 Set_Array_Dim(distr_addr, *curr_distr, bound, index);
00612 (*curr_distr)++;
00613
00614
00615
00616 bound = dinfo->Dimsize(dim);
00617 index = LWN_Copy_Tree(WN_array_index(_array_ref, dim),
00618 TRUE, LNO_Info_Map);
00619 LWN_Copy_Def_Use (WN_array_index(_array_ref, dim), index, Du_Mgr);
00620
00621 DO_LOOP_INFO* pdli = Get_Do_Loop_Info (proc_wn);
00622 index = AWN_Sub (WN_rtype(index),
00623 index,
00624 AWN_LdidSym(&(pdli->Lego_LB_Symbols[rrdim->Index()])));
00625
00626 Set_Array_Dim(local_addr, *curr_local, bound, index);
00627 (*curr_local)++;
00628
00629 return;
00630 }
00631
00632
00633 INT64 ref_stride;
00634 INT64 ref_offset;
00635 ARRAY_LOWER_LOOP *ref_loop = Get_Ref_Loop(dim, &ref_stride, &ref_offset);
00636 Is_True(ref_loop, ("Create_Local_Block_Dim: ref_loop is NULL\n"));
00637
00638 LEGO_INFO *lego_info = ref_loop->Get_Lego_Info();
00639 Is_True(lego_info && !lego_info->Is_Too_Messy(),
00640 ("Create_Local_Block_Dim: bad LEGO_INFO for ref_loop\n"));
00641
00642 DISTR_INFO *dinfo = Dact()->Dinfo();
00643
00644
00645
00646 WN *bound = dinfo->Numprocs(dim);
00647 WN* index = lego_info->Pid0(Array_Ref());
00648
00649 Set_Array_Dim(distr_addr, *curr_distr, bound, index);
00650 (*curr_distr)++;
00651
00652
00653
00654 if (!lego_info->Has_Local_Index())
00655 lego_info->Create_Local_Index(ref_loop->Doloop());
00656
00657 bound = dinfo->Dimsize(dim);
00658 index = lego_info->Local_Index();
00659
00660 TYPE_ID type = WN_rtype(index);
00661 WN *offset_wn = LWN_Make_Icon(type, (ref_offset - lego_info->Offset()));
00662 index = AWN_Add(type, index, offset_wn);
00663
00664 Set_Array_Dim(local_addr, *curr_local, bound, index);
00665 (*curr_local)++;
00666 }
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679 void
00680 ARRAY_LOWER_REF::Create_Remote_Block_Dim(INT dim,
00681 WN *distr_addr,
00682 WN *local_addr,
00683 INT *curr_distr,
00684 INT *curr_local)
00685 {
00686 DISTR_INFO *dinfo = Dact()->Dinfo();
00687
00688
00689
00690 WN *bound = dinfo->Numprocs(dim);
00691
00692 WN *old_index = WN_array_index(Array_Ref(), dim);
00693 WN *old_index_copy = LWN_Copy_Tree(old_index, TRUE, LNO_Info_Map);
00694 LWN_Copy_Def_Use(old_index, old_index_copy, Du_Mgr);
00695
00696 WN *dim_size = dinfo->Dimsize(dim);
00697 TYPE_ID type = Max_Wtype(WN_rtype(dim_size),
00698 WN_rtype(old_index));
00699 WN *index = AWN_Div_Safe(type, old_index_copy, dim_size);
00700
00701 Set_Array_Dim(distr_addr, *curr_distr, bound, index);
00702 (*curr_distr)++;
00703
00704
00705
00706 old_index_copy = LWN_Copy_Tree(old_index, TRUE, LNO_Info_Map);
00707 LWN_Copy_Def_Use(old_index, old_index_copy, Du_Mgr);
00708
00709 bound = dinfo->Dimsize(dim);
00710 index = AWN_Rem_Safe(type, old_index_copy, dinfo->Dimsize(dim));
00711
00712 Set_Array_Dim(local_addr, *curr_local, bound, index);
00713 (*curr_local)++;
00714 }
00715
00716
00717
00718
00719
00720 void
00721 ARRAY_LOWER_REF::Create_Cyclic_Dim(INT dim,
00722 WN *distr_addr,
00723 WN *local_addr,
00724 INT *curr_distr,
00725 INT *curr_local)
00726 {
00727 if (!disable_divmod_opts && Is_Cyclic_Dim_Local(dim)) {
00728 Create_Local_Cyclic_Dim(dim, distr_addr, local_addr,
00729 curr_distr, curr_local);
00730 } else {
00731 Create_Remote_Cyclic_Dim(dim, distr_addr, local_addr,
00732 curr_distr, curr_local);
00733 }
00734 }
00735
00736
00737
00738
00739
00740 mBOOL
00741 ARRAY_LOWER_REF::Is_Cyclic_Dim_Local(INT dim)
00742 {
00743 INT64 ref_stride;
00744 INT64 ref_offset;
00745
00746 ARRAY_LOWER_LOOP *ref_loop = Get_Ref_Loop(dim, &ref_stride, &ref_offset);
00747 if (!ref_loop) return FALSE;
00748
00749 LEGO_INFO *lego_info = ref_loop->Get_Lego_Info();
00750 if (!lego_info || lego_info->Is_Too_Messy()) return FALSE;
00751
00752 SYMBOL *affinity_array = lego_info->Array();
00753 DISTR_ARRAY *affinity_dact = Lookup_DACT(affinity_array->St());
00754
00755
00756
00757
00758 if (Dact()->DACT_Equiv(affinity_dact, dim, lego_info->Dim_Num())) {
00759
00760 INT64 step = lego_info->Get_Local_Step(ref_loop->Doloop());
00761 if (step <= 0) return FALSE;
00762
00763 return ((ref_stride == lego_info->Stride()) &&
00764 (ref_offset == lego_info->Offset()));
00765 }
00766
00767 return FALSE;
00768 }
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784 void
00785 ARRAY_LOWER_REF::Create_Local_Cyclic_Dim(INT dim,
00786 WN *distr_addr,
00787 WN *local_addr,
00788 INT *curr_distr,
00789 INT *curr_local)
00790 {
00791 INT64 ref_stride;
00792 INT64 ref_offset;
00793 ARRAY_LOWER_LOOP *ref_loop = Get_Ref_Loop(dim, &ref_stride, &ref_offset);
00794 Is_True(ref_loop, ("Create_Local_Cyclic_Dim: ref_loop is NULL\n"));
00795
00796 LEGO_INFO *lego_info = ref_loop->Get_Lego_Info();
00797 Is_True(lego_info && !lego_info->Is_Too_Messy(),
00798 ("Create_Local_Cyclic_Dim: bad LEGO_INFO for ref_loop\n"));
00799
00800 DISTR_INFO *dinfo = Dact()->Dinfo();
00801
00802
00803
00804 WN *bound = dinfo->Numprocs(dim);
00805 WN *index = lego_info->Pid0(Array_Ref());
00806
00807 Set_Array_Dim(distr_addr, *curr_distr, bound, index);
00808 (*curr_distr)++;
00809
00810
00811
00812 if (!lego_info->Has_Local_Index())
00813 lego_info->Create_Local_Index(ref_loop->Doloop());
00814
00815 bound = dinfo->Dimsize(dim);
00816 index = lego_info->Local_Index();
00817
00818 TYPE_ID type = WN_rtype(index);
00819 WN *offset_wn = LWN_Make_Icon(type, (ref_offset - lego_info->Offset()));
00820 index = AWN_Add(type, index, offset_wn);
00821
00822 Set_Array_Dim(local_addr, *curr_local, bound, index);
00823 (*curr_local)++;
00824 }
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837 void
00838 ARRAY_LOWER_REF::Create_Remote_Cyclic_Dim(INT dim,
00839 WN *distr_addr,
00840 WN *local_addr,
00841 INT *curr_distr,
00842 INT *curr_local)
00843 {
00844 DISTR_INFO *dinfo = Dact()->Dinfo();
00845
00846
00847
00848 WN *bound = dinfo->Numprocs(dim);
00849
00850 WN *old_index = WN_array_index(Array_Ref(), dim);
00851 WN *old_index_copy = LWN_Copy_Tree(old_index, TRUE, LNO_Info_Map);
00852 LWN_Copy_Def_Use(old_index, old_index_copy, Du_Mgr);
00853
00854 WN *num_procs = dinfo->Numprocs(dim);
00855 TYPE_ID type = Max_Wtype(WN_rtype(num_procs),
00856 WN_rtype(old_index));
00857 WN *index = AWN_Rem_Safe(type, old_index_copy, num_procs);
00858
00859 Set_Array_Dim(distr_addr, *curr_distr, bound, index);
00860 (*curr_distr)++;
00861
00862
00863
00864 old_index_copy = LWN_Copy_Tree(old_index, TRUE, LNO_Info_Map);
00865 LWN_Copy_Def_Use(old_index, old_index_copy, Du_Mgr);
00866
00867 bound = dinfo->Dimsize(dim);
00868 index = AWN_Div_Safe(type, old_index_copy, dinfo->Numprocs(dim));
00869 Set_Array_Dim(local_addr, *curr_local, bound, index);
00870 (*curr_local)++;
00871 }
00872
00873
00874
00875
00876
00877 void
00878 ARRAY_LOWER_REF::Create_Blkcyc_Dim(INT dim,
00879 WN *distr_addr,
00880 WN *local_addr,
00881 INT *curr_distr,
00882 INT *curr_local,
00883 WN *chunk_nd)
00884
00885 {
00886 if (!disable_divmod_opts && Is_Blkcyc_Dim_Local(dim)) {
00887 Create_Local_Blkcyc_Dim(dim, distr_addr, local_addr,
00888 curr_distr, curr_local, chunk_nd);
00889 } else {
00890 Create_Remote_Blkcyc_Dim(dim, distr_addr, local_addr,
00891 curr_distr, curr_local, chunk_nd);
00892 }
00893 }
00894
00895
00896
00897
00898
00899 mBOOL
00900 ARRAY_LOWER_REF::Is_Blkcyc_Dim_Local(INT dim)
00901 {
00902 INT64 ref_stride;
00903 INT64 ref_offset;
00904
00905 ARRAY_LOWER_LOOP *ref_loop = Get_Ref_Loop(dim, &ref_stride, &ref_offset);
00906 if (!ref_loop) return FALSE;
00907
00908 LEGO_INFO *lego_info = ref_loop->Get_Lego_Info();
00909 if (!lego_info || lego_info->Is_Too_Messy()) return FALSE;
00910
00911 SYMBOL *affinity_array = lego_info->Array();
00912 DISTR_ARRAY *affinity_dact = Lookup_DACT(affinity_array->St());
00913
00914
00915
00916
00917 if (Dact()->DACT_Equiv(affinity_dact, dim, lego_info->Dim_Num())) {
00918
00919 INT64 step = lego_info->Get_Local_Step(ref_loop->Doloop());
00920 if (step <= 0) return FALSE;
00921
00922 return ((ref_stride == lego_info->Stride()) &&
00923 (ref_offset == lego_info->Offset()));
00924 }
00925
00926 return FALSE;
00927 }
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944 void
00945 ARRAY_LOWER_REF::Create_Local_Blkcyc_Dim(INT dim,
00946 WN *distr_addr,
00947 WN *local_addr,
00948 INT *curr_distr,
00949 INT *curr_local,
00950 WN *chunk_nd)
00951
00952 {
00953 INT64 ref_stride;
00954 INT64 ref_offset;
00955 ARRAY_LOWER_LOOP *ref_loop = Get_Ref_Loop(dim, &ref_stride, &ref_offset);
00956 Is_True(ref_loop, ("Create_Local_Blkcyc_Dim: ref_loop is NULL\n"));
00957
00958 LEGO_INFO *lego_info = ref_loop->Get_Lego_Info();
00959 Is_True(lego_info && !lego_info->Is_Too_Messy(),
00960 ("Create_Local_Blkcyc_Dim: bad LEGO_INFO for ref_loop\n"));
00961
00962 DISTR_INFO *dinfo = Dact()->Dinfo();
00963
00964
00965
00966 WN *bound = dinfo->Numprocs(dim);
00967 WN *index = lego_info->Pid0(Array_Ref());
00968
00969 Set_Array_Dim(distr_addr, *curr_distr, bound, index);
00970 (*curr_distr)++;
00971
00972
00973
00974
00975 bound = dinfo->Dimsize(dim);
00976 index = lego_info->Pid1(Array_Ref());
00977
00978 Set_Array_Dim(local_addr, *curr_local, bound, index);
00979 (*curr_local)++;
00980
00981
00982
00983 if (!lego_info->Has_Local_Index())
00984 lego_info->Create_Local_Index(ref_loop->Doloop());
00985
00986 bound = chunk_nd;
00987 index = lego_info->Local_Index();
00988
00989 TYPE_ID type = WN_rtype(index);
00990 WN *offset_wn = LWN_Make_Icon(type, (ref_offset - lego_info->Offset()));
00991 index = AWN_Add(type, index, offset_wn);
00992
00993 Set_Array_Dim(local_addr, *curr_local, bound, index);
00994 (*curr_local)++;
00995 }
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010 void
01011 ARRAY_LOWER_REF::Create_Remote_Blkcyc_Dim(INT dim,
01012 WN *distr_addr,
01013 WN *local_addr,
01014 INT *curr_distr,
01015 INT *curr_local,
01016 WN *chunk_nd)
01017
01018 {
01019 DISTR_INFO *dinfo = Dact()->Dinfo();
01020
01021
01022
01023 WN *bound = dinfo->Numprocs(dim);
01024
01025 WN *old_index = WN_array_index(Array_Ref(), dim);
01026 WN *old_index_copy = LWN_Copy_Tree(old_index, TRUE, LNO_Info_Map);
01027 LWN_Copy_Def_Use(old_index, old_index_copy, Du_Mgr);
01028 WN *chunk_nd_copy = LWN_Copy_Tree(chunk_nd, TRUE, LNO_Info_Map);
01029 LWN_Copy_Def_Use(chunk_nd, chunk_nd_copy, Du_Mgr);
01030
01031 WN *num_procs = dinfo->Numprocs(dim);
01032 TYPE_ID type = Max_Wtype(WN_rtype(num_procs),
01033 WN_rtype(old_index));
01034 type = Max_Wtype(type, WN_rtype(chunk_nd));
01035 WN *div = AWN_Div_Safe(type, old_index_copy, chunk_nd_copy);
01036 WN *index = AWN_Rem_Safe(type, div, num_procs);
01037
01038 Set_Array_Dim(distr_addr, *curr_distr, bound, index);
01039 (*curr_distr)++;
01040
01041
01042
01043 old_index_copy = LWN_Copy_Tree(old_index, TRUE, LNO_Info_Map);
01044 LWN_Copy_Def_Use(old_index, old_index_copy, Du_Mgr);
01045 chunk_nd_copy = LWN_Copy_Tree(chunk_nd, TRUE, LNO_Info_Map);
01046 LWN_Copy_Def_Use(chunk_nd, chunk_nd_copy, Du_Mgr);
01047
01048 WN *pb = AWN_Mpy(type, dinfo->Numprocs(dim), chunk_nd_copy);
01049 bound = dinfo->Dimsize(dim);
01050 index = AWN_Div_Safe(type, old_index_copy, pb);
01051 Set_Array_Dim(local_addr, *curr_local, bound, index);
01052 (*curr_local)++;
01053
01054
01055
01056 old_index_copy = LWN_Copy_Tree(old_index, TRUE, LNO_Info_Map);
01057 LWN_Copy_Def_Use(old_index, old_index_copy, Du_Mgr);
01058 chunk_nd_copy = LWN_Copy_Tree(chunk_nd, TRUE, LNO_Info_Map);
01059 LWN_Copy_Def_Use(chunk_nd, chunk_nd_copy, Du_Mgr);
01060
01061 bound = chunk_nd_copy;
01062 index = AWN_Rem_Safe(type, old_index_copy, chunk_nd);
01063 Set_Array_Dim(local_addr, *curr_local, bound, index);
01064 (*curr_local)++;
01065 }
01066
01067
01068
01069
01070
01071
01072
01073
01074
01075
01076
01077
01078 void
01079 ARRAY_LOWER_REF::Create_Star_Dim(INT dim,
01080 WN *local_addr,
01081 INT *curr_local)
01082 {
01083
01084
01085 WN *old_index = WN_array_index(Array_Ref(), dim);
01086 WN *old_bound = WN_array_dim(Array_Ref(), dim);
01087
01088 WN *bound = LWN_Copy_Tree(old_bound, TRUE, LNO_Info_Map);
01089 LWN_Copy_Def_Use(old_bound, bound, Du_Mgr);
01090
01091 WN *index = LWN_Copy_Tree(old_index, TRUE, LNO_Info_Map);
01092 LWN_Copy_Def_Use(old_index, index, Du_Mgr);
01093
01094 Set_Array_Dim(local_addr, *curr_local, bound, index);
01095 (*curr_local)++;
01096 }
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106 extern mBOOL Single_Loop_Coeff(ACCESS_VECTOR *av,
01107 INT64 *stride,
01108 INT64 *offset,
01109 mINT32 *depth)
01110 {
01111 *stride = 0;
01112 *offset = 0;
01113 *depth = -1;
01114
01115 if (av->Too_Messy ||
01116 av->Contains_Lin_Symb() ||
01117 av->Contains_Non_Lin_Symb() ||
01118 av->Is_Const() ||
01119 !av->Has_Loop_Coeff())
01120 return FALSE;
01121
01122 for (INT i = 0; i < av->Nest_Depth(); i++) {
01123 if (av->Loop_Coeff(i) != 0) {
01124 if (*stride != 0) return FALSE;
01125
01126 *stride = av->Loop_Coeff(i);
01127 *depth = i;
01128 }
01129 }
01130
01131 *offset = av->Const_Offset;
01132 return TRUE;
01133 }
01134
01135
01136
01137
01138
01139
01140
01141
01142
01143 WN *Get_Call_Parent(WN *curr_nd)
01144 {
01145 WN *parent = LWN_Get_Parent(curr_nd);
01146
01147 while (parent) {
01148 if (OPCODE_is_call(WN_opcode(parent)) ||
01149 WN_operator(parent) == OPR_INTRINSIC_OP
01150 #ifdef KEY
01151 || WN_operator(parent) == OPR_PURE_CALL_OP
01152 #endif
01153 ) {
01154 return parent;
01155 } else {
01156 parent = LWN_Get_Parent(parent);
01157 }
01158 }
01159
01160 return NULL;
01161 }
01162
01163
01164
01165
01166
01167 TY_IDX Get_Callee_TY(WN *call_nd,
01168 ST *array_st)
01169 {
01170 if (WN_operator(call_nd) == OPR_CALL
01171 #ifdef KEY
01172 || WN_operator(call_nd) == OPR_PURE_CALL_OP
01173 #endif
01174 ) {
01175 ST* callee_st = ST_ptr(WN_entry_name(call_nd));
01176 return (ST_type(callee_st));
01177
01178 } else if (WN_operator(call_nd) == OPR_ICALL) {
01179 return WN_ty(call_nd);
01180
01181 } else if (WN_operator(call_nd) != OPR_INTRINSIC_OP) {
01182
01183
01184 DevWarn("Bad reference at line %d: Reshaped array %s in invalid call statement\n",
01185 Srcpos_To_Line(LWN_Get_Linenum(call_nd)), ST_name(array_st));
01186 }
01187 return TY_IDX_ZERO;
01188 }
01189
01190
01191
01192
01193
01194 INT Find_Param_Num(WN *array_param,
01195 WN *call_nd)
01196 {
01197 WN *kid;
01198 for (INT kidno = 0; kidno < WN_kid_count(call_nd); kidno++) {
01199 kid = WN_kid(call_nd, kidno);
01200
01201 if (Is_Descendent(array_param, kid)) return kidno;
01202 }
01203
01204 return -1;
01205 }
01206
01207
01208 static WN* Lower_Single_Array_Dim (WN* array_wn) {
01209
01210 Is_True (WN_operator(array_wn) == OPR_ARRAY,
01211 ("Lower_Reshaped_Reference called on non-array\n"));
01212 INT ndims = WN_kid_count(array_wn) >> 1;
01213
01214 if (ndims > 1) {
01215
01216 WN* bounds_wn = NULL;
01217 for (INT i=0; i<ndims; i++) {
01218
01219
01220 WN* prod_wn = LWN_Copy_Tree(WN_array_index(array_wn, i),
01221 TRUE, LNO_Info_Map);
01222 LWN_Copy_Def_Use (WN_array_index(array_wn, i), prod_wn, Du_Mgr);
01223 TYPE_ID type = WN_rtype(prod_wn);
01224
01225 for (INT j=i+1; j<ndims; j++) {
01226 WN* dim_wn = LWN_Copy_Tree (WN_array_dim(array_wn, j),
01227 TRUE, LNO_Info_Map);
01228 LWN_Copy_Def_Use (WN_array_dim(array_wn, j), dim_wn, Du_Mgr);
01229 prod_wn = AWN_Mpy (type, prod_wn, dim_wn);
01230 }
01231 if (bounds_wn == NULL) bounds_wn = prod_wn;
01232 else {
01233 bounds_wn = AWN_Add (type, bounds_wn, prod_wn);
01234 }
01235 }
01236
01237 TYPE_ID type = WN_rtype(bounds_wn);
01238 OPCODE op = OPCODE_make_op(OPR_ARRAY, Pointer_type, MTYPE_V);
01239 WN* new_array_wn = WN_Create(op, 3);
01240 WN_array_base(new_array_wn) = LWN_Copy_Tree (WN_array_base(array_wn),
01241 TRUE, LNO_Info_Map);
01242 LWN_Copy_Def_Use (WN_array_base(array_wn),
01243 WN_array_base(new_array_wn),
01244 Du_Mgr);
01245 op = OPCODE_make_op(OPR_INTCONST, type, MTYPE_V);
01246 WN_array_dim(new_array_wn, 0) = WN_CreateIntconst (op, 1);
01247 WN_array_index(new_array_wn, 0) = bounds_wn;
01248 WN_element_size(new_array_wn) = WN_element_size(array_wn);
01249 LWN_Parentize(new_array_wn);
01250
01251 Replace_WN (array_wn, new_array_wn);
01252 LWN_Delete_Tree (array_wn);
01253 array_wn = new_array_wn;
01254 }
01255 return array_wn;
01256 }
01257
01258
01259
01260
01261
01262
01263
01264 static WN* Lower_Reshaped_Reference (WN* array_wn) {
01265
01266 Is_True (WN_operator(array_wn) == OPR_ARRAY,
01267 ("Lower_Reshaped_Reference called on non-array\n"));
01268 Is_True (WN_operator(WN_array_base(array_wn)) == OPR_ILOAD,
01269 ("Lower_Reshaped_Reference called on array with non-iload base\n"));
01270 Is_True (WN_operator(WN_kid0(WN_array_base(array_wn))) ==
01271 OPR_ARRAY,
01272 ("Lower_Reshaped_Reference called on array with non-array iload base\n"));
01273
01274 array_wn = Lower_Single_Array_Dim (array_wn);
01275 Lower_Single_Array_Dim (WN_kid0(WN_array_base(array_wn)));
01276 return array_wn;
01277 }
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294 static WN* Hoist_Expression (WN* expr_wn,
01295 WN* hoist_place,
01296 WN* hoist_place2 = NULL) {
01297 if (LWN_Get_Parent(expr_wn) == LWN_Get_Parent(hoist_place))
01298 return expr_wn;
01299
01300
01301
01302
01303 if (WN_operator(hoist_place) == OPR_DO_LOOP &&
01304 Do_Loop_Is_Mp(hoist_place)) {
01305
01306 WN* first_wn = WN_first(WN_do_body(hoist_place));
01307 if (first_wn) hoist_place = first_wn;
01308 else {
01309
01310
01311 hoist_place = WN_do_body(hoist_place);
01312 }
01313 }
01314
01315
01316 if (WN_operator(expr_wn) == OPR_ILOAD) {
01317 TYPE_ID expr_type = WN_rtype(expr_wn);
01318
01319 #if 0
01320 static INT counter = 0;
01321 char name[64];
01322 sprintf (name, "$hoist_%d", counter++);
01323 SYMBOL sym = Create_Local_Symbol (name, expr_type);
01324 #endif
01325
01326 #if 1
01327 WN* array_wn = WN_kid0(expr_wn);
01328 Is_True (WN_operator(array_wn) == OPR_ARRAY,
01329 ("Hoist_Expr ILOAD: expected an OPR_ARRAY"));
01330 WN* base_wn = WN_array_base(array_wn);
01331 Is_True (WN_operator(base_wn) == OPR_LDID ||
01332 WN_operator(base_wn) == OPR_LDA,
01333 ("Hoist_Expr ARRAY: expected an LDID/LDA as base"));
01334 ST* array_st = WN_st(base_wn);
01335 DISTR_INFO* dinfo = da_hash->Find(array_st);
01336 Is_True (dinfo && dinfo->IsReshaped(),
01337 ("Hoist_Expr ARRAY-BASE: expected a reshaped array"));
01338
01339 dinfo->Hoist_Proc_Init (expr_type);
01340 SYMBOL sym (dinfo->Hoist_Proc_Array(),
01341 dinfo->Hoist_Proc_Next_Offset(),
01342 expr_type);
01343
01344 #endif
01345
01346 Set_ST_pt_to_unique_mem(sym.St());
01347 Set_ST_pt_to_compiler_generated_mem(sym.St());
01348 WN* ldid_wn = AWN_LdidSym (&sym);
01349
01350
01351 WN_set_ty(ldid_wn, WN_ty(expr_wn));
01352 Set_TY_ptr_as_array(WN_ty(ldid_wn));
01353
01354
01355 Replace_WN (expr_wn, ldid_wn);
01356
01357
01358
01359
01360
01361
01362 WN *iwn = LWN_Get_Parent(ldid_wn);
01363 while (iwn) {
01364 OPERATOR opr = WN_operator(iwn);
01365 if (opr == OPR_ILOAD ||
01366 opr == OPR_ISTORE ||
01367 opr == OPR_PREFETCH ||
01368 opr == OPR_PREFETCHX ||
01369 opr == OPR_PARM ||
01370 (WN_io_item(iwn) == IOL_VAR)) {
01371 break;
01372 }
01373
01374 iwn = LWN_Get_Parent(iwn);
01375 }
01376
01377 if (iwn && (WN_operator(iwn) == OPR_ILOAD ||
01378 WN_operator(iwn) == OPR_ISTORE)) {
01379 dinfo->Hoist_Proc_Alias(iwn);
01380 }
01381 else if (iwn == NULL) {
01382 DevWarn ("Missing iload/istore/prefetch/parm for reshaped reference");
01383 }
01384
01385 WN* stid_wn = AWN_StidIntoSym (&sym, expr_wn);
01386 WN_set_ty(stid_wn, WN_ty(ldid_wn));
01387
01388 if (WN_operator(hoist_place) == OPR_BLOCK)
01389
01390 LWN_Insert_Block_Before(hoist_place, NULL, stid_wn);
01391 else
01392 LWN_Insert_Block_Before(LWN_Get_Parent(hoist_place),hoist_place,stid_wn);
01393 Copy_alias_info (Alias_Mgr, ldid_wn, stid_wn);
01394 Du_Mgr->Add_Def_Use(stid_wn, ldid_wn);
01395 Add_Pragma_To_MP_Region (stid_wn, sym.St(), 0, WN_PRAGMA_LOCAL);
01396
01397 if (hoist_place2) {
01398 WN* stid_wn2 = LWN_Copy_Tree (stid_wn, TRUE, LNO_Info_Map);
01399 Copy_alias_info (Alias_Mgr, stid_wn, stid_wn2);
01400 LWN_Copy_Def_Use (WN_kid0(stid_wn), WN_kid0(stid_wn2), Du_Mgr);
01401 Du_Mgr->Add_Def_Use (stid_wn2, ldid_wn);
01402 if (WN_operator(hoist_place2) == OPR_BLOCK)
01403
01404 LWN_Insert_Block_Before(hoist_place2, NULL, stid_wn2);
01405 else
01406
01407 LWN_Insert_Block_After(LWN_Get_Parent(hoist_place2),
01408 hoist_place2,
01409 stid_wn2);
01410 }
01411 return expr_wn;
01412 }
01413 else {
01414
01415 FmtAssert (hoist_place2 == NULL,
01416 ("Hoisting a non-ILOAD expression, unexpected hoist_place2"));
01417
01418 OPCODE op = OPCODE_make_op(OPR_EVAL, MTYPE_V, MTYPE_V);
01419 WN* eval_wn = WN_Create (op, 1);
01420 WN_kid0(eval_wn) = LWN_Copy_Tree (expr_wn, TRUE, LNO_Info_Map);
01421 LWN_Set_Parent (WN_kid0(eval_wn), eval_wn);
01422 LWN_Copy_Def_Use (expr_wn, WN_kid0(eval_wn), Du_Mgr);
01423 if (WN_operator(hoist_place) == OPR_BLOCK)
01424
01425 LWN_Insert_Block_Before(hoist_place, NULL, eval_wn);
01426 else
01427 LWN_Insert_Block_Before(LWN_Get_Parent(hoist_place),hoist_place,eval_wn);
01428 return WN_kid0(eval_wn);
01429 }
01430 }
01431
01432
01433
01434
01435
01436
01437
01438 extern void Try_Hoist_Expression (WN* expr_wn) {
01439 OPERATOR opr = WN_operator(expr_wn);
01440
01441
01442 if (opr == OPR_LDID ||
01443 opr == OPR_LDA ||
01444 opr == OPR_INTCONST ||
01445 opr == OPR_CONST)
01446 return;
01447
01448
01449 if (opr == OPR_ADD || opr == OPR_SUB) {
01450 OPERATOR opr1 = WN_operator(WN_kid0(expr_wn));
01451 OPERATOR opr2 = WN_operator(WN_kid1(expr_wn));
01452 if ((opr1 == OPR_INTCONST) &&
01453 (opr2 == OPR_INTCONST || opr2 == OPR_LDID))
01454 return;
01455 if ((opr2 == OPR_INTCONST) &&
01456 (opr1 == OPR_INTCONST || opr1 == OPR_LDID))
01457 return;
01458 }
01459
01460
01461 WN* hoist_place = Hoistable_Place (expr_wn, Du_Mgr);
01462 if (hoist_place) {
01463 WN* my_stmt = expr_wn;
01464 OPCODE opc = WN_opcode(my_stmt);
01465 while (!OPCODE_is_scf(opc) && !OPCODE_is_stmt(opc)) {
01466 my_stmt = LWN_Get_Parent(my_stmt);
01467 opc = WN_opcode(my_stmt);
01468 }
01469
01470 if (LWN_Get_Parent(my_stmt) != LWN_Get_Parent(hoist_place)) {
01471
01472 expr_wn = Hoist_Expression (expr_wn, hoist_place);
01473 }
01474 }
01475
01476
01477 for (INT i=0; i<WN_kid_count(expr_wn); i++) {
01478 Try_Hoist_Expression (WN_kid(expr_wn, i));
01479 }
01480 }
01481
01482
01483
01484
01485
01486
01487
01488
01489
01490
01491 static void Hoist_Reshaped_Reference (WN* array_wn) {
01492 INT i;
01493 INT ndim;
01494
01495 Is_True (WN_operator(array_wn) == OPR_ARRAY,
01496 ("Hoist_Reshaped_Reference called on non-array\n"));
01497 Is_True (WN_operator(WN_array_base(array_wn)) == OPR_ILOAD,
01498 ("Hoist_Reshaped_Reference called on array with non-iload base\n"));
01499 Is_True (WN_operator(WN_kid0(WN_array_base(array_wn))) ==
01500 OPR_ARRAY,
01501 ("Hoist_Reshaped_Reference called on array with non-array iload base\n"));
01502
01503
01504 ndim = WN_kid_count(array_wn) >> 1;
01505 for (i=0; i<ndim; i++) {
01506 WN* index_wn = WN_array_index (array_wn, i);
01507 Try_Hoist_Expression (index_wn);
01508 }
01509
01510
01511 WN* iload_wn = WN_array_base(array_wn);
01512 WN* hoist_place = Hoistable_Place (iload_wn, Du_Mgr);
01513 if (hoist_place &&
01514 (LWN_Get_Parent(iload_wn) != LWN_Get_Parent(hoist_place))) {
01515 FmtAssert (FALSE, ("Trying to hoist an ILOAD"));
01516 Hoist_Expression (iload_wn, hoist_place);
01517 return;
01518 }
01519
01520
01521 WN* base_wn = WN_kid0(iload_wn);
01522 WN* base_sym = WN_kid0(base_wn);
01523 Is_True (WN_operator(base_sym) == OPR_LDID ||
01524 WN_operator(base_sym) == OPR_LDA,
01525 ("Base of reshaped array not an LDID/LDA"));
01526 ndim = WN_kid_count(base_wn);
01527
01528 hoist_place = Initial_Hoist_Place (base_wn);
01529 Is_True (hoist_place, ("Initial_Hoist_Place returned NULL"));
01530 for (i=0; i<ndim; i++) {
01531 WN* this_hoist = Hoistable_Place (WN_kid(base_wn,i), Du_Mgr);
01532 if (this_hoist == NULL) break;
01533
01534 hoist_place = Hoist_Merge (hoist_place, this_hoist);
01535 }
01536
01537 if (i == ndim) {
01538
01539
01540 Hoist_Expression (iload_wn, hoist_place);
01541 }
01542 else {
01543
01544
01545
01546 hoist_place = LWN_Get_Parent(iload_wn);
01547 WN* hoist_place2 = NULL;
01548
01549 OPCODE opc = WN_opcode(hoist_place);
01550 while (!OPCODE_is_scf(opc) && !OPCODE_is_stmt(opc)) {
01551 hoist_place = LWN_Get_Parent(hoist_place);
01552 opc = WN_opcode(hoist_place);
01553 }
01554
01555 if (OPCODE_is_scf(opc)) {
01556
01557 switch (OPCODE_operator(opc)) {
01558 case OPR_DO_LOOP:
01559
01560 hoist_place2 = WN_last(WN_do_body(hoist_place));
01561 if (hoist_place2 == NULL)
01562 hoist_place2 = WN_do_body(hoist_place);
01563 break;
01564 case OPR_DO_WHILE:
01565 case OPR_WHILE_DO:
01566 hoist_place2 = WN_last(WN_while_body(hoist_place));
01567 if (hoist_place2 == NULL)
01568 hoist_place2 = WN_do_body(hoist_place);
01569 break;
01570 }
01571 }
01572 Hoist_Expression (iload_wn, hoist_place, hoist_place2);
01573 }
01574
01575
01576 ndim = WN_kid_count(base_wn) >> 1;
01577 for (i=0; i<ndim; i++) {
01578 WN* index_wn = WN_array_index (base_wn, i);
01579 Try_Hoist_Expression (index_wn);
01580 }
01581 }