00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056 #ifdef USE_PCH
00057 #include "lno_pch.h"
00058 #endif // USE_PCH
00059 #pragma hdrstop
00060
00061 const static char *source_file = __FILE__;
00062
00063 #include <alloca.h>
00064 #include <sys/types.h>
00065 #include <ctype.h>
00066 #include <limits.h>
00067
00068 #include "pu_info.h"
00069 #include "lnopt_main.h"
00070 #include "errors.h"
00071 #include "lego_util.h"
00072 #include "lego_pragma.h"
00073 #include "lwn_util.h"
00074 #include "lnoutils.h"
00075 #include "lego_opts.h"
00076 #include "strtab.h"
00077 #include "const.h"
00078 #include "targ_const.h"
00079 #include "tile.h"
00080 #include "targ_sim.h"
00081
00082 extern VAR_KIND ST_Var_Kind (ST* array_st);
00083 extern WN* Get_Numthreads_Ldid (LEGO_INFO* li);
00084 extern WN* Get_Runtime_Numthreads_Ldid ();
00085 extern mBOOL Single_Loop_Coeff(ACCESS_VECTOR *av, INT64 *stride, INT64 *offset,
00086 mINT32 *depth);
00087
00088
00089
00090
00091
00092
00093
00094 VAR_KIND ST_Var_Kind (ST* array_st) {
00095 VAR_KIND retval;
00096
00097 #ifdef _NEW_SYMTAB
00098 switch (ST_sclass(array_st)) {
00099
00100 case SCLASS_PSTATIC:
00101 case SCLASS_AUTO:
00102 retval = var_local;
00103 break;
00104 case SCLASS_FORMAL:
00105 retval = var_formal;
00106 break;
00107
00108
00109 case SCLASS_FSTATIC:
00110
00111 case SCLASS_EXTERN:
00112 case SCLASS_UGLOBAL:
00113
00114
00115
00116 case SCLASS_DGLOBAL:
00117
00118
00119 retval = var_global;
00120 break;
00121
00122
00123
00124
00125
00126 case SCLASS_COMMON:
00127
00128 FmtAssert (ST_base(array_st) != array_st,
00129 ("SCLASS of array (%s) is a COMMON", ST_name(array_st)));
00130 Is_True (ST_sclass(ST_base(array_st)) == SCLASS_COMMON,
00131 ("ST (%s) is BASED, but base is not a COMMON or AUTO\n",
00132 ST_name(array_st)));
00133 retval = var_common;
00134 break;
00135
00136
00137 case SCLASS_TEXT:
00138 case SCLASS_REG:
00139 default:
00140 FmtAssert (FALSE, ("Unexpected SCLASS (%d) of distributed array\n",
00141 ST_sclass(array_st)));
00142 break;
00143 }
00144 Is_True (((retval != var_global) && (retval != var_common)) ||
00145 (ST_level(array_st) == GLOBAL_SYMTAB),
00146 ("ST %s: is in Global_Symtab, but we don't think it is global\n",
00147 ST_name(array_st)));
00148
00149 #else
00150 switch (ST_sclass(array_st)) {
00151
00152 case SCLASS_PSTATIC:
00153 case SCLASS_AUTO:
00154 retval = var_local;
00155 break;
00156 case SCLASS_FORMAL:
00157 retval = var_formal;
00158 break;
00159
00160
00161 case SCLASS_FSTATIC:
00162
00163 case SCLASS_EXTERN:
00164 case SCLASS_UGLOBAL:
00165
00166
00167
00168 case SCLASS_DGLOBAL:
00169
00170
00171 retval = var_global;
00172 break;
00173
00174
00175
00176
00177
00178 case SCLASS_BASED:
00179 if (ST_sclass(ST_base(array_st)) == SCLASS_COMMON)
00180 retval = var_common;
00181 else if (ST_sclass(ST_base(array_st)) == SCLASS_AUTO)
00182 retval = var_local;
00183 else
00184 FmtAssert(FALSE, ("ST (%s) is BASED, but base is not a COMMON or AUTO\n",
00185 ST_name(array_st)));
00186 break;
00187 case SCLASS_COMMON:
00188 FmtAssert (FALSE, ("SCLASS of array (%s) is a COMMON", ST_name(array_st)));
00189 break;
00190
00191
00192 case SCLASS_TEXT:
00193 case SCLASS_THREAD:
00194 case SCLASS_REG:
00195 default:
00196 FmtAssert (FALSE, ("Unexpected SCLASS (%d) of distributed array\n",
00197 ST_sclass(array_st)));
00198 break;
00199 }
00200 Is_True ((retval != var_global) || (ST_is_global(array_st)),
00201 ("ST %s: is in Global_Symtab, but we don't think it is global\n",
00202 ST_name(array_st)));
00203 #endif
00204
00205 return retval;
00206 }
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216 extern TY_IDX Get_Original_Type (ST* st) {
00217
00218 TY_IDX ty;
00219
00220 if (ST_class(st) != CLASS_VAR) return ST_type(st);
00221
00222 #ifdef _NEW_SYMTAB
00223 if (ST_level(st) == GLOBAL_SYMTAB && ST_is_reshaped(st)) {
00224 #else
00225 if (ST_is_global(st) && ST_is_reshaped(st)) {
00226 #endif
00227
00228 DISTR_GLOBAL_INFO* dgi = da_global->Find(st);
00229
00230 if (dgi) {
00231
00232 ty = dgi->Get_TY();
00233 }
00234 else {
00235
00236
00237 ty = (TY_IDX) NULL;
00238
00239
00240
00241
00242 if (FILE_INFO_ipa(File_info) && Read_Global_Data) {
00243 WN *pwn = WN_first(WN_func_pragmas(Current_Func_Node));
00244 while (pwn) {
00245 if (WN_operator(pwn) == OPR_PRAGMA &&
00246 WN_pragma(pwn) == WN_PRAGMA_TYPE_OF_RESHAPED_ARRAY &&
00247 WN_st(pwn) == st) {
00248 ty = WN_pragma_arg1(pwn);
00249 break;
00250 }
00251 pwn = WN_next(pwn);
00252 }
00253 }
00254
00255 if (ty == (TY_IDX) NULL) {
00256 ty = ST_type(st);
00257 }
00258 DISTR_GLOBAL_INFO* dgi = CXX_NEW (DISTR_GLOBAL_INFO(ty),
00259 Malloc_Mem_Pool);
00260 da_global->Enter (st, dgi);
00261 }
00262 }
00263 else {
00264 ty = ST_type(st);
00265 }
00266 return ty;
00267 }
00268
00269
00270
00271
00272
00273
00274 extern TY_IDX Get_Array_Type (ST* st) {
00275 TY_IDX ty;
00276
00277 ty = Get_Original_Type(st);
00278
00279 if ((TY_kind(ty) == KIND_POINTER) && (ST_isFormal(st) || ST_isLocal(st))) {
00280 ty = TY_pointed(ty);
00281 }
00282
00283 return ty;
00284 }
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294 DISTR_ARRAY *Lookup_DACT(ST *array_st) {
00295
00296 DISTR_INFO* dinfo = da_hash->Find (array_st);
00297 if (!dinfo) return NULL;
00298 Is_True (dinfo->Num_Dact() == 1,
00299 ("Array %s has %d distributions\n",
00300 ST_name(array_st), dinfo->Num_Dact()));
00301 return dinfo->Get_Dact(0);
00302 }
00303
00304
00305
00306
00307
00308
00309
00310
00311 extern WN* Get_Numthreads_Ldid (LEGO_INFO* li) {
00312 ST *array_st = (li->Array())->St();
00313 Is_True (array_st, ("Lego_Info has no distributed array"));
00314 DISTR_INFO* dinfo = da_hash->Find(array_st);
00315 Is_True (dinfo, ("Array %s has no dinfo", ST_name(array_st)));
00316 return dinfo->Numprocs(li->Dim_Num());
00317 }
00318
00319
00320
00321
00322
00323
00324
00325 extern WN* Get_Runtime_Numthreads_Ldid () {
00326 #ifdef KEY
00327 if (LNO_Num_Processors != 0)
00328 return LWN_Make_Icon(MTYPE_I4, LNO_Num_Processors);
00329 #endif
00330 OPCODE ldid_op = OPCODE_make_op(OPR_LDID, MTYPE_I4, MTYPE_I4);
00331 WN* ldid_wn = WN_CreateLdid (ldid_op, 0, distr_st_entries[mp_sug_numthreads],
00332 Be_Type_Tbl(MTYPE_I4));
00333 Create_global_alias (Alias_Mgr, distr_st_entries[mp_sug_numthreads],
00334 ldid_wn, NULL);
00335 Du_Mgr->Add_Def_Use (Current_Func_Node, ldid_wn);
00336 return ldid_wn;
00337 }
00338
00339
00340
00341
00342
00343
00344
00345
00346 extern WN* Get_Runtime_Numthreads_Ldid_From_Func (WN* prev_wn) {
00347
00348 OPCODE callop = OPCODE_make_op(OPR_CALL, MTYPE_I4, MTYPE_V);
00349 WN* call_wn = WN_Create(callop, 0);
00350 WN_st_idx(call_wn) = ST_st_idx(distr_st_entries[mp_numthreads_fn]);
00351 Set_Runtime_Call_Side_Effects (call_wn);
00352 LWN_Insert_Block_Before (NULL, prev_wn, call_wn);
00353
00354 PREG_NUM rreg1, rreg2;
00355 ST* rst = Find_Return_Registers (MTYPE_I4, &rreg1, &rreg2);
00356 FmtAssert(rreg1 != 0 && rreg2 == 0, ("Bad MTYPE_I4 return regs"));
00357
00358 WN* ldid_wn = WN_CreateLdid (OPCODE_make_op(OPR_LDID, MTYPE_I4, MTYPE_I4),
00359 rreg1, rst, Be_Type_Tbl(MTYPE_I4));
00360 Create_alias (Alias_Mgr, ldid_wn);
00361 Du_Mgr->Add_Def_Use (call_wn, ldid_wn);
00362 return ldid_wn;
00363 }
00364
00365
00366
00367
00368
00369
00370 extern WN* Get_Runtime_Cur_Numthreads_Ldid () {
00371 OPCODE ldid_op = OPCODE_make_op(OPR_LDID, MTYPE_I4, MTYPE_I4);
00372 WN* ldid_wn = WN_CreateLdid (ldid_op, 0, distr_st_entries[mp_cur_numthreads],
00373 Be_Type_Tbl(MTYPE_I4));
00374 Create_global_alias (Alias_Mgr, distr_st_entries[mp_cur_numthreads],
00375 ldid_wn, NULL);
00376 Du_Mgr->Add_Def_Use (Current_Func_Node, ldid_wn);
00377 return ldid_wn;
00378 }
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390 static WN *Fast_32_Div(TYPE_ID rtype, WN *kid0, WN *kid1, BOOL can_speculate)
00391 {
00392 WN *cvti = LWN_CreateExp1(OPCODE_make_op(OPR_CVT,MTYPE_F8,rtype),kid0);
00393 WN *cvtj = LWN_CreateExp1(OPCODE_make_op(OPR_CVT,MTYPE_F8,rtype),kid1);
00394 WN *eps = Make_Const (Host_To_Targ_Float (MTYPE_F8, 1.000000000000001));
00395 WN *div = LWN_CreateExp2(OPC_F8DIV,eps,cvtj);
00396 if (can_speculate) WN_MAP_Set(Safe_Spec_Map, div, (void*) 1);
00397 WN *mpy = LWN_CreateExp2(OPC_F8MPY,cvti,div);
00398 WN *trunc = LWN_CreateExp1(OPCODE_make_op(OPR_TRUNC,rtype,MTYPE_F8),mpy);
00399 return trunc;
00400 }
00401
00402
00403
00404
00405
00406
00407 static WN *Fast_32_Rem(TYPE_ID rtype, WN *kid0, WN *kid1, BOOL can_speculate)
00408 {
00409 WN *cvtj = LWN_CreateExp1(OPCODE_make_op(OPR_CVT,MTYPE_F8,rtype),kid1);
00410 WN *newcvtj = LWN_Copy_Tree(cvtj,TRUE, LNO_Info_Map);
00411 LWN_Copy_Def_Use(cvtj, newcvtj, Du_Mgr);
00412 WN *eps = Make_Const (Host_To_Targ_Float (MTYPE_F8, 1.000000000000001));
00413 WN *div = LWN_CreateExp2(OPC_F8DIV,eps,cvtj);
00414 if (can_speculate) WN_MAP_Set(Safe_Spec_Map, div, (void*) 1);
00415 WN *cvti = LWN_CreateExp1(OPCODE_make_op(OPR_CVT,MTYPE_F8,rtype),kid0);
00416 WN *newcvti = LWN_Copy_Tree(cvti,TRUE,LNO_Info_Map);
00417 LWN_Copy_Def_Use(cvti, newcvti, Du_Mgr);
00418 WN *mpy = LWN_CreateExp2(OPC_F8MPY,cvti,div);
00419 WN *trunc = LWN_CreateExp1(OPCODE_make_op(OPR_TRUNC,rtype,MTYPE_F8),mpy);
00420 WN *cvt = LWN_CreateExp1(OPCODE_make_op(OPR_CVT,MTYPE_F8,rtype),trunc);
00421 mpy = LWN_CreateExp2(OPC_F8MPY,cvt,newcvtj);
00422 WN *sub = LWN_CreateExp2(OPC_F8SUB,newcvti,mpy);
00423 return LWN_CreateExp1(OPCODE_make_op(OPR_TRUNC,rtype,MTYPE_F8),sub);
00424 }
00425
00426 WN*
00427 AWN_Binary(OPERATOR opr,
00428 TYPE_ID rtype,
00429 WN *kid0,
00430 WN *kid1,
00431 BOOL can_speculate)
00432 {
00433 if (!Get_Trace(TP_LNOPT2, TT_LEGO_DISABLE_FP_DIVMOD)) {
00434 if (opr == OPR_REM) {
00435 TYPE_ID r0type = WN_rtype(kid0);
00436 TYPE_ID r1type = WN_rtype(kid1);
00437 if (((rtype == MTYPE_I4) || (rtype == MTYPE_U4)) &&
00438 ((r1type == MTYPE_I4) || (r1type == MTYPE_U4)) &&
00439 ((r1type == MTYPE_I4) || (r1type == MTYPE_U4))) {
00440 return Fast_32_Rem(rtype, kid0, kid1, can_speculate);
00441 }
00442 } else if (opr == OPR_DIV) {
00443 TYPE_ID r0type = WN_rtype(kid0);
00444 TYPE_ID r1type = WN_rtype(kid1);
00445 if (((rtype == MTYPE_I4) || (rtype == MTYPE_U4)) &&
00446 ((r1type == MTYPE_I4) || (r1type == MTYPE_U4)) &&
00447 ((r1type == MTYPE_I4) || (r1type == MTYPE_U4))) {
00448 return Fast_32_Div(rtype,kid0,kid1,can_speculate);
00449 }
00450 }
00451 }
00452 OPCODE op = OPCODE_make_op(opr, rtype, MTYPE_V);
00453 WN* ret_wn = LWN_CreateExp2(op, kid0, kid1);
00454 if ((opr == OPR_REM || opr == OPR_DIV || opr == OPR_MOD) && can_speculate)
00455 WN_MAP_Set(Safe_Spec_Map, ret_wn, (void*) 1);
00456 return ret_wn;
00457 }
00458
00459
00460 WN*
00461 AWN_LdidSym(SYMBOL *var)
00462 {
00463 Is_True(var && ((ST_class(var->St()) == CLASS_PREG) ||
00464 (ST_class(var->St()) == CLASS_VAR)),
00465 ("AWN_LdidSym called with SYMBOL that is not a preg or a variable\n"));
00466
00467 TYPE_ID desc = var->Type;
00468 WN *the_ldid = WN_RLdid(Promote_Type(desc), desc, var->WN_Offset(),
00469 var->St(), ST_type(var->St()));
00470 Create_alias(Alias_Mgr, the_ldid);
00471
00472 return (the_ldid);
00473 }
00474
00475
00476 WN*
00477 AWN_StidIntoSym(SYMBOL *var,
00478 WN *val)
00479 {
00480 Is_True(var && ((ST_class(var->St()) == CLASS_PREG) ||
00481 (ST_class(var->St()) == CLASS_VAR)),
00482 ("AWN_StidIntoSym called with SYMBOL that is not a preg or a variable\n"));
00483
00484 TYPE_ID desc = var->Type;
00485 OPCODE op = OPCODE_make_op(OPR_STID, MTYPE_V, desc);
00486 WN *the_stid = LWN_CreateStid(op, var->WN_Offset(), var->St(),
00487 ST_type(var->St()), val);
00488 Create_alias(Alias_Mgr, the_stid);
00489
00490 return (the_stid);
00491 }
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502 WN*
00503 Create_Positive_Divceil(TYPE_ID type,
00504 WN *kid0,
00505 WN *kid1,
00506 BOOL can_speculate)
00507 {
00508 WN *kid1_copy = LWN_Copy_Tree(kid1);
00509 LWN_Copy_Def_Use(kid1, kid1_copy, Du_Mgr);
00510
00511 WN *sub = AWN_Sub(type, kid1_copy, LWN_Make_Icon(type, 1));
00512 WN *add = AWN_Add(type, kid0, sub);
00513
00514 WN* div;
00515 if (can_speculate) div = AWN_Div_Safe(type, add, kid1);
00516 else div = AWN_Div(type, add, kid1);
00517 return (div);
00518 }
00519
00520
00521 void
00522 Set_Array_Dim(WN *array_expr,
00523 INT dim,
00524 WN *bound,
00525 WN *index)
00526 {
00527 INT num_dim = WN_num_dim(array_expr);
00528 Is_True((dim >= 0) && (dim < num_dim),
00529 ("Dim %d out of range 0..%d\n", dim, num_dim - 1));
00530
00531 WN_array_dim(array_expr, dim) = bound;
00532 WN_array_index(array_expr, dim) = index;
00533 LWN_Set_Parent(bound, array_expr);
00534 LWN_Set_Parent(index, array_expr);
00535 }
00536
00537
00538
00539
00540
00541
00542 void
00543 Replace_WN(WN *old_wn,
00544 WN *new_wn)
00545 {
00546 WN *parent = LWN_Get_Parent(old_wn);
00547
00548 Is_True (parent, ("Replace_WN: expected a parent node"));
00549
00550 if (WN_opcode(parent) != OPC_BLOCK) {
00551 INT kidno;
00552
00553 for (kidno = 0; kidno < WN_kid_count(parent); kidno++) {
00554 if (WN_kid(parent, kidno) == old_wn)
00555 break;
00556 }
00557 Is_True(kidno < WN_kid_count(parent), ("Bad parent pointer\n"));
00558
00559 WN_kid(parent, kidno) = new_wn;
00560 }
00561 else {
00562 WN_prev(new_wn) = WN_prev(old_wn);
00563 WN_next(new_wn) = WN_next(old_wn);
00564
00565 if (WN_prev(new_wn)) WN_next(WN_prev(new_wn)) = new_wn;
00566 else WN_first(parent) = new_wn;
00567 if (WN_next(new_wn)) WN_prev(WN_next(new_wn)) = new_wn;
00568 else WN_last(parent) = new_wn;
00569 }
00570 LWN_Set_Parent(new_wn, parent);
00571 LWN_Set_Parent(old_wn, NULL);
00572 }
00573
00574
00575
00576
00577
00578
00579
00580
00581 extern void Set_Runtime_Call_Side_Effects (WN* call_wn) {
00582 INT i;
00583 Is_True (call_wn && (WN_operator(call_wn) == OPR_CALL
00584 || WN_operator(call_wn) == OPR_INTRINSIC_CALL),
00585 ("Set_Runtime_Call_Side_Effects: expected a call node\n"));
00586 ST* call_st = WN_st(call_wn);
00587 for (i=0; i<DST_MAX; i++) {
00588 if (distr_st_entries[i] == call_st) break;
00589 }
00590 Is_True (i<DST_MAX,
00591 ("Set_Runtime_Call_Side_Effects: Could not find call-st\n"));
00592 switch (i) {
00593 case HT_Push:
00594
00595 WN_Set_Call_Non_Data_Mod (call_wn);
00596 WN_Set_Call_Non_Data_Ref (call_wn);
00597 break;
00598 case HT_Pop:
00599 WN_Set_Call_Non_Data_Mod (call_wn);
00600 WN_Set_Call_Non_Data_Ref (call_wn);
00601 WN_Set_Call_Non_Parm_Mod (call_wn);
00602 WN_Set_Call_Non_Parm_Ref (call_wn);
00603 break;
00604 case HT_Top:
00605 case HT_Check:
00606 WN_Set_Call_Non_Data_Ref (call_wn);
00607 WN_Set_Call_Non_Parm_Ref (call_wn);
00608 WN_Set_Call_Parm_Ref (call_wn);
00609 break;
00610 case HT_Replace:
00611 WN_Set_Call_Non_Data_Mod (call_wn);
00612 WN_Set_Call_Non_Data_Ref (call_wn);
00613 WN_Set_Call_Non_Parm_Mod (call_wn);
00614 WN_Set_Call_Non_Parm_Ref (call_wn);
00615 WN_Set_Call_Parm_Ref (call_wn);
00616 break;
00617 case Initialize_Dart:
00618 WN_Set_Call_Parm_Mod (call_wn);
00619 WN_Set_Call_Parm_Ref (call_wn);
00620 break;
00621 case Allocate_Dart:
00622 WN_Set_Call_Non_Data_Mod (call_wn);
00623 WN_Set_Call_Non_Data_Ref (call_wn);
00624 break;
00625 case Alloc_Reshape:
00626 WN_Set_Call_Non_Data_Mod (call_wn);
00627 WN_Set_Call_Non_Data_Ref (call_wn);
00628 WN_Set_Call_Parm_Ref (call_wn);
00629 break;
00630 case Dealloc_Reshape:
00631 WN_Set_Call_Non_Data_Mod (call_wn);
00632 WN_Set_Call_Non_Data_Ref (call_wn);
00633 WN_Set_Call_Parm_Mod (call_wn);
00634 break;
00635 case Migrate_Array:
00636 WN_Set_Call_Non_Data_Mod (call_wn);
00637 WN_Set_Call_Non_Data_Ref (call_wn);
00638 WN_Set_Call_Parm_Ref (call_wn);
00639 break;
00640 case Unmigrate_Array:
00641 WN_Set_Call_Non_Data_Mod (call_wn);
00642 WN_Set_Call_Non_Data_Ref (call_wn);
00643 WN_Set_Call_Parm_Ref (call_wn);
00644 break;
00645 case Migrate_Pages:
00646 WN_Set_Call_Non_Data_Mod (call_wn);
00647 WN_Set_Call_Non_Data_Ref (call_wn);
00648 WN_Set_Call_Parm_Ref (call_wn);
00649 break;
00650 case mp_my_threadnum:
00651 WN_Set_Call_Non_Data_Ref (call_wn);
00652 break;
00653 case mp_numthreads_fn:
00654 WN_Set_Call_Non_Data_Ref (call_wn);
00655 break;
00656 case Proc_Pool_Push:
00657 WN_Set_Call_Non_Data_Mod (call_wn);
00658 WN_Set_Call_Non_Data_Ref (call_wn);
00659 break;
00660 case Proc_Pool_Pop:
00661 WN_Set_Call_Non_Data_Mod (call_wn);
00662 WN_Set_Call_Non_Data_Ref (call_wn);
00663 break;
00664 case Cyclic_Bounds:
00665 WN_Set_Call_Parm_Mod (call_wn);
00666 WN_Set_Call_Parm_Ref (call_wn);
00667 break;
00668 case Deallocate_Dart:
00669 WN_Set_Call_Non_Data_Mod (call_wn);
00670 WN_Set_Call_Non_Data_Ref (call_wn);
00671 WN_Set_Call_Parm_Mod (call_wn);
00672 WN_Set_Call_Parm_Ref (call_wn);
00673 break;
00674 case Compare_Darts:
00675 WN_Set_Call_Parm_Ref (call_wn);
00676 break;
00677 #ifndef KEY // Pathscale does not have this
00678 case mp_cur_numthreads_func:
00679 break;
00680 #endif
00681 case DST_MAX:
00682 default:
00683 FmtAssert (FALSE, ("Set_Runtime_Call_Side_Effects: switch failed\n"));
00684 break;
00685 }
00686 }
00687
00688
00689
00690
00691
00692
00693
00694 extern WN* Lego_Find_Node(SYMBOL sym,
00695 WN* wn_tree)
00696 {
00697 if (OPCODE_has_sym(WN_opcode(wn_tree)) && SYMBOL(wn_tree) == sym)
00698 return wn_tree;
00699 if (WN_opcode(wn_tree) == OPC_BLOCK) {
00700 for (WN* wn = WN_first(wn_tree); wn != NULL; wn = WN_next(wn)) {
00701 WN* wn_result = Lego_Find_Node(sym, wn);
00702 if (wn_result != NULL)
00703 return wn_result;
00704 }
00705 } else {
00706 for (INT i = 0; i < WN_kid_count(wn_tree); i++) {
00707 WN* wn_result = Lego_Find_Node(sym, WN_kid(wn_tree, i));
00708 if (wn_result != NULL)
00709 return wn_result;
00710 }
00711 }
00712 return NULL;
00713 }
00714
00715
00716
00717
00718
00719
00720
00721
00722 extern void Lego_Find_Nodes(OPERATOR opr,
00723 SYMBOL sym,
00724 WN* wn_tree,
00725 STACK<WN*>* stack)
00726 {
00727 if (WN_operator(wn_tree) == opr) {
00728 SYMBOL newsym = SYMBOL(wn_tree);
00729 if (newsym == sym)
00730 stack->Push(wn_tree);
00731 }
00732 if (WN_opcode(wn_tree) == OPC_BLOCK) {
00733 for (WN* wn = WN_first(wn_tree); wn != NULL; wn = WN_next(wn))
00734 Lego_Find_Nodes(opr, sym, wn, stack);
00735 } else {
00736 for (INT i = 0; i < WN_kid_count(wn_tree); i++)
00737 Lego_Find_Nodes(opr, sym, WN_kid(wn_tree, i), stack);
00738 }
00739 }
00740
00741 MP_INFO::MP_INFO(WN* wn_pragmas)
00742 {
00743 _pid_sym0 = NULL;
00744 _pid_sym1 = NULL;
00745 _nest_layout = NULL;
00746 _sched_type = MP_SCHED_SIMPLE;
00747 _nest_index = 0;
00748 _nest_total = 1;
00749 _is_pdo = FALSE;
00750 _plower_disabled = FALSE;
00751 _sym_frozen = NULL;
00752 BOOL found_schedtype = FALSE;
00753 for (WN* wn = WN_first(wn_pragmas); wn != NULL; wn = WN_next(wn)) {
00754 if (WN_opcode(wn) == OPC_PRAGMA) {
00755 switch (WN_pragma(wn)) {
00756 case WN_PRAGMA_MPSCHEDTYPE:
00757 found_schedtype = TRUE;
00758 switch (WN_pragma_arg1(wn)) {
00759 case WN_PRAGMA_SCHEDTYPE_UNKNOWN:
00760 _sched_type = MP_SCHED_UNKNOWN;
00761 _plower_disabled = TRUE;
00762 break;
00763 case WN_PRAGMA_SCHEDTYPE_SIMPLE:
00764 _sched_type = MP_SCHED_SIMPLE;
00765 _plower_disabled = FALSE;
00766 break;
00767 case WN_PRAGMA_SCHEDTYPE_DYNAMIC:
00768 _sched_type = MP_SCHED_DYNAMIC;
00769 _plower_disabled = TRUE;
00770 break;
00771 case WN_PRAGMA_SCHEDTYPE_GSS:
00772 _sched_type = MP_SCHED_GSS;
00773 _plower_disabled = TRUE;
00774 break;
00775 case WN_PRAGMA_SCHEDTYPE_INTERLEAVE:
00776 _sched_type = MP_SCHED_INTERLEAVE;
00777 _plower_disabled = FALSE;
00778 break;
00779 case WN_PRAGMA_SCHEDTYPE_RUNTIME:
00780 _sched_type = MP_SCHED_RUNTIME;
00781 _plower_disabled = TRUE;
00782 break;
00783 case WN_PRAGMA_SCHEDTYPE_PSEUDOLOWERED:
00784 _sched_type = MP_SCHED_PSEUDOLOWERED;
00785 _plower_disabled = TRUE;
00786 break;
00787 }
00788 break;
00789 case WN_PRAGMA_PDO_BEGIN:
00790 _is_pdo = TRUE;
00791
00792 case WN_PRAGMA_DOACROSS:
00793 case WN_PRAGMA_PARALLEL_DO:
00794 _nest_index = WN_pragma_arg1(wn);
00795 _nest_total = WN_pragma_arg2(wn);
00796 break;
00797 }
00798 }
00799 }
00800 DO_LOOP_INFO* dli = NULL;
00801 if (!found_schedtype && _nest_index != 0) {
00802 WN* wn = NULL;
00803 WN* wn_first = LWN_Get_Parent(wn_pragmas);
00804 for (wn = wn_first; wn != NULL; wn = LWN_Get_Parent(wn)) {
00805 if (WN_opcode(wn) == OPC_DO_LOOP) {
00806 dli = Get_Do_Loop_Info(wn);
00807 if (dli->Mp_Info != NULL && dli->Mp_Info->Nest_Index() == 0)
00808 break;
00809 }
00810 }
00811 FmtAssert(wn != NULL,
00812 ("Could not find mp_info on outermore nested doacross loop"));
00813 _sched_type = dli->Mp_Info->Sched_Type();
00814 _plower_disabled = dli->Mp_Info->Plower_Disabled();
00815 }
00816 }
00817
00818 MP_INFO::MP_INFO(MP_INFO* mp_info)
00819 {
00820 _pid_sym0 = mp_info->_pid_sym0;
00821 _pid_sym1 = mp_info->_pid_sym1;
00822 _nest_index = mp_info->_nest_index;
00823 _nest_total = mp_info->_nest_total;
00824 _sched_type = mp_info->_sched_type;
00825 _nest_index = mp_info->_nest_index;
00826 _nest_total = mp_info->_nest_total;
00827 _nest_layout = mp_info->_nest_layout;
00828 _is_pdo = mp_info->_is_pdo;
00829 _plower_disabled = mp_info->_plower_disabled;
00830 _sym_frozen = mp_info->_sym_frozen;
00831 }
00832
00833 MP_INFO::MP_INFO(MP_SCHED_TYPE sched_type,
00834 BOOL is_pdo)
00835 {
00836 _pid_sym0 = NULL;
00837 _pid_sym1 = NULL;
00838 _sched_type = sched_type;
00839 _nest_index = 0;
00840 _nest_total = 1;
00841 _nest_layout = NULL;
00842 _is_pdo = is_pdo;
00843 _plower_disabled = FALSE;
00844 _sym_frozen = NULL;
00845 }
00846
00847 void MP_INFO::Print(FILE* fp)
00848 {
00849 switch (_sched_type) {
00850 case MP_SCHED_SIMPLE:
00851 fprintf(fp, " Scheduled: SIMPLE\n");
00852 break;
00853 case MP_SCHED_DYNAMIC:
00854 fprintf(fp, " Scheduled: DYNAMIC\n");
00855 break;
00856 case MP_SCHED_GSS:
00857 fprintf(fp, " Scheduled: GSS\n");
00858 break;
00859 case MP_SCHED_INTERLEAVE:
00860 fprintf(fp, " Scheduled: INTERLEAVE\n");
00861 break;
00862 case MP_SCHED_RUNTIME:
00863 fprintf(fp, " Scheduled: RUNTIME\n");
00864 break;
00865 case MP_SCHED_PSEUDOLOWERED:
00866 fprintf(fp, " Scheduled: PSEUDOLOWERED\n");
00867 break;
00868 }
00869 if (Pid_Sym0() != NULL) {
00870 const char* name = ST_class(Pid_Sym0()->St()) != CLASS_PREG
00871 ? ST_name(Pid_Sym0()->St())
00872 : Pid_Sym0()->WN_Offset() > Last_Dedicated_Preg_Offset
00873 ? Preg_Name(Pid_Sym0()->WN_Offset()) : "DEDICATED PREG";
00874 fprintf(fp, " Pid_Sym0 = %s\n", name);
00875 }
00876 fprintf(stdout, " Doacross %d out of %d\n", _nest_index,
00877 _nest_total);
00878 if (Pid_Sym1() != NULL) {
00879 const char* name = ST_class(Pid_Sym1()->St()) != CLASS_PREG
00880 ? ST_name(Pid_Sym1()->St())
00881 : Pid_Sym1()->WN_Offset() > Last_Dedicated_Preg_Offset
00882 ? Preg_Name(Pid_Sym1()->WN_Offset()) : "DEDICATED PREG";
00883 fprintf(fp, " Pid_Sym1 = %s\n", name);
00884 }
00885 if (Sym_Frozen() != NULL) {
00886 const char* name = ST_class(Sym_Frozen()->St()) != CLASS_PREG
00887 ? ST_name(Sym_Frozen()->St())
00888 : Sym_Frozen()->WN_Offset() > Last_Dedicated_Preg_Offset
00889 ? Preg_Name(Sym_Frozen()->WN_Offset()) : "DEDICATED PREG";
00890 fprintf(fp, " Sym_Frozen = %s\n", name);
00891 }
00892 if (Nest_Layout() != NULL)
00893 fprintf(stdout, " layout pid = %s\n", ST_name(Nest_Layout()->St()));
00894 if (_is_pdo)
00895 fprintf(stdout, " Loop is PDO\n");
00896 if (_plower_disabled)
00897 fprintf(stdout, " Pseudo-lowering is disabled\n");
00898 }
00899
00900 extern void Freeze_Cur_Numthreads_Func(WN* wn_loop)
00901 {
00902 char Str_Buf[67];
00903 DU_MANAGER* du = Du_Mgr;
00904 #ifndef KEY
00905 OPCODE op_call = OPCODE_make_op(OPR_CALL, MTYPE_I4, MTYPE_V);
00906 WN* wn_call = WN_Create(op_call, 0);
00907 WN_st_idx(wn_call) = ST_st_idx(distr_st_entries[mp_cur_numthreads_func]);
00908 Set_Runtime_Call_Side_Effects(wn_call);
00909 PREG_NUM rreg1, rreg2;
00910 ST* rst = Find_Return_Registers(MTYPE_I4, &rreg1, &rreg2);
00911 FmtAssert(rreg1 != 0 && rreg2 == 0, ("Bad pointer type ret regs"));
00912 #endif
00913 WN* wn_region = LWN_Get_Parent(LWN_Get_Parent(wn_loop));
00914 FmtAssert(WN_opcode(wn_region) == OPC_REGION,
00915 ("Freeze_Numthreads_Ldid: Could not find mp region"));
00916 #ifndef KEY
00917 LWN_Insert_Block_Before(LWN_Get_Parent(wn_region), wn_region, wn_call);
00918 WN* wn_ldid = WN_CreateLdid(OPCODE_make_op(OPR_LDID, MTYPE_I4, MTYPE_I4),
00919 rreg1, rst, Be_Type_Tbl(MTYPE_I4));
00920 du->Add_Def_Use(wn_call, wn_ldid);
00921 #else // load the variable __ompc_cur_numthreads instead of doing a call
00922 WN* wn_ldid = WN_CreateLdid(OPCODE_make_op(OPR_LDID, MTYPE_I4, MTYPE_I4),
00923 0, distr_st_entries[mp_cur_numthreads], Be_Type_Tbl(MTYPE_I4));
00924 #endif
00925 sprintf(Str_Buf, "$frz_cur_num_threads%d", WN_map_id(wn_loop));
00926 SYMBOL* sym_frozen = Create_Local_Symbol(Str_Buf, MTYPE_I4);
00927 WN* wn_stid = AWN_StidIntoSym(sym_frozen, wn_ldid);
00928 Create_local_alias(Alias_Mgr, wn_stid);
00929 WN_Set_Linenum(wn_stid, WN_Get_Linenum(wn_loop));
00930 #ifndef KEY
00931 LWN_Insert_Block_After(LWN_Get_Parent(wn_call), wn_call, wn_stid);
00932 #else
00933 LWN_Insert_Block_Before(LWN_Get_Parent(wn_region), wn_region, wn_stid);
00934 #endif
00935 DO_LOOP_INFO* dli_loop = Get_Do_Loop_Info(wn_loop);
00936 dli_loop->Mp_Info->Set_Sym_Frozen(sym_frozen);
00937 Add_Pragma_To_MP_Region(wn_loop, sym_frozen->St(),
00938 sym_frozen->WN_Offset(), WN_PRAGMA_SHARED);
00939 }
00940
00941
00942 extern void Freeze_Numthreads_Ldid(WN* wn_loop)
00943 {
00944 DU_MANAGER* du = Du_Mgr;
00945 char Str_Buf[64];
00946 DO_LOOP_INFO* dli = Get_Do_Loop_Info(wn_loop);
00947 Is_True(LNO_Pseudo_Lower || dli->Mp_Info->Nest_Total() > 1,
00948 ("Freeze_Numthreads_Ldid called but plower is off"));
00949 WN* wn_ldid = Get_Runtime_Numthreads_Ldid();
00950 TYPE_ID type = WN_desc(wn_ldid);
00951 TYPE_ID type_trip = Promote_Type(Do_Wtype((WN *) wn_loop));
00952 MP_SCHED_TYPE sched_type = dli->Mp_Info->Sched_Type();
00953 FmtAssert(sched_type == MP_SCHED_SIMPLE || sched_type == MP_SCHED_INTERLEAVE,
00954 ("Only freezing threads for SIMPLE and INTERLEAVE scheduling"));
00955 WN* wn_trip = Trip_Count(wn_loop);
00956 wn_trip = LWN_Integer_Cast(wn_trip, type, type_trip);
00957 if (dli->Mp_Info->Sched_Type() == MP_SCHED_INTERLEAVE) {
00958 WN* wn_chunk = Interleaved_Pragma_Chunksize(wn_loop, Du_Mgr);
00959 if (WN_operator(wn_chunk) != OPR_INTCONST
00960 || WN_const_val(wn_chunk) != 1) {
00961 wn_chunk = LWN_Integer_Cast(wn_chunk, type, type_trip);
00962 wn_trip = LWN_CreateDivceil(type, wn_trip, wn_chunk);
00963 }
00964 }
00965 sprintf(Str_Buf, "$frz_num_threads%d", WN_map_id(wn_loop));
00966 SYMBOL* sym_frozen = Create_Local_Symbol(Str_Buf, type);
00967 WN* wn_stid = AWN_StidIntoSym(sym_frozen, wn_ldid);
00968 Create_local_alias(Alias_Mgr, wn_stid);
00969 WN* wn_region = LWN_Get_Parent(LWN_Get_Parent(wn_loop));
00970 FmtAssert(WN_opcode(wn_region) == OPC_REGION,
00971 ("Freeze_Numthreads_Ldid: Could not find mp region"));
00972 LWN_Insert_Block_Before(LWN_Get_Parent(wn_region), wn_region, wn_stid);
00973
00974 WN* wn_fzldid = AWN_LdidSym(sym_frozen);
00975 du->Add_Def_Use(wn_stid, wn_fzldid);
00976 Copy_alias_info(Alias_Mgr, wn_stid, wn_fzldid);
00977 WN* wn_min = AWN_Min(type, wn_fzldid, wn_trip);
00978 sprintf(Str_Buf, "$frz_min%d", WN_map_id(wn_loop));
00979 SYMBOL* sym_fzmin = Create_Local_Symbol(Str_Buf, type);
00980 WN* wn_fzstid = AWN_StidIntoSym(sym_fzmin, wn_min);
00981 Create_local_alias(Alias_Mgr, wn_fzstid);
00982 dli->Mp_Info->Set_Sym_Frozen(sym_fzmin);
00983 LWN_Insert_Block_Before(LWN_Get_Parent(wn_loop), wn_loop, wn_fzstid);
00984
00985
00986 WN *wn;
00987 for (wn = wn_loop; wn != NULL; wn = LWN_Get_Parent(wn))
00988 if (WN_opcode(wn) == OPC_IF)
00989 break;
00990 if (wn == NULL || !WN_Is_If_MpVersion(wn))
00991 return;
00992 LWN_Extract_From_Block(wn_stid);
00993 LWN_Insert_Block_Before(LWN_Get_Parent(wn), wn, wn_stid);
00994 WN* wn_pattern = AWN_LdidSym(sym_frozen);
00995 du->Add_Def_Use(wn_stid, wn_pattern);
00996 LWN_ITER* itr = LWN_WALK_TreeIter(wn);
00997 for (; itr != NULL; itr = LWN_WALK_TreeNext(itr)) {
00998 WN* wn = itr->wn;
00999 if (WN_operator(wn) == OPR_LDID
01000 && SYMBOL(wn) == SYMBOL(wn_ldid)) {
01001 Replace_Symbol(wn, SYMBOL(wn), SYMBOL(wn_stid), wn_pattern, wn);
01002 du->Add_Def_Use(wn_stid, wn);
01003 }
01004 }
01005 DOLOOP_STACK dostack(&LNO_local_pool);
01006 Build_Doloop_Stack(LWN_Get_Parent(wn), &dostack);
01007 LNO_Build_Access(wn, &dostack, &LNO_default_pool);
01008 LWN_Delete_Tree(wn_pattern);
01009 }
01010
01011 extern WN* Get_Frozen_Numthreads_Ldid(WN* wn_loop)
01012 {
01013
01014
01015 WN *wn = WN_Intconst( MTYPE_I4, 4 );
01016 return wn;
01017 for (wn = wn_loop; wn != NULL; wn = LWN_Get_Parent(wn)) {
01018 if (WN_opcode(wn) == OPC_DO_LOOP) {
01019 DO_LOOP_INFO* dli_wn = Get_Do_Loop_Info(wn);
01020 if (dli_wn->Mp_Info != NULL && dli_wn->Mp_Info->Sym_Frozen() != NULL)
01021 break;
01022 }
01023 }
01024 FmtAssert(wn != NULL, ("Could not find frozen value for number of threads"));
01025 WN* wn_outer_loop = wn;
01026 DO_LOOP_INFO* dli = Get_Do_Loop_Info(wn_outer_loop);
01027 if (dli->Mp_Info->Is_Pdo())
01028 if (Is_Versioned_Mp_Loop(wn_outer_loop))
01029 return Get_Runtime_Cur_Numthreads_Ldid();
01030 else
01031 return Get_Runtime_Cur_Numthreads_Func(wn_outer_loop);
01032 for (wn = wn_outer_loop; wn != NULL; wn = WN_prev(wn))
01033 if (WN_operator(wn) == OPR_STID
01034 && SYMBOL(wn) == *(dli->Mp_Info->Sym_Frozen()))
01035 break;
01036 FmtAssert(wn != NULL, ("Could not find frozen value for number of threads"));
01037 WN* wn_stid = wn;
01038 WN* wn_ldid = AWN_LdidSym(dli->Mp_Info->Sym_Frozen());
01039 Copy_alias_info (Alias_Mgr, wn_stid, wn_ldid);
01040 Du_Mgr->Add_Def_Use(wn_stid, wn_ldid);
01041 return wn_ldid;
01042 }
01043
01044 extern WN* Get_Runtime_Cur_Numthreads_Func(WN* wn_loop)
01045 {
01046 DO_LOOP_INFO* dli = Get_Do_Loop_Info(wn_loop);
01047 FmtAssert(dli->Mp_Info->Is_Pdo(),
01048 ("Get_Runtime_Cur_Numthreads_Func: Expected a PDO"));
01049 DO_LOOP_INFO* dli_wn = NULL;
01050 WN *wn;
01051 for (wn = wn_loop; wn != NULL; wn = LWN_Get_Parent(wn)) {
01052 if (WN_opcode(wn) == OPC_DO_LOOP) {
01053 dli_wn = Get_Do_Loop_Info(wn);
01054 if (dli_wn->Mp_Info != NULL && dli_wn->Mp_Info->Sym_Frozen() != NULL)
01055 break;
01056 }
01057 }
01058 FmtAssert(wn != NULL, ("Could not find frozen value for number of threads"));
01059 FmtAssert(dli_wn->Mp_Info != NULL && dli_wn->Mp_Info->Sym_Frozen(),
01060 ("Get_Runtime_Cur_Numthreads_Func: Can't find frozen symbol"));
01061 WN* wn_sym_loop = wn;
01062 WN* wn_region = LWN_Get_Parent(LWN_Get_Parent(wn_sym_loop));
01063 for (wn = wn_region; wn != NULL; wn = WN_prev(wn))
01064 if (WN_operator(wn) == OPR_STID
01065 && SYMBOL(wn) == *(dli_wn->Mp_Info->Sym_Frozen()))
01066 break;
01067 FmtAssert(wn != NULL, ("Could not find frozen value for number of threads"));
01068 WN* wn_stid = wn;
01069 WN* wn_ldid = AWN_LdidSym(dli_wn->Mp_Info->Sym_Frozen());
01070 Copy_alias_info (Alias_Mgr, wn_stid, wn_ldid);
01071 Du_Mgr->Add_Def_Use(wn_stid, wn_ldid);
01072 return wn_ldid;
01073 }
01074
01075
01076 static INT Current_Highest_Lego_Mp_Tile_Key = 0;
01077
01078
01079
01080
01081
01082
01083
01084 extern INT Get_New_Lego_Mp_Tile_Key(void)
01085 {
01086 return ++Current_Highest_Lego_Mp_Tile_Key;
01087 }
01088
01089
01090
01091
01092
01093
01094
01095 extern SYMBOL* Create_Local_Symbol (char* name, TYPE_ID mtype) {
01096 ST* st = New_ST(CURRENT_SYMTAB);
01097 ST_Init (st,
01098 Save_Str(name),
01099 CLASS_VAR,
01100 SCLASS_AUTO,
01101 EXPORT_LOCAL,
01102 Be_Type_Tbl(mtype));
01103 Set_ST_is_temp_var(st);
01104 SYMBOL* sym = CXX_NEW (SYMBOL (st, 0, mtype), &LNO_default_pool);
01105 return sym;
01106 }
01107
01108
01109
01110
01111
01112
01113
01114 extern WN* Get_MP_Region (WN* wn) {
01115 while (wn) {
01116 if (Is_Mp_Region(wn)) return wn;
01117 wn = LWN_Get_Parent(wn);
01118 }
01119 return wn;
01120 }
01121
01122
01123
01124
01125
01126
01127 extern BOOL Fixed_Size_Array_Is_Stride_One(ST* array_st)
01128 {
01129 TY_IDX array_ty=Get_Array_Type(array_st);
01130 INT ndims = TY_AR_ndims(array_ty);
01131 for (INT i=0; i<ndims; i++) {
01132 FmtAssert (TY_AR_const_lbnd(array_ty, i) &&
01133 TY_AR_const_ubnd(array_ty, i) &&
01134 TY_AR_const_stride(array_ty, i),
01135 ("Fixed size array (%s) must have constant %s\n",
01136 ST_name(array_st),
01137 (!TY_AR_const_lbnd(array_ty,i) ? "lbnd" :
01138 (!TY_AR_const_ubnd(array_ty,i) ? "ubnd" :
01139 "stride"))));
01140
01141 INT stride = TY_size(TY_AR_etype(array_ty));
01142 for (INT j=i+1; j<ndims; j++)
01143 stride = (stride * (TY_AR_ubnd_val(array_ty, j) -
01144 TY_AR_lbnd_val(array_ty, j) + 1));
01145 if (TY_AR_stride_val(array_ty, i) != stride)
01146 return FALSE;
01147 }
01148 return TRUE;
01149 }
01150