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 #include <elf.h>
00039 #include <sys/types.h>
00040 #include "wn_util.h"
00041 #include "lwn_util.h"
00042 #include "ipa_section.h"
00043 #include "ipa_lno_file.h"
00044 #include "ipl_lno_util.h"
00045 #include "ipl_summarize.h"
00046 #include "ipl_array_bread_write.h"
00047
00048
00049
00050
00051
00052
00053 extern TYPE_ID
00054 Machine_Type(WN* wn_argument)
00055 {
00056 INT mtype = MTYPE_UNKNOWN;
00057 if (WN_operator(wn_argument) == OPR_PARM)
00058 wn_argument = WN_kid0(wn_argument);
00059 if (!OPCODE_has_sym(WN_opcode(wn_argument)))
00060 return mtype;
00061 ST* st_formal = WN_st(wn_argument);
00062 TY_IDX ty_idx_formal = ST_type(st_formal);
00063 while (TY_kind(ty_idx_formal) == KIND_POINTER)
00064 ty_idx_formal = TY_pointed(ty_idx_formal);
00065 if (TY_kind(ty_idx_formal) == KIND_ARRAY)
00066 mtype = TY_mtype(TY_etype(ty_idx_formal));
00067 else
00068 mtype = TY_mtype(ty_idx_formal);
00069 return mtype;
00070 }
00071
00072 #if (!defined(_STANDALONE_INLINER) && !defined(_LIGHTWEIGHT_INLINER))
00073
00074 extern SUMMARY *Summary;
00075 extern ARRAY_SUMMARY Array_Summary;
00076
00077
00078
00079
00080 extern INT32
00081 Formal_Position (const ST* formal_st)
00082 {
00083 Is_True(ST_sclass(formal_st) == SCLASS_FORMAL ||
00084 ST_sclass(formal_st) == SCLASS_FORMAL_REF,
00085 ("Expected a formal ST"));
00086
00087 FmtAssert(Current_PU_Info, ("Current_PU_Info is not set"));
00088 WN* func_entry = PU_Info_tree_ptr(Current_PU_Info);
00089 FmtAssert(func_entry, ("Function entry is not set"));
00090
00091 for (INT32 pos = 0; pos < WN_num_formals(func_entry); ++pos) {
00092 if (WN_st(WN_formal(func_entry, pos)) == formal_st) {
00093 return pos;
00094 }
00095 }
00096 Fail_FmtAssertion("Couldn't find formal %s in function %s",
00097 ST_name(formal_st), ST_name(WN_st(func_entry)));
00098 return -1;
00099 }
00100
00101
00102
00103
00104
00105
00106
00107
00108 extern INT Node_Count(WN* wn_node,
00109 INT limit,
00110 BOOL symbol_only)
00111 {
00112 INT count = 0;
00113 if (!symbol_only || OPCODE_has_sym(WN_opcode(wn_node)))
00114 count++;
00115 if (limit > 0 && count > limit)
00116 return count;
00117 if (WN_opcode(wn_node) == OPC_BLOCK) {
00118 for (WN* wn = WN_first(wn_node); wn != NULL; wn = WN_next(wn)) {
00119 count += Node_Count(wn, limit, symbol_only);
00120 if (limit > 0 && count > limit)
00121 return count;
00122 }
00123 } else {
00124 for (INT i = 0; i < WN_kid_count(wn_node); i++) {
00125 count += Node_Count(WN_kid(wn_node, i), limit, symbol_only);
00126 if (limit > 0 && count > limit)
00127 return count;
00128 }
00129 }
00130 return count;
00131 }
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141 extern WN* True_Bound(WN* wn_func,
00142 ST_IDX st_idx_exp)
00143 {
00144 WN_ITER *wni = WN_WALK_TreeIter(wn_func);
00145 WN* wn = NULL;
00146 for (; wni != NULL; wni = WN_WALK_TreeNext(wni)) {
00147 wn = wni->wn;
00148 if (WN_operator(wn) == OPR_STID && WN_st_idx(wn) == st_idx_exp)
00149 break;
00150 }
00151 if (wni == NULL)
00152 return NULL;
00153 WN* wn_exp = WN_kid0(wn);
00154 return LWN_Copy_Tree(wn_exp);
00155 }
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165 static BOOL Is_Constant_Tree(WN* wn_exp,
00166 INT64* const_value)
00167 {
00168 INT64 const_left, const_right;
00169 switch (WN_operator(wn_exp)) {
00170 case OPR_ADD:
00171 if (!Is_Constant_Tree(WN_kid0(wn_exp), &const_left))
00172 return FALSE;
00173 if (!Is_Constant_Tree(WN_kid1(wn_exp), &const_right))
00174 return FALSE;
00175 *const_value = const_left + const_right;
00176 break;
00177 case OPR_SUB:
00178 if (!Is_Constant_Tree(WN_kid0(wn_exp), &const_left))
00179 return FALSE;
00180 if (!Is_Constant_Tree(WN_kid1(wn_exp), &const_right))
00181 return FALSE;
00182 *const_value = const_left - const_right;
00183 break;
00184 case OPR_MPY:
00185 if (!Is_Constant_Tree(WN_kid0(wn_exp), &const_left))
00186 return FALSE;
00187 if (!Is_Constant_Tree(WN_kid1(wn_exp), &const_right))
00188 return FALSE;
00189 *const_value = const_left * const_right;
00190 break;
00191 case OPR_NEG:
00192 if (!Is_Constant_Tree(WN_kid0(wn_exp), &const_left))
00193 return FALSE;
00194 *const_value = -const_left;
00195 break;
00196 case OPR_INTCONST:
00197 *const_value = WN_const_val(wn_exp);
00198 break;
00199 default:
00200 return FALSE;
00201 }
00202 return TRUE;
00203 }
00204
00205
00206
00207
00208
00209
00210
00211 static BOOL Is_Exp_Linexable(WN* wn_exp,
00212 BOOL Is_LNO)
00213 {
00214 INT64 dummy_const;
00215 switch (WN_operator(wn_exp)) {
00216 case OPR_ADD:
00217 case OPR_SUB:
00218 case OPR_NEG:
00219 break;
00220 case OPR_MPY:
00221 if (Is_Constant_Tree(WN_kid0(wn_exp), &dummy_const))
00222 return Is_Exp_Linexable(WN_kid1(wn_exp), Is_LNO);
00223 if (Is_Constant_Tree(WN_kid1(wn_exp), &dummy_const))
00224 return Is_Exp_Linexable(WN_kid0(wn_exp), Is_LNO);
00225 return FALSE;
00226 case OPR_INTCONST:
00227 return TRUE;
00228 case OPR_LDID:
00229 if (Is_LNO)
00230 return TRUE;
00231 else {
00232 const ST* st_exp = WN_st(wn_exp);
00233 return (ST_class(st_exp) == CLASS_VAR &&
00234 (ST_level(st_exp) == GLOBAL_SYMTAB ||
00235 (ST_level(st_exp) == CURRENT_SYMTAB &&
00236 (ST_sclass(st_exp) == SCLASS_FORMAL ||
00237 ST_sclass(st_exp) == SCLASS_FORMAL_REF))));
00238 }
00239 default:
00240 return FALSE;
00241 }
00242 for (INT i = 0; i < WN_kid_count(wn_exp); i++)
00243 if (!Is_Exp_Linexable(WN_kid(wn_exp, i), Is_LNO))
00244 return FALSE;
00245 return TRUE;
00246 }
00247
00248
00249
00250
00251
00252
00253
00254 static void Exp_To_Linex_Array(WN* wn_exp,
00255 TERM_ARRAY* terms,
00256 MEM_POOL* mem_pool,
00257 BOOL Is_LNO,
00258 IPA_LNO_READ_FILE* IPA_LNO_File)
00259 {
00260 INT i = 0;
00261 INT idx = -1;
00262 INT64 const_value = 0;
00263 TERM* tm = NULL;
00264 TERM_ARRAY tm_left(mem_pool);
00265 TERM_ARRAY tm_right(mem_pool);
00266 OPERATOR opr = WN_operator(wn_exp);
00267 switch (opr) {
00268 case OPR_ADD:
00269 Exp_To_Linex_Array(WN_kid0(wn_exp), &tm_left, mem_pool, Is_LNO,
00270 IPA_LNO_File);
00271 Exp_To_Linex_Array(WN_kid1(wn_exp), &tm_right, mem_pool, Is_LNO,
00272 IPA_LNO_File);
00273 for (i = 0; i <= tm_left.Lastidx(); i++) {
00274 idx = terms->Newidx();
00275 (*terms)[idx] = tm_left[i];
00276 }
00277 for (i = 0; i <= tm_right.Lastidx(); i++) {
00278 idx = terms->Newidx();
00279 (*terms)[idx] = tm_right[i];
00280 }
00281 tm_left.Free_array();
00282 tm_right.Free_array();
00283 break;
00284 case OPR_SUB:
00285 Exp_To_Linex_Array(WN_kid0(wn_exp), &tm_left, mem_pool, Is_LNO,
00286 IPA_LNO_File);
00287 Exp_To_Linex_Array(WN_kid1(wn_exp), &tm_right, mem_pool, Is_LNO,
00288 IPA_LNO_File);
00289 for (i = 0; i <= tm_left.Lastidx(); i++) {
00290 idx = terms->Newidx();
00291 (*terms)[idx] = tm_left[i];
00292 }
00293 for (i = 0; i <= tm_right.Lastidx(); i++) {
00294 idx = terms->Newidx();
00295 tm_right[i].Set_coeff(-tm_right[i].Get_coeff());
00296 (*terms)[idx] = tm_right[i];
00297 }
00298 tm_left.Free_array();
00299 tm_right.Free_array();
00300 break;
00301 case OPR_NEG:
00302 Exp_To_Linex_Array(WN_kid0(wn_exp), &tm_left, mem_pool, Is_LNO,
00303 IPA_LNO_File);
00304 for (i = 0; i <= tm_left.Lastidx(); i++) {
00305 idx = terms->Newidx();
00306 tm_left[i].Set_coeff(-tm_left[i].Get_coeff());
00307 (*terms)[idx] = tm_left[i];
00308 }
00309 tm_left.Free_array();
00310 break;
00311 case OPR_MPY: {
00312 WN* wn_base = NULL;
00313 if (Is_Constant_Tree(WN_kid0(wn_exp), &const_value))
00314 wn_base = WN_kid1(wn_exp);
00315 else if (Is_Constant_Tree(WN_kid1(wn_exp), &const_value))
00316 wn_base = WN_kid0(wn_exp);
00317 FmtAssert(wn_base != NULL,
00318 ("Exp_To_Linex_Array: Should have screened this out"));
00319 Exp_To_Linex_Array(wn_base, &tm_left, mem_pool, Is_LNO, IPA_LNO_File);
00320 for (i = 0; i <= tm_left.Lastidx(); i++) {
00321 idx = terms->Newidx();
00322 tm_left[i].Set_coeff((COEFF) const_value * tm_left[i].Get_coeff());
00323 (*terms)[idx] = tm_left[i];
00324 }
00325 tm_left.Free_array();
00326 }
00327 break;
00328 case OPR_INTCONST:
00329 const_value = WN_const_val(wn_exp);
00330 terms->AddElement(TERM(LTKIND_CONST, (COEFF) const_value, CONST_DESC, 0));
00331 break;
00332 case OPR_LDID: {
00333 const ST* st = WN_st(wn_exp);
00334 WN_OFFSET offset = WN_offset(wn_exp);
00335 TYPE_ID mtype = WN_rtype(wn_exp);
00336 INT32 ivar_idx;
00337 IVAR ivar;
00338
00339 if (Is_LNO) {
00340 new (&ivar) IVAR(st, offset, mtype);
00341 ivar_idx = IPA_LNO_File->Add_Translated_Ivar_Unique(ivar);
00342 }
00343 else {
00344 if (ST_IDX_level(ST_st_idx(st)) == GLOBAL_SYMTAB) {
00345 new (&ivar) IVAR(st, offset, mtype);
00346 }
00347 else if (ST_sclass(st) == SCLASS_FORMAL ||
00348 ST_sclass(st) == SCLASS_FORMAL_REF) {
00349 UINT32 position = Formal_Position(st);
00350 new (&ivar) IVAR(position, offset, mtype);
00351 }
00352 IVAR_ARRAY& ivar_array = *Array_Summary_Output->Get_ivar_array();
00353 for (ivar_idx = 0; ivar_idx < ivar_array.Elements(); ivar_idx++) {
00354 if (ivar_array[ivar_idx] == ivar) {
00355 break;
00356 }
00357 }
00358 if (ivar_idx == ivar_array.Elements()) {
00359 ivar_array.AddElement(ivar);
00360 }
00361 }
00362 terms->AddElement(TERM(LTKIND_IV, (COEFF) 1, ivar_idx, 0));
00363 break;
00364 }
00365 default:
00366 FmtAssert(TRUE, ("Exp_To_Linex_Array: Should have screened this out"));
00367 break;
00368 }
00369 }
00370
00371
00372
00373
00374
00375
00376
00377 extern BOOL Exp_To_Linex(WN* wn_exp,
00378 LINEX* lx_exp,
00379 MEM_POOL* mem_pool,
00380 BOOL negate,
00381 BOOL Is_LNO,
00382 IPA_LNO_READ_FILE* IPA_LNO_File)
00383 {
00384 TERM_ARRAY terms(mem_pool);
00385 if (!Is_Exp_Linexable(wn_exp, Is_LNO))
00386 return FALSE;
00387 Exp_To_Linex_Array(wn_exp, &terms, mem_pool, Is_LNO, IPA_LNO_File);
00388 for (INT i = 0; i <= terms.Lastidx(); i++) {
00389 TERM* tm = &terms[i];
00390 if (negate)
00391 tm->Set_coeff(-tm->Get_coeff());
00392 lx_exp->Set_term(tm);
00393 }
00394 return TRUE;
00395 }
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406 extern PROJECTED_REGION* Projected_Region_From_St(WN* wn_func,
00407 ST* st,
00408 MEM_POOL* mem_pool,
00409 BOOL Is_LNO,
00410 IPA_LNO_READ_FILE*
00411 IPA_LNO_File)
00412 {
00413 TY_IDX ty_idx = ST_type(st);
00414 if (TY_kind(ty_idx) == KIND_POINTER)
00415 ty_idx = TY_pointed(ty_idx);
00416 if (TY_kind(ty_idx) != KIND_ARRAY)
00417 return NULL;
00418 INT dim_count = TY_AR_ndims(ty_idx);
00419 PROJECTED_REGION* pr =
00420 CXX_NEW(PROJECTED_REGION(NON_MESSY_REGION, 0, dim_count, mem_pool),
00421 mem_pool);
00422 pr->Set_is_formal();
00423 pr->Reset_is_unprojected();
00424 PROJECTED_ARRAY* pa = pr->Get_projected_array();
00425 for (INT j = 0; j < dim_count; j++) {
00426 PROJECTED_NODE* pn = &(*pa)[j];
00427 pn->Init(mem_pool);
00428 pn->Reset_is_unprojected();
00429 LINEX* lx_lb = pn->Get_lower_linex();
00430 mINT64 lb_const = 0LL;
00431 lx_lb->Set_term(LTKIND_CONST, (COEFF) lb_const, CONST_DESC, 0);
00432 LINEX* lx_ub = pn->Get_upper_linex();
00433 if (TY_AR_const_lbnd(ty_idx, j)) {
00434 mINT64 lb_const = TY_AR_lbnd_val(ty_idx, j);
00435 lx_ub->Set_term(LTKIND_CONST, (COEFF) -lb_const, CONST_DESC, 0);
00436 } else {
00437 ST_IDX st_idx_lb = TY_AR_lbnd_var(ty_idx, j);
00438 if (st_idx_lb == (ST_IDX)0) {
00439 FmtAssert(j == 0,
00440 ("Process_Array_Formals: Expecting assumed shape array"));
00441 pn->Set_assumed_shape();
00442 } else {
00443 WN* wn_lb_true = True_Bound(wn_func, st_idx_lb);
00444 if (wn_lb_true == NULL) {
00445 FmtAssert(j == 0,
00446 ("Process_Array_Formals: Expecting assumed shape array"));
00447 pn->Set_assumed_shape();
00448 } else {
00449 BOOL ok = Exp_To_Linex(wn_lb_true, lx_ub, mem_pool, TRUE,
00450 Is_LNO, IPA_LNO_File);
00451 if (!ok)
00452 pn->Set_messy_ub();
00453 }
00454 }
00455 }
00456 if (!pn->Is_messy_ub()) {
00457 if (TY_AR_const_ubnd(ty_idx, j)) {
00458 mINT64 ub_const = TY_AR_ubnd_val(ty_idx, j);
00459 lx_ub->Set_term(LTKIND_CONST, (COEFF) ub_const, CONST_DESC, 0);
00460 } else {
00461 ST_IDX st_idx_ub = TY_AR_ubnd_var(ty_idx, j);
00462 if (st_idx_ub == (ST_IDX)0) {
00463 FmtAssert(j == 0,
00464 ("Process_Array_Formals: Expecting assumed shape array"));
00465 pn->Set_assumed_shape();
00466 } else {
00467 WN* wn_ub_true = True_Bound(wn_func, st_idx_ub);
00468 if (wn_ub_true == NULL) {
00469 FmtAssert(j == 0,
00470 ("Process_Array_Formals: Expecting assumed shape array"));
00471 pn->Set_assumed_shape();
00472 } else {
00473 BOOL ok = Exp_To_Linex(wn_ub_true, lx_ub, mem_pool, FALSE,
00474 Is_LNO, IPA_LNO_File);
00475 if (!ok)
00476 pn->Set_messy_ub();
00477 }
00478 }
00479 }
00480 lx_ub->Simplify();
00481 }
00482 LINEX* lx_stride = pn->Get_step_linex();
00483 mINT64 stride_const = 1LL;
00484 lx_stride->Set_term(LTKIND_CONST, (COEFF) stride_const, CONST_DESC, 0);
00485 }
00486 return pr;
00487 }
00488
00489
00490
00491
00492
00493
00494
00495 extern PROJECTED_REGION* Projected_Region_From_Access_Array(ACCESS_ARRAY* aa,
00496 MEM_POOL* mem_pool, IPA_LNO_READ_FILE* IPA_LNO_File)
00497 {
00498 return CXX_NEW(PROJECTED_REGION(aa, mem_pool, NULL, FALSE,
00499 IPA_LNO_File), mem_pool);
00500 }
00501
00502
00503 #endif // _STANDALONE_INLINER