Open64 (mfef90, whirl2f, and IR tools)
TAG: version-openad; SVN changeset: 916
|
00001 /* 00002 00003 Copyright (C) 2000, 2001 Silicon Graphics, Inc. All Rights Reserved. 00004 00005 This program is free software; you can redistribute it and/or modify it 00006 under the terms of version 2 of the GNU General Public License as 00007 published by the Free Software Foundation. 00008 00009 This program is distributed in the hope that it would be useful, but 00010 WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00012 00013 Further, this software is distributed without any warranty that it is 00014 free of the rightful claim of any third person regarding infringement 00015 or the like. Any license provided herein, whether implied or 00016 otherwise, applies only to this software file. Patent licenses, if 00017 any, provided herein do not apply to combinations of this program with 00018 other software, or any other product whatsoever. 00019 00020 You should have received a copy of the GNU General Public License along 00021 with this program; if not, write the Free Software Foundation, Inc., 59 00022 Temple Place - Suite 330, Boston MA 02111-1307, USA. 00023 00024 Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pky, 00025 Mountain View, CA 94043, or: 00026 00027 http://www.sgi.com 00028 00029 For further information regarding this notice, see: 00030 00031 http://oss.sgi.com/projects/GenInfo/NoticeExplan 00032 00033 */ 00034 00035 00036 //* -*-Mode: c++;-*- (Tell emacs to use c++ mode) */ 00037 00038 #include <elf.h> // Elf64_Word 00039 #include <sys/types.h> // ir_bwrite.h needs it 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 // NAME: Machine_Type 00050 // FUNCTION: Given an argument passed to a call 'wn_argument', determine 00051 // return the machine type of its base type. 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 // Find the position of the formal parameter in the function 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 // NAME: Node_Count 00103 // FUNCTION: Return the node count of the tree rooted at 'wn_node'. If 00104 // 'limit' > 0, stop counting when you get over 'limit' nodes. If 00105 // 'symbol_only' is true, count only nodes with symbols. 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 // NAME: True_Bound 00135 // FUNCTION: Given the array bound expression 'wn_exp' in the subprogram 00136 // 'wn_func', return an equivalent expression which uses original rather 00137 // than frozen symbol values in the LDIDs. Get memory for the expression 00138 // from 'mem_pool'. 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 // NAME: Is_Constant_Tree 00159 // FUNCTION: If 'wn_exp' is a tree all of whose leaves are INTCONSTs, 00160 // (and whose interior nodes are of a few simple types), then return 00161 // TRUE and set '*const_value' to the value of 'wn_exp'. Otherwise 00162 // return FALSE. 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 // NAME: Is_Exp_Linexable 00207 // FUNCTION: Returns TRUE if 'wn_exp' can be converted to a LINEX (easily) 00208 // FALSE otherwise. 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 // NAME: Exp_To_Linex_Array 00250 // FUNCTION: Place on the TERM_ARRAY 'terms' the equivalent LINEX repre- 00251 // sentation of 'wn_exp'. Take needed meory from 'mem_pool'. 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 // NAME: Exp_To_Linex 00373 // FUNCTION: Convert 'wn_exp' to LINEX form, adding terms to the LINEX i 00374 // 'lx_exp'. Return TRUE if the conversion worked, FALSE otherwise. 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 // NAME: Projected_Region_From_St 00399 // FUNCTION: For the array variable with the given 'st' in the function 00400 // 'wn_func' use memory from 'mem_pool' to construct a projected region 00401 // its declaration. Return NULL if the variable is not an array. 00402 // NOTE: This has been changed so that the PROJECTED_REGION created is 00403 // "zero-based". 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 // NAME: Projected_Region_From_Access_Array 00491 // FUNCTION: Return a projected region from the access array 'aa' using 00492 // memory from the 'mem_pool'. 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