00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 #define __STDC_LIMIT_MACROS
00041 #include <stdint.h>
00042 #ifdef USE_PCH
00043 #include "lno_pch.h"
00044 #endif // USE_PCH
00045 #pragma hdrstop
00046
00047
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
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127 #include <alloca.h>
00128 #include <sys/types.h>
00129 #include <ctype.h>
00130 #include <limits.h>
00131
00132 #include "pu_info.h"
00133 #include "lnopt_main.h"
00134 #include "config_targ.h"
00135 #include "cxx_memory.h"
00136 #include "erbe.h"
00137 #include "erglob.h"
00138 #include "strtab.h"
00139 #include "wn_pragmas.h"
00140 #include "lego_pragma.h"
00141 #include "lwn_util.h"
00142 #include "opt_du.h"
00143 #include "opt_alias_interface.h"
00144 #include "lego_util.h"
00145 #include "lego_opts.h"
00146 #include "lnoutils.h"
00147 #include "data_layout.h"
00148 #include "lego_affinity.h"
00149 #include "region_util.h"
00150 #include <alloca.h>
00151 #include "prompf.h"
00152 #include "anl_driver.h"
00153 #include "tile.h"
00154 #include "be_symtab.h"
00155
00156 #pragma weak New_Construct_Id
00157
00158
00159
00160
00161
00162
00163
00164 DA_HASH_TABLE *da_hash;
00165 DA_STACK *da_stack;
00166 DA_GLOBAL_HASH_TABLE *da_global;
00167
00168 extern void Read_Distr_Pragmas (WN* func_nd);
00169 TY_IDX DART_ptr_TY = (TY_IDX) NULL;
00170 extern ST *Find_Return_Registers(TYPE_ID type,PREG_NUM *rreg1,PREG_NUM *rreg2);
00171 extern WN* Read_Pragma_Redistribute (WN* pwn, BOOL gen_phase);
00172 extern WN* Numprocs (ST* array_st, INT dim, WN** block_wn);
00173 extern WN* Find_SCF_Inside(WN* parent_wn, OPCODE opc);
00174 extern ST* Create_Local_Array_ST(char* array_name, TY_IDX ty, INT num);
00175 extern void Move_Alloca (ST* st);
00176
00177
00178
00179
00180
00181
00182 static WN* Read_Pragma_Distribute_Reshape (WN* pwn);
00183 static WN* Read_Pragma_Affinity (WN* pwn);
00184 static WN* Read_Pragma_Page_Place (WN* pwn);
00185
00186 static void Read_Pragma_Data_Affinity (WN* do_wn, WN* rwn);
00187 static void Read_Pragma_Thread_Affinity (WN* pwn, WN* do_wn, WN* rwn);
00188 static void Do_Loop_Explicit_Affinity (WN* loop);
00189 static void Do_Loop_Implicit_Affinity (WN* loop);
00190 static WN* Thread_Affinity_Lower (WN* do_wn,
00191 SYMBOL* thread_sym,
00192 WN* stid_wn);
00193 static void Increment_Loop_Depths (WN* wn);
00194
00195 static DISTR_ARRAY* New_DACT (WN** pwn, ST* array_st, INT ndims);
00196 static BOOL Check_Expr (WN* expr_wn, SYMBOL* index_sym,
00197 INT32* coeff, INT32* constant);
00198 #ifdef _NEW_SYMTAB
00199 static ST* Lookup_Variable(char *nm, INT stab);
00200 #else
00201 static ST* Lookup_Variable(char *nm, SYMTAB *stab);
00202 #endif
00203 static ST* Create_Global_Variable (char* nm, TYPE_ID type, ST* array_st,
00204 INT32 i);
00205 static ST* Create_Local_Variable (const char* nm, TYPE_ID type, ST* array_st,
00206 INT32 i);
00207 static ST* New_DART (ST* array_st);
00208 static ST* Create_Common_Block (ST* array_st, INT numdim);
00209 static mBOOL Array_Bounds_Equiv(TY_IDX array_ty1, TY_IDX array_ty2, INT32 dim1,
00210 INT32 dim2);
00211 static mBOOL Lower_Bounds_Equiv(TY_IDX array_ty1, TY_IDX array_ty2, INT32 dim1,
00212 INT32 dim2);
00213 static mBOOL Upper_Bounds_Equiv(TY_IDX array_ty1, TY_IDX array_ty2, INT32 dim1,
00214 INT32 dim2);
00215 static mBOOL Strides_Equiv(TY_IDX array_ty1, TY_IDX array_ty2, INT32 dim1,
00216 INT32 dim2);
00217
00218
00219
00220
00221 typedef HASH_TABLE<ST*, BOOL> ST_HASH_TABLE;
00222 static ST_HASH_TABLE *dynamic_list = NULL;
00223
00224
00225
00226
00227
00228
00229
00230 extern BOOL Is_VLA (ST* st) {
00231 if (st &&
00232 ST_sclass(st) == SCLASS_AUTO &&
00233 TY_kind(ST_type(st)) == KIND_POINTER &&
00234 TY_kind(TY_pointed(ST_type(st))) == KIND_ARRAY &&
00235 TY_size(TY_pointed(ST_type(st))) == 0)
00236 return TRUE;
00237 return FALSE;
00238 }
00239
00240
00241
00242
00243
00244
00245
00246 void DISTR_DIM::Init_Block_Star (DISTRIBUTE_TYPE dt) {
00247 Is_True ((dt == DISTRIBUTE_BLOCK) || (dt == DISTRIBUTE_STAR),
00248 ("Distribute type must be BLOCK or STAR"));
00249 _distr_type = dt;
00250 return;
00251 }
00252
00253
00254
00255
00256
00257
00258 void DISTR_DIM::Init_Cyclic_Const (DISTRIBUTE_TYPE dt,
00259 INT64 const_val,
00260 WN* pwn) {
00261 Is_True (dt == DISTRIBUTE_CYCLIC_CONST,
00262 ("Distribute type must be CYCLIC_CONST"));
00263 _distr_type = dt;
00264 _chunksize.const_val = const_val;
00265 if (const_val < 1) {
00266 ErrMsgSrcpos(EC_LNO_Bad_Pragma_String, WN_Get_Linenum(pwn),
00267 WN_pragmas[WN_PRAGMA_DISTRIBUTE].name,
00268 "chunksize is 0 or -ve, assuming 1");
00269 _chunksize.const_val = 1;
00270 }
00271 return;
00272 }
00273
00274
00275
00276
00277
00278
00279 void DISTR_DIM::Init_Cyclic_Expr (DISTRIBUTE_TYPE dt, WN* val_wn) {
00280 Is_True (dt == DISTRIBUTE_CYCLIC_EXPR,
00281 ("Distribute type must be CYCLIC_EXPR"));
00282 _distr_type = dt;
00283 _chunk_val_wn = val_wn;
00284 return;
00285 }
00286
00287
00288
00289
00290
00291
00292
00293 BOOL DISTR_DIM::operator ==(const DISTR_DIM& test_dim) const
00294 {
00295 if (Distr_Type() != test_dim.Distr_Type()) return FALSE;
00296
00297 else if ((Distr_Type() == DISTRIBUTE_CYCLIC_CONST) &&
00298 (Chunk_Const_Val() != test_dim.Chunk_Const_Val())) return FALSE;
00299
00300 else if ((Distr_Type() == DISTRIBUTE_CYCLIC_EXPR) &&
00301 (Tree_Equiv(Chunk_WN(), test_dim.Chunk_WN()))) return FALSE;
00302
00303 return TRUE;
00304 }
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314 WN* DISTR_DIM::Chunksize () {
00315 WN* ldid_wn = NULL;
00316 switch (_distr_type) {
00317 case DISTRIBUTE_CYCLIC_EXPR:
00318 Is_True (_chunksize.sym,
00319 ("DISTR_DIM::Chunksize called before evaluating chunksize expr"));
00320
00321 ldid_wn = WN_CreateLdid (OPCODE_make_op(OPR_LDID, _chunksize.sym->Type,
00322 _chunksize.sym->Type),
00323 _chunksize.sym->WN_Offset(),
00324 _chunksize.sym->St(),
00325 Be_Type_Tbl(_chunksize.sym->Type));
00326 Copy_alias_info (Alias_Mgr, _chunk_stid_wn, ldid_wn);
00327 Du_Mgr->Add_Def_Use (_chunk_stid_wn, ldid_wn);
00328 break;
00329 case DISTRIBUTE_CYCLIC_CONST:
00330 if (_chunksize.const_val <= INT32_MAX)
00331 ldid_wn = LWN_Make_Icon (MTYPE_I4, _chunksize.const_val);
00332 else ldid_wn = LWN_Make_Icon (MTYPE_I8, _chunksize.const_val);
00333 break;
00334 default:
00335 FmtAssert (FALSE, ("Chunksize called on illegal distribution"));
00336 break;
00337 }
00338 return ldid_wn;
00339 }
00340
00341 void DISTR_DIM::Print (FILE* fp) const {
00342 fprintf (fp, "%s",
00343 (_distr_type == DISTRIBUTE_STAR) ? "STAR" :
00344 (_distr_type == DISTRIBUTE_BLOCK) ? "BLOCK" :
00345 (_distr_type == DISTRIBUTE_CYCLIC_EXPR) ? "CYCLIC_VAR" :
00346 (_distr_type == DISTRIBUTE_CYCLIC_CONST) ? "CYCLIC_CONST" :
00347 "unknown");
00348 if (_distr_type == DISTRIBUTE_CYCLIC_EXPR) {
00349 fprintf (fp, " (");
00350 _chunksize.sym->Print(fp);
00351 fprintf (fp, ")");
00352 }
00353 if (_distr_type == DISTRIBUTE_CYCLIC_CONST) {
00354 fprintf (fp, " (%lld)", _chunksize.const_val);
00355 }
00356 fprintf (fp, "\n");
00357 }
00358
00359
00360 INT DISTR_ARRAY::Num_Distr_Dim () {
00361 INT count = 0;
00362 Is_True (_dinfo, ("Num_Distr_Dim: _dinfo is NULL\n"));
00363 for (INT i=0; i<_dinfo->Num_Dim(); i++)
00364 if (_dims[i].Distr_Type() != DISTRIBUTE_STAR) count++;
00365 return count;
00366 }
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381 mBOOL
00382 DISTR_ARRAY::DACT_Equiv(DISTR_ARRAY *test_dact, INT32 my_dim, INT32 test_dim)
00383 {
00384 FmtAssert(test_dact, ("DACT_Equiv: test_dact is NULL\n"));
00385
00386 DISTR_INFO *test_dinfo = test_dact->Dinfo();
00387 Is_True(_dinfo && test_dinfo, ("DACT_Equiv: dinfo is NULL\n"));
00388
00389
00390 if (Num_Distr_Dim() != test_dact->Num_Distr_Dim()) return FALSE;
00391
00392 INT32 curr_pos=0, test_pos=0;
00393 INT i;
00394 for (i=0; i<=my_dim; i++) {
00395 DISTRIBUTE_TYPE dt = Get_Dim(i)->Distr_Type ();
00396 if (dt != DISTRIBUTE_STAR) curr_pos++;
00397 }
00398 for (i=0; i<=test_dim; i++) {
00399 DISTRIBUTE_TYPE dt = test_dact->Get_Dim(i)->Distr_Type ();
00400 if (dt != DISTRIBUTE_STAR) test_pos++;
00401 }
00402 if (curr_pos != test_pos) return FALSE;
00403
00404
00405 if (Has_Onto() && !test_dact->Has_Onto()) return FALSE;
00406 if (!Has_Onto() && test_dact->Has_Onto()) return FALSE;
00407 if (Has_Onto()) {
00408 curr_pos = 0; test_pos = 0;
00409 for (i = 0; i<Num_Distr_Dim(); i++) {
00410 while (Get_Dim(curr_pos)->Distr_Type() == DISTRIBUTE_STAR)
00411 curr_pos++;
00412 while (test_dact->Get_Dim(test_pos)->Distr_Type() == DISTRIBUTE_STAR)
00413 test_pos++;
00414 if (Onto(curr_pos) != test_dact->Onto(test_pos)) return FALSE;
00415 curr_pos++;
00416 test_pos++;
00417 }
00418 }
00419
00420 DISTR_DIM *curr_distr_dim = this->Get_Dim(my_dim);
00421 DISTR_DIM *test_distr_dim = test_dact->Get_Dim(test_dim);
00422
00423
00424
00425
00426
00427 WN* my_ubound = Array_Size_WN(my_dim);
00428 WN* test_ubound = test_dact->Array_Size_WN(test_dim);
00429 mBOOL retval = (Tree_Equiv(my_ubound, test_ubound) &&
00430 (*curr_distr_dim == *test_distr_dim));
00431 LWN_Delete_Tree (my_ubound);
00432 LWN_Delete_Tree (test_ubound);
00433 return retval;
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448 }
00449
00450
00451
00452
00453
00454
00455
00456 mBOOL DISTR_ARRAY::DACT_Equiv(DISTR_ARRAY *test_dact)
00457 {
00458 DISTR_INFO *test_dinfo = test_dact->Dinfo();
00459 Is_True(_dinfo && test_dinfo, ("DACT_Equiv: dinfo is NULL\n"));
00460
00461 if (test_dinfo->Num_Dim() != _dinfo->Num_Dim()) return FALSE;
00462
00463 for (INT i = 0; i < _dinfo->Num_Dim(); i++) {
00464 if (!DACT_Equiv(test_dact, i, i)) return FALSE;
00465 }
00466
00467 return TRUE;
00468 }
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478 void DISTR_ARRAY::Convert_Expr_To_Symbol () {
00479 INT ndims = _dinfo->Num_Dim();
00480 INT i;
00481 WN* first_wn = _first_pragma_wn;
00482 for (i=0; i<ndims; i++) {
00483 DISTR_DIM* dd = &(_dims[i]);
00484 if (dd->Distr_Type() != DISTRIBUTE_CYCLIC_EXPR) continue;
00485
00486 ST* local_st;
00487 SYMBOL* sym;
00488
00489 if (_dinfo->Small_Index()) {
00490 local_st = Create_Local_Variable("chunksize",
00491 MTYPE_I4,
00492 _dinfo->Array_ST(),
00493 i);
00494 sym = CXX_NEW (SYMBOL (local_st, 0, MTYPE_I4), LEGO_pool);
00495 }
00496 else {
00497 local_st = Create_Local_Variable("chunksize",
00498 MTYPE_I4,
00499 _dinfo->Array_ST(),
00500 i);
00501 sym = CXX_NEW (SYMBOL (local_st, 0, MTYPE_I8), LEGO_pool);
00502 }
00503
00504 WN* chunk_wn = dd->Chunk_WN();
00505 if ((WN_operator(chunk_wn) == OPR_INTCONST) &&
00506 (WN_const_val(chunk_wn) == 0)) {
00507
00508
00509 DISTR_INFO *dinfo = Dinfo();
00510 OPCODE call_op = OPCODE_make_op (OPR_CALL, MTYPE_V, MTYPE_V);
00511
00512 WN *call_wn = WN_Create(call_op, 1);
00513 WN *array_load_wn = dinfo->Load_Distr_Array ();
00514 if (LNO_Use_Parm) {
00515 WN* parm_wn = WN_CreateParm (Pointer_type, array_load_wn,
00516 Be_Type_Tbl(Pointer_type),
00517 WN_PARM_BY_VALUE);
00518 LWN_Set_Parent (array_load_wn, parm_wn);
00519 array_load_wn = parm_wn;
00520 }
00521 WN_kid(call_wn, 0) = array_load_wn;
00522 WN_st_idx(call_wn) = ST_st_idx(distr_st_entries[HT_Top]);
00523 Set_Runtime_Call_Side_Effects (call_wn);
00524 LWN_Set_Parent(array_load_wn, call_wn);
00525 LWN_Insert_Block_Before (NULL, first_wn, call_wn);
00526 WN_linenum(call_wn) = LWN_Get_Linenum(first_wn);
00527
00528
00529 PREG_NUM rreg1, rreg2;
00530 ST* rst = Find_Return_Registers (Pointer_type, &rreg1, &rreg2);
00531 FmtAssert(rreg1 != 0 && rreg2 == 0, ("Bad pointer type ret regs"));
00532
00533
00534
00535
00536 WN *ldid_wn = WN_CreateLdid (OPCODE_make_op(OPR_LDID,
00537 Pointer_type,
00538 Pointer_type),
00539 rreg1, rst, Be_Type_Tbl(Pointer_type));
00540 Create_alias (Alias_Mgr, ldid_wn);
00541 Du_Mgr->Add_Def_Use (call_wn, ldid_wn);
00542 OPCODE iload_op = OPCODE_make_op(OPR_ILOAD, MTYPE_I8, MTYPE_I8);
00543 WN* dart_k_wn = LWN_CreateIload
00544 (iload_op,
00545 dart_offset_distr_k+i*TY_size(distr_ty_entries[RT_dim_struct]),
00546 Be_Type_Tbl(MTYPE_I8),
00547 Make_Pointer_Type(Be_Type_Tbl(MTYPE_I8)),
00548 ldid_wn);
00549 LWN_Parentize (dart_k_wn);
00550 WN* stid_wn = LWN_CreateStid(OPCODE_make_op(OPR_STID, MTYPE_V,
00551 sym->Type),
00552 sym->WN_Offset(), sym->St(),
00553 Be_Type_Tbl(sym->Type),
00554 dart_k_wn);
00555 Create_local_alias (Alias_Mgr, stid_wn);
00556 LWN_Insert_Block_After (NULL, call_wn, stid_wn);
00557 dd->Evaluate_Chunk_Into_Symbol (sym, stid_wn);
00558 continue;
00559 }
00560
00561
00562 WN* expr_wn = LWN_Copy_Tree (dd->Chunk_WN());
00563 LWN_Copy_Def_Use (dd->Chunk_WN(), expr_wn, Du_Mgr);
00564 LWN_Parentize (expr_wn);
00565 WN* stid_wn = LWN_CreateStid (OPCODE_make_op(OPR_STID, MTYPE_V, sym->Type),
00566 sym->WN_Offset(), sym->St(),
00567 Be_Type_Tbl(sym->Type),
00568 expr_wn);
00569 Create_local_alias (Alias_Mgr, stid_wn);
00570 LWN_Insert_Block_Before (NULL, first_wn, stid_wn);
00571 dd->Evaluate_Chunk_Into_Symbol (sym, stid_wn);
00572 }
00573 }
00574
00575 void DISTR_ARRAY::Print (FILE* fp) const {
00576 INT i;
00577 fprintf (fp, "Distribution: \n");
00578 for (i=0; i<_dinfo->Num_Dim(); i++) {
00579 _dims[i].Print (fp);
00580 }
00581 }
00582
00583
00584
00585
00586
00587
00588
00589 #ifdef _NEW_SYMTAB
00590 static ST* Lookup_Variable(char *nm, INT stab)
00591 {
00592 ST *st;
00593 INT i;
00594
00595 FOREACH_SYMBOL(stab,st,i) {
00596 if ((ST_class(st) == CLASS_VAR) && (strcmp(ST_name(st), nm) == 0))
00597 return st;
00598 }
00599
00600 return NULL;
00601 }
00602 #else
00603 static ST* Lookup_Variable(char *nm, SYMTAB *stab)
00604 {
00605 ST *st;
00606
00607 FOR_ALL_SYMBOLS(stab, st) {
00608 if ((ST_class(st) == CLASS_VAR) && (strcmp(ST_name(st), nm) == 0))
00609 return st;
00610 }
00611
00612 return NULL;
00613 }
00614 #endif
00615
00616
00617
00618
00619
00620
00621 static ST* Create_Global_Variable (const char* nm, TYPE_ID type, ST* array_st,
00622 INT32 i) {
00623 char *name;
00624 if (ST_base(array_st) != array_st && ST_isCommon(array_st)) {
00625 name = (char*) alloca (strlen(ST_name(ST_base(array_st))) +
00626 strlen(ST_name(array_st)) + strlen(nm) + 10);
00627 sprintf (name, "_%s_%s_%s_%d", ST_name(ST_base(array_st)),
00628 ST_name(array_st), nm, i);
00629 } else {
00630 name = (char*) alloca (strlen(ST_name(array_st)) + strlen(nm) + 10);
00631 sprintf (name, "_%s_%s_%d", ST_name(array_st), nm, i);
00632 }
00633
00634
00635 #ifdef _NEW_SYMTAB
00636 ST *st = Lookup_Variable(name, GLOBAL_SYMTAB);
00637 #else
00638 ST *st = Lookup_Variable(name, Global_Symtab);
00639 #endif
00640 if (st) return st;
00641
00642
00643 st = New_ST(GLOBAL_SYMTAB);
00644 ST_Init (st,
00645 Save_Str(name),
00646 CLASS_VAR,
00647 ((ST_base_idx(array_st) != ST_st_idx(array_st)) ?
00648
00649 SCLASS_COMMON :
00650 ST_sclass(array_st)),
00651 EXPORT_PREEMPTIBLE,
00652 Be_Type_Tbl(type));
00653
00654 Allocate_Object (st);
00655 return st;
00656 }
00657
00658
00659
00660
00661
00662
00663 static ST* Create_Local_Variable (const char* nm, TYPE_ID type, ST* array_st,
00664 INT32 i) {
00665 char *name;
00666 if (ST_base(array_st) != array_st) {
00667 name = (char*) alloca (strlen(ST_name(ST_base(array_st))) +
00668 strlen(ST_name(array_st)) + strlen(nm) + 10);
00669 sprintf (name, "_%s_%s_%s_%d", ST_name(ST_base(array_st)),
00670 ST_name(array_st), nm, i);
00671 } else {
00672 name = (char*) alloca (strlen(ST_name(array_st)) + strlen(nm) + 10);
00673 sprintf (name, "_%s_%s_%d", ST_name(array_st), nm, i);
00674 }
00675
00676
00677
00678
00679
00680
00681
00682
00683 ST* st;
00684 st = New_ST(CURRENT_SYMTAB);
00685 ST_Init (st,
00686 Save_Str(name),
00687 CLASS_VAR,
00688 SCLASS_AUTO,
00689 EXPORT_LOCAL,
00690 Be_Type_Tbl(type));
00691 return st;
00692 }
00693
00694
00695
00696
00697
00698
00699
00700 static ST* New_DART (ST* array_st) {
00701 char *name;
00702 BOOL isglobal = ST_isGlobal(array_st);
00703 if (ST_isCommon(array_st)) {
00704 name = (char*) alloca (strlen(ST_name(ST_base(array_st))) +
00705 strlen(ST_name(array_st)) + 10);
00706 sprintf (name, "_%s_%s_dart", ST_name(ST_base(array_st)),
00707 ST_name(array_st));
00708 } else {
00709 char* tmps = ST_name(array_st);
00710 name = (char*) alloca (strlen(tmps) + 10);
00711 sprintf (name, "_%s_dart", tmps);
00712 }
00713
00714
00715
00716 ST* dart_st;
00717 if (isglobal) {
00718 #ifdef _NEW_SYMTAB
00719 dart_st = Lookup_Variable(name,
00720 isglobal ? GLOBAL_SYMTAB : CURRENT_SYMTAB);
00721 #else
00722 dart_st = Lookup_Variable(name,
00723 isglobal ? Global_Symtab : Current_Symtab);
00724 #endif
00725 if (dart_st) return dart_st;
00726 }
00727
00728
00729 dart_st = New_ST(isglobal ? GLOBAL_SYMTAB : CURRENT_SYMTAB);
00730 if (!isglobal) {
00731 ST_Init (dart_st,
00732 Save_Str(name),
00733 CLASS_VAR,
00734 SCLASS_AUTO,
00735 EXPORT_LOCAL,
00736 DART_ptr_TY);
00737 } else {
00738 ST_Init (dart_st,
00739 Save_Str(name),
00740 CLASS_VAR,
00741 ((ST_base_idx(array_st) != ST_st_idx(array_st)) ?
00742
00743 SCLASS_COMMON :
00744 ST_sclass(array_st)),
00745 EXPORT_PREEMPTIBLE,
00746 DART_ptr_TY);
00747 Allocate_Object(dart_st);
00748 }
00749
00750
00751 Set_ST_pt_to_unique_mem(dart_st);
00752 Set_ST_pt_to_compiler_generated_mem(dart_st);
00753 return dart_st;
00754 }
00755
00756
00757
00758
00759
00760
00761
00762 #ifdef _NEW_SYMTAB
00763 static ST* Create_Common_Block (ST* array_st, INT numdim) {
00764 Is_True (ST_isCommon(array_st),
00765 ("Create_Common_Block called with non-COMMON ST (%s)",
00766 ST_name(array_st)));
00767 char *name;
00768 name = CXX_NEW_ARRAY (char, (strlen(ST_name(ST_base(array_st)))+
00769 strlen(ST_name(array_st))+11),
00770 LEGO_pool);
00771
00772 ST *base_st = ST_base(array_st);
00773 Is_True (ST_class(base_st) == CLASS_VAR,
00774 ("Base of common (%s) not CLASS_VAR", ST_name(base_st)));
00775 Is_True (ST_sclass(base_st) == SCLASS_COMMON,
00776 ("Base of common (%s) not SCLASS_COMMON", ST_name(base_st)));
00777 Is_True (ST_level(base_st) == GLOBAL_SYMTAB &&
00778 ST_level(base_st) == GLOBAL_SYMTAB,
00779 ("COMMON Array %s or base %s not in global symtab",
00780 ST_name(array_st), ST_name(base_st)));
00781
00782
00783 TY_IDX array_ty_idx;
00784 TY& array_ty = New_TY(array_ty_idx);
00785 TY_Init (array_ty,
00786 numdim*TY_size(Be_Type_Tbl(MTYPE_I8)),
00787 KIND_ARRAY,
00788 MTYPE_UNKNOWN,
00789 Save_Str ("array_I8"));
00790
00791 ARB_HANDLE arb = New_ARB ();
00792 ARB_Init(arb,0,numdim-1,1);
00793 Set_ARB_first_dimen (arb);
00794 Set_ARB_last_dimen (arb);
00795 Set_TY_etype(array_ty,Be_Type_Tbl(MTYPE_I8));
00796
00797 Set_TY_align(array_ty_idx,8);
00798 Set_TY_arb(array_ty,arb);
00799
00800
00801 FLD_HANDLE fld = New_FLD();
00802 FLD_HANDLE first_fld = fld;
00803 FLD_Init(fld,Save_Str("dart"),DART_ptr_TY,0);
00804
00805
00806
00807 TY_IDX element_type = TY_AR_etype(Get_Array_Type(array_st));
00808 TY_IDX array_type =
00809 Make_Pointer_Type(Make_Pointer_Type(element_type));
00810 Set_TY_ptr_as_array(array_type);
00811 Set_TY_ptr_as_array(TY_pointed(array_type));
00812
00813 fld = New_FLD ();
00814 FLD_Init(fld,Save_Str("ST_name(array_st)"),array_type,
00815 TY_size(Be_Type_Tbl(MTYPE_I8)));
00816
00817 fld = New_FLD ();
00818 FLD_Init(fld,Save_Str("dimsize_array"),array_ty_idx,
00819 2*TY_size(Be_Type_Tbl(MTYPE_I8)));
00820
00821 fld = New_FLD ();
00822 FLD_Init(fld,Save_Str("numprocs_array"),array_ty_idx,
00823 TY_size(array_ty) + 2*TY_size(Be_Type_Tbl(MTYPE_I8)));
00824 Set_FLD_last_field(fld);
00825
00826
00827 char ty_name[64]; sprintf (ty_name, "BKblock_ty_%d", numdim);
00828 TY_IDX ty_idx;
00829 TY& struct_ty = New_TY(ty_idx);
00830 TY_Init (struct_ty,
00831 2*TY_size(array_ty)+2*TY_size(Be_Type_Tbl(MTYPE_I8)),
00832 KIND_STRUCT,
00833 MTYPE_M,
00834 Save_Str(ty_name));
00835 Set_TY_fld(struct_ty,first_fld);
00836 Set_TY_align(ty_idx,8);
00837
00838
00839
00840 sprintf (name, "_%s_%s_BKblock", ST_name(ST_base(array_st)),
00841 ST_name(array_st));
00842 ST *st = New_ST(GLOBAL_SYMTAB);
00843 ST_Init (st,
00844 Save_Str(name),
00845 CLASS_VAR,
00846 SCLASS_COMMON,
00847 EXPORT_PREEMPTIBLE,
00848 ty_idx);
00849 Set_ST_base(st,st);
00850
00851
00852
00853 Set_ST_is_const_var(st);
00854 Set_BE_ST_unknown_const(st);
00855
00856 CXX_DELETE_ARRAY (name, LEGO_pool);
00857 return st;
00858 }
00859
00860 #else // _NEW_SYMTAB
00861
00862 static ST* Create_Common_Block (ST* array_st, INT numdim) {
00863 Is_True (ST_isCommon(array_st),
00864 ("Create_Common_Block called with non-COMMON ST (%s)",
00865 ST_name(array_st)));
00866 char *name;
00867 name = CXX_NEW_ARRAY (char, (strlen(ST_name(ST_base(array_st)))+
00868 strlen(ST_name(array_st))+11),
00869 LEGO_pool);
00870
00871 ST *base_st = ST_base(array_st);
00872 Is_True (ST_class(base_st) == CLASS_VAR,
00873 ("Base of common (%s) not CLASS_VAR", ST_name(base_st)));
00874 Is_True (ST_sclass(base_st) == SCLASS_COMMON,
00875 ("Base of common (%s) not SCLASS_COMMON", ST_name(base_st)));
00876 Is_True (!ST_is_global(base_st) && !ST_is_global(array_st),
00877 ("Array %s or base %s not in local ST",
00878 ST_name(array_st), ST_name(base_st)));
00879
00880
00881 TY_IDX array_ty = New_TY(FALSE);
00882 TY_kind(array_ty) = KIND_ARRAY;
00883 TY_btype(array_ty) = MTYPE_M;
00884
00885 ARI *ari = New_ARI (1, FALSE);
00886 ARI_etype(ari) = Be_Type_Tbl(MTYPE_I8);
00887 ARI_const_zofst(ari) = TRUE;
00888 ARI_zofst_val(ari) = 0;
00889 ARB_const_lbnd(ARI_bnd(ari,0)) = TRUE;
00890 ARB_lbnd_val(ARI_bnd(ari,0)) = 0;
00891 ARB_const_ubnd(ARI_bnd(ari,0)) = TRUE;
00892 ARB_ubnd_val(ARI_bnd(ari,0)) = numdim-1;
00893 ARB_const_stride(ARI_bnd(ari,0)) = TRUE;
00894 ARB_stride_val(ARI_bnd(ari,0)) = 1;
00895 TY_size(array_ty) = numdim*TY_size(Be_Type_Tbl(MTYPE_I8));
00896 TY_align(array_ty) = 8;
00897 TY_name(array_ty) = Save_Str ("array_I8");
00898 TY_arinfo(array_ty) = ari;
00899 Enter_TY (array_ty);
00900
00901
00902 FLD *field, *next;
00903 field = New_FLD (4, FALSE);
00904 FLD_name(field) = Save_Str("dart");
00905 FLD_type(field) = DART_ptr_TY;
00906 FLD_ofst(field) = 0;
00907 FLD_flags(field) = 0;
00908
00909 next = FLD_next(field);
00910 TY_IDX element_type = TY_AR_etype(Get_Array_Type(array_st));
00911 TY_IDX array_type =
00912 Make_Pointer_Type(Make_Pointer_Type(element_type));
00913 Set_TY_ptr_as_array(array_type);
00914 Set_TY_ptr_as_array(TY_pointed(array_type));
00915 FLD_type(next) = array_type;
00916 FLD_name(next) = Save_Str(ST_name(array_st));
00917
00918
00919
00920 FLD_ofst(next) = TY_size(Be_Type_Tbl(MTYPE_I8));
00921 FLD_flags(next) = 0;
00922
00923 next = FLD_next(next);
00924 FLD_name(next) = Save_Str("dimsize_array");
00925 FLD_type(next) = array_ty;
00926
00927 FLD_ofst(next) = 2*TY_size(Be_Type_Tbl(MTYPE_I8));
00928 FLD_flags(next) = 0;
00929
00930 next = FLD_next(next);
00931 FLD_name(next) = Save_Str("numprocs_array");
00932 FLD_type(next) = array_ty;
00933 FLD_ofst(next) = TY_size(array_ty) + 2*TY_size(Be_Type_Tbl(MTYPE_I8));
00934 FLD_flags(next) = 0;
00935
00936
00937 TY_IDX struct_ty = New_TY(FALSE);
00938 TY_kind(struct_ty) = KIND_STRUCT;
00939 TY_btype(struct_ty) = MTYPE_M;
00940 char ty_name[64]; sprintf (ty_name, "BKblock_ty_%d", numdim);
00941 TY_name(struct_ty) = Save_Str(ty_name);
00942 TY_flist(struct_ty) = field;
00943 TY_size(struct_ty) = 2*TY_size(array_ty)+2*TY_size(Be_Type_Tbl(MTYPE_I8));
00944 TY_align(struct_ty) = 8;
00945 Enter_TY(struct_ty);
00946
00947
00948
00949 sprintf (name, "_%s_%s_BKblock", ST_name(ST_base(array_st)),
00950 ST_name(array_st));
00951 ST *st = New_ST(CURRENT_SYMTAB);
00952 ST_Init (st,
00953 Save_Str(name),
00954 CLASS_VAR,
00955 SCLASS_COMMON,
00956 EXPORT_PREEMPTIBLE,
00957 struct_ty);
00958 ST_base(st) = st;
00959
00960
00961
00962 Set_ST_is_const_var(st);
00963
00964 CXX_DELETE_ARRAY (name, LEGO_pool);
00965 return st;
00966 }
00967 #endif
00968
00969
00970
00971
00972
00973
00974
00975 mBOOL Upper_Bounds_Equiv(TY_IDX array_ty1, TY_IDX array_ty2,
00976 INT32 dim1, INT32 dim2)
00977 {
00978
00979 if (TY_AR_const_ubnd(array_ty1, dim1) &&
00980 TY_AR_const_ubnd(array_ty2, dim2)) {
00981
00982 return (TY_AR_ubnd_val(array_ty1, dim1) ==
00983 TY_AR_ubnd_val(array_ty2, dim2));
00984
00985 } else if (!TY_AR_const_ubnd(array_ty1, dim1) &&
00986 !TY_AR_const_ubnd(array_ty2, dim2)) {
00987
00988 return (TY_AR_ubnd_var(array_ty1, dim1) ==
00989 TY_AR_ubnd_var(array_ty2, dim2));
00990 }
00991
00992 return FALSE;
00993 }
00994
00995
00996 mBOOL Lower_Bounds_Equiv(TY_IDX array_ty1, TY_IDX array_ty2, INT32 dim1,
00997 INT32 dim2)
00998 {
00999
01000 if (TY_AR_const_lbnd(array_ty1, dim1) &&
01001 TY_AR_const_lbnd(array_ty2, dim2)) {
01002
01003 return (TY_AR_lbnd_val(array_ty1, dim1) ==
01004 TY_AR_lbnd_val(array_ty2, dim2));
01005
01006 } else if (!TY_AR_const_lbnd(array_ty1, dim1) &&
01007 !TY_AR_const_lbnd(array_ty2, dim2)) {
01008
01009 return (TY_AR_lbnd_var(array_ty1, dim1) ==
01010 TY_AR_lbnd_var(array_ty2, dim2));
01011 }
01012
01013 return FALSE;
01014 }
01015
01016 mBOOL Strides_Equiv(TY_IDX array_ty1, TY_IDX array_ty2, INT32 dim1, INT32 dim2)
01017 {
01018
01019 if (TY_AR_const_stride(array_ty1, dim1) &&
01020 TY_AR_const_stride(array_ty2, dim2)) {
01021
01022 return (TY_AR_stride_val(array_ty1,dim1) ==
01023 TY_AR_stride_val(array_ty2,dim2));
01024
01025 } else if (!TY_AR_const_stride(array_ty1, dim1) &&
01026 !TY_AR_const_stride(array_ty2, dim2)) {
01027
01028 return (TY_AR_stride_var(array_ty1, dim1) ==
01029 TY_AR_stride_var(array_ty2, dim2));
01030 }
01031
01032 return FALSE;
01033 }
01034
01035
01036 mBOOL Array_Bounds_Equiv(TY_IDX array_ty1, TY_IDX array_ty2, INT32 dim1,
01037 INT32 dim2)
01038 {
01039 if (array_ty1 == array_ty2) return TRUE;
01040
01041 return (Lower_Bounds_Equiv(array_ty1, array_ty2, dim1, dim2) &&
01042 Upper_Bounds_Equiv(array_ty1, array_ty2, dim1, dim2) &&
01043 Strides_Equiv(array_ty1, array_ty2, dim1, dim2));
01044
01045 }
01046
01047
01048 DISTR_INFO::DISTR_INFO (mBOOL isreshaped, INT numdim, SYMBOL* array) {
01049 INT i;
01050 _isreshaped = isreshaped;
01051
01052 if (_isreshaped) {
01053 Note_Invalid_Based_Symbol(array->St());
01054 }
01055 _isdynamic = FALSE;
01056 _num_dim = numdim;
01057 _array = array;
01058 _dart_st = NULL;
01059 _dart_ptr_alias_wn = NULL;
01060 _dart_wn.Set_Mem_Pool(LEGO_pool);
01061
01062 _ec_dart_def_wn = NULL;
01063 _ec_dart_ptr_wn = NULL;
01064
01065 _array_alias_wn = NULL;
01066 _array_ptr_alias_wn = NULL;
01067 _array_def_wn = NULL;
01068
01069 _dimsize = CXX_NEW_ARRAY (SYMBOL*, numdim, LEGO_pool);
01070 _numprocs = CXX_NEW_ARRAY (SYMBOL*, numdim, LEGO_pool);
01071 _array_common = NULL;
01072 _array_common_alias_wn = NULL;
01073
01074 ST* array_st = array->St();
01075 _orig_ty = Get_Array_Type(array_st);
01076
01077 _small_index = FALSE;
01078
01079
01080 INT small_index_size = TY_size(Be_Type_Tbl(MTYPE_U4));
01081 if (TY_size(Be_Type_Tbl(Pointer_type)) <= small_index_size) {
01082
01083 _small_index = TRUE;
01084 }
01085 else {
01086
01087 INT ndims = TY_AR_ndims(_orig_ty);
01088 INT i;
01089 for (i=0; i<ndims; i++) {
01090
01091
01092 if (TY_AR_const_lbnd(_orig_ty, i) && TY_AR_const_ubnd(_orig_ty, i)) {
01093 INT64 size = TY_AR_ubnd_val(_orig_ty,i) - TY_AR_lbnd_val(_orig_ty,i);
01094 if (size > INT32_MAX) break;
01095 else continue;
01096 }
01097
01098
01099 if (!TY_AR_const_lbnd(_orig_ty, i)) {
01100 #ifdef _NEW_SYMTAB
01101 ST* dim_var = ST_ptr(TY_AR_lbnd_var(_orig_ty, i));
01102 TYPE_ID dim_type = ST_type(dim_var);
01103 #else
01104 WN *dim_wn = TY_AR_lbnd_tree(_orig_ty,i);
01105 TY *dim_type = Be_Type_Tbl(WN_rtype(dim_wn));
01106 #endif
01107 if (TY_size(dim_type) <= small_index_size)
01108 continue;
01109 else break;
01110 }
01111 if (!TY_AR_const_ubnd(_orig_ty, i)) {
01112 #ifdef _NEW_SYMTAB
01113 ST* dim_var = ST_ptr(TY_AR_ubnd_var(_orig_ty, i));
01114 TYPE_ID dim_type = ST_type(dim_var);
01115 #else
01116 WN* dim_wn = TY_AR_ubnd_tree(_orig_ty, i);
01117 TY* dim_type = Be_Type_Tbl(WN_rtype(dim_wn));
01118 #endif
01119 if (TY_size(dim_type) <= small_index_size)
01120 continue;
01121 else break;
01122 }
01123 }
01124
01125 if (i == ndims) _small_index = TRUE;
01126 }
01127
01128 _hoist_proc_array = NULL;
01129 _hoist_proc_index = -1;
01130 _hoist_proc_alias = NULL;
01131 _buddy_dinfo = NULL;
01132
01133
01134 ST* base_st = NULL;
01135 if (ST_isCommon(array_st)) {
01136 base_st = Create_Common_Block (array_st, numdim);
01137
01138 char name[64];
01139 char* tmps = ST_name(array_st);
01140 sprintf (name, "_%s_dart", ((strlen(tmps) < 50) ? tmps : "LongName"));
01141
01142 #ifdef _NEW_SYMTAB
01143 _dart_st = New_ST(GLOBAL_SYMTAB);
01144 #else
01145 _dart_st = New_ST(CURRENT_SYMTAB);
01146 #endif
01147 ST_Init (_dart_st,
01148 Save_Str(name),
01149 CLASS_VAR,
01150 SCLASS_COMMON,
01151 EXPORT_LOCAL,
01152 DART_ptr_TY);
01153 Set_ST_base_idx(_dart_st,ST_st_idx(base_st));
01154 Set_ST_ofst(_dart_st,0);
01155 Set_ST_pt_to_unique_mem(_dart_st);
01156 Set_ST_pt_to_compiler_generated_mem(_dart_st);
01157
01158 if (_isreshaped) {
01159 TY_IDX element_type = TY_AR_etype(Get_Array_Type(array_st));
01160 TY_IDX array_type =
01161 Make_Pointer_Type(Make_Pointer_Type(element_type));
01162 Set_TY_ptr_as_array(array_type);
01163 Set_TY_ptr_as_array(TY_pointed(array_type));
01164 sprintf (name, "_%s_array", ((strlen(tmps) < 50) ? tmps : "LongName"));
01165
01166 #ifdef _NEW_SYMTAB
01167 ST* array_common_st = New_ST(GLOBAL_SYMTAB);
01168 #else
01169 ST* array_common_st = New_ST(CURRENT_SYMTAB);
01170 #endif
01171 ST_Init (array_common_st,
01172 Save_Str(name),
01173 CLASS_VAR,
01174 SCLASS_COMMON,
01175 EXPORT_LOCAL,
01176 array_type);
01177 Set_ST_base_idx(array_common_st,ST_st_idx(base_st));
01178 Set_ST_ofst(array_common_st,TY_size(Be_Type_Tbl(MTYPE_I8)));
01179 Set_ST_pt_to_unique_mem(array_common_st);
01180 Set_ST_pt_to_compiler_generated_mem(array_common_st);
01181 Set_ST_is_const_var(array_common_st);
01182 Set_BE_ST_unknown_const(array_common_st);
01183
01184 _array_common = CXX_NEW (SYMBOL(array_common_st, 0,
01185 Pointer_type), LEGO_pool);
01186 Set_ST_is_const_var(_dart_st);
01187 Set_BE_ST_unknown_const(_dart_st);
01188 }
01189 }
01190 else _dart_st = New_DART(array_st);
01191
01192
01193 for (i=0; i<numdim; i++) {
01194 switch (ST_Var_Kind(array_st)) {
01195 case var_global:
01196 {
01197 ST* numprocs_st = Create_Global_Variable ("numprocs", MTYPE_I8,
01198 array_st, i);
01199 SYMBOL *numprocs_sym = CXX_NEW(SYMBOL(numprocs_st,0,MTYPE_I8),
01200 LEGO_pool);
01201 _numprocs[i] = numprocs_sym;
01202 ST* dimsize_st = Create_Global_Variable ("dimsize", MTYPE_I8,
01203 array_st, i);
01204 SYMBOL *dimsize_sym = CXX_NEW (SYMBOL(dimsize_st,0, MTYPE_I8),
01205 LEGO_pool);
01206 _dimsize[i] = dimsize_sym;
01207 break;
01208 }
01209 case var_local:
01210 case var_formal:
01211 {
01212
01213
01214
01215 ST* numprocs_st = Create_Local_Variable ("numprocs", MTYPE_I8,
01216 array_st, i);
01217 SYMBOL *numprocs_sym = CXX_NEW(SYMBOL(numprocs_st,0,MTYPE_I8),
01218 LEGO_pool);
01219 _numprocs[i] = numprocs_sym;
01220 ST* dimsize_st = Create_Local_Variable ("dimsize", MTYPE_I8,
01221 array_st, i);
01222 SYMBOL *dimsize_sym = CXX_NEW (SYMBOL(dimsize_st,0, MTYPE_I8),
01223 LEGO_pool);
01224 _dimsize[i] = dimsize_sym;
01225 break;
01226 }
01227 case var_common:
01228 {
01229 char name[64];
01230 sprintf (name, "_%s_dart_dimsize_%d", ((strlen(ST_name(array_st)) < 40)
01231 ? ST_name(array_st) :
01232 "LongName"), i);
01233 #ifdef _NEW_SYMTAB
01234 ST* st = New_ST(GLOBAL_SYMTAB);
01235 #else
01236 ST* st = New_ST(CURRENT_SYMTAB);
01237 #endif
01238 ST_Init (st,
01239 Save_Str(name),
01240 CLASS_VAR,
01241 SCLASS_COMMON,
01242 EXPORT_LOCAL,
01243 Be_Type_Tbl(MTYPE_I8));
01244 Set_ST_base(st,base_st);
01245 Set_ST_ofst(st,(2*TY_size(Be_Type_Tbl(MTYPE_I8)) +
01246 (i*TY_size(Be_Type_Tbl(MTYPE_I8)))));
01247 Set_ST_is_const_var(st);
01248 Set_BE_ST_unknown_const(st);
01249 _dimsize[i] = CXX_NEW(SYMBOL(st, 0, MTYPE_I8), LEGO_pool);
01250
01251 sprintf (name, "_%s_dart_numprocs_%d",((strlen(ST_name(array_st)) < 40)
01252 ? ST_name(array_st) :
01253 "LongName"), i);
01254 #ifdef _NEW_SYMTAB
01255 st = New_ST(GLOBAL_SYMTAB);
01256 #else
01257 st = New_ST(CURRENT_SYMTAB);
01258 #endif
01259 ST_Init (st,
01260 Save_Str(name),
01261 CLASS_VAR,
01262 SCLASS_COMMON,
01263 EXPORT_LOCAL,
01264 Be_Type_Tbl(MTYPE_I8));
01265 Set_ST_base(st,base_st);
01266 Set_ST_ofst(st,(2*TY_size(Be_Type_Tbl(MTYPE_I8)) +
01267 ((numdim+i)*TY_size(Be_Type_Tbl(MTYPE_I8)))));
01268 Set_ST_is_const_var(st);
01269 Set_BE_ST_unknown_const(st);
01270 _numprocs[i] = CXX_NEW(SYMBOL(st, 0, MTYPE_I8), LEGO_pool);
01271
01272 break;
01273 }
01274 }
01275 }
01276
01277 _dimsize_wn = CXX_NEW_ARRAY (DYN_ARRAY<WN*>, numdim, LEGO_pool);
01278 _numprocs_wn = CXX_NEW_ARRAY (DYN_ARRAY<WN*>, numdim, LEGO_pool);
01279 for (i=0; i<numdim; i++) {
01280 _dimsize_wn[i].Set_Mem_Pool(LEGO_pool);
01281 _numprocs_wn[i].Set_Mem_Pool(LEGO_pool);
01282 }
01283
01284 _dact_da.Set_Mem_Pool (LEGO_pool);
01285 _redistr_da.Set_Mem_Pool (LEGO_pool);
01286 _gen_redistr_da.Set_Mem_Pool (LEGO_pool);
01287 }
01288
01289 DISTR_INFO::~DISTR_INFO () {
01290 INT i;
01291
01292 ST* array_st = _array->St();
01293 for (i=0; i<_num_dim; i++) {
01294 Is_True (_dimsize[i], ("_dimsize is NULL"));
01295 CXX_DELETE (_dimsize[i], LEGO_pool);
01296 Is_True (_numprocs[i], ("_numprocs is NULL"));
01297 CXX_DELETE (_numprocs[i], LEGO_pool);
01298 }
01299 CXX_DELETE_ARRAY (_dimsize, LEGO_pool);
01300 CXX_DELETE_ARRAY (_numprocs, LEGO_pool);
01301
01302
01303 if (_hoist_proc_array) {
01304 FmtAssert (_hoist_proc_index >= 0,
01305 ("Hoist-proc-array has zero elements\n"));
01306 TY_IDX ty_idx = ST_type(_hoist_proc_array);
01307 Set_TY_size(ty_idx,(_hoist_proc_index+1) * TY_size(TY_AR_etype(ty_idx)));
01308 Set_TY_AR_ubnd_val(ty_idx,TY_AR_ndims(ty_idx)-1,_hoist_proc_index);
01309 }
01310
01311 for (i=0; i<_num_dim; i++) {
01312
01313 WN* wn;
01314 if (_dimsize_wn[i].Elements() == 1) {
01315 wn = _dimsize_wn[i][0];
01316 if (WN_operator(wn) == OPR_LDID)
01317 LWN_Delete_Tree (wn);
01318 }
01319 if (_numprocs_wn[i].Elements() == 1) {
01320 wn = _numprocs_wn[i][0];
01321 if (WN_operator(wn) == OPR_LDID)
01322 LWN_Delete_Tree (wn);
01323 }
01324 }
01325 if (_array_alias_wn) LWN_Delete_Tree(_array_alias_wn);
01326 if (_array_ptr_alias_wn) LWN_Delete_Tree(_array_ptr_alias_wn);
01327 CXX_DELETE_ARRAY (_dimsize_wn, LEGO_pool);
01328 CXX_DELETE_ARRAY (_numprocs_wn, LEGO_pool);
01329
01330 CXX_DELETE (_array, LEGO_pool);
01331 for (i=0; i<_dact_da.Elements(); i++)
01332 CXX_DELETE (_dact_da[i], LEGO_pool);
01333 for (i=0; i<_redistr_da.Elements(); i++)
01334 CXX_DELETE (_redistr_da[i], LEGO_pool);
01335 for (i=0; i<_gen_redistr_da.Elements(); i++)
01336 CXX_DELETE (_gen_redistr_da[i], LEGO_pool);
01337 }
01338
01339 void DISTR_INFO::Hoist_Proc_Init (TYPE_ID type) {
01340 if (_hoist_proc_array == NULL) {
01341 Is_True (_hoist_proc_index == -1,
01342 ("Hoist-array is NULL, but index is not 0"));
01343 char *name = (char*) alloca (strlen(ST_name(Array_ST()))+10);
01344 sprintf (name, "$%s_hoist", ST_name(Array_ST()));
01345 _hoist_proc_array = Create_Local_Array_ST (name, Be_Type_Tbl(type), 1);
01346 }
01347 }
01348
01349
01350
01351
01352
01353
01354
01355 void DISTR_INFO::Numprocs_Ldid (INT dim, WN* ldid_wn) {
01356 if (_numprocs_wn[dim].Elements() == 0) {
01357
01358
01359 if (ST_isLocal(WN_st(ldid_wn)))
01360 Create_local_alias (Alias_Mgr, ldid_wn);
01361 else Create_global_alias (Alias_Mgr, WN_st(ldid_wn), ldid_wn, NULL);
01362 WN* copy_wn = LWN_Copy_Tree(ldid_wn);
01363 _numprocs_wn[dim][_numprocs_wn[dim].Newidx()] = copy_wn;
01364 Copy_alias_info (Alias_Mgr, ldid_wn, copy_wn);
01365 Du_Mgr->Add_Def_Use (Current_Func_Node, ldid_wn);
01366 return;
01367 }
01368
01369 WN* wn = _numprocs_wn[dim][_numprocs_wn[dim].Lastidx()];
01370 if (WN_operator(wn) == OPR_LDID) {
01371
01372 FmtAssert (_numprocs_wn[dim].Elements() == 1,
01373 ("Numprocs_Ldid: why are we storing more than 1 ldid?"));
01374 Copy_alias_info (Alias_Mgr, wn, ldid_wn);
01375 Du_Mgr->Add_Def_Use (Current_Func_Node, ldid_wn);
01376 return;
01377 }
01378
01379 Copy_alias_info (Alias_Mgr, wn, ldid_wn);
01380
01381 for (INT i=0; i<_numprocs_wn[dim].Elements(); i++) {
01382 wn = _numprocs_wn[dim][i];
01383 FmtAssert (WN_operator(wn) == OPR_STID,
01384 ("Numprocs_Ldid: stored wn neither ldid nor stid"));
01385 Du_Mgr->Add_Def_Use (wn, ldid_wn);
01386 }
01387 if (!ST_isLocal(_numprocs[dim]->St())) {
01388
01389 Du_Mgr->Add_Def_Use (Current_Func_Node, ldid_wn);
01390 }
01391 }
01392
01393
01394
01395
01396
01397
01398
01399 void DISTR_INFO::Numprocs_Stid (INT dim, WN* stid_wn) {
01400 if (_numprocs_wn[dim].Elements() == 0) {
01401
01402 _numprocs_wn[dim][_numprocs_wn[dim].Newidx()] = stid_wn;
01403 if (ST_isLocal(WN_st(stid_wn)))
01404 Create_local_alias (Alias_Mgr, stid_wn);
01405 else Create_global_alias (Alias_Mgr, WN_st(stid_wn), stid_wn, NULL);
01406 return;
01407 }
01408
01409 WN* wn = _numprocs_wn[dim][_numprocs_wn[dim].Lastidx()];
01410 if (WN_operator(wn) == OPR_LDID) {
01411
01412 FmtAssert (_numprocs_wn[dim].Elements() == 1,
01413 ("Numprocs_Stid: why are we storing more than 1 ldid?"));
01414 Copy_alias_info (Alias_Mgr, wn, stid_wn);
01415
01416 LWN_Delete_Tree (wn);
01417 _numprocs_wn[dim][_numprocs_wn[dim].Lastidx()] = stid_wn;
01418 USE_LIST* use_list = Du_Mgr->Du_Get_Use(Current_Func_Node);
01419 USE_LIST_ITER use_iter(use_list);
01420 DU_NODE* node;
01421
01422
01423 for (node = use_iter.First(); !use_iter.Is_Empty();
01424 node = use_iter.Next()) {
01425 WN* uwn = node->Wn();
01426 if (WN_operator(uwn) == OPR_LDID) {
01427 SYMBOL sym(uwn);
01428 if (sym == *(_numprocs[dim])) {
01429
01430 if (!ST_isLocal(_numprocs[dim]->St()))
01431
01432 Du_Mgr->Delete_Def_Use (Current_Func_Node, uwn);
01433 Du_Mgr->Add_Def_Use (stid_wn, uwn);
01434 Du_Mgr->Ud_Get_Def(uwn)->Set_loop_stmt(NULL);
01435 }
01436 }
01437 }
01438 return;
01439 }
01440
01441 FmtAssert (WN_operator(wn) == OPR_STID,
01442 ("Numprocs_Stid: Expected stored STID"));
01443 _numprocs_wn[dim][_numprocs_wn[dim].Newidx()] = stid_wn;
01444 Copy_alias_info (Alias_Mgr, wn, stid_wn);
01445 USE_LIST* use_list = Du_Mgr->Du_Get_Use(wn);
01446 USE_LIST_ITER use_iter(use_list);
01447 DU_NODE* node;
01448
01449 for (node = use_iter.First(); !use_iter.Is_Empty();
01450 node = use_iter.Next()) {
01451 WN* uwn = node->Wn();
01452 if (WN_operator(uwn) == OPR_LDID) {
01453 SYMBOL sym(uwn);
01454 if (sym == *(_numprocs[dim])) {
01455
01456 Du_Mgr->Add_Def_Use (stid_wn, uwn);
01457 Du_Mgr->Ud_Get_Def(uwn)->Set_loop_stmt(NULL);
01458 }
01459 }
01460 }
01461 }
01462
01463
01464
01465
01466
01467
01468 WN* DISTR_INFO::Numprocs (INT dim) {
01469 if (_buddy_dinfo) return _buddy_dinfo->Numprocs(dim);
01470
01471 SYMBOL* numprocs = _numprocs[dim];
01472 WN* ldid_wn = NULL;
01473
01474 Is_True(numprocs, ("Numprocs is NULL ST(%s)\n", ST_name(Array_ST())));
01475
01476
01477
01478 OPCODE ldid_op = OPCODE_make_op(OPR_LDID, MTYPE_I4, MTYPE_I8);
01479 ldid_wn = WN_CreateLdid (ldid_op, numprocs->WN_Offset(),
01480 numprocs->St(), Be_Type_Tbl(MTYPE_I4));
01481 Numprocs_Ldid(dim, ldid_wn);
01482 return ldid_wn;
01483 }
01484
01485
01486
01487
01488
01489
01490
01491
01492
01493
01494 extern WN* Numprocs (ST* array_st, INT dim, BOOL inside_loop, WN** block_wn) {
01495
01496 OPCODE call_op = OPCODE_make_op (OPR_CALL, MTYPE_V, MTYPE_V);
01497 WN *call_wn = WN_Create(call_op, 1);
01498 WN* array_load_wn = Load_Distr_Array (array_st);
01499 if (LNO_Use_Parm) {
01500 WN* parm_wn = WN_CreateParm (Pointer_type, array_load_wn,
01501 Be_Type_Tbl(Pointer_type),
01502 WN_PARM_BY_VALUE);
01503 LWN_Set_Parent (array_load_wn, parm_wn);
01504 array_load_wn = parm_wn;
01505 }
01506 WN_kid(call_wn, 0) = array_load_wn;
01507 WN_st_idx(call_wn) = ST_st_idx(ST_is_reshaped(array_st) ?
01508 distr_st_entries[HT_Top] :
01509 distr_st_entries[HT_Check]);
01510 Set_Runtime_Call_Side_Effects (call_wn);
01511 LWN_Set_Parent(array_load_wn, call_wn);
01512 if (inside_loop)
01513 Array_Dependence_Graph->Add_Vertex(call_wn);
01514
01515
01516 PREG_NUM rreg1, rreg2;
01517 ST* rst = Find_Return_Registers (Pointer_type, &rreg1, &rreg2);
01518 FmtAssert(rreg1 != 0 && rreg2 == 0, ("Bad I8 type ret regs"));
01519
01520
01521
01522
01523 WN *ldid_wn = WN_CreateLdid (OPCODE_make_op(OPR_LDID,
01524 Pointer_type,
01525 Pointer_type),
01526 rreg1, rst, Be_Type_Tbl(Pointer_type));
01527 Create_alias (Alias_Mgr, ldid_wn);
01528 Du_Mgr->Add_Def_Use (call_wn, ldid_wn);
01529 SYMBOL* preg_sym = CXX_NEW (SYMBOL(Create_Preg_Symbol("$local_dart",
01530 Pointer_type)),
01531 LEGO_pool);
01532 WN *stid_wn = AWN_StidIntoSym (preg_sym, ldid_wn);
01533 *block_wn = WN_CreateBlock ();
01534 LWN_Insert_Block_Before (*block_wn, NULL, call_wn);
01535 LWN_Insert_Block_After (*block_wn, call_wn, stid_wn);
01536 ldid_wn = AWN_LdidSym (preg_sym);
01537 Create_alias (Alias_Mgr, stid_wn);
01538 Du_Mgr->Add_Def_Use (stid_wn, ldid_wn);
01539
01540 if (!ST_is_reshaped(array_st)) {
01541
01542
01543
01544
01545 WN *cond_wn = AWN_LdidSym (preg_sym);
01546 Du_Mgr->Add_Def_Use (stid_wn, cond_wn);
01547 WN *if_wn = WN_CreateIf(cond_wn, WN_CreateBlock(), WN_CreateBlock());
01548 LWN_Parentize(if_wn);
01549
01550 SYMBOL* numprocs_sym = CXX_NEW (SYMBOL(Create_Preg_Symbol("$numprocs",
01551 MTYPE_I4)),
01552 LEGO_pool);
01553
01554
01555
01556 WN *iload_wn= LWN_CreateIload(OPCODE_make_op(OPR_ILOAD,MTYPE_I4,MTYPE_I8),
01557 dart_offset_distr_p +
01558 dim*TY_size(distr_ty_entries[RT_dim_struct]),
01559 Be_Type_Tbl(MTYPE_I4),
01560 Make_Pointer_Type(Be_Type_Tbl(MTYPE_I8)),
01561 ldid_wn);
01562 Create_alias (Alias_Mgr, iload_wn);
01563 if (inside_loop) Array_Dependence_Graph->Add_Vertex(iload_wn);
01564 WN *then_stid = AWN_StidIntoSym (numprocs_sym, iload_wn);
01565 LWN_Insert_Block_After (WN_then(if_wn), NULL, then_stid);
01566
01567
01568
01569
01570
01571
01572
01573
01574
01575
01576
01577
01578
01579 OPCODE opc = OPCODE_make_op(OPR_INTCONST, MTYPE_I4, MTYPE_V);
01580 WN *else_stid = AWN_StidIntoSym (numprocs_sym, WN_CreateIntconst(opc, 1));
01581 LWN_Insert_Block_After (WN_else(if_wn), NULL, else_stid);
01582
01583
01584
01585 LWN_Insert_Block_Before (*block_wn, NULL, if_wn);
01586
01587 ldid_wn = AWN_LdidSym(numprocs_sym);
01588 Create_alias (Alias_Mgr, then_stid);
01589 Copy_alias_info (Alias_Mgr, then_stid, else_stid);
01590 Du_Mgr->Add_Def_Use (then_stid, ldid_wn);
01591 Du_Mgr->Add_Def_Use (else_stid, ldid_wn);
01592 return ldid_wn;
01593 }
01594
01595
01596
01597 ldid_wn = LWN_CreateIload (OPCODE_make_op(OPR_ILOAD, MTYPE_I4, MTYPE_I8),
01598 dart_offset_distr_p +
01599 dim*TY_size(distr_ty_entries[RT_dim_struct]),
01600 Be_Type_Tbl(MTYPE_I4),
01601 Make_Pointer_Type(Be_Type_Tbl(MTYPE_I8)),
01602 ldid_wn);
01603 Create_alias (Alias_Mgr, ldid_wn);
01604 if (inside_loop)
01605 Array_Dependence_Graph->Add_Vertex(ldid_wn);
01606 return ldid_wn;
01607 }
01608
01609
01610
01611
01612
01613
01614
01615 void DISTR_INFO::Dimsize_Ldid (INT dim, WN* ldid_wn) {
01616 if (_dimsize_wn[dim].Elements() == 0) {
01617
01618
01619 if (ST_isLocal(WN_st(ldid_wn)))
01620 Create_local_alias (Alias_Mgr, ldid_wn);
01621 else Create_global_alias (Alias_Mgr, WN_st(ldid_wn), ldid_wn, NULL);
01622 WN* copy_wn = LWN_Copy_Tree (ldid_wn);
01623 _dimsize_wn[dim][_dimsize_wn[dim].Newidx()] = copy_wn;
01624 Copy_alias_info (Alias_Mgr, ldid_wn, copy_wn);
01625 Du_Mgr->Add_Def_Use (Current_Func_Node, ldid_wn);
01626 return;
01627 }
01628
01629 WN* wn = _dimsize_wn[dim][_dimsize_wn[dim].Lastidx()];
01630 if (WN_operator(wn) == OPR_LDID) {
01631
01632 FmtAssert (_dimsize_wn[dim].Elements() == 1,
01633 ("Dimsize_Ldid: why are we storing more than 1 ldid?"));
01634 Copy_alias_info (Alias_Mgr, wn, ldid_wn);
01635 Du_Mgr->Add_Def_Use (Current_Func_Node, ldid_wn);
01636 return;
01637 }
01638
01639 Copy_alias_info (Alias_Mgr, wn, ldid_wn);
01640
01641 for (INT i=0; i<_dimsize_wn[dim].Elements(); i++) {
01642 wn = _dimsize_wn[dim][i];
01643 FmtAssert (WN_operator(wn) == OPR_STID,
01644 ("Dimsize_Ldid: stored wn neither ldid nor stid"));
01645 Du_Mgr->Add_Def_Use (wn, ldid_wn);
01646 }
01647 if (ST_isLocal(_dimsize[dim]->St()))
01648
01649 Du_Mgr->Add_Def_Use (Current_Func_Node, ldid_wn);
01650 }
01651
01652
01653
01654
01655
01656
01657
01658 void DISTR_INFO::Dimsize_Stid (INT dim, WN* stid_wn) {
01659 if (_dimsize_wn[dim].Elements() == 0) {
01660
01661 _dimsize_wn[dim][_dimsize_wn[dim].Newidx()] = stid_wn;
01662 if (ST_isLocal(WN_st(stid_wn)))
01663 Create_local_alias (Alias_Mgr, stid_wn);
01664 else Create_global_alias (Alias_Mgr, WN_st(stid_wn), stid_wn, NULL);
01665 return;
01666 }
01667
01668 WN* wn = _dimsize_wn[dim][_dimsize_wn[dim].Lastidx()];
01669 if (WN_operator(wn) == OPR_LDID) {
01670
01671 FmtAssert (_dimsize_wn[dim].Elements() == 1,
01672 ("Dimsize_Stid: why are we storing more than 1 ldid?"));
01673 Copy_alias_info (Alias_Mgr, wn, stid_wn);
01674
01675 LWN_Delete_Tree (wn);
01676 _dimsize_wn[dim][_dimsize_wn[dim].Lastidx()] = stid_wn;
01677 USE_LIST* use_list = Du_Mgr->Du_Get_Use(Current_Func_Node);
01678 USE_LIST_ITER use_iter(use_list);
01679 DU_NODE* node;
01680
01681
01682 for (node = use_iter.First(); !use_iter.Is_Empty();
01683 node = use_iter.Next()) {
01684 WN* uwn = node->Wn();
01685 if (WN_operator(uwn) == OPR_LDID) {
01686 SYMBOL sym (uwn);
01687 if (sym == *(_dimsize[dim])) {
01688
01689 if (ST_isLocal(_dimsize[dim]->St()))
01690
01691 Du_Mgr->Delete_Def_Use (Current_Func_Node, uwn);
01692 Du_Mgr->Add_Def_Use (stid_wn, uwn);
01693 Du_Mgr->Ud_Get_Def(uwn)->Set_loop_stmt(NULL);
01694 }
01695 }
01696 }
01697 return;
01698 }
01699
01700 FmtAssert (WN_operator(wn) == OPR_STID,
01701 ("Dimsize_Stid: Expected stored STID"));
01702 _dimsize_wn[dim][_dimsize_wn[dim].Newidx()] = stid_wn;
01703 Copy_alias_info (Alias_Mgr, wn, stid_wn);
01704 USE_LIST* use_list = Du_Mgr->Du_Get_Use(wn);
01705 USE_LIST_ITER use_iter(use_list);
01706 DU_NODE* node;
01707
01708 for (node = use_iter.First(); !use_iter.Is_Empty();
01709 node = use_iter.Next()) {
01710 WN* uwn = node->Wn();
01711 if (WN_operator(uwn) == OPR_LDID) {
01712 SYMBOL sym (uwn);
01713 if (sym == *(_dimsize[dim])) {
01714
01715 Du_Mgr->Add_Def_Use (stid_wn, uwn);
01716 Du_Mgr->Ud_Get_Def(uwn)->Set_loop_stmt(NULL);
01717 }
01718 }
01719 }
01720 }
01721
01722
01723
01724
01725
01726
01727 WN* DISTR_INFO::Dimsize (INT dim) {
01728 if (_buddy_dinfo) return _buddy_dinfo->Dimsize(dim);
01729
01730 SYMBOL* dimsize = _dimsize[dim];
01731 WN* ldid_wn = NULL;
01732
01733 Is_True (dimsize, ("Asking for dimsize of a STAR distributed dimension"));
01734 if (Small_Index()) {
01735 OPCODE ldid_op = OPCODE_make_op(OPR_LDID, MTYPE_I4, MTYPE_I8);
01736 ldid_wn = WN_CreateLdid (ldid_op, dimsize->WN_Offset(),
01737 dimsize->St(), Be_Type_Tbl(MTYPE_I4));
01738 }
01739 else {
01740 OPCODE ldid_op = OPCODE_make_op(OPR_LDID, MTYPE_I8, MTYPE_I8);
01741 ldid_wn = WN_CreateLdid (ldid_op, dimsize->WN_Offset(),
01742 dimsize->St(), Be_Type_Tbl(MTYPE_I8));
01743 }
01744 Dimsize_Ldid(dim, ldid_wn);
01745 return ldid_wn;
01746 }
01747
01748
01749
01750
01751
01752
01753 WN* DISTR_INFO::Chunksize (INT dim) {
01754 DISTR_ARRAY* dact = Lookup_DACT(Array_ST());
01755 WN* chunksize_wn = dact->Chunksize(dim);
01756 return chunksize_wn;
01757 }
01758
01759
01760
01761
01762
01763
01764
01765
01766
01767
01768 WN* DISTR_INFO::Get_Array_Dim_Size (INT dim) {
01769 DISTR_ARRAY* dact = NULL;
01770 if (Num_Dact() > 0) {
01771 if (Num_Dact() != 1)
01772 DevWarn ("Array %s has more than one dact", ST_name(_array->St()));
01773
01774 dact = _dact_da[0];
01775 }
01776 else if (Num_Redistr() > 0) {
01777 dact = Get_Redistr(0);
01778 }
01779 else FmtAssert (FALSE, ("Array %s has no dact", ST_name(_array->St())));
01780 return dact->Array_Size_WN (dim);
01781 }
01782
01783
01784 static BOOL DU_Closure_Collect_Defs (DYN_ARRAY<WN*> &stmt_stack, WN* load_wn);
01785
01786
01787
01788
01789
01790
01791
01792
01793
01794
01795
01796 extern void Move_Alloca (ST* st) {
01797
01798 if (!Is_VLA (st)) {
01799 DevWarn ("Move_Alloca: suspicious looking ST - %s\n", ST_name(st));
01800 }
01801
01802
01803 WN *wn;
01804 wn = WN_first(WN_func_body(Current_Func_Node));
01805 WN* preamble_wn = NULL;
01806 while (wn) {
01807
01808 if (WN_operator(wn) == OPR_PRAGMA &&
01809 WN_pragma(wn) == WN_PRAGMA_PREAMBLE_END)
01810 preamble_wn = wn;
01811
01812
01813 if (WN_operator(wn) == OPR_STID && WN_st(wn) == st) {
01814
01815 WN* prev_wn = WN_prev(wn);
01816
01817 FmtAssert (prev_wn &&
01818 WN_operator(prev_wn) == OPR_INTRINSIC_CALL &&
01819 (Pointer_Size == 8 ?
01820 WN_intrinsic(prev_wn) == INTRN_U8I8ALLOCA :
01821 WN_intrinsic(prev_wn) == INTRN_U4I4ALLOCA),
01822 ("Unable to distribute VLA (%s). Check bounds expression",
01823 ST_name(st)));
01824
01825
01826 if (preamble_wn == NULL) {
01827
01828 return;
01829 }
01830
01831 MEM_POOL_Push (LEGO_pool);
01832 {
01833 DYN_ARRAY<WN*> stmt_stack;
01834 stmt_stack.Set_Mem_Pool (LEGO_pool);
01835 stmt_stack.AddElement (wn);
01836 stmt_stack.AddElement (prev_wn);
01837
01838 INT idx = 1;
01839
01840 BOOL ok_to_move = TRUE;
01841 while (idx < stmt_stack.Elements()) {
01842 WN* stmt_wn = stmt_stack[idx];
01843 WN* load_wn = WN_kid0(stmt_wn);
01844
01845 if (DU_Closure_Collect_Defs (stmt_stack, load_wn) == (BOOL) 0) {
01846 ok_to_move = FALSE;
01847 break;
01848 }
01849
01850 idx++;
01851 }
01852
01853 FmtAssert (ok_to_move,
01854 ("Cannot support distribute/redistribute on this VLA %s.\n Please simplify the bounds expression\n",
01855 ST_name(st)));
01856
01857
01858
01859
01860
01861 WN* stmt_wn = stmt_stack[0];
01862 while (!(WN_operator(stmt_wn) == OPR_PRAGMA &&
01863 WN_pragma(stmt_wn) == WN_PRAGMA_PREAMBLE_END)) {
01864
01865
01866 BOOL in_stmt_stack = FALSE;
01867 INT i;
01868 for (i=0; i<stmt_stack.Elements(); i++) {
01869 if (stmt_stack[i] == stmt_wn) break;
01870 }
01871
01872 if (i < stmt_stack.Elements()) {
01873
01874 WN* tmp = stmt_wn;
01875 stmt_wn = WN_prev(stmt_wn);
01876 tmp = LWN_Extract_From_Block (tmp);
01877 LWN_Insert_Block_Before (WN_func_body(Current_Func_Node),
01878 preamble_wn,
01879 tmp);
01880 preamble_wn = tmp;
01881 }
01882 else stmt_wn = WN_prev(stmt_wn);
01883 }
01884 }
01885
01886 MEM_POOL_Pop (LEGO_pool);
01887 return;
01888 }
01889 wn = WN_next(wn);
01890 }
01891
01892
01893 FmtAssert (FALSE, ("Unable to find alloca of %s\n", ST_name(st)));
01894 }
01895
01896
01897
01898
01899
01900
01901
01902
01903
01904
01905
01906
01907
01908
01909 static BOOL DU_Closure_Collect_Defs (DYN_ARRAY<WN*> &stmt_stack, WN* load_wn) {
01910 if (load_wn == NULL) return TRUE;
01911
01912
01913 if (WN_operator(load_wn) == OPR_ILOAD ||
01914 WN_operator(load_wn) == OPR_LDA)
01915 return FALSE;
01916
01917 if (WN_operator(load_wn) == OPR_LDID) {
01918
01919
01920 WN* pos_wn = load_wn;
01921 while (pos_wn) {
01922 if (LWN_Get_Parent(pos_wn) == WN_func_body(Current_Func_Node))
01923 break;
01924 pos_wn = LWN_Get_Parent(pos_wn);
01925 }
01926 FmtAssert (pos_wn, ("DU_Closure_Collect_Defs -- error processing %s\n",
01927 ST_name(WN_st(load_wn))));
01928
01929 DEF_LIST* def_list = Du_Mgr->Ud_Get_Def(load_wn);
01930 if (!def_list || def_list->Incomplete()) return FALSE;
01931
01932
01933 DEF_LIST_ITER iter(def_list);
01934 DU_NODE* node = iter.First();
01935 DU_NODE* tmp = iter.Next();
01936 if (!iter.Is_Empty()) return FALSE;
01937
01938 WN* def_wn = node->Wn();
01939
01940
01941
01942 if (WN_opcode(def_wn) == OPC_FUNC_ENTRY) return TRUE;
01943
01944 if (WN_operator(def_wn) != OPR_STID ||
01945 WN_st(def_wn) != WN_st(load_wn)) {
01946 return FALSE;
01947 }
01948
01949
01950 if (LWN_Get_Parent(def_wn) != WN_func_body(Current_Func_Node))
01951 return FALSE;
01952
01953
01954 WN* prev_wn = WN_prev(pos_wn);
01955 while (prev_wn) {
01956 if (prev_wn == def_wn) break;
01957 prev_wn = WN_prev(prev_wn);
01958 }
01959 if (prev_wn == NULL) return FALSE;
01960
01961
01962
01963 INT i;
01964 for (i=0; i<stmt_stack.Elements(); i++) {
01965 if (def_wn == stmt_stack[i]) {
01966
01967 break;
01968 }
01969 }
01970 if (i == stmt_stack.Elements()) {
01971
01972 stmt_stack.AddElement (def_wn);
01973 }
01974 return TRUE;
01975 }
01976 else {
01977
01978 for (INT i=0; i<WN_kid_count(load_wn); i++) {
01979 if (DU_Closure_Collect_Defs (stmt_stack, WN_kid(load_wn,i)) == FALSE)
01980 return FALSE;
01981 }
01982 return TRUE;
01983 }
01984 }
01985
01986
01987
01988
01989
01990
01991
01992
01993
01994
01995 static WN* Find_Alloca (ST* st) {
01996 WN* wn = WN_func_body(Current_Func_Node);
01997 Is_True (WN_operator(wn) == OPR_BLOCK,
01998 ("Expected function body to be a OPR_BLOCK\n"));
01999 wn = WN_first(wn);
02000 while (wn) {
02001 FmtAssert ((WN_operator(wn) != OPR_PRAGMA) ||
02002 (WN_pragma(wn) != WN_PRAGMA_PREAMBLE_END),
02003 ("Reached end of preamble w/o finding alloca of %s\n",
02004 ST_name(st)));
02005 if ((WN_operator(wn) == OPR_STID) && (WN_st(wn) == st)) {
02006 return wn;
02007 }
02008 wn = WN_next(wn);
02009 }
02010 FmtAssert (FALSE,
02011 ("Reached end of function w/o finding either preamble or alloca of %s\n",
02012 ST_name(st)));
02013 return NULL;
02014 }
02015
02016
02017
02018
02019
02020
02021
02022
02023
02024 void DISTR_INFO::Find_Alloca () {
02025 if (Get_Array_Def_WN()) return;
02026 ST* array_st = Array_ST();
02027 WN* wn = WN_func_body(Current_Func_Node);
02028 Is_True (WN_operator(wn) == OPR_BLOCK,
02029 ("Expected function body to be a OPR_BLOCK\n"));
02030 wn = WN_first(wn);
02031 while (wn) {
02032 FmtAssert ((WN_operator(wn) != OPR_PRAGMA) ||
02033 (WN_pragma(wn) != WN_PRAGMA_PREAMBLE_END),
02034 ("Reached end of preamble w/o finding alloca of %s\n",
02035 ST_name(array_st)));
02036 if ((WN_operator(wn) == OPR_STID) &&
02037 (WN_st(wn) == array_st)) {
02038 Create_unique_pointer_alias (Alias_Mgr, array_st, wn, NULL);
02039 WN* copy_wn = LWN_Copy_Tree(wn);
02040 Copy_alias_info (Alias_Mgr, wn, copy_wn);
02041 Set_Array_Alias_WN (copy_wn);
02042 Set_Array_Def_WN (wn);
02043 return;
02044 }
02045 wn = WN_next(wn);
02046 }
02047 FmtAssert (FALSE,
02048 ("Reached end of function w/o finding either preamble or alloca of %s\n",
02049 ST_name(array_st)));
02050 }
02051
02052
02053
02054
02055
02056
02057
02058
02059
02060
02061 extern WN* Load_Distr_Array (ST* array_st) {
02062 DISTR_INFO* dinfo = da_hash->Find(array_st);
02063 if (dinfo) return dinfo->Load_Distr_Array ();
02064
02065 WN *array_load_wn = NULL;
02066
02067 if (TY_kind(ST_type(array_st)) == KIND_POINTER) {
02068
02069 Is_True (ST_isFormal(array_st) || ST_isLocal(array_st),
02070 ("ST (%s) is kind_pointer: Must be formal or local\n",
02071 ST_name(array_st)));
02072 OPCODE ldid_op = OPCODE_make_op (OPR_LDID, Pointer_type, Pointer_type);
02073 array_load_wn = WN_CreateLdid (ldid_op, 0, array_st, ST_type(array_st));
02074 switch (ST_Var_Kind(array_st)) {
02075 case var_local:
02076 {
02077 WN* stid_wn = Find_Alloca(array_st);
02078 Create_local_alias (Alias_Mgr, stid_wn);
02079 Copy_alias_info (Alias_Mgr, stid_wn, array_load_wn);
02080 Du_Mgr->Add_Def_Use (stid_wn, array_load_wn);
02081 break;
02082 }
02083 case var_formal:
02084 {
02085 Create_formal_alias (Alias_Mgr, array_st, array_load_wn, NULL);
02086 Du_Mgr->Add_Def_Use (Current_Func_Node, array_load_wn);
02087 break;
02088 }
02089 default:
02090 FmtAssert (FALSE, ("ST (%s) must be local or formal\n",
02091 ST_name(array_st)));
02092 break;
02093 }
02094 } else {
02095 OPCODE lda_op = OPCODE_make_op (OPR_LDA, Pointer_type, MTYPE_V);
02096 array_load_wn = WN_CreateLda
02097 (lda_op, 0, Make_Pointer_Type(ST_type(array_st)),
02098 array_st);
02099 }
02100 return array_load_wn;
02101 }
02102
02103
02104
02105
02106
02107
02108
02109
02110 WN* DISTR_INFO::Load_Distr_Array () {
02111 ST* array_st = Array_ST();
02112 WN *array_load_wn = NULL;
02113
02114
02115
02116
02117
02118 if (TY_kind(ST_type(array_st)) == KIND_POINTER) {
02119
02120 Is_True (ST_isFormal(array_st) || ST_isLocal(array_st) || IsReshaped(),
02121 ("ST (%s) is kind_pointer: Must be formal, local, or reshaped\n",
02122 ST_name(array_st)));
02123 OPCODE ldid_op = OPCODE_make_op (OPR_LDID, Pointer_type, Pointer_type);
02124 array_load_wn = WN_CreateLdid (ldid_op, 0, array_st, ST_type(array_st));
02125 switch (ST_Var_Kind(array_st)) {
02126 case var_local:
02127 if (Get_Array_Alias_WN())
02128 Copy_alias_info (Alias_Mgr,Get_Array_Alias_WN(),
02129 array_load_wn);
02130 else {
02131 Create_local_alias (Alias_Mgr, array_load_wn);
02132 WN* copy_wn = LWN_Copy_Tree (array_load_wn);
02133 Copy_alias_info (Alias_Mgr, array_load_wn, copy_wn);
02134 Set_Array_Alias_WN(copy_wn);
02135 }
02136 break;
02137 #if 0
02138 Is_True (Get_Array_Alias_WN() && Get_Array_Def_WN(),
02139 ("ST (%s) is local: where is the alias and def info?\n",
02140 ST_name(array_st)));
02141 Copy_alias_info (Alias_Mgr, Get_Array_Alias_WN(), array_load_wn);
02142 break;
02143 #endif
02144 case var_global:
02145 case var_common:
02146 if (Get_Array_Alias_WN())
02147 Copy_alias_info (Alias_Mgr,Get_Array_Alias_WN(), array_load_wn);
02148 else {
02149 Create_global_alias (Alias_Mgr, array_st, array_load_wn, NULL);
02150 WN* copy_wn = LWN_Copy_Tree (array_load_wn);
02151 Copy_alias_info (Alias_Mgr, array_load_wn, copy_wn);
02152 Set_Array_Alias_WN(copy_wn);
02153 }
02154 break;
02155 case var_formal:
02156 if (Get_Array_Alias_WN())
02157 Copy_alias_info (Alias_Mgr,Get_Array_Alias_WN(), array_load_wn);
02158 else {
02159 Create_formal_alias (Alias_Mgr, array_st, array_load_wn, NULL);
02160 WN* copy_wn = LWN_Copy_Tree (array_load_wn);
02161 Copy_alias_info (Alias_Mgr, array_load_wn, copy_wn);
02162 Set_Array_Alias_WN(copy_wn);
02163 }
02164 break;
02165 }
02166 Add_Array_Use_WN(array_load_wn);
02167 } else {
02168 OPCODE lda_op = OPCODE_make_op (OPR_LDA, Pointer_type, MTYPE_V);
02169 array_load_wn = WN_CreateLda
02170 (lda_op, 0, Make_Pointer_Type(ST_type(array_st)),
02171 array_st);
02172 }
02173 return array_load_wn;
02174 }
02175
02176
02177
02178
02179
02180
02181
02182
02183
02184
02185
02186 WN* DISTR_INFO::Load_New_Distr_Array () {
02187 ST* array_st = Array_ST();
02188 Is_True (IsReshaped(),
02189 ("Load_New_Distr_Array called for non-reshaped array %s\n",
02190 ST_name(array_st)));
02191 Is_True (ST_Var_Kind(array_st) == var_common,
02192 ("Load_New_Distr_Array called for non-common array %s\n",
02193 ST_name(array_st)));
02194
02195 OPCODE ldid_op = OPCODE_make_op (OPR_LDID, Pointer_type, Pointer_type);
02196 WN* array_load_wn = WN_CreateLdid (ldid_op, _array_common->WN_Offset(),
02197 _array_common->St(),
02198 ST_type(_array_common->St()));
02199 if (_array_common_alias_wn)
02200 Copy_alias_info (Alias_Mgr, _array_common_alias_wn, array_load_wn);
02201 else {
02202 Create_global_alias (Alias_Mgr, _array_common->St(),
02203 array_load_wn, NULL);
02204 _array_common_alias_wn = array_load_wn;
02205 }
02206 Du_Mgr->Add_Def_Use (Current_Func_Node, array_load_wn);
02207 return array_load_wn;
02208 }
02209
02210
02211
02212
02213
02214
02215 WN* DISTR_INFO::DART_Ldid (ST* st) {
02216
02217
02218
02219
02220 if (st != NULL) {
02221 WN *dart_ldid_wn = WN_CreateLdid (OPCODE_make_op(OPR_LDID,
02222 Pointer_type,
02223 Pointer_type),
02224 0, st, distr_ty_entries[RT_ptr]);
02225 Is_True (_ec_dart_def_wn, ("EC-dart-ldid: expected a def\n"));
02226 Copy_alias_info (Alias_Mgr, _ec_dart_def_wn, dart_ldid_wn);
02227 Du_Mgr->Add_Def_Use (_ec_dart_def_wn, dart_ldid_wn);
02228 return dart_ldid_wn;
02229 }
02230
02231
02232
02233
02234
02235
02236
02237
02238 WN *dart_ldid_wn = WN_CreateLdid (OPCODE_make_op(OPR_LDID,
02239 Pointer_type,
02240 Pointer_type),
02241 0, _dart_st, distr_ty_entries[RT_ptr]);
02242
02243 if (_dart_wn.Elements() == 0) {
02244
02245 if (ST_isLocal(_dart_st))
02246 Create_local_alias (Alias_Mgr, dart_ldid_wn);
02247 else Create_global_alias (Alias_Mgr, WN_st(dart_ldid_wn),
02248 dart_ldid_wn, NULL);
02249 WN* copy_wn = LWN_Copy_Tree (dart_ldid_wn);
02250 Copy_alias_info (Alias_Mgr, dart_ldid_wn, copy_wn);
02251 Du_Mgr->Add_Def_Use (Current_Func_Node, dart_ldid_wn);
02252 _dart_wn[_dart_wn.Newidx()] = copy_wn;
02253 return dart_ldid_wn;
02254 }
02255
02256 WN* wn = _dart_wn[_dart_wn.Lastidx()];
02257 if (WN_operator(wn) == OPR_LDID) {
02258
02259 FmtAssert (_dart_wn.Elements() == 1,
02260 ("DART_Ldid: why are we storing more than 1 ldid?"));
02261 Copy_alias_info (Alias_Mgr, wn, dart_ldid_wn);
02262 Du_Mgr->Add_Def_Use (Current_Func_Node, dart_ldid_wn);
02263 return dart_ldid_wn;
02264 }
02265
02266 Copy_alias_info (Alias_Mgr, wn, dart_ldid_wn);
02267
02268 for (INT i=0; i<_dart_wn.Elements(); i++) {
02269 wn = _dart_wn[i];
02270 FmtAssert (WN_operator(wn) == OPR_STID,
02271 ("DART_Ldid: stored wn neither ldid nor stid"));
02272 Du_Mgr->Add_Def_Use (wn, dart_ldid_wn);
02273 }
02274 if (ST_level(_dart_st) == GLOBAL_SYMTAB)
02275
02276 Du_Mgr->Add_Def_Use (Current_Func_Node, dart_ldid_wn);
02277 return dart_ldid_wn;
02278 }
02279
02280
02281
02282
02283
02284
02285 void DISTR_INFO::DART_Stid (WN* stid_wn, ST* st) {
02286
02287
02288
02289
02290 if (st != NULL) {
02291 _ec_dart_def_wn = stid_wn;
02292 Create_local_alias (Alias_Mgr, stid_wn);
02293 return;
02294 }
02295
02296
02297
02298
02299
02300
02301
02302
02303 if (_dart_wn.Elements() == 0) {
02304
02305 _dart_wn[_dart_wn.Newidx()] = stid_wn;
02306 if (ST_isLocal(_dart_st))
02307 Create_local_alias (Alias_Mgr, stid_wn);
02308 else Create_global_alias (Alias_Mgr, WN_st(stid_wn), stid_wn, NULL);
02309 return;
02310 }
02311
02312 WN* wn = _dart_wn[_dart_wn.Lastidx()];
02313 if (WN_operator(wn) == OPR_LDID) {
02314
02315 FmtAssert (_dart_wn.Elements() == 1,
02316 ("Dart_Stid: why are we storing more than 1 ldid?"));
02317 Copy_alias_info (Alias_Mgr, wn, stid_wn);
02318 _dart_wn[_dart_wn.Lastidx()] = stid_wn;
02319 USE_LIST* use_list = Du_Mgr->Du_Get_Use(Current_Func_Node);
02320 USE_LIST_ITER use_iter(use_list);
02321 DU_NODE* node;
02322 SYMBOL dart_sym (wn);
02323
02324
02325 for (node = use_iter.First(); !use_iter.Is_Empty();
02326 node = use_iter.Next()) {
02327 WN* uwn = node->Wn();
02328 if (WN_operator(uwn) == OPR_LDID) {
02329 SYMBOL sym (uwn);
02330 if (sym == dart_sym) {
02331
02332 if (ST_level(_dart_st) != GLOBAL_SYMTAB)
02333
02334 Du_Mgr->Delete_Def_Use (Current_Func_Node, uwn);
02335 Du_Mgr->Add_Def_Use (stid_wn, uwn);
02336 Du_Mgr->Ud_Get_Def(uwn)->Set_loop_stmt(NULL);
02337 }
02338 }
02339 }
02340
02341
02342 LWN_Delete_Tree (wn);
02343
02344 return;
02345 }
02346
02347 FmtAssert (WN_operator(wn) == OPR_STID,
02348 ("Dart_Stid: Expected stored STID"));
02349 _dart_wn[_dart_wn.Newidx()] = stid_wn;
02350 Copy_alias_info (Alias_Mgr, wn, stid_wn);
02351 USE_LIST* use_list = Du_Mgr->Du_Get_Use(wn);
02352 USE_LIST_ITER use_iter(use_list);
02353 DU_NODE* node;
02354 SYMBOL dart_sym (_dart_st, 0, Pointer_type);
02355
02356 for (node = use_iter.First(); !use_iter.Is_Empty();
02357 node = use_iter.Next()) {
02358 WN* uwn = node->Wn();
02359 if (WN_operator(uwn) == OPR_LDID) {
02360 SYMBOL sym (uwn);
02361 if (sym == dart_sym) {
02362
02363 Du_Mgr->Add_Def_Use (stid_wn, uwn);
02364 Du_Mgr->Ud_Get_Def(uwn)->Set_loop_stmt(NULL);
02365 }
02366 }
02367 }
02368 }
02369
02370 void DISTR_INFO::DART_Ptr_Ref (WN* wn, ST* st) {
02371
02372 if (st != NULL) {
02373 if (_ec_dart_ptr_wn)
02374 Copy_alias_info (Alias_Mgr, _ec_dart_ptr_wn, wn);
02375 else {
02376 Create_unique_pointer_alias (Alias_Mgr, st, NULL, wn);
02377 _ec_dart_ptr_wn = wn;
02378 }
02379 }
02380
02381 else {
02382 if (_dart_ptr_alias_wn)
02383 Copy_alias_info (Alias_Mgr, _dart_ptr_alias_wn, wn);
02384 else {
02385 Create_unique_pointer_alias (Alias_Mgr, _dart_st, NULL, wn);
02386 _dart_ptr_alias_wn = wn;
02387 }
02388 }
02389 }
02390
02391
02392
02393
02394
02395
02396
02397 void Read_Distr_Pragmas (WN* func_nd) {
02398 WN *pwn = func_nd;
02399 extern MEM_POOL LNO_local_pool;
02400 MEM_POOL_Push (&LNO_local_pool);
02401 dynamic_list = CXX_NEW (ST_HASH_TABLE(20, &LNO_local_pool),
02402 &LNO_local_pool);
02403
02404
02405 while (pwn) {
02406 if ((WN_opcode(pwn) == OPC_PRAGMA) || (WN_opcode(pwn) == OPC_XPRAGMA)) {
02407 switch (WN_pragma(pwn)) {
02408
02409
02410
02411 case WN_PRAGMA_DISTRIBUTE:
02412 DB_PRINT(printf ("Found a distribute pragma\n"));
02413 if (WN_st(pwn)) pwn = Read_Pragma_Distribute (pwn);
02414 else pwn = LWN_Get_Next_Stmt_Node (pwn);
02415 break;
02416 case WN_PRAGMA_REDISTRIBUTE:
02417 DB_PRINT(printf ("Found a redistribute pragma\n"));
02418 if (WN_st(pwn)) pwn = Read_Pragma_Redistribute (pwn);
02419 else pwn = LWN_Get_Next_Stmt_Node (pwn);
02420 break;
02421 case WN_PRAGMA_DISTRIBUTE_RESHAPE:
02422 DB_PRINT(printf ("Found a distribute-reshape pragma\n"));
02423 if (WN_st(pwn)) pwn = Read_Pragma_Distribute_Reshape (pwn);
02424 else pwn = LWN_Get_Next_Stmt_Node (pwn);
02425 break;
02426 case WN_PRAGMA_DYNAMIC:
02427 {
02428 DB_PRINT(printf ("Found a dynamic pragma\n"));
02429 DISTR_INFO* dinfo = da_hash->Find(WN_st(pwn));
02430 if (dinfo) dinfo->Set_Dynamic();
02431 else dynamic_list->Enter (WN_st(pwn), TRUE);
02432 WN* tmp_wn = pwn;
02433 pwn = LWN_Get_Next_Stmt_Node (pwn);
02434 LWN_Delete_Tree_From_Block (tmp_wn);
02435 break;
02436 }
02437 case WN_PRAGMA_AFFINITY:
02438 case WN_PRAGMA_DATA_AFFINITY:
02439 case WN_PRAGMA_THREAD_AFFINITY:
02440 DB_PRINT(printf ("Found an affinity pragma\n"));
02441 pwn = Read_Pragma_Affinity (pwn);
02442 break;
02443 case WN_PRAGMA_PAGE_PLACE:
02444 DB_PRINT(printf ("Found a page-place pragma\n"));
02445 pwn = Read_Pragma_Page_Place (pwn);
02446 break;
02447 default:
02448 pwn = LWN_Get_Next_Stmt_Node (pwn);
02449 break;
02450 }
02451 } else pwn = LWN_Get_Next_Stmt_Node (pwn);
02452 }
02453
02454
02455 HASH_TABLE_ITER<ST*, BOOL> iter (dynamic_list);
02456 ST* st;
02457 BOOL mybool;
02458 while (iter.Step(&st, &mybool)) {
02459 DISTR_INFO* dinfo = da_hash->Find (st);
02460 if (dinfo) dinfo->Set_Dynamic();
02461
02462
02463 }
02464 CXX_DELETE (dynamic_list, &LNO_local_pool);
02465 dynamic_list = NULL;
02466 MEM_POOL_Pop (&LNO_local_pool);
02467 }
02468
02469
02470
02471
02472
02473
02474
02475
02476 static WN* Read_Pragma_Affinity (WN* pwn) {
02477 #ifdef Is_True_On
02478
02479
02480
02481
02482 {
02483 WN* tmp_wn = WN_next(pwn);
02484 Is_True (tmp_wn && (WN_opcode(tmp_wn) == OPC_XPRAGMA ||
02485 WN_opcode(tmp_wn) == OPC_PRAGMA) &&
02486 ((WN_pragma(tmp_wn) == WN_PRAGMA_AFFINITY) ||
02487 (WN_pragma(tmp_wn) == WN_PRAGMA_DATA_AFFINITY) ||
02488 (WN_pragma(tmp_wn) == WN_PRAGMA_THREAD_AFFINITY)),
02489 ("Affinity statements should have 2 xpragmas, but found only 1"));
02490 tmp_wn = WN_first(LWN_Get_Parent(pwn));
02491 while (tmp_wn) {
02492 if ((WN_opcode(tmp_wn) == OPC_PRAGMA) &&
02493 ((WN_pragma(tmp_wn) == WN_PRAGMA_DOACROSS) ||
02494 (WN_pragma(tmp_wn) == WN_PRAGMA_PDO_BEGIN) ||
02495 (WN_pragma(tmp_wn) == WN_PRAGMA_PARALLEL_DO)))
02496 break;
02497 tmp_wn = WN_next(tmp_wn);
02498 }
02499 Is_True (tmp_wn, ("Missing doacross/pdo before affinity XPRAGMA"));
02500
02501
02502
02503 WN* do_wn = WN_first(WN_kid(LWN_Get_Parent(LWN_Get_Parent(pwn)), 2));
02504 while (do_wn) {
02505 if (WN_operator(do_wn) == OPR_DO_LOOP) break;
02506 do_wn = WN_next(do_wn);
02507 }
02508 Is_True (do_wn,("Missing DO-LOOP after doacross and affinity pragma"));
02509 }
02510 #endif
02511
02512
02513 WN* tmp_wn = WN_next(pwn);
02514 while (tmp_wn) {
02515 if (((WN_opcode(tmp_wn) == OPC_PRAGMA) ||
02516 (WN_opcode(tmp_wn) == OPC_XPRAGMA)) &&
02517 ((WN_pragma(tmp_wn) == WN_PRAGMA_DATA_AFFINITY) ||
02518 (WN_pragma(tmp_wn) == WN_PRAGMA_THREAD_AFFINITY)))
02519 break;
02520 tmp_wn = WN_next(tmp_wn);
02521 }
02522 FmtAssert (tmp_wn, ("Missing type of affinity pragma\n"));
02523
02524
02525 WN* do_wn = WN_first(WN_region_body(LWN_Get_Parent(LWN_Get_Parent(pwn))));
02526 while (do_wn) {
02527 if (WN_operator(do_wn) == OPR_DO_LOOP) break;
02528 do_wn = WN_next(do_wn);
02529 }
02530 Is_True (do_wn, ("Missing parallel do loop\n"));
02531
02532
02533
02534
02535
02536
02537
02538 WN* rwn = do_wn;
02539 INT32 nest_count = Get_Do_Loop_Info(do_wn)->Mp_Info->Nest_Total();
02540 for (INT i=1; i<nest_count; i++) {
02541 rwn = WN_first(WN_do_body(rwn));
02542 while (rwn && (WN_operator(rwn) != OPR_REGION)) {
02543 rwn = WN_next(rwn);
02544 }
02545 FmtAssert (rwn, ("nested-doacross: cannot find nested region %d\n", i));
02546 rwn = WN_first(WN_region_body(rwn));
02547 while (rwn && (WN_operator(rwn) != OPR_DO_LOOP)) {
02548 rwn = WN_next(rwn);
02549 }
02550 FmtAssert(rwn, ("nested-doacross: missing doloop in MP region %d\n",i));
02551 }
02552
02553
02554 rwn = WN_do_body(rwn);
02555 rwn = WN_first(rwn);
02556 while (rwn) {
02557 if ((WN_opcode(rwn) == OPC_XPRAGMA) &&
02558 (WN_pragma(rwn) == WN_PRAGMA_AFFINITY))
02559 break;
02560 rwn = WN_next(rwn);
02561 }
02562 FmtAssert (rwn, ("Missing affinity pragma in do-loop body\n"));
02563
02564 if (!Get_Trace(TP_LNOPT2, TT_LEGO_DISABLE_EXPLICIT_AFFINITY)) {
02565 switch (WN_pragma(tmp_wn)) {
02566 case WN_PRAGMA_DATA_AFFINITY:
02567 Read_Pragma_Data_Affinity (do_wn, rwn);
02568 break;
02569 case WN_PRAGMA_THREAD_AFFINITY:
02570 Read_Pragma_Thread_Affinity (pwn, do_wn, rwn);
02571 break;
02572 }
02573 }
02574
02575
02576
02577
02578 while (rwn) {
02579 if ((WN_opcode(rwn) == OPC_XPRAGMA) &&
02580 (WN_pragma(rwn) == WN_PRAGMA_AFFINITY)) {
02581
02582 WN* tmp_wn = rwn;
02583 rwn = WN_next(rwn);
02584 LWN_Delete_Tree_From_Block (tmp_wn);
02585 continue;
02586 }
02587 if ((WN_opcode(rwn) == OPC_XPRAGMA) &&
02588 (WN_pragma(rwn) == WN_PRAGMA_DATA_AFFINITY)) {
02589
02590
02591 WN* tmp_wn = rwn;
02592 rwn = WN_next(rwn);
02593 LWN_Delete_Tree_From_Block (tmp_wn);
02594 continue;
02595 }
02596 if ((WN_opcode(rwn) == OPC_XPRAGMA) &&
02597 (WN_pragma(rwn) == WN_PRAGMA_THREAD_AFFINITY)) {
02598 LWN_Delete_Tree_From_Block (rwn);
02599 break;
02600 }
02601
02602 break;
02603 }
02604
02605
02606
02607 WN* pragma_block_wn = LWN_Get_Parent(pwn);
02608 do {
02609 WN* prev_wn = pwn;
02610 pwn = WN_next(pwn);
02611 LWN_Delete_Tree_From_Block(prev_wn);
02612 } while (pwn &&
02613 (WN_opcode(pwn) == OPC_XPRAGMA) &&
02614 ((WN_pragma(pwn) == WN_PRAGMA_AFFINITY) ||
02615 (WN_pragma(pwn) == WN_PRAGMA_DATA_AFFINITY) ||
02616 (WN_pragma(pwn) == WN_PRAGMA_THREAD_AFFINITY)));
02617
02618 if (pwn == NULL)
02619
02620 pwn = WN_kid(LWN_Get_Parent(pragma_block_wn), 2);
02621 return pwn;
02622 }
02623
02624
02625
02626
02627
02628
02629
02630
02631 static void Propagate_Loop_Index (SYMBOL* sym, WN* expr_wn) {
02632 if (!expr_wn) return;
02633
02634 if (WN_operator(expr_wn) == OPR_LDID) {
02635 SYMBOL this_sym (expr_wn);
02636 if (*sym == this_sym) return;
02637
02638 DEF_LIST* def_list = Du_Mgr->Ud_Get_Def(expr_wn);
02639 if (!def_list || def_list->Incomplete()) return;
02640
02641 DEF_LIST_ITER iter(def_list);
02642 const DU_NODE* node = NULL;
02643
02644
02645 INT count = 0;
02646 for (node = iter.First(); !iter.Is_Empty(); node = iter.Next()) {
02647 if (count > 0) return;
02648 count++;
02649 }
02650
02651 node = iter.First();
02652 WN* def_wn = node->Wn();
02653 SYMBOL def_sym (def_wn);
02654 if ((def_sym != *sym) ||
02655 (WN_operator(def_wn) != OPR_STID)) return;
02656
02657 WN* rhs_wn = WN_kid0(def_wn);
02658 WN* new_rhs = LWN_Copy_Tree (rhs_wn, TRUE, LNO_Info_Map);
02659 LWN_Copy_Def_Use (rhs_wn, new_rhs, Du_Mgr);
02660 Replace_WN (expr_wn, new_rhs);
02661 LWN_Delete_Tree (expr_wn);
02662 Propagate_Loop_Index (sym, new_rhs);
02663 return;
02664 }
02665
02666 Is_True (WN_operator(expr_wn) != OPR_BLOCK,
02667 ("Expr cannot contain a BLOCK"));
02668 for (INT i=0; i<WN_kid_count(expr_wn); i++) {
02669 WN* kid = WN_kid (expr_wn, i);
02670 Propagate_Loop_Index (sym, kid);
02671 }
02672 }
02673
02674
02675
02676
02677
02678
02679
02680
02681
02682 static void Read_Pragma_Data_Affinity (WN* do_wn, WN* rwn) {
02683
02684
02685
02686
02687 if (!Loop_Bounds_Simple(do_wn)) {
02688 ErrMsgSrcpos(EC_LNO_Bad_Pragma_String, WN_Get_Linenum(rwn),
02689 WN_pragmas[WN_pragma(rwn)].name,
02690 "step-size of loop must be 1 (ignoring).");
02691 return;
02692 }
02693
02694 INT nest_count = 0;
02695 WN* index_wn = rwn;
02696 WN* array_wn = rwn;
02697 while ((WN_opcode(array_wn) == OPC_XPRAGMA) &&
02698 (WN_pragma(array_wn) == WN_PRAGMA_AFFINITY)) {
02699 nest_count++;
02700 array_wn = WN_next(array_wn);
02701 }
02702 MP_INFO* mpi = Get_Do_Loop_Info(do_wn)->Mp_Info;
02703 if ((mpi == NULL) ||
02704 (mpi->Nest_Index() != 0) ||
02705 (mpi->Nest_Total() != nest_count)) {
02706 ErrMsgSrcpos(EC_LNO_Bad_Pragma_String, WN_Get_Linenum(rwn),
02707 WN_pragmas[WN_pragma(rwn)].name,
02708 "mismatch in data-affinity clause and nesting of doacross (ignoring).");
02709 return;
02710 }
02711 if ((WN_opcode(array_wn) != OPC_XPRAGMA) ||
02712 (WN_pragma(array_wn) != WN_PRAGMA_DATA_AFFINITY)) {
02713 ErrMsgSrcpos(EC_LNO_Bad_Pragma_String, WN_Get_Linenum(rwn),
02714 WN_pragmas[WN_pragma(rwn)].name,
02715 "missing reference in data-affinity clause (ignoring).");
02716 return;
02717 }
02718 array_wn = WN_kid0(array_wn);
02719 if (WN_operator(array_wn) != OPR_ILOAD) {
02720 ErrMsgSrcpos(EC_LNO_Bad_Pragma_String, WN_Get_Linenum(rwn),
02721 WN_pragmas[WN_pragma(rwn)].name,
02722 "affinity must be for an array reference (ignoring).");
02723 return;
02724 }
02725 array_wn = WN_kid0(array_wn);
02726 if (WN_operator(array_wn) != OPR_ARRAY) {
02727 ErrMsgSrcpos(EC_LNO_Bad_Pragma_String, WN_Get_Linenum(rwn),
02728 WN_pragmas[WN_pragma(rwn)].name,
02729 "affinity must be for an array reference (ignoring).");
02730 return;
02731 }
02732 #if defined(__linux) || defined(BUILD_OS_DARWIN)
02733
02734 return;
02735 #endif
02736
02737
02738
02739 DYN_ARRAY<WN*> do_list;
02740 do_list.Set_Mem_Pool (LEGO_pool);
02741
02742 INT i;
02743 for (i=0; i<nest_count; i++) {
02744
02745 INT32 dimnum = -1, coeff, constant;
02746 INT32 tmp_coeff, tmp_constant;
02747 SYMBOL index_sym (WN_index(do_wn));
02748
02749 for (INT32 j=0; j<WN_num_dim(array_wn); j++) {
02750 Propagate_Loop_Index (&index_sym, WN_array_index(array_wn, j));
02751 if (Check_Expr (WN_array_index(array_wn,j),
02752 &index_sym,&tmp_coeff,&tmp_constant)) {
02753 if (dimnum != -1) {
02754 ErrMsgSrcpos(EC_LNO_Bad_Pragma_String, WN_Get_Linenum(rwn),
02755 WN_pragmas[WN_pragma(rwn)].name,
02756 "cannot have coupled subscripts (ignoring).");
02757 goto cleanup;
02758 }
02759 dimnum = j;
02760 constant = tmp_constant;
02761 coeff = tmp_coeff;
02762
02763 }
02764 }
02765 if (dimnum == -1) {
02766 ErrMsgSrcpos(EC_LNO_Bad_Pragma_String, WN_Get_Linenum(rwn),
02767 WN_pragmas[WN_pragma(rwn)].name,
02768 "bad array subscripts (ignoring).");
02769 goto cleanup;
02770 }
02771
02772 WN* base = WN_array_base(array_wn);
02773 if ((WN_operator(base) != OPR_LDA) &&
02774 (WN_operator(base) != OPR_LDID)) {
02775 ErrMsgSrcpos(EC_LNO_Bad_Pragma_String, WN_Get_Linenum(rwn),
02776 WN_pragmas[WN_pragma(rwn)].name,
02777 "must have an array reference (ignoring).");
02778 goto cleanup;
02779 }
02780 SYMBOL *symb = CXX_NEW (SYMBOL, LEGO_pool);
02781 symb->Init (base);
02782
02783
02784 {
02785 ST* array_st = WN_st(base);
02786 DISTR_INFO* dinfo = da_hash->Find(array_st);
02787 if (dinfo) {
02788
02789 DISTRIBUTE_TYPE dt=dinfo->Get_Dact(0)->Get_Dim(dimnum)->Distr_Type ();
02790 if (dt == DISTRIBUTE_STAR) {
02791 ErrMsgSrcpos(EC_LNO_Bad_Pragma_String, WN_Get_Linenum(rwn),
02792 WN_pragmas[WN_pragma(rwn)].name,
02793 "has a non-distributed array (ignoring).");
02794 goto cleanup;
02795 }
02796 INT num_distr_dim = 0;
02797 DISTR_ARRAY* dact = dinfo->Get_Dact(0);
02798 for (INT j=0; j<dinfo->Num_Dim(); j++) {
02799 DISTRIBUTE_TYPE dt = dact->Get_Dim(j)->Distr_Type ();
02800 if (dt != DISTRIBUTE_STAR) num_distr_dim++;
02801 }
02802 if (num_distr_dim == 0) {
02803 ErrMsgSrcpos(EC_LNO_Bad_Pragma_String, WN_Get_Linenum(rwn),
02804 WN_pragmas[WN_pragma(rwn)].name,
02805 "has a non-distributed array (ignoring).");
02806 goto cleanup;
02807 }
02808 if (num_distr_dim != nest_count) {
02809 ErrMsgSrcpos(EC_LNO_Bad_Pragma_String, WN_Get_Linenum(rwn),
02810 WN_pragmas[WN_pragma(rwn)].name,
02811 "array has multiple distributed dimensions, may get poor load-balancing");
02812 }
02813 }
02814 }
02815
02816
02817
02818 if (coeff < 0) {
02819 DISTR_ARRAY* dact = Lookup_DACT (WN_st(base));
02820 if (dact && dact->Get_Dim(dimnum)->Distr_Type() != DISTRIBUTE_BLOCK) {
02821 ErrMsgSrcpos(EC_LNO_Bad_Pragma_String, WN_Get_Linenum(rwn),
02822 WN_pragmas[WN_pragma(rwn)].name,
02823 "-ve stride allowed only on BLOCK distribution (ignoring).");
02824 goto cleanup;
02825 }
02826 }
02827
02828 LEGO_INFO* li = CXX_NEW (LEGO_INFO (symb, dimnum, coeff, constant, 0, 0),
02829 LEGO_pool);
02830 ST* array_st = WN_st(base);
02831 DISTR_INFO* dinfo = da_hash->Find(array_st);
02832 if (!dinfo || dinfo->IsDynamic ())
02833 li->Set_Dynamic_Affinity ();
02834 DO_LOOP_INFO* dli = Get_Do_Loop_Info(do_wn);
02835 dli->Lego_Info = li;
02836
02837
02838 do_list.AddElement (do_wn);
02839
02840
02841 if (i<(nest_count-1)) {
02842 index_wn = WN_next(index_wn);
02843 do_wn = WN_do_body(do_wn);
02844 do_wn = WN_first(do_wn);
02845 while (do_wn && WN_operator(do_wn) != OPR_REGION) {
02846 do_wn = WN_next(do_wn);
02847 }
02848 FmtAssert (do_wn, ("Missing region in nested doacross"));
02849 do_wn = WN_first(WN_region_body(do_wn));
02850 while (do_wn && (WN_operator(do_wn) != OPR_DO_LOOP)) {
02851 do_wn = WN_next(do_wn);
02852 }
02853 FmtAssert (do_wn, ("Missing do-loop in nested doacross"));
02854 }
02855 }
02856 return;
02857
02858 cleanup:
02859 for (i=0; i<do_list.Elements(); i++) {
02860 DO_LOOP_INFO* dli = Get_Do_Loop_Info (do_list[i]);
02861 FmtAssert (dli->Lego_Info,
02862 ("lego-info cleanup: missing lego-info\n"));
02863 CXX_DELETE (dli->Lego_Info, LEGO_pool);
02864 dli->Lego_Info = NULL;
02865 }
02866 #if 0
02867
02868 {
02869 ST* array_st = WN_st(base);
02870 DISTR_INFO* dinfo = da_hash->Find(array_st);
02871 if (!dinfo || dinfo->IsDynamic ()) {
02872
02873
02874
02875
02876 WN* gen_wn = WN_CreatePragma (WN_PRAGMA_DATA_AFFINITY, array_st, 1, 0);
02877 LWN_Insert_Block_Before (NULL, pwn, gen_wn);
02878 gen_wn = WN_CreatePragma (WN_PRAGMA_AFFINITY, NULL, 0, 0);
02879 WN_pragma_index(gen_wn) = 0;
02880 WN_pragma_distr_type(gen_wn) = 0;
02881 WN_pragma_preg(gen_wn) = dimnum;
02882 LWN_Insert_Block_Before (NULL, pwn, gen_wn);
02883 gen_wn = WN_CreatePragma (WN_PRAGMA_AFFINITY, NULL, 0, 0);
02884 WN_pragma_index(gen_wn) = 0;
02885 WN_pragma_distr_type(gen_wn) = 1;
02886 WN_pragma_preg(gen_wn) = constant;
02887 LWN_Insert_Block_Before (NULL, pwn, gen_wn);
02888 gen_wn = WN_CreatePragma (WN_PRAGMA_AFFINITY, NULL, 0, 0);
02889 WN_pragma_index(gen_wn) = 0;
02890 WN_pragma_distr_type(gen_wn) = 2;
02891 WN_pragma_preg(gen_wn) = coeff;
02892 LWN_Insert_Block_Before (NULL, pwn, gen_wn);
02893 continue;
02894 }
02895 }
02896 #endif
02897 }
02898
02899
02900
02901
02902
02903
02904
02905
02906
02907
02908
02909
02910 static BOOL Check_Expr (WN* expr_wn, SYMBOL* index_sym,
02911 INT32* coeff, INT32* constant) {
02912 switch (WN_operator(expr_wn)) {
02913 case OPR_LDID:
02914 {
02915
02916 SYMBOL expr_sym (expr_wn);
02917 if (expr_sym == *index_sym) {
02918 *coeff = 1;
02919 *constant = 0;
02920 return TRUE;
02921 }
02922 return FALSE;
02923 }
02924
02925 case OPR_MPY:
02926 {
02927
02928 WN* e1 = WN_kid0(expr_wn);
02929 WN* e2 = WN_kid1(expr_wn);
02930 if (WN_operator(e1) != OPR_INTCONST) {
02931 WN* tmp_wn = e1;
02932 e1 = e2;
02933 e2 = tmp_wn;
02934 }
02935 if ((WN_operator(e1) != OPR_INTCONST) ||
02936 (WN_operator(e2) != OPR_LDID)) {
02937 ErrMsgSrcpos(EC_LNO_Bad_Pragma_String, WN_Get_Linenum(expr_wn),
02938 "AFFINITY", "bad array subscripts (ignoring).");
02939 return FALSE;
02940 }
02941
02942 SYMBOL expr_sym (e2);
02943 if (expr_sym == *index_sym) {
02944 *coeff = WN_const_val(e1);
02945 *constant = 0;
02946 return TRUE;
02947 }
02948 return FALSE;
02949 }
02950
02951 case OPR_ADD:
02952 case OPR_SUB:
02953 {
02954 BOOL did_swap = FALSE;
02955 BOOL is_sub = WN_operator(expr_wn) == OPR_SUB;
02956
02957
02958 WN* e1 = WN_kid0(expr_wn);
02959 WN* e2 = WN_kid1(expr_wn);
02960 if (WN_operator(e1) != OPR_INTCONST) {
02961 WN* tmp_wn = e1;
02962 e1 = e2;
02963 e2 = tmp_wn;
02964 did_swap = TRUE;
02965 }
02966 if (WN_operator(e1) != OPR_INTCONST) {
02967 ErrMsgSrcpos(EC_LNO_Bad_Pragma_String, WN_Get_Linenum(expr_wn),
02968 "AFFINITY", "bad subscripts (ignoring).");
02969 return FALSE;
02970 }
02971
02972 *constant = WN_const_val(e1);
02973 if (is_sub && did_swap)
02974 *constant = (0-*constant);
02975
02976 switch (WN_operator(e2)) {
02977 case OPR_LDID:
02978 {
02979
02980 SYMBOL expr_sym (e2);
02981 if (expr_sym == *index_sym) {
02982 *coeff = 1;
02983 if (is_sub && !did_swap) *coeff = -1;
02984 return TRUE;
02985 }
02986 return FALSE;
02987 }
02988 case OPR_MPY:
02989 {
02990 WN* e3 = WN_kid0(e2);
02991 e2 = WN_kid1(e2);
02992 if (WN_operator(e2) != OPR_INTCONST) {
02993 WN* tmp_wn = e2;
02994 e2 = e3;
02995 e3 = tmp_wn;
02996 }
02997 if (WN_operator(e2) != OPR_INTCONST) {
02998 ErrMsgSrcpos(EC_LNO_Bad_Pragma_String, WN_Get_Linenum(expr_wn),
02999 "AFFINITY", "bad subscripts (ignoring).");
03000 return FALSE;
03001 }
03002 if (WN_operator(e3) != OPR_LDID) {
03003 ErrMsgSrcpos(EC_LNO_Bad_Pragma_String, WN_Get_Linenum(expr_wn),
03004 "AFFINITY", "bad subscripts (ignoring).");
03005 return FALSE;
03006 }
03007 SYMBOL expr_sym (e3);
03008 if (expr_sym == *index_sym) {
03009 *coeff = WN_const_val(e2);
03010 if (is_sub && !did_swap) *coeff = (-1) * (*coeff);
03011 return TRUE;
03012 }
03013 return FALSE;
03014 }
03015 default:
03016 ErrMsgSrcpos(EC_LNO_Bad_Pragma_String, WN_Get_Linenum(expr_wn),
03017 "AFFINITY", "bad subscripts (ignoring).");
03018 return FALSE;
03019 }
03020 }
03021
03022 default:
03023
03024 return FALSE;
03025 }
03026 }
03027
03028
03029
03030
03031
03032
03033
03034
03035
03036
03037 static void Read_Pragma_Thread_Affinity (WN* pwn, WN* do_wn, WN* rwn) {
03038
03039 #if defined(__linux) || defined(BUILD_OS_DARWIN)
03040
03041 return;
03042 #endif
03043
03044
03045 while (rwn) {
03046 if ((WN_opcode(rwn) == OPC_XPRAGMA) &&
03047 (WN_pragma(rwn) == WN_PRAGMA_THREAD_AFFINITY)) break;
03048 rwn = WN_next(rwn);
03049 }
03050 FmtAssert (rwn, ("Missing thread-affinity pragma in do-loop body\n"));
03051
03052
03053 BOOL is_doacross;
03054 {
03055 WN* tmp_wn = WN_first(LWN_Get_Parent(pwn));
03056 while (tmp_wn) {
03057 if (WN_operator(tmp_wn) == OPR_PRAGMA) {
03058 if (WN_pragma(tmp_wn) == WN_PRAGMA_DOACROSS
03059 || WN_pragma(tmp_wn) == WN_PRAGMA_PARALLEL_DO) {
03060 is_doacross = TRUE;
03061 break;
03062 }
03063 else if (WN_pragma(tmp_wn) == WN_PRAGMA_PDO_BEGIN) {
03064 is_doacross = FALSE;
03065 break;
03066 }
03067 }
03068 tmp_wn = WN_next(tmp_wn);
03069 }
03070 Is_True(tmp_wn, ("Missing doacross/pdo for thread-affinity"));
03071 }
03072
03073
03074
03075
03076
03077
03078
03079
03080
03081
03082
03083
03084
03085
03086
03087
03088
03089
03090
03091 SYMBOL thread_sym;
03092 WN* stid_wn;
03093 if (is_doacross) {
03094
03095 ST* st = New_ST(CURRENT_SYMTAB);
03096 ST_Init (st,
03097 Save_Str("$thr_aff_max"),
03098 CLASS_VAR,
03099 SCLASS_AUTO,
03100 EXPORT_LOCAL,
03101 Be_Type_Tbl(MTYPE_I8));
03102 thread_sym = SYMBOL (st, 0, MTYPE_I8);
03103 stid_wn = AWN_StidIntoSym (&thread_sym, Get_Runtime_Numthreads_Ldid());
03104 }
03105 else {
03106
03107 Freeze_Cur_Numthreads_Func(do_wn);
03108 thread_sym = SYMBOL (MTYPE_To_PREG(MTYPE_I8),
03109 Create_Preg(MTYPE_I8, "$thr_aff_max"),
03110 MTYPE_I8);
03111 stid_wn = AWN_StidIntoSym (&thread_sym,
03112 Get_Runtime_Cur_Numthreads_Func(do_wn));
03113 }
03114
03115
03116 {
03117 WN* tmp_wn = pwn;
03118 while (tmp_wn) {
03119 if (WN_opcode(tmp_wn) == OPC_REGION &&
03120 (RID_TYPE_mp(REGION_get_rid(tmp_wn))))
03121 break;
03122 tmp_wn = LWN_Get_Parent(tmp_wn);
03123 }
03124 Is_True(tmp_wn, ("Missing MP-region for thread-affinity"));
03125 LWN_Insert_Block_Before (NULL, tmp_wn, stid_wn);
03126 }
03127 Create_local_alias (Alias_Mgr, stid_wn);
03128
03129
03130 WN* newdo_wn = Thread_Affinity_Lower (do_wn, &thread_sym, stid_wn);
03131
03132
03133
03134
03135 WN* thread_wn = LWN_Copy_Tree(WN_kid0(rwn));
03136 LWN_Copy_Def_Use (WN_kid0(rwn), thread_wn, Du_Mgr);
03137 WN* max_threads_wn = AWN_LdidSym (&thread_sym);
03138 Copy_alias_info (Alias_Mgr, stid_wn, max_threads_wn);
03139 Du_Mgr->Add_Def_Use (stid_wn, max_threads_wn);
03140 thread_wn=AWN_Rem_Safe(MTYPE_I4, thread_wn, max_threads_wn);
03141
03142
03143 SYMBOL index_sym(WN_start(newdo_wn));
03144 WN* myid_wn = AWN_LdidSym(&index_sym);
03145 Du_Mgr->Add_Def_Use (WN_start(newdo_wn), myid_wn);
03146 Du_Mgr->Add_Def_Use (WN_step(newdo_wn), myid_wn);
03147 DEF_LIST* deflist = Du_Mgr->Ud_Get_Def(myid_wn);
03148 deflist->Set_loop_stmt (newdo_wn);
03149 WN* cond_wn = LWN_CreateExp2 (OPCODE_make_op(OPR_EQ,
03150 Boolean_type,
03151 Promote_Type(MTYPE_I4)),
03152 thread_wn, myid_wn);
03153 WN* block_wn = WN_CreateBlock();
03154 WN* if_wn = LWN_CreateIf (cond_wn, WN_do_body(do_wn), block_wn);
03155 block_wn = WN_CreateBlock ();
03156 LWN_Insert_Block_Before (block_wn, NULL, if_wn);
03157 WN_do_body(do_wn) = block_wn;
03158 LWN_Set_Parent(block_wn, do_wn);
03159
03160
03161 BOOL has_do_loops = FALSE;
03162 DO_LOOP_INFO* dli = Get_Do_Loop_Info(do_wn);
03163 if (!dli->Is_Inner) has_do_loops = TRUE;
03164 IF_INFO *ii=CXX_NEW (IF_INFO(&LNO_default_pool,has_do_loops,
03165 Find_SCF_Inside(if_wn,OPC_REGION)!=NULL),
03166 &LNO_default_pool);
03167 WN_MAP_Set(LNO_Info_Map,if_wn,(void *)ii);
03168 DOLOOP_STACK* stack = CXX_NEW(DOLOOP_STACK(&LNO_local_pool),
03169 &LNO_local_pool);
03170 Build_Doloop_Stack(if_wn, stack);
03171 LNO_Build_If_Access(if_wn, stack);
03172 CXX_DELETE(stack, &LNO_local_pool);
03173
03174 return;
03175
03176 #if 0
03177
03178 OPCODE callop = OPCODE_make_op(OPR_CALL, MTYPE_I4, MTYPE_V);
03179 WN* call_wn = WN_Create(callop, 0);
03180 WN_st(call_wn) = distr_st_entries[mp_my_threadnum];
03181 Set_Runtime_Call_Side_Effects (call_wn);
03182 LWN_Insert_Block_Before (NULL, do_wn, call_wn);
03183
03184 PREG_NUM rreg1, rreg2;
03185 ST* rst = Find_Return_Registers (MTYPE_I4, &rreg1, &rreg2);
03186 FmtAssert(rreg1 != 0 && rreg2 == 0, ("Bad MTYPE_I4 return regs"));
03187
03188 SYMBOL preg = Create_Preg_Symbol ("$myid", MTYPE_I4);
03189 WN* ldid_wn = WN_CreateLdid (OPCODE_make_op(OPR_LDID, MTYPE_I4, MTYPE_I4),
03190 rreg1, rst, Be_Type_Tbl(MTYPE_I4));
03191 Create_alias (Alias_Mgr, ldid_wn);
03192 Du_Mgr->Add_Def_Use (call_wn, ldid_wn);
03193 WN* stid_wn = LWN_CreateStid (OPCODE_make_op(OPR_STID, MTYPE_V, MTYPE_I4),
03194 preg.WN_Offset(), preg.St(),
03195 Be_Type_Tbl(MTYPE_I4), ldid_wn);
03196 Create_local_alias (Alias_Mgr, stid_wn);
03197 LWN_Insert_Block_After (NULL, call_wn, stid_wn);
03198 WN* myid_wn = WN_CreateLdid (OPCODE_make_op(OPR_LDID, MTYPE_I4, MTYPE_I4),
03199 preg.WN_Offset(), preg.St(),
03200 Be_Type_Tbl(MTYPE_I4));
03201 Copy_alias_info (Alias_Mgr, stid_wn, myid_wn);
03202 Du_Mgr->Add_Def_Use (stid_wn, myid_wn);
03203
03204 WN* cond_wn = LWN_CreateExp2 (OPCODE_make_op(OPR_EQ,
03205 Boolean_type,
03206 Promote_Type(MTYPE_I4)),
03207 thread_wn, myid_wn);
03208 WN* block_wn = WN_CreateBlock();
03209 WN* if_wn = LWN_CreateIf (cond_wn, WN_do_body(do_wn), block_wn);
03210 block_wn = WN_CreateBlock ();
03211 LWN_Insert_Block_Before (block_wn, NULL, if_wn);
03212 WN_do_body(do_wn) = block_wn;
03213 LWN_Set_Parent(block_wn, do_wn);
03214
03215
03216
03217 IF_INFO *ii=CXX_NEW (IF_INFO(&LNO_default_pool,TRUE,
03218 Find_SCF_Inside(if_wn,OPC_REGION)!=NULL),
03219 &LNO_default_pool);
03220 WN_MAP_Set(LNO_Info_Map,if_wn,(void *)ii);
03221 DOLOOP_STACK* stack = CXX_NEW(DOLOOP_STACK(&LNO_local_pool),
03222 &LNO_local_pool);
03223 Build_Doloop_Stack(if_wn, stack);
03224 LNO_Build_If_Access(if_wn, stack);
03225 CXX_DELETE(stack, &LNO_local_pool);
03226
03227 return;
03228 #endif
03229 }
03230
03231
03232
03233
03234
03235
03236
03237
03238
03239
03240
03241
03242 static WN* Thread_Affinity_Lower (WN* do_wn, SYMBOL* thread_sym, WN* stid_wn) {
03243 Is_True (do_wn && WN_opcode(do_wn) == OPC_DO_LOOP,
03244 ("Lower_Thread_Affinity -- do-loop node missing\n"));
03245
03246
03247
03248 SYMBOL index_sym = Create_Preg_Symbol ("$thr_aff_index", MTYPE_I4);
03249 WN* index_wn = WN_CreateIdname(index_sym.WN_Offset(), index_sym.St());
03250 WN* start_def = AWN_StidIntoSym (&index_sym, LWN_Make_Icon(MTYPE_I4, 0));
03251 LWN_Copy_Linenumber(do_wn, start_def);
03252 WN* compare_use = AWN_LdidSym (&index_sym);
03253 WN* compare_th = AWN_LdidSym (thread_sym);
03254 Copy_alias_info (Alias_Mgr, stid_wn, compare_th);
03255 Du_Mgr->Add_Def_Use (stid_wn, compare_th);
03256 compare_th = LWN_CreateExp2(OPCODE_make_op(OPR_SUB, MTYPE_I4, MTYPE_V),
03257 compare_th, LWN_Make_Icon(MTYPE_I4, 1));
03258 WN* compare_wn=LWN_CreateExp2(OPCODE_make_op(OPR_LE, Boolean_type, MTYPE_I4),
03259 compare_use, compare_th);
03260 WN* step_use = AWN_LdidSym(&index_sym);
03261 WN* step_def = AWN_StidIntoSym
03262 (&index_sym, LWN_CreateExp2(OPCODE_make_op(OPR_ADD, MTYPE_I4, MTYPE_V),
03263 step_use,
03264 LWN_Make_Icon (MTYPE_I4, 1)));
03265 WN* newdo_wn = LWN_CreateDO(index_wn,
03266 start_def,
03267 compare_wn,
03268 step_def,
03269 WN_CreateBlock());
03270
03271 if (Prompf_Info != NULL && Prompf_Info->Is_Enabled()) {
03272 INT old_id = WN_MAP32_Get(Prompf_Id_Map, do_wn);
03273 INT new_id = New_Construct_Id();
03274 WN_MAP32_Set(Prompf_Id_Map, do_wn, new_id);
03275 WN_MAP32_Set(Prompf_Id_Map, newdo_wn, old_id);
03276 INT new_ids[1];
03277 new_ids[0] = new_id;
03278 Prompf_Info->Mp_Tile(old_id, new_ids, 1);
03279 }
03280
03281 LWN_Copy_Linenumber(do_wn, newdo_wn);
03282 LWN_Copy_Linenumber(do_wn, WN_do_body(newdo_wn));
03283 LWN_Insert_Block_Before (NULL, do_wn, newdo_wn);
03284 LWN_Extract_From_Block (do_wn);
03285 LWN_Insert_Block_Before (WN_do_body(newdo_wn), NULL, do_wn);
03286
03287
03288 Create_alias (Alias_Mgr, start_def);
03289 Du_Mgr->Add_Def_Use (start_def, compare_use);
03290 Du_Mgr->Add_Def_Use (start_def, step_use);
03291 Du_Mgr->Add_Def_Use (step_def, compare_use);
03292 Du_Mgr->Add_Def_Use (step_def, step_use);
03293 DEF_LIST *deflist = Du_Mgr->Ud_Get_Def(compare_use);
03294 deflist->Set_loop_stmt(newdo_wn);
03295 deflist = Du_Mgr->Ud_Get_Def(step_use);
03296 deflist->Set_loop_stmt(newdo_wn);
03297
03298
03299 {
03300 DO_LOOP_INFO* odli = (DO_LOOP_INFO*) Get_Do_Loop_Info(do_wn);
03301 DO_LOOP_INFO* dli = ((DO_LOOP_INFO*) CXX_NEW
03302 (DO_LOOP_INFO(odli, &LNO_default_pool),
03303 &LNO_default_pool));
03304 CXX_DELETE (odli->Mp_Info, odli->Pool());
03305 odli->Mp_Info = NULL;
03306 dli->Is_Inner = FALSE;
03307 Increment_Loop_Depths (do_wn);
03308 dli->Mp_Info->Disable_Plowering();
03309 Set_Do_Loop_Info (newdo_wn, dli);
03310 }
03311 return newdo_wn;
03312 }
03313
03314
03315
03316
03317
03318
03319
03320 static void Increment_Loop_Depths (WN* wn) {
03321 if (wn == NULL) return;
03322
03323 if (WN_opcode(wn) == OPC_DO_LOOP) {
03324 DO_LOOP_INFO* dli = (DO_LOOP_INFO*) Get_Do_Loop_Info(wn);
03325 dli->Depth = dli->Depth+1;
03326 Increment_Loop_Depths(WN_do_body(wn));
03327 return;
03328 }
03329
03330 if (WN_opcode(wn) == OPC_BLOCK) {
03331 WN* kid = WN_first(wn);
03332 while (kid) {
03333 Increment_Loop_Depths(kid);
03334 kid = WN_next(kid);
03335 }
03336 return;
03337 }
03338
03339 for (INT kidno = 0; kidno < WN_kid_count(wn); kidno++) {
03340 Increment_Loop_Depths(WN_kid(wn, kidno));
03341 }
03342 return;
03343 }
03344
03345
03346
03347
03348
03349
03350
03351
03352
03353 static WN* Read_Pragma_Page_Place (WN* pwn) {
03354 WN *addr_xpwn, *size_xpwn, *proc_xpwn;
03355
03356 if ((WN_opcode(pwn) != OPC_XPRAGMA) ||
03357 (WN_pragma(pwn) != WN_PRAGMA_PAGE_PLACE)) {
03358 ErrMsgSrcpos(EC_LNO_Bad_Pragma_String, WN_Get_Linenum(pwn),
03359 WN_pragmas[WN_pragma(pwn)].name,
03360 "Missing address expression (ignoring).");
03361 return pwn;
03362 }
03363 addr_xpwn = pwn;
03364 pwn = WN_next(pwn);
03365 if ((WN_opcode(pwn) != OPC_XPRAGMA) ||
03366 (WN_pragma(pwn) != WN_PRAGMA_PAGE_PLACE)) {
03367 ErrMsgSrcpos(EC_LNO_Bad_Pragma_String, WN_Get_Linenum(pwn),
03368 WN_pragmas[WN_pragma(pwn)].name,
03369 "Missing size expression (ignoring).");
03370 LWN_Delete_Tree_From_Block (addr_xpwn);
03371 return pwn;
03372 }
03373 size_xpwn = pwn;
03374 pwn = WN_next(pwn);
03375 if ((WN_opcode(pwn) != OPC_XPRAGMA) ||
03376 (WN_pragma(pwn) != WN_PRAGMA_PAGE_PLACE)) {
03377 ErrMsgSrcpos(EC_LNO_Bad_Pragma_String, WN_Get_Linenum(pwn),
03378 WN_pragmas[WN_pragma(pwn)].name,
03379 "Missing thread-num expression (ignoring).");
03380 LWN_Delete_Tree_From_Block (addr_xpwn);
03381 LWN_Delete_Tree_From_Block (size_xpwn);
03382 return pwn;
03383 }
03384 proc_xpwn = pwn;
03385 pwn = LWN_Get_Next_Stmt_Node(pwn);
03386
03387 OPCODE callop = OPCODE_make_op (OPR_CALL, MTYPE_V, MTYPE_V);
03388 WN* call_wn = WN_Create (callop, 3);
03389 WN_st_idx(call_wn) = ST_st_idx(distr_st_entries[Migrate_Pages]);
03390 Set_Runtime_Call_Side_Effects (call_wn);
03391 WN_linenum(call_wn) = LWN_Get_Linenum(pwn);
03392 WN* tmp_wn = LWN_Copy_Tree(WN_kid0(addr_xpwn));
03393 LWN_Copy_Def_Use (WN_kid0(addr_xpwn), tmp_wn, Du_Mgr);
03394 WN* parm_wn = WN_CreateParm (Pointer_type, tmp_wn,
03395 Be_Type_Tbl(Pointer_type),
03396 WN_PARM_BY_VALUE);
03397 LWN_Set_Parent (tmp_wn, parm_wn);
03398 WN_kid(call_wn, 0) = parm_wn;
03399 LWN_Set_Parent (parm_wn, call_wn);
03400 tmp_wn = LWN_Copy_Tree(WN_kid0(size_xpwn));
03401 parm_wn = WN_CreateParm (MTYPE_I8, tmp_wn,
03402 Be_Type_Tbl(MTYPE_I8), WN_PARM_BY_VALUE);
03403 LWN_Set_Parent (tmp_wn, parm_wn);
03404 WN_kid(call_wn, 1) = parm_wn;
03405 LWN_Set_Parent (parm_wn, call_wn);
03406 tmp_wn = LWN_Copy_Tree(WN_kid0(proc_xpwn));
03407 parm_wn = WN_CreateParm (MTYPE_I8, tmp_wn,
03408 Be_Type_Tbl(MTYPE_I8),
03409 WN_PARM_BY_VALUE);
03410 LWN_Set_Parent (tmp_wn, parm_wn);
03411 WN_kid(call_wn, 2) = parm_wn;
03412 LWN_Set_Parent (parm_wn, call_wn);
03413 LWN_Insert_Block_After (NULL, proc_xpwn, call_wn);
03414
03415 LWN_Delete_Tree_From_Block (addr_xpwn);
03416 LWN_Delete_Tree_From_Block (size_xpwn);
03417 LWN_Delete_Tree_From_Block (proc_xpwn);
03418 return pwn;
03419 }
03420
03421
03422
03423
03424
03425
03426 static BOOL Array_TY_OK (TY_IDX array_ty) {
03427 INT i;
03428 Is_True (TY_kind(array_ty) == KIND_ARRAY,
03429 ("Check_Array_TY called on a non-array"));
03430 INT ndims = TY_AR_ndims(array_ty);
03431 if (ndims == 0) return FALSE;
03432
03433 INT elem_size = TY_size(TY_AR_etype(array_ty));
03434 for (i=0; i<ndims; i++) {
03435
03436 if ((!TY_AR_const_lbnd(array_ty, i)) &&
03437 (TY_AR_lbnd_val(array_ty, i) == 0))
03438 return FALSE;
03439 if ((!TY_AR_const_ubnd(array_ty, i)) &&
03440 (TY_AR_ubnd_val(array_ty, i) == 0))
03441 return FALSE;
03442
03443
03444
03445
03446 if ((!TY_AR_const_stride(array_ty, i)) &&
03447 (TY_AR_stride_val(array_ty, i) == 0))
03448 return FALSE;
03449
03450
03451
03452
03453
03454 if ((i == ndims-1) && (TY_AR_stride_val(array_ty, i) != elem_size))
03455 return FALSE;
03456 }
03457 return TRUE;
03458 }
03459
03460
03461
03462
03463
03464
03465
03466
03467
03468
03469
03470
03471
03472
03473
03474 WN* Read_Pragma_Distribute (WN* pwn) {
03475 WN* first_pwn = pwn;
03476
03477
03478 ST *array_st = WN_st(pwn);
03479
03480 TY_IDX array_ty = Get_Array_Type(array_st);
03481
03482 if (TY_kind(array_ty) != KIND_ARRAY) {
03483 printf ("Pragma Distribute on a non-array\n");
03484 WN* retval = LWN_Get_Next_Stmt_Node(pwn);
03485 LWN_Delete_Tree_From_Block (pwn);
03486 return retval;
03487 }
03488
03489 if (!Array_TY_OK (array_ty)) {
03490 ErrMsgSrcpos(EC_LNO_Bad_Pragma_String, WN_Get_Linenum(pwn),
03491 WN_pragmas[WN_pragma(pwn)].name,
03492 "Bad array type, ignoring.");
03493 WN* retval = LWN_Get_Next_Stmt_Node(pwn);
03494 LWN_Delete_Tree_From_Block (pwn);
03495 return retval;
03496 }
03497
03498 mINT16 ndims = TY_AR_ndims (array_ty);
03499
03500 INT i;
03501
03502 #if 0
03503 printf ("Printing ST\n"); Print_ST (stdout, array_st, TRUE);
03504 printf ("Printing TY\n"); Print_TY (stdout, array_ty, TRUE);
03505 #endif
03506
03507 #ifdef Is_True_On
03508 FmtAssert (ST_class(array_st) == CLASS_VAR,
03509 ("Distributed array is not a variable"));
03510 FmtAssert (TY_AR_ndims(array_ty) > 0, ("Array with zero dimensions?\n"));
03511 #endif
03512
03513 #if 0
03514 ARI* ari = TY_arinfo(array_ty);
03515 printf ("printing element type\n");
03516 Print_TY (stdout, TY_AR_etype(array_ty), TRUE);
03517 printf ("%d dims\n", ndims);
03518 for (i=0; i<ndims; i++) {
03519 printf ("Dimension %d: lbnd = ", i);
03520 if (TY_AR_const_lbnd(array_ty, i))
03521 printf ("const, %d. ", TY_AR_lbnd_val(array_ty, i));
03522 else printf ("non-constant. ");
03523 printf (" ubnd = ");
03524 if (TY_AR_const_ubnd(array_ty, i))
03525 printf ("const, %d. \n", TY_AR_ubnd_val(array_ty, i));
03526 else printf ("non-constant. \n");
03527 }
03528 printf ("Now for the args: flag = %d, index = %d, preg = %d\n",
03529 WN_pragma_flag(pwn), WN_pragma_index(pwn), WN_pragma_preg(pwn));
03530 #endif
03531
03532
03533
03534
03535
03536
03537 if (Is_VLA (array_st)) {
03538 if (PU_src_lang(CURRENT_SYMTAB) == PU_C_LANG ||
03539 PU_src_lang(CURRENT_SYMTAB) == PU_CXX_LANG) {
03540 Move_Alloca (array_st);
03541 }
03542 }
03543
03544 DISTR_ARRAY* dact = New_DACT (&pwn, array_st, ndims);
03545 if (dact == NULL) {
03546
03547 WN* retval;
03548 while (first_pwn != pwn) {
03549 retval = LWN_Get_Next_Stmt_Node (first_pwn);
03550 LWN_Delete_Tree_From_Block (first_pwn);
03551 first_pwn = retval;
03552 }
03553 retval = LWN_Get_Next_Stmt_Node (first_pwn);
03554 LWN_Delete_Tree_From_Block (first_pwn);
03555 return retval;
03556 }
03557
03558 DISTR_INFO* dinfo = da_hash->Find(array_st);
03559 if (!dinfo) {
03560 SYMBOL* st_sym = CXX_NEW (SYMBOL(array_st, (WN_OFFSET) 0, 0),
03561 LEGO_pool);
03562 dinfo = CXX_NEW (DISTR_INFO (FALSE, ndims, st_sym), LEGO_pool);
03563 if (dynamic_list && dynamic_list->Find (array_st)) dinfo->Set_Dynamic();
03564 da_hash->Enter (array_st, dinfo);
03565 da_stack->Push (dinfo);
03566 }
03567 dinfo->Add_Dact (dact);
03568 dact->Convert_Expr_To_Symbol ();
03569 DB_PRINT(printf ("Distribute DACT\n");
03570 dact->Print (stdout));
03571
03572 return LWN_Get_Next_Stmt_Node(pwn);
03573 }
03574
03575
03576
03577
03578
03579
03580
03581
03582
03583
03584
03585
03586
03587
03588
03589
03590 static WN* Read_Pragma_Distribute_Reshape (WN* pwn) {
03591 WN* first_pwn = pwn;
03592 ST* array_st = WN_st(pwn);
03593
03594 if (ST_sclass(array_st) == SCLASS_DGLOBAL) {
03595
03596 FmtAssert (FALSE, ("Cannot reshape initialized data (%s)",
03597 ST_name(array_st)));
03598 WN* retval = LWN_Get_Next_Stmt_Node(pwn);
03599 LWN_Delete_Tree_From_Block (pwn);
03600 return retval;
03601 }
03602
03603 if (ST_is_initialized(array_st)) {
03604
03605 FmtAssert (FALSE, ("Cannot reshape initialized data (%s)",
03606 ST_name(array_st)));
03607 WN* retval = LWN_Get_Next_Stmt_Node(pwn);
03608 LWN_Delete_Tree_From_Block (pwn);
03609 return retval;
03610 }
03611
03612 TY_IDX array_ty = Get_Array_Type (array_st);
03613
03614 if (TY_kind(array_ty) != KIND_ARRAY) {
03615 FmtAssert (FALSE, ("Pragma Distribute-Reshape on a non-array (%s)\n",
03616 ST_name(array_st)));
03617 WN* retval = LWN_Get_Next_Stmt_Node(pwn);
03618 LWN_Delete_Tree_From_Block (pwn);
03619 return retval;
03620 }
03621
03622 if (!Array_TY_OK (array_ty)) {
03623 ErrMsgSrcpos(EC_LNO_Bad_Pragma_String, WN_Get_Linenum(pwn),
03624 WN_pragmas[WN_pragma(pwn)].name,
03625 "Bad array type, ignoring.");
03626 FmtAssert (FALSE, ("Cannot reshape array %s\n",
03627 ST_name(array_st)));
03628 WN* retval = LWN_Get_Next_Stmt_Node(pwn);
03629 LWN_Delete_Tree_From_Block (pwn);
03630 return retval;
03631 }
03632
03633 mINT16 ndims = TY_AR_ndims (array_ty);
03634 FmtAssert (ST_class(array_st) == CLASS_VAR,
03635 ("Distribute-reshaped array is not a variable"));
03636 FmtAssert (TY_AR_ndims(array_ty) > 0, ("Array with zero dimensions?\n"));
03637
03638 DISTR_ARRAY* dact = New_DACT (&pwn, array_st, ndims);
03639 if (dact == NULL) {
03640 FmtAssert (FALSE, ("Could not process distribute_reshape %s\n",
03641 ST_name(array_st)));
03642 WN* retval;
03643 while (first_pwn != pwn) {
03644 retval = LWN_Get_Next_Stmt_Node (first_pwn);
03645 LWN_Delete_Tree_From_Block (first_pwn);
03646 first_pwn = retval;
03647 }
03648 retval = LWN_Get_Next_Stmt_Node (first_pwn);
03649 LWN_Delete_Tree_From_Block (first_pwn);
03650 return retval;
03651 }
03652
03653 DISTR_INFO* dinfo = da_hash->Find(array_st);
03654 if (!dinfo) {
03655 SYMBOL* st_sym = CXX_NEW (SYMBOL(array_st, (WN_OFFSET) 0, 0),
03656 LEGO_pool);
03657 dinfo = CXX_NEW (DISTR_INFO (TRUE, ndims, st_sym), LEGO_pool);
03658 if (dynamic_list->Find (array_st)) dinfo->Set_Dynamic();
03659 da_hash->Enter (array_st, dinfo);
03660 da_stack->Push (dinfo);
03661 }
03662 dinfo->Add_Dact (dact);
03663 dact->Convert_Expr_To_Symbol();
03664 DB_PRINT(printf ("Distribute-Reshape DACT\n");
03665 dact->Print (stdout));
03666 if (ST_Var_Kind(array_st) == var_common)
03667 PU_has_reshaped_commons = TRUE;
03668 return LWN_Get_Next_Stmt_Node(pwn);
03669 }
03670
03671
03672
03673
03674
03675
03676
03677
03678
03679
03680
03681
03682
03683
03684
03685
03686
03687
03688 extern WN* Read_Pragma_Redistribute (WN* pwn, BOOL gen_phase) {
03689
03690
03691
03692
03693
03694
03695 WN* first_pwn = pwn;
03696 ST* array_st = WN_st(pwn);
03697
03698 TY_IDX array_ty = Get_Array_Type(array_st);
03699
03700 if (TY_kind(array_ty) != KIND_ARRAY) {
03701 printf ("Pragma ReDistribute on a non-array\n");
03702 WN* retval = LWN_Get_Next_Stmt_Node(pwn);
03703 LWN_Delete_Tree_From_Block (pwn);
03704 return retval;
03705 }
03706
03707 if (!Array_TY_OK (array_ty)) {
03708 ErrMsgSrcpos(EC_LNO_Bad_Pragma_String, WN_Get_Linenum(pwn),
03709 WN_pragmas[WN_pragma(pwn)].name,
03710 "Bad array type, ignoring.");
03711 WN* retval = LWN_Get_Next_Stmt_Node(pwn);
03712 LWN_Delete_Tree_From_Block (pwn);
03713 return retval;
03714 }
03715
03716 mINT16 ndims = TY_AR_ndims (array_ty);
03717
03718 INT i;
03719
03720 #ifdef Is_True_On
03721 FmtAssert (ST_class(array_st) == CLASS_VAR,
03722 ("ReDistributed array is not a variable"));
03723 FmtAssert (TY_AR_ndims(array_ty) > 0, ("Array with zero dimensions?\n"));
03724 #endif
03725
03726
03727 if (Is_VLA (array_st)) {
03728 if (PU_src_lang(CURRENT_SYMTAB) == PU_C_LANG ||
03729 PU_src_lang(CURRENT_SYMTAB) == PU_CXX_LANG) {
03730 Move_Alloca (array_st);
03731 }
03732 }
03733
03734 DISTR_ARRAY* dact = New_DACT (&pwn, array_st, ndims);
03735 if (dact == NULL) {
03736
03737 WN* retval;
03738 while (first_pwn != pwn) {
03739 retval = LWN_Get_Next_Stmt_Node (first_pwn);
03740 LWN_Delete_Tree_From_Block (first_pwn);
03741 first_pwn = retval;
03742 }
03743 retval = LWN_Get_Next_Stmt_Node (first_pwn);
03744 LWN_Delete_Tree_From_Block (first_pwn);
03745 return retval;
03746 }
03747
03748 DISTR_INFO* dinfo = da_hash->Find(array_st);
03749 if (!dinfo) {
03750 SYMBOL* st_sym = CXX_NEW (SYMBOL(array_st, (WN_OFFSET) 0, 0),
03751 LEGO_pool);
03752 dinfo = CXX_NEW (DISTR_INFO (FALSE, ndims, st_sym), LEGO_pool);
03753 if (dynamic_list->Find (array_st)) dinfo->Set_Dynamic();
03754 da_hash->Enter (array_st, dinfo);
03755 da_stack->Push (dinfo);
03756 }
03757 if (gen_phase) dinfo->Add_Gen_Redistr (dact);
03758 else dinfo->Add_Redistr (dact);
03759 dact->Convert_Expr_To_Symbol();
03760 DB_PRINT(printf ("Redistribute DACT\n");
03761 dact->Print (stdout));
03762
03763 return LWN_Get_Next_Stmt_Node(pwn);
03764 }
03765
03766
03767
03768
03769
03770
03771
03772
03773
03774
03775
03776
03777
03778
03779
03780
03781
03782
03783
03784
03785
03786
03787
03788
03789
03790
03791 static DISTR_ARRAY* New_DACT (WN** pwn_addr, ST* array_st, INT ndims) {
03792 INT i;
03793 DISTR_DIM* dd;
03794 DISTR_ARRAY* dact = NULL;
03795 WN *pwn = *pwn_addr;
03796 WN *first_pwn = pwn;
03797 WN *last_pwn = pwn;
03798 INT distr_dim = 0;
03799 WN_PRAGMA_ID pragma_id = WN_PRAGMA_UNDEFINED;
03800 WN** bounds_wns;
03801
03802 dd = CXX_NEW_ARRAY (DISTR_DIM, ndims, LEGO_pool);
03803 bounds_wns = CXX_NEW_ARRAY (WN*, ndims, LEGO_pool);
03804 for (i=0; i<ndims; i++) {
03805
03806 FmtAssert (WN_opcode(pwn) == OPC_PRAGMA,
03807 ("Distribute_Pragma: node isn't a pragma node\n"));
03808 pragma_id = (WN_PRAGMA_ID) WN_pragma(pwn);
03809 FmtAssert ((pragma_id == WN_PRAGMA_DISTRIBUTE) ||
03810 (pragma_id == WN_PRAGMA_DISTRIBUTE_RESHAPE) ||
03811 (pragma_id == WN_PRAGMA_REDISTRIBUTE),
03812 ("Distribute_Pragma: node isn't a distribute pragma\n"));
03813 #ifdef Is_True_On
03814 if (WN_pragma_index(pwn) != i) {
03815 DevWarn ("Subscript mismatch: expect %d, got %d, in distr pragma",
03816 i, WN_pragma_index(pwn));
03817 }
03818 #endif
03819 switch (WN_pragma_distr_type(pwn)) {
03820 case DISTRIBUTE_STAR:
03821 dd[i].Init_Block_Star ((DISTRIBUTE_TYPE) WN_pragma_distr_type(pwn));
03822 break;
03823 case DISTRIBUTE_BLOCK:
03824 distr_dim++;
03825 dd[i].Init_Block_Star ((DISTRIBUTE_TYPE) WN_pragma_distr_type(pwn));
03826 break;
03827 case DISTRIBUTE_CYCLIC_CONST:
03828 distr_dim++;
03829 dd[i].Init_Cyclic_Const ((DISTRIBUTE_TYPE) WN_pragma_distr_type(pwn),
03830 (INT64) WN_pragma_arg2(pwn), pwn);
03831 break;
03832 case DISTRIBUTE_CYCLIC_EXPR:
03833 distr_dim++;
03834 last_pwn = pwn;
03835 pwn = LWN_Get_Next_Stmt_Node(pwn);
03836 FmtAssert (WN_operator(pwn) == OPR_XPRAGMA,
03837 ("Expected an XPRAGMA node"));
03838 FmtAssert (WN_pragma(pwn) == pragma_id,
03839 ("Unexpected type of XPRAGMA node"));
03840 if ((pragma_id == WN_PRAGMA_DISTRIBUTE_RESHAPE) &&
03841 (WN_operator(WN_kid0(pwn)) == OPR_INTCONST) &&
03842 (WN_const_val(WN_kid0(pwn)) == 0)) {
03843 FmtAssert (ST_Var_Kind(array_st) == var_formal,
03844 ("cyclic_expr(0) can only be on formal parameters"));
03845 FmtAssert (WN_pragma_compiler_generated(pwn),
03846 ("cyclic_expr(0) should be a compiler-generated pragma"));
03847 }
03848 dd[i].Init_Cyclic_Expr ((DISTRIBUTE_TYPE)
03849 WN_pragma_distr_type(last_pwn),
03850 WN_kid0 (pwn));
03851 break;
03852 default:
03853 FmtAssert (FALSE, ("Strange distribute type\n"));
03854 break;
03855 }
03856 last_pwn = pwn;
03857 pwn = LWN_Get_Next_Stmt_Node(pwn);
03858
03859
03860 FmtAssert (WN_opcode(pwn) == OPC_XPRAGMA,
03861 ("Distribute_Pragma: expected a bounds xpragma\n"));
03862 pragma_id = (WN_PRAGMA_ID) WN_pragma(pwn);
03863 FmtAssert (pragma_id == WN_pragma(pwn),
03864 ("Distribute_Pragma: bound has different pragma type\n"));
03865
03866
03867
03868
03869 if (PU_has_altentry(Get_Current_PU()) &&
03870 WN_operator(WN_kid0(pwn)) != OPR_INTCONST) {
03871 ErrMsgSrcpos(EC_DRA_unsupported_type,
03872 WN_Get_Linenum(pwn),
03873 WN_pragmas[WN_pragma(pwn)].name,
03874 ST_name(array_st),
03875 "Distribution of adjustable size arrays in functions with alternate entry points is currently not supported");
03876 }
03877
03878 bounds_wns[i] = pwn;
03879 last_pwn = pwn;
03880 pwn = LWN_Get_Next_Stmt_Node(pwn);
03881 }
03882
03883
03884 INT64* onto = NULL;
03885 {
03886 WN* onto_wn = pwn;
03887
03888 INT count = 0;
03889 while (onto_wn) {
03890 if (WN_operator(onto_wn) != OPR_STID) break;
03891 count++;
03892 if (count > 2) break;
03893 onto_wn = LWN_Get_Next_Stmt_Node (onto_wn);
03894 }
03895 if (onto_wn &&
03896 WN_opcode(onto_wn) == OPC_XPRAGMA &&
03897 WN_pragma(onto_wn) == WN_PRAGMA_ONTO) {
03898
03899 onto = CXX_NEW_ARRAY (INT64, ndims, LEGO_pool);
03900 for (INT i=0; i<ndims; i++) {
03901 onto[i] = -1;
03902 if (dd[i].Distr_Type() != DISTRIBUTE_STAR) {
03903 Is_True (onto_wn &&
03904 WN_opcode(onto_wn) == OPC_XPRAGMA &&
03905 WN_pragma(onto_wn) == WN_PRAGMA_ONTO,
03906 ("Searching for ONTO: not enough of them\n"));
03907 Is_True (WN_kid0(onto_wn) &&
03908 WN_operator(WN_kid0(onto_wn))==OPR_INTCONST,
03909 ("Searching for ONTO: expected an INT-CONST kid\n"));
03910 onto[i] = WN_const_val(WN_kid0(onto_wn));
03911 last_pwn = onto_wn;
03912 onto_wn = WN_next(onto_wn);
03913 }
03914 }
03915 pwn = onto_wn;
03916 }
03917 }
03918
03919 if (distr_dim) {
03920 SYMBOL* st_sym = CXX_NEW (SYMBOL(array_st, (WN_OFFSET) 0, 0),
03921 LEGO_pool);
03922 dact = CXX_NEW (DISTR_ARRAY(dd, first_pwn, last_pwn, bounds_wns, onto),
03923 LEGO_pool);
03924
03925 #if 0
03926
03927
03928 WN* xpwn = LWN_Get_Next_Stmt_Node(last_pwn);
03929 if (xpwn != pwn)
03930 DevWarn ("Array %s with no dimensions???", ST_name(array_st));
03931 Is_True (WN_operator(xpwn) == OPR_XPRAGMA,
03932 ("Array %s: Missing xpragma node with sample array reference",
03933 ST_name(array_st)));
03934 Is_True (WN_pragma(xpwn) == pragma_id,
03935 ("Array %s: Bad pragma type in sample array reference xpragma",
03936 ST_name(array_st)));
03937 Is_True (WN_operator(WN_kid0(xpwn)) == OPR_ARRAY,
03938 ("Array %s: Expected opc_array as kid of sample ref xpragma",
03939 ST_name(array_st)));
03940 WN* base = WN_array_base(WN_kid0(xpwn));
03941 Is_True ((WN_operator(base) == OPR_LDA) ||
03942 (WN_operator(base) == OPR_LDID),
03943 ("Array %s: sample reference has bad base", ST_name(array_st)));
03944 Is_True (WN_st(base) == array_st,
03945 ("Array %s: unexpected ST in base of sample reference",
03946 ST_name(array_st), ST_name(WN_st(base))));
03947 dact->Set_Array_XPragma_WN(xpwn);
03948 #endif
03949 #if 0
03950
03951 {
03952
03953 TY_IDX array_ty = Get_Array_Type(array_st);
03954 INT ndims = TY_AR_ndims(array_ty);
03955 INT i;
03956 OPCODE array_op = OPCODE_make_op(OPR_ARRAY, (Pointer_Size == 8 ?
03957 MTYPE_U8 : MTYPE_U4),
03958 MTYPE_V);
03959 WN* array_wn = WN_Create (array_op, 2*ndims+1);
03960 WN* base_wn;
03961 if (TY_kind(array_ty) == KIND_POINTER) {
03962 OPCODE ldid_op = OPCODE_make_op (OPR_LDID, Pointer_type, Pointer_type);
03963 base_wn = WN_CreateLdid (ldid_op, 0, array_st, ST_type(array_st));
03964 }
03965 else {
03966 OPCODE lda_op = OPCODE_make_op (OPR_LDA, Pointer_type, MTYPE_V);
03967 base_wn = WN_CreateLda(lda_op, 0,
03968 Make_Pointer_Type(ST_type(array_st)),
03969 array_st);
03970 }
03971 WN_array_base(array_wn) = base_wn;
03972 for (i=0; i<ndims; i++) {
03973 WN_array_index(array_wn, i) = LWN_Make_Icon (MTYPE_I4, 0);
03974 if (TY_AR_const_ubnd(array_ty, ndims-i-1))
03975 WN_array_dim(array_wn, i) =
03976 LWN_Make_Icon (MTYPE_I4, TY_AR_ubnd_val(array_ty, ndims-i-1));
03977 else
03978 WN_array_dim(array_wn, i) =
03979 LWN_Copy_Tree (TY_AR_ubnd_tree(array_ty, ndims-i-1));
03980 }
03981
03982
03983 WN* xpwn = WN_Create(OPC_XPRAGMA, 1);
03984 WN_pragma(xpwn) = pragma_id;
03985 WN_st(xpwn) = array_st;
03986 WN_kid0(xpwn) = array_wn;
03987 LWN_Parentize(xpwn);
03988 dact->Set_Array_XPragma_WN(xpwn);
03989 dact->Set_Last_Pragma_WN(xpwn);
03990 LWN_Insert_Block_After (NULL, last_pwn, xpwn);
03991 last_pwn = xpwn;
03992 }
03993 #endif
03994 }
03995 else {
03996 CXX_DELETE_ARRAY (dd, LEGO_pool);
03997 CXX_DELETE_ARRAY (bounds_wns, LEGO_pool);
03998 }
03999 *pwn_addr = last_pwn;
04000 return dact;
04001 }