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