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 #define __STDC_LIMIT_MACROS
00047 #include <stdint.h>
00048 #include <alloca.h>
00049
00050 #include "defs.h"
00051 #include "opcode.h"
00052 #include "symtab.h"
00053 #include "const.h"
00054 #include "cxx_template.h"
00055 #include "wn_tree_util.h"
00056 #include "lwn_util.h"
00057 #include "wn_simp.h"
00058
00059 #include "ipo_defs.h"
00060 #include "ipa_df.h"
00061 #include "ipaa.h"
00062 #include "ipa_cprop.h"
00063 #include "ipa_option.h"
00064 #include "ipo_parent.h"
00065 #include "ipo_const.h"
00066 #include "ipc_symtab_merge.h"
00067 #include "ipa_section_annot.h"
00068
00069
00070 typedef HASH_TABLE<ST*,WN*> ST_TO_WN_MAP;
00071 typedef HASH_TABLE<TY_IDX,TY_IDX> TY_TO_TY_MAP;
00072
00073
00074
00075
00076
00077
00078 static BOOL
00079 ST_has_const_value (ST* st,
00080 WN* stid,
00081 ST_TO_WN_MAP* st_to_intconst_map)
00082 {
00083 Is_True (WN_operator(stid) == OPR_STID &&
00084 WN_st(stid) == st &&
00085 WN_offset(stid) == 0,
00086 ("ST_has_const_value: mismatched ST_IDX in STID node"));
00087
00088 WN* rhs = WN_kid0(stid);
00089 if (WN_operator(rhs) == OPR_INTCONST) {
00090 st_to_intconst_map->Enter_If_Unique(st, rhs);
00091 return TRUE;
00092 }
00093
00094 return FALSE;
00095 }
00096
00097
00098
00099
00100
00101
00102 static BOOL
00103 TY_AR_has_new_const (TY_IDX ty_idx,
00104 const ST_TO_WN_MAP* st_to_stid_map,
00105 ST_TO_WN_MAP* st_to_intconst_map)
00106 {
00107 Is_True (TY_kind(ty_idx) == KIND_ARRAY,
00108 ("TY_AR_has_new_const: non-array type passed"));
00109
00110 BOOL found_new_constants = FALSE;
00111
00112 INT32 num_dims = TY_AR_ndims(ty_idx);
00113
00114 for (INT32 i = 0; i < num_dims; ++i) {
00115 if (!TY_AR_const_lbnd(ty_idx, i) && TY_AR_lbnd_var(ty_idx, i)) {
00116 ST* lbnd_st = ST_ptr(TY_AR_lbnd_var(ty_idx, i));
00117 WN* lbnd_stid = st_to_stid_map->Find(lbnd_st);
00118 if (lbnd_stid &&
00119 ST_has_const_value(lbnd_st, lbnd_stid, st_to_intconst_map)) {
00120 found_new_constants = TRUE;
00121 }
00122 }
00123 if (!TY_AR_const_ubnd(ty_idx, i) && TY_AR_ubnd_var(ty_idx, i)) {
00124 ST* ubnd_st = ST_ptr(TY_AR_ubnd_var(ty_idx, i));
00125 WN* ubnd_stid = st_to_stid_map->Find(ubnd_st);
00126 if (ubnd_stid &&
00127 ST_has_const_value(ubnd_st, ubnd_stid, st_to_intconst_map)) {
00128 found_new_constants = TRUE;
00129 }
00130 }
00131 if (!TY_AR_const_stride(ty_idx, i) && TY_AR_stride_var(ty_idx, i)) {
00132 ST* stride_st = ST_ptr(TY_AR_stride_var(ty_idx, i));
00133 WN* stride_stid = st_to_stid_map->Find(stride_st);
00134 if (stride_stid &&
00135 ST_has_const_value(stride_st, stride_stid, st_to_intconst_map)){
00136 found_new_constants = TRUE;
00137 }
00138 }
00139 }
00140
00141 return found_new_constants;
00142 }
00143
00144
00145
00146
00147
00148 static TY_IDX
00149 Copy_array_type (TY_IDX ty_idx)
00150 {
00151 const TY& old_ty = Ty_Table[ty_idx];
00152 Is_True (TY_kind(old_ty) == KIND_ARRAY, ("Copy_array_type: non-array TY"));
00153
00154
00155 TY_IDX new_ty_idx;
00156 TY& new_ty = New_TY(new_ty_idx);
00157 TY_Init(new_ty, TY_size(old_ty), KIND_ARRAY, MTYPE_UNKNOWN, 0);
00158 Set_TY_align(new_ty_idx, TY_align(ty_idx));
00159 Set_TY_etype(new_ty, TY_etype(old_ty));
00160
00161 INT32 num_dims = TY_AR_ndims(old_ty);
00162 Is_True (num_dims > 0, ("Copy_array_type: no array dimensions"));
00163
00164
00165 ARB_HANDLE new_arb = New_ARB();
00166 Set_TY_arb(new_ty, new_arb);
00167
00168
00169 ARB_HANDLE old_arb = TY_arb(old_ty);
00170 ARB_copy(new_arb, old_arb);
00171 for (INT32 i = 1; i < num_dims; ++i) {
00172 ARB_copy(New_ARB(), old_arb[i]);
00173 }
00174
00175 return new_ty_idx;
00176 }
00177
00178
00179
00180
00181
00182
00183 static void
00184 TY_AR_propagate_constants (TY_IDX ty_idx,
00185 const ST_TO_WN_MAP* st_to_intconst_map)
00186 {
00187 Is_True (TY_kind(ty_idx) == KIND_ARRAY,
00188 ("TY_AR_propagate_constants: non-array type passed"));
00189
00190 INT32 num_dims = TY_AR_ndims(ty_idx);
00191
00192 for (INT32 i = 0; i < num_dims; ++i) {
00193 if (!TY_AR_const_lbnd(ty_idx, i) && TY_AR_lbnd_var(ty_idx, i)) {
00194 ST* lbnd_st = ST_ptr(TY_AR_lbnd_var(ty_idx, i));
00195 WN* lbnd_intconst = st_to_intconst_map->Find(lbnd_st);
00196 if (lbnd_intconst) {
00197 Is_True (WN_operator(lbnd_intconst) == OPR_INTCONST,
00198 ("TY_AR_propagate_constants: expected INTCONST node"));
00199 Set_TY_AR_const_lbnd(ty_idx, i);
00200 Set_TY_AR_lbnd_val(ty_idx, i, WN_const_val(lbnd_intconst));
00201 }
00202 }
00203 if (!TY_AR_const_ubnd(ty_idx, i) && TY_AR_ubnd_var(ty_idx, i)) {
00204 ST* ubnd_st = ST_ptr(TY_AR_ubnd_var(ty_idx, i));
00205 WN* ubnd_intconst = st_to_intconst_map->Find(ubnd_st);
00206 if (ubnd_intconst) {
00207 Is_True (WN_operator(ubnd_intconst) == OPR_INTCONST,
00208 ("TY_AR_propagate_constants: expected INTCONST node"));
00209 Set_TY_AR_const_ubnd(ty_idx, i);
00210 Set_TY_AR_ubnd_val(ty_idx, i, WN_const_val(ubnd_intconst));
00211 }
00212 }
00213 if (!TY_AR_const_stride(ty_idx, i) && TY_AR_stride_var(ty_idx, i)) {
00214 ST* stride_st = ST_ptr(TY_AR_stride_var(ty_idx, i));
00215 WN* stride_intconst = st_to_intconst_map->Find(stride_st);
00216 if (stride_intconst) {
00217 Is_True (WN_operator(stride_intconst) == OPR_INTCONST,
00218 ("TY_AR_propagate_constants: expected INTCONST node"));
00219 Set_TY_AR_const_stride(ty_idx, i);
00220 Set_TY_AR_stride_val(ty_idx, i, WN_const_val(stride_intconst));
00221 }
00222 }
00223 }
00224 }
00225
00226
00227
00228
00229
00230
00231
00232
00233 struct fix_array_bounds
00234 {
00235 const ST_TO_WN_MAP* st_to_stid_map;
00236 TY_TO_TY_MAP* old_to_new_ty_map;
00237
00238 fix_array_bounds (const ST_TO_WN_MAP* st_map, TY_TO_TY_MAP* ty_map)
00239 : st_to_stid_map (st_map),
00240 old_to_new_ty_map (ty_map)
00241 {}
00242
00243 void operator() (UINT32, ST* st) const
00244 {
00245 TY_IDX ptr_ty_idx = TY_IDX_ZERO;
00246 TY_IDX ty_idx = ST_type(st);
00247
00248 if (TY_kind(ty_idx) == KIND_POINTER) {
00249 ptr_ty_idx = ty_idx;
00250 ty_idx = TY_pointed(ptr_ty_idx);
00251 }
00252
00253 if (TY_kind(ty_idx) == KIND_ARRAY) {
00254
00255
00256 TY_IDX new_ty_idx = old_to_new_ty_map->Find(ty_idx);
00257 if (new_ty_idx) {
00258 if (ptr_ty_idx == TY_IDX_ZERO) {
00259 Set_ST_type(st, new_ty_idx);
00260 }
00261 else {
00262
00263 TY_IDX new_ptr_ty_idx = old_to_new_ty_map->Find(ptr_ty_idx);
00264 if (!new_ptr_ty_idx) {
00265 new_ptr_ty_idx = TY_is_f90_pointer(ptr_ty_idx) ?
00266 Make_F90_Pointer_Type(new_ty_idx) :
00267 Make_Pointer_Type(new_ty_idx);
00268 old_to_new_ty_map->Enter(ptr_ty_idx, new_ptr_ty_idx);
00269 }
00270 Set_ST_type(st, new_ptr_ty_idx);
00271 }
00272 }
00273
00274 else {
00275
00276 ST_TO_WN_MAP st_to_intconst_map(16, Malloc_Mem_Pool);
00277
00278 if (TY_AR_has_new_const(ty_idx, st_to_stid_map, &st_to_intconst_map)) {
00279
00280 TY_IDX new_ty_idx = Copy_array_type(ty_idx);
00281 TY_AR_propagate_constants(new_ty_idx, &st_to_intconst_map);
00282 old_to_new_ty_map->Enter(ty_idx, new_ty_idx);
00283
00284 if (ptr_ty_idx == TY_IDX_ZERO) {
00285 Set_ST_type(st, new_ty_idx);
00286 }
00287 else {
00288 TY_IDX new_ptr_ty_idx = TY_is_f90_pointer(ptr_ty_idx) ?
00289 Make_F90_Pointer_Type(new_ty_idx) :
00290 Make_Pointer_Type(new_ty_idx);
00291 Set_ST_type(st, new_ptr_ty_idx);
00292 old_to_new_ty_map->Enter(ptr_ty_idx, new_ptr_ty_idx);
00293 }
00294 }
00295 }
00296 }
00297 }
00298 };
00299
00300
00301
00302
00303
00304
00305 static void
00306 Update_wn_types (WN* pu, const TY_TO_TY_MAP* old_to_new_ty_map)
00307 {
00308 Is_True (WN_operator(pu) == OPR_FUNC_ENTRY,
00309 ("Update_wn_types: expected FUNC_ENTRY node"));
00310
00311 for (WN_ITER* wni = WN_WALK_TreeIter(pu); wni; wni = WN_WALK_TreeNext(wni)) {
00312
00313 WN* wn = WN_ITER_wn(wni);
00314 OPERATOR opr = WN_operator(wn);
00315
00316 if (OPERATOR_has_1ty(opr)) {
00317 TY_IDX new_ty = old_to_new_ty_map->Find(WN_ty(wn));
00318 if (new_ty) {
00319 WN_set_ty(wn, new_ty);
00320 }
00321 }
00322
00323 else if (OPERATOR_has_2ty(opr)) {
00324 TY_IDX new_ty = old_to_new_ty_map->Find(WN_ty(wn));
00325 if (new_ty) {
00326 WN_set_ty(wn, new_ty);
00327 }
00328 new_ty = old_to_new_ty_map->Find(WN_load_addr_ty(wn));
00329 if (new_ty) {
00330 WN_set_load_addr_ty(wn, new_ty);
00331 }
00332 }
00333 }
00334 }
00335
00336 #if 0
00337
00338
00339
00340 static void
00341 Replace_ldid_with_constant (WN* ldid_wn, WN* const_wn)
00342 {
00343 WN* parent = LWN_Get_Parent(ldid_wn);
00344 Is_True (parent, ("Replace_ldid_with_constant: no parent for LDID node"));
00345
00346 INT k = 0;
00347 while (k < WN_kid_count(parent) && WN_kid(parent,k) != ldid_wn) {
00348 ++k;
00349 }
00350 Is_True(k < WN_kid_count(parent),
00351 ("Replace_ldid_with_constant: broken parent pointer"));
00352
00353 WN_Delete(ldid_wn);
00354 WN_kid(parent,k) = WN_COPY_Tree(const_wn);
00355 LWN_Set_Parent(WN_kid(parent, k), parent);
00356 }
00357 #endif
00358
00359
00360
00361
00362
00363 static void
00364 Update_array_bounds (WN* pu)
00365 {
00366 Is_True (WN_operator(pu) == OPR_FUNC_ENTRY,
00367 ("Update_array_bounds: expected FUNC_ENTRY node"));
00368
00369 ST_TO_WN_MAP st_to_stid_map(16, Malloc_Mem_Pool);
00370
00371 for (WN* wn = WN_entry_first(pu); wn; wn = WN_next(wn)) {
00372
00373 if (WN_operator(wn) == OPR_PRAGMA &&
00374 WN_pragma(wn) == WN_PRAGMA_PREAMBLE_END) {
00375 break;
00376 }
00377
00378
00379 else if (WN_operator(wn) == OPR_STID && WN_offset(wn) == 0) {
00380 WN* new_stid = WN_Simplify_Tree(wn);
00381 WN* rhs = WN_kid0(new_stid);
00382 if (WN_operator(rhs) == OPR_INTCONST) {
00383 ST* st = WN_st(wn);
00384 st_to_stid_map.Enter(st, new_stid);
00385
00386 TREE_ITER iter(pu);
00387 while (WN* node = iter.Wn()) {
00388 OPERATOR opr = WN_operator(node);
00389
00390 if (opr == OPR_PRAGMA && WN_pragma(node) == WN_PRAGMA_PREAMBLE_END){
00391 break;
00392 }
00393
00394 else if (opr == OPR_LDID && WN_st(node) == st
00395 #ifdef KEY
00396
00397
00398
00399 && WN_offset(node) == 0
00400 #endif
00401 ) {
00402 iter.Replace(WN_COPY_Tree(rhs));
00403 }
00404 ++iter;
00405 }
00406 Is_True (iter.Wn(), ("Update_array_bounds: no PREAMBLE_END"));
00407 }
00408 }
00409 }
00410
00411 TY_TO_TY_MAP old_to_new_ty_map(16, Malloc_Mem_Pool);
00412
00413 For_all (St_Table,
00414 CURRENT_SYMTAB,
00415 fix_array_bounds(&st_to_stid_map, &old_to_new_ty_map));
00416
00417 Update_wn_types(pu, &old_to_new_ty_map);
00418 }
00419
00420
00421
00422
00423
00424
00425 static WN*
00426 Summary_value_to_intconst (const SUMMARY_VALUE& value, TYPE_ID mtype,
00427 BOOL is_ref_param)
00428 {
00429 if (is_ref_param) {
00430 if (!value.Is_addr_of ())
00431 return NULL;
00432 } else if (value.Is_addr_of ())
00433 return NULL;
00434
00435 if (value.Is_int_const()) {
00436 return WN_Intconst(mtype, value.Get_int_const_value());
00437 }
00438 if (value.Is_const_st()) {
00439 TCON& tcon = Tcon_Table[value.Get_tcon_idx()];
00440 INT64 intval;
00441 if (Targ_Is_Integral(tcon, &intval)) {
00442 return WN_Intconst(mtype, intval);
00443 }
00444 }
00445 return NULL;
00446 }
00447
00448
00449
00450
00451
00452 static BOOL
00453 IPA_constant_in_array_bounds (const SUMMARY_VALUE& value,
00454 WN* pu,
00455 ST* formal_st)
00456 {
00457 TYPE_ID mtype = TY_mtype(ST_type(formal_st));
00458
00459 if (!MTYPE_is_integral(mtype)) {
00460 return FALSE;
00461 }
00462
00463 WN* const_wn =
00464 Summary_value_to_intconst(value, Mtype_comparison(mtype),
00465 ST_sclass(formal_st) == SCLASS_FORMAL_REF);
00466 if (!const_wn) {
00467 return FALSE;
00468 }
00469
00470 Is_True (WN_operator(pu) == OPR_FUNC_ENTRY,
00471 ("IPA_constant_in_array_bounds: expected FUNC_ENTRY node"));
00472
00473 BOOL found_formal_ldid = FALSE;
00474
00475 TREE_ITER iter(pu);
00476 while (WN* wn = iter.Wn()) {
00477 OPERATOR opr = WN_operator(wn);
00478
00479 if (opr == OPR_PRAGMA && WN_pragma(wn) == WN_PRAGMA_PREAMBLE_END) {
00480 break;
00481 }
00482
00483 else if (opr == OPR_LDID && WN_st(wn) == formal_st) {
00484 #ifdef KEY
00485 TYPE_ID rtype = WN_rtype(wn);
00486 #endif
00487 iter.Replace(WN_COPY_Tree(const_wn));
00488 #ifdef KEY
00489
00490
00491 WN_set_rtype (iter.Wn(), rtype);
00492 #endif
00493 found_formal_ldid = TRUE;
00494 }
00495 ++iter;
00496 }
00497
00498 Is_True (iter.Wn(),
00499 ("IPA_constant_in_array_bounds: can't find PREAMBLE_END"));
00500
00501 return found_formal_ldid;
00502 }
00503
00504 #if 0
00505
00506
00507
00508 static WN*
00509 Create_Stmt (ST* formal, WN* const_wn, TYPE_ID desc)
00510 {
00511 WN* result = WN_Stid (desc, 0, formal, ST_type (formal), const_wn);
00512 LWN_Set_Parent (const_wn, result);
00513 return result;
00514
00515 }
00516 #endif
00517
00518 #ifdef Is_True_On
00519
00520
00521 static inline WN*
00522 Create_Assert (ST* formal, WN* const_wn, TYPE_ID desc)
00523 {
00524 WN* load = WN_Ldid (desc, 0, formal, ST_type (formal));
00525 return WN_CreateAssert (0, WN_EQ (Mtype_comparison (desc), load,
00526 WN_COPY_Tree (const_wn)));
00527
00528 }
00529 #endif // Is_True_On
00530
00531
00532
00533
00534 static WN*
00535 Gen_WN_Const (const SUMMARY_VALUE& value)
00536 {
00537 Is_True (! value.Is_addr_of (), ("Invalid value for simple constant"));
00538
00539 switch (value.Get_const_type ()) {
00540 case VALUE_INT_CONST:
00541 return WN_Intconst (Mtype_comparison (value.Get_mtype ()),
00542 value.Get_int_const_value());
00543
00544 case VALUE_CONST:
00545 Is_True (! MTYPE_is_integral (value.Get_mtype ()),
00546 ("Integral value should not be a const ST"));
00547 const ST* st = NULL;
00548 if (value.Get_const_st_idx ())
00549 st = &St_Table[value.Get_const_st_idx ()];
00550 const TCON& tc = Tcon_Table[value.Get_tcon_idx ()];
00551 if (st == NULL || ST_class (st) != CLASS_CONST) {
00552 Is_True (st == NULL || ST_is_const_var (st),
00553 ("Non constant found during constant propagation"));
00554 st = New_Const_Sym (value.Get_tcon_idx (),
00555 MTYPE_To_TY (TCON_ty (tc)));
00556 }
00557 OPCODE op = OPCODE_make_op (OPR_CONST, TCON_ty (tc),
00558 MTYPE_V);
00559 return WN_CreateConst (op, ST_st_idx (st));
00560 }
00561
00562 Fail_FmtAssertion ("Unsupported constant type");
00563
00564 return NULL;
00565 }
00566
00567
00568
00569
00570 static ST*
00571 #ifdef KEY
00572 Create_Global_ST (const SUMMARY_VALUE& value, BOOL * incompatible = NULL)
00573 #else
00574 Create_Global_ST (const SUMMARY_VALUE& value)
00575 #endif
00576 {
00577 Is_True (value.Is_addr_of (), ("Expecting a memory address"));
00578
00579 TYPE_ID mtype = value.Is_addr_of () ? value.Target_mtype () :
00580 value.Get_mtype ();
00581
00582 switch (value.Get_const_type ()) {
00583
00584 case VALUE_INT_CONST:
00585 if (!value.Is_convertible_to_global ())
00586 return NULL;
00587 else {
00588 TYPE_ID mtype = value.Is_addr_of () ? value.Target_mtype () :
00589 value.Get_mtype ();
00590 #ifdef KEY
00591 if (!MTYPE_is_integral (mtype) && incompatible) {
00592 *incompatible = TRUE;
00593 return NULL;
00594 }
00595 #endif
00596 return New_Const_Sym (Enter_tcon (Host_To_Targ (mtype,
00597 value.Get_int_const_value ())),
00598 MTYPE_To_TY (mtype));
00599 }
00600
00601 case VALUE_CONST:
00602 if (!value.Is_convertible_to_global ())
00603 return NULL;
00604 else {
00605 ST* st = NULL;
00606 if (value.Get_const_st_idx ())
00607 st = &St_Table[value.Get_const_st_idx ()];
00608 if (st == NULL || ST_class (st) != CLASS_CONST) {
00609 Is_True (st == NULL || ST_is_const_var (st),
00610 ("Non constant found during constant propagation"));
00611 const TCON& tc = Tcon_Table[value.Get_tcon_idx ()];
00612 st = New_Const_Sym (value.Get_tcon_idx (),
00613 MTYPE_To_TY (TCON_ty (tc)));
00614 }
00615 return st;
00616 }
00617
00618 case VALUE_GLOBAL:
00619 return &St_Table[value.Get_global_st_idx ()];
00620
00621 default:
00622 return NULL;
00623 }
00624 }
00625
00626
00627
00628 static inline WN*
00629 Gen_LDA (const SUMMARY_VALUE& value, const ST* formal)
00630 {
00631 ST* st = Create_Global_ST (value);
00632
00633 if (st == NULL)
00634 return NULL;
00635
00636 Is_True (ST_level (st) == GLOBAL_SYMTAB, ("Invalid ST level"));
00637
00638 OPCODE op = OPCODE_make_op (OPR_LDA, Pointer_type, MTYPE_V);
00639 return WN_CreateLda (op, 0, ST_type (formal), ST_st_idx (st));
00640 }
00641
00642
00643
00644
00645
00646 static void
00647 Generate_Assignment_Stmt (ST* formal, WN* block, WN* const_wn)
00648 {
00649 TYPE_ID desc = TY_mtype (ST_type (formal));
00650 const_wn = WN_Type_Conversion (const_wn, desc);
00651 WN* stmt = WN_Stid (desc, 0, formal, ST_type (formal), const_wn);
00652 LWN_Set_Parent (const_wn, stmt);
00653 WN_INSERT_BlockBefore(block, NULL, stmt);
00654
00655 #ifdef Is_True_On
00656 if (IPA_Enable_Assert && !IPA_Enable_Cprop2) {
00657 WN_INSERT_BlockBefore (block, stmt,
00658 Create_Assert (formal, const_wn, desc));
00659 }
00660 #endif // Is_True_On
00661
00662 }
00663
00664
00665 namespace {
00666
00667 struct simple_replace {
00668 const ST_IDX formal;
00669 const ST_IDX actual;
00670
00671 simple_replace (ST_IDX f, ST_IDX a) : formal (f), actual (a) {}
00672
00673 void operator() (TREE_ITER& iter) const {
00674 WN* wn = iter.Wn ();
00675 if (OPERATOR_has_sym (WN_operator (wn)) &&
00676 WN_st_idx (wn) == formal) {
00677 WN_st_idx (wn) = actual;
00678 }
00679 }
00680 };
00681
00682 struct replace_by_int_const {
00683 const ST_IDX formal;
00684 const ST_IDX actual;
00685 const TYPE_ID mtype;
00686 const INT64 value;
00687 BOOL modified;
00688
00689 replace_by_int_const (ST_IDX f, ST_IDX a, TYPE_ID m, INT64 v) :
00690 formal (f), actual (a), mtype (m), value (v), modified (FALSE) {}
00691
00692 void operator() (TREE_ITER& iter) {
00693 WN* wn = iter.Wn ();
00694 OPERATOR opr = WN_operator (wn);
00695 if (OPERATOR_has_sym (opr) && WN_st_idx (wn) == formal) {
00696 if (opr == OPR_LDID) {
00697 iter.Replace (WN_Intconst (Mtype_comparison (mtype),
00698 value));
00699 modified = TRUE;
00700 } else
00701 WN_st_idx (wn) == actual;
00702 }
00703 }
00704 };
00705
00706 template <class OPERATION>
00707 inline void
00708 for_all_wn (WN* wn, OPERATION& op) {
00709 TREE_ITER iter (wn);
00710 while (iter.Wn () != NULL) {
00711 op (iter);
00712 ++iter;
00713 }
00714 }
00715 }
00716
00717
00718 static inline void
00719 Replace_Formal_By_Actual (WN* func_body, ST_IDX formal, const ST* actual)
00720 {
00721
00722
00723 Is_True (WN_operator (func_body) != OPR_FUNC_ENTRY,
00724 ("expecting function body"));
00725
00726 const TY& ty = Ty_Table[ST_type (actual)];
00727 simple_replace simp_op (formal, ST_st_idx (actual));
00728
00729 if (ST_class (actual) == CLASS_CONST &&
00730 MTYPE_is_integral (TY_mtype (ty))) {
00731
00732
00733 TCON& tcon = Tcon_Table[ST_tcon (actual)];
00734 TYPE_ID mtype = TY_mtype (ty);
00735 Is_True (mtype == TCON_ty (tcon),
00736 ("Inconsistent mtype between TCON and TY"));
00737 INT64 int_value = Targ_To_Host (tcon);
00738
00739 replace_by_int_const fix_expr (formal, ST_st_idx (actual), mtype,
00740 int_value);
00741 TREE_ITER iter (func_body);
00742 while (iter.Wn () != NULL) {
00743 WN* wn = iter.Wn ();
00744 OPERATOR opr = WN_operator (wn);
00745 if (opr == OPR_IO_ITEM) {
00746 for_all_wn (wn, simp_op);
00747 iter.WN_TREE_next_skip ();
00748 continue;
00749 } else if (OPERATOR_is_expression (opr)) {
00750 fix_expr.modified = FALSE;
00751 if (OPERATOR_is_leaf (opr))
00752 fix_expr (iter);
00753 else
00754 for_all_wn (wn, fix_expr);
00755 if (fix_expr.modified)
00756 iter.Replace (WN_Simplify_Tree (iter.Wn ()));
00757 iter.WN_TREE_next_skip ();
00758 continue;
00759 } else if (OPERATOR_has_sym (opr) && WN_st_idx (wn) == formal) {
00760 WN_st_idx (wn) = ST_st_idx (actual);
00761 }
00762 ++iter;
00763 }
00764 } else {
00765
00766 for_all_wn (func_body, simp_op);
00767 }
00768 }
00769
00770
00771
00772 static void
00773 Replace_Icall (TREE_ITER& iter, const WN* icall, ST* actual)
00774 {
00775 WN* call = WN_generic_call (OPR_CALL, WN_rtype (icall), WN_desc (icall),
00776 WN_kid_count (icall) - 1, actual);
00777 for (INT i = 0; i < WN_kid_count (icall) - 1; ++i) {
00778 WN_kid (call, i) = WN_kid (icall, i);
00779 }
00780 #ifdef KEY // bug 1050
00781 WN_call_flag(call) = WN_call_flag(icall);
00782 #endif
00783 iter.Replace (call);
00784 }
00785
00786
00787
00788
00789
00790 static BOOL
00791 Replace_Formal_By_LDA (WN* func_body, ST_IDX formal, ST* actual)
00792 {
00793
00794
00795 Is_True (WN_operator (func_body) != OPR_FUNC_ENTRY,
00796 ("expecting function body"));
00797
00798 TREE_ITER iter (func_body);
00799 OPCODE lda = OPCODE_make_op (OPR_LDA, Pointer_type, MTYPE_V);
00800 UINT fail_count = 0;
00801
00802 while (iter.Wn () != NULL) {
00803 WN* wn = iter.Wn ();
00804 OPERATOR opr = WN_operator (wn);
00805
00806 switch (opr) {
00807 case OPR_LDID:
00808 if (WN_st_idx (wn) == formal && WN_offset (wn) == 0)
00809 iter.Replace (WN_CreateLda (lda, 0, WN_ty (wn), actual));
00810 else
00811 ++fail_count;
00812 break;
00813
00814 case OPR_ILOAD:
00815 if (WN_operator (WN_kid0 (wn)) == OPR_LDID &&
00816 WN_st_idx (WN_kid0 (wn)) == formal) {
00817 if (WN_field_id (wn)) {
00818 #ifdef KEY
00819
00820
00821
00822 iter.Replace (WN_CreateLdid (OPR_LDID, WN_rtype(wn),
00823 WN_desc (wn), WN_offset (wn),
00824 actual, WN_ty (wn),
00825 WN_field_id (wn)));
00826 #else
00827
00828 iter.Replace (WN_Ldid (WN_desc (wn), WN_offset (wn),
00829 actual, WN_ty (wn),
00830 WN_field_id (wn)));
00831 #endif
00832 } else if (WN_offset (WN_kid0 (wn)) == 0) {
00833
00834 iter.Replace (WN_Ldid (WN_desc (wn), WN_offset (wn),
00835 actual, WN_ty (wn)));
00836 } else
00837 ++fail_count;
00838 }
00839 break;
00840
00841 case OPR_ISTORE:
00842 if (WN_operator (WN_kid1 (wn)) == OPR_LDID &&
00843 WN_st_idx (WN_kid1 (wn)) == formal) {
00844 if (WN_field_id (wn)) {
00845
00846 iter.Replace (WN_Stid (WN_desc (wn), WN_offset (wn),
00847 actual, TY_pointed (WN_ty (wn)),
00848 WN_kid0(wn), WN_field_id (wn)));
00849 } else if (WN_offset (WN_kid1 (wn)) == 0) {
00850
00851 iter.Replace (WN_Stid (WN_desc (wn), WN_offset (wn),
00852 actual, TY_pointed (WN_ty (wn)),
00853 WN_kid0(wn)));
00854 } else
00855 ++fail_count;
00856 }
00857 break;
00858
00859 case OPR_ICALL:
00860 {
00861 const WN* func_addr = WN_kid (wn, WN_kid_count (wn) - 1);
00862 if (WN_operator (func_addr) == OPR_LDID &&
00863 WN_st_idx (func_addr) == formal) {
00864 if (WN_offset (func_addr) == 0) {
00865 Replace_Icall (iter, wn, actual);
00866 } else
00867 ++fail_count;
00868 }
00869 break;
00870 }
00871
00872 default:
00873 if (OPERATOR_has_sym (opr) && WN_st_idx (wn) == formal) {
00874 Is_True (opr != OPR_STID, ("formal parameter is not readonly"));
00875 ++fail_count;
00876 }
00877 break;
00878 }
00879 ++iter;
00880 }
00881
00882 return fail_count == 0;
00883 }
00884
00885
00886 namespace
00887 {
00888 struct replace_lda {
00889 const ST_IDX formal;
00890 const WN* actual;
00891
00892 replace_lda (ST_IDX f, const WN* a) : formal(f), actual (a) {}
00893
00894 void operator() (TREE_ITER& iter) const {
00895 WN* wn = iter.Wn ();
00896 if (WN_operator (wn) == OPR_LDA && WN_st_idx (wn) == formal &&
00897 WN_offset (wn) == 0)
00898 iter.Replace (WN_CopyNode (actual));
00899 }
00900 };
00901 }
00902
00903 static void
00904 Replace_Addr_Of_Formal_By_Actual (WN* func_body, ST_IDX formal,
00905 const WN* actual)
00906 {
00907
00908
00909 Is_True (WN_operator (func_body) != OPR_FUNC_ENTRY,
00910 ("expecting function body"));
00911
00912 replace_lda op (formal, actual);
00913
00914 for_all_wn (func_body, op);
00915
00916 }
00917
00918
00919
00920
00921
00922
00923
00924 static void
00925 Check_If_Global_Has_Const_Value (IPA_NODE* node,
00926 WN* block,
00927 ST* global_st)
00928 {
00929
00930 ST* base_st = ST_base(global_st);
00931 if (base_st != global_st && ST_sclass(base_st) == SCLASS_COMMON) {
00932 GLOBAL_ANNOT* gannot = node->Global_Annot();
00933 if (gannot) {
00934 const GLOBAL_VALUE* gval =
00935 gannot->Find(GLOBAL_ANNOT::Index(ST_st_idx(base_st)),
00936 ST_ofst(global_st),
00937 (UINT32) TY_size(ST_type(global_st)));
00938 if (gval) {
00939 SUMMARY_VALUE* value = gval->Value();
00940 if (value) {
00941 Generate_Assignment_Stmt(global_st, block, Gen_WN_Const(*value));
00942 }
00943 }
00944 }
00945 }
00946 }
00947
00948 #ifdef KEY
00949 BOOL
00950 Store_To_Formal ( ST* formal, WN* w )
00951 {
00952 OPCODE opc = WN_opcode(w);
00953
00954 if (opc == OPC_BLOCK) {
00955 for (WN* stmt = WN_first(w); stmt; stmt = WN_next(stmt)) {
00956 if (WN_operator(stmt) == OPR_STID &&
00957 WN_st(stmt) == formal)
00958 return TRUE;
00959 for (UINT kidno = 0; kidno < WN_kid_count(stmt); kidno++) {
00960 if (Store_To_Formal (formal, WN_kid(stmt, kidno)))
00961 return TRUE;
00962 }
00963 }
00964 } else {
00965 for (UINT kidno = 0; kidno < WN_kid_count(w); kidno++) {
00966 if (Store_To_Formal (formal, WN_kid(w, kidno)))
00967 return TRUE;
00968 }
00969 }
00970 return FALSE;
00971 }
00972 #endif
00973
00974
00975
00976
00977 static void
00978 Propagate_Constants (IPA_NODE* node, WN* w, VALUE_DYN_ARRAY* cprop_annot)
00979 {
00980 Is_True (w != NULL && cprop_annot != NULL &&
00981 cprop_annot != (VALUE_DYN_ARRAY*) -1,
00982 ("Invalid input to Propagate_Constants"));
00983
00984 BOOL need_to_update_array_bounds = FALSE;
00985
00986 WN *block = WN_CreateBlock();
00987
00988 for (INT i = 0; i < WN_num_formals(w); ++i) {
00989
00990 SUMMARY_VALUE& annot_node = (*cprop_annot)[i];
00991
00992 if (!annot_node.Is_constant ())
00993 continue;
00994
00995 ST* formal = WN_st(WN_formal(w,i));
00996 ST* const_st = NULL;
00997
00998 #ifdef KEY
00999
01000 if (ST_sclass (formal) != SCLASS_FORMAL_REF &&
01001 MTYPE_is_complex(TY_mtype(ST_type(formal))))
01002 continue;
01003 #endif
01004
01005 if (IPA_constant_in_array_bounds(annot_node, w, formal)) {
01006 need_to_update_array_bounds = TRUE;
01007 }
01008
01009 if (ST_sclass (formal) != SCLASS_FORMAL_REF) {
01010
01011
01012 WN *const_wn = NULL;
01013 if (!annot_node.Is_addr_of ()) {
01014 Generate_Assignment_Stmt (formal, block,
01015 Gen_WN_Const (annot_node));
01016 annot_node.Remove_param ();
01017 } else {
01018 const IPAA_NODE_INFO* mod_ref_info = node->Mod_Ref_Info ();
01019 if (mod_ref_info && ! mod_ref_info->Is_formal_dmod_elmt (i)) {
01020
01021 const_st = Create_Global_ST (annot_node);
01022 if (const_st) {
01023 if (Replace_Formal_By_LDA (WN_func_body (w),
01024 ST_st_idx (formal),
01025 const_st)) {
01026 annot_node.Remove_param ();
01027 }
01028 }
01029 } else if (annot_node.Is_global ()) {
01030
01031
01032 const_st = &St_Table[annot_node.Get_global_st_idx ()];
01033
01034
01035
01036
01037
01038 if (!ST_addr_saved (const_st))
01039 continue;
01040
01041 WN* lda = Gen_LDA (annot_node, formal);
01042 if (lda == NULL)
01043 continue;
01044 Generate_Assignment_Stmt (formal, block, lda);
01045 annot_node.Remove_param ();
01046 }
01047 }
01048 } else {
01049 #ifdef KEY
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061 if (Store_To_Formal (formal ,
01062 w ))
01063 continue;
01064 #endif
01065
01066
01067
01068
01069
01070
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090 if (annot_node.Is_addr_of ()) {
01091
01092 const IPAA_NODE_INFO* mod_ref_info = node->Mod_Ref_Info ();
01093 if (mod_ref_info &&
01094 ! mod_ref_info->Is_formal_dmod_elmt (i) &&
01095 ! mod_ref_info->Is_formal_imod_elmt (i))
01096 annot_node.Set_convertible_to_global ();
01097 #ifdef KEY
01098
01099
01100
01101 BOOL incompatible = FALSE;
01102 const_st = Create_Global_ST (annot_node, &incompatible);
01103 if (incompatible) continue;
01104 #else
01105 const_st = Create_Global_ST (annot_node);
01106 #endif
01107 if (const_st) {
01108 if (annot_node.Is_global()) {
01109 Check_If_Global_Has_Const_Value(node, block, const_st);
01110 }
01111 Replace_Formal_By_Actual (WN_func_body (w),
01112 ST_st_idx (formal),
01113 const_st);
01114 annot_node.Remove_param ();
01115 } else {
01116 SUMMARY_VALUE value = annot_node;
01117 value.Clear_is_addr_of ();
01118 value.Set_mtype (annot_node.Target_mtype ());
01119 Generate_Assignment_Stmt (formal, block,
01120 Gen_WN_Const (value));
01121 }
01122 } else {
01123
01124 const WN* actual = Gen_WN_Const (annot_node);
01125 if (actual) {
01126 Replace_Addr_Of_Formal_By_Actual (WN_func_body (w),
01127 ST_st_idx (formal),
01128 actual);
01129 }
01130 }
01131 }
01132 }
01133
01134
01135 if (need_to_update_array_bounds) {
01136 Update_array_bounds (w);
01137 }
01138
01139
01140 if (WN_first(block)) {
01141 LWN_Insert_Block_Before(WN_func_body(w), WN_first(WN_func_body(w)),
01142 block);
01143 }
01144
01145 LWN_Parentize(w);
01146 WN_verifier (w);
01147
01148 }
01149
01150
01151 struct fix_aliased_formals
01152 {
01153 void operator() (UINT32, ST* st) const {
01154 if ((ST_sclass (st) == SCLASS_FORMAL ||
01155 ST_sclass (st) == SCLASS_FORMAL_REF) &&
01156 ST_base_idx (st) != ST_st_idx (st)) {
01157
01158 const ST& base_st = St_Table[ST_base_idx (st)];
01159 if (ST_sclass (base_st) == SCLASS_AUTO) {
01160 Set_ST_sclass (st, SCLASS_AUTO);
01161 Clear_ST_is_value_parm (st);
01162 }
01163 }
01164 }
01165 };
01166
01167
01168
01169
01170
01171
01172
01173
01174 void
01175 IPA_Propagate_Constants (IPA_NODE* n, BOOL delete_const_param)
01176 {
01177 INT i;
01178
01179 VALUE_DYN_ARRAY* cprop_annot = n->Cprop_Annot();
01180
01181 if (cprop_annot == NULL || cprop_annot == (VALUE_DYN_ARRAY*) -1)
01182 return;
01183
01184 IPA_NODE_CONTEXT context (n);
01185
01186 WN* w = n->Whirl_Tree();
01187
01188 Propagate_Constants (n, w, cprop_annot);
01189
01190 if (!delete_const_param) {
01191 for (i = 0; i < cprop_annot->Sizeof (); ++i)
01192 (*cprop_annot)[i].Reset_remove_param ();
01193 return;
01194 }
01195
01196 UINT param_count = WN_num_formals (w);
01197 for (i = 0; i < WN_num_formals (w); ++i)
01198 if ((*cprop_annot)[i].Is_remove_param ())
01199 --param_count;
01200
01201 if (param_count == WN_num_formals (w))
01202 return;
01203
01204
01205 WN* func_node = WN_CreateEntry (param_count, WN_st_idx(w),
01206 WN_func_body(w),
01207 WN_func_pragmas(w),
01208 WN_func_varrefs(w));
01209
01210 WN_set_map_id(func_node, WN_map_id(w));
01211 WN_linenum(func_node) = WN_linenum(w);
01212
01213
01214 STATE_ARRAY* state_formal_array = NULL;
01215 VALUE_DYN_ARRAY* const_formal_array = NULL;
01216 if (IPA_Enable_Array_Sections) {
01217 IPA_NODE_SECTION_INFO* sec = n->Section_Annot();
01218 if (sec != NULL)
01219 state_formal_array = (STATE_ARRAY*) sec->Get_formals();
01220 }
01221 INT k=0;
01222 #ifdef KEY
01223 TYLIST_IDX tylist_idx;
01224 TYLIST_IDX from_idx = TY_tylist(PU_prototype(Pu_Table[ST_pu(WN_st(w))]));
01225
01226 Set_TYLIST_type (New_TYLIST (tylist_idx), Tylist_Table[from_idx]);
01227 Set_TY_tylist (PU_prototype(Pu_Table[ST_pu(WN_st(w))]), tylist_idx);
01228 ++from_idx;
01229 #endif
01230
01231 for (i = 0; i < WN_num_formals(w); i++) {
01232 WN* id = WN_kid(w,i);
01233 if ((*cprop_annot)[i].Is_remove_param ()) {
01234
01235
01236 ST* st = WN_st(id);
01237 Clear_ST_is_value_parm(st);
01238 Set_ST_sclass(st, SCLASS_AUTO);
01239 if (IPA_Enable_Array_Sections) {
01240 if (state_formal_array != NULL)
01241 (*state_formal_array)[i].Set_is_removed();
01242 }
01243 } else {
01244 WN_kid(func_node,k) = id;
01245 ++k;
01246 #ifdef KEY
01247 Set_TYLIST_type (New_TYLIST (tylist_idx), Tylist_Table[from_idx]);
01248 #endif
01249
01250 }
01251 #ifdef KEY
01252 ++from_idx;
01253 #endif
01254
01255 }
01256 #ifdef KEY
01257 Set_TYLIST_type (New_TYLIST (tylist_idx), 0);
01258 #endif
01259
01260 if (n->Has_Aliased_Formal ()) {
01261
01262
01263 For_all (St_Table, CURRENT_SYMTAB, fix_aliased_formals ());
01264 }
01265
01266 WN_func_body(func_node) = WN_func_body(w);
01267 LWN_Parentize(func_node);
01268 n->Set_Whirl_Tree(func_node);
01269
01270 }
01271
01272
01273
01274
01275
01276 static UINT32
01277 Compute_param_count (INT kid, const VALUE_DYN_ARRAY& cprop_annot)
01278 {
01279 #ifdef KEY
01280 INT last = MIN (kid, cprop_annot.Lastidx () + 1);
01281 #else
01282 INT last = min (kid, cprop_annot.Lastidx () + 1);
01283 #endif
01284
01285 for (INT i = 0; i < last; ++i) {
01286 if (cprop_annot[i].Is_remove_param())
01287 --kid;
01288 }
01289
01290 return kid;
01291 }
01292
01293
01294
01295
01296
01297 void
01298 Reset_param_list (IPA_NODE *caller, IPA_NODE *callee, IPA_EDGE *edge,
01299 IPA_CALL_GRAPH* cg)
01300 {
01301 IPA_NODE_CONTEXT context (caller);
01302 cg->Map_Callsites (caller);
01303 WN* caller_wn = caller->Whirl_Tree();
01304 WN* call = edge->Whirl_Node();
01305 UINT orig_param_count = WN_kid_count (call);
01306
01307
01308 Is_True (WN_operator(call) != OPR_ICALL,
01309 ("Cannot constant propagate through indirect call"));
01310
01311 VALUE_DYN_ARRAY *cprop_annot = callee->Cprop_Annot();
01312 if (cprop_annot == NULL) {
01313 return;
01314 }
01315
01316 UINT used_param_count = Compute_param_count (orig_param_count,
01317 *cprop_annot);
01318
01319 if (used_param_count == orig_param_count)
01320
01321 return;
01322
01323 INT fake_param_count = 0;
01324
01325 if (IPA_Enable_Readonly_Ref && (edge->Has_Readonly_Param() ||
01326 edge->Has_Pass_Not_Saved_Param())) {
01327 UINT annot_size = cprop_annot->Lastidx() + 1;
01328 for (INT i = 0; i < orig_param_count; ++i)
01329 if ((WN_Parm_Read_Only(WN_kid(call, i)) ||
01330 WN_Parm_Passed_Not_Saved(WN_kid(call, i))) &&
01331 (i >= annot_size || (*cprop_annot)[i].Is_remove_param()))
01332 ++fake_param_count;
01333 }
01334
01335 WN* parent_block = WN_Get_Parent (call, Parent_Map, Current_Map_Tab);
01336
01337 if (Trace_IPA)
01338 fprintf(TFile, "Fixing call site in caller %s \n",
01339 ST_name(WN_st(caller_wn)));
01340
01341 TYPE_ID rtype = WN_rtype(call);
01342 TYPE_ID desc = WN_desc(call);
01343 WN* new_call = WN_Call (rtype, desc, used_param_count + fake_param_count,
01344 WN_st(call));
01345 WN_call_flag (new_call) = WN_call_flag (call);
01346 #ifdef KEY
01347 WN_Set_Linenum (new_call, WN_Get_Linenum (call));
01348 #endif // KEY
01349
01350 if (caller->Has_frequency ())
01351 IPA_WN_MAP32_Set (Current_Map_Tab, WN_MAP_FEEDBACK, new_call,
01352 IPA_WN_MAP32_Get (Current_Map_Tab,
01353 WN_MAP_FEEDBACK, call));
01354
01355 INT first=0;
01356 INT last = used_param_count;
01357 INT i;
01358
01359 if (Trace_IPA || Trace_Perf) {
01360 fprintf (TFile, "%s called from ", DEMANGLE (callee->Name ()));
01361 fprintf (TFile, "%s (parm pos): ", DEMANGLE (caller->Name ()));
01362 }
01363
01364 for (i = 0; i < orig_param_count; ++i) {
01365 if (i > cprop_annot->Lastidx() ||
01366 ! (*cprop_annot)[i].Is_remove_param ()) {
01367 WN_kid(new_call,first) = WN_kid(call,i);
01368 WN_Set_Parent(WN_kid(call,i), new_call, Parent_Map,Current_Map_Tab);
01369 ++first;
01370 } else {
01371
01372 if (WN_Parm_Read_Only(WN_kid(call, i)) ||
01373 WN_Parm_Passed_Not_Saved(WN_kid(call, i))) {
01374
01375 WN_kid(new_call,last) = WN_kid(call, i);
01376 WN_Set_Parm_Dummy (WN_kid (new_call, last));
01377 WN_Set_Parent(WN_kid(call,i), new_call, Parent_Map,
01378 Current_Map_Tab);
01379 ++last;
01380 if (Trace_IPA || Trace_Perf)
01381 fprintf (TFile, "%d faked ", i);
01382 } else if (Trace_IPA || Trace_Perf)
01383 fprintf (TFile, "%d removed ", i);
01384
01385 }
01386 }
01387
01388 #ifdef KEY
01389
01390
01391
01392 if (WN_kid_count (new_call) > last)
01393 WN_set_kid_count (new_call, last);
01394
01395
01396 edge->Summary_Callsite()->Set_param_count (WN_kid_count (new_call));
01397 #endif
01398
01399 if (Trace_IPA || Trace_Perf)
01400 fputc ('\n', TFile);
01401
01402
01403 if (WN_operator (parent_block) == OPR_BLOCK) {
01404 LWN_Insert_Block_Before (parent_block, call, new_call);
01405 LWN_Extract_From_Block (parent_block, call);
01406 } else {
01407 for (i = 0; i < WN_kid_count (parent_block); ++i) {
01408 if (WN_kid (parent_block, i) == call) {
01409 WN_kid (parent_block, i) = new_call;
01410 LWN_Set_Parent (new_call, parent_block);
01411 }
01412 }
01413 }
01414 edge->Set_Whirl_Node(new_call);
01415 }
01416
01417
01418
01419
01420
01421 static ST*
01422 Create_Const_ST (const SUMMARY_VALUE& value)
01423 {
01424 if (value.Is_int_const()) {
01425 return
01426 New_Const_Sym(Enter_tcon(Host_To_Targ(value.Get_mtype(),
01427 value.Get_int_const_value())),
01428 MTYPE_To_TY(value.Get_mtype()));
01429 }
01430 else if (value.Is_const_st() && value.Get_const_st_idx()) {
01431 ST* st = ST_ptr(value.Get_const_st_idx());
01432 if (ST_class (st) != CLASS_CONST) {
01433 Is_True (ST_is_const_var(st),
01434 ("Non constant found during constant propagation"));
01435 const TCON& tc = Tcon_Table[value.Get_tcon_idx()];
01436 st = New_Const_Sym(value.Get_tcon_idx(), MTYPE_To_TY(TCON_ty(tc)));
01437 }
01438 return st;
01439 }
01440
01441 return 0;
01442 }
01443
01444 #if 0
01445 typedef HASH_TABLE<ST_IDX,ST_IDX> ST_IDX_HASH_TABLE;
01446 #endif
01447
01448
01449
01450
01451 extern void
01452 IPO_propagate_globals(IPA_NODE *n)
01453 {
01454 #if 0
01455 static MEM_POOL Temp_pool;
01456 static BOOL Temp_pool_initialized = FALSE;
01457
01458 if (!Temp_pool_initialized) {
01459 Temp_pool_initialized = TRUE;
01460 MEM_POOL_Initialize(&Temp_pool, "temp pool", 0);
01461 }
01462 MEM_POOL_Push(&Temp_pool);
01463 #endif
01464
01465 IPAA_NODE_INFO* modref_info = n->Mod_Ref_Info();
01466 GLOBAL_ANNOT* gannot = n->Global_Annot();
01467
01468 if (gannot && modref_info) {
01469
01470 BOOL need_to_update_array_bounds = FALSE;
01471 WN* new_block = WN_CreateBlock();
01472 WN* pu = n->Whirl_Tree();
01473 #ifdef KEY // bug 12371
01474 LWN_Parentize(pu);
01475 #endif
01476
01477
01478 for (UINT32 i = 0; i < GLOBAL_ANNOT::Size; ++i) {
01479 if (!gannot->Top(i) && !gannot->Bottom(i)) {
01480 INT32 modref_key = ST_IDX_index(GLOBAL_ANNOT::Common_ST[i]);
01481 const GLOBAL_DYN_ARRAY& gvals = gannot->Global_Value_Array(i);
01482 for (UINT32 j = 0; j < gvals.Elements(); ++j) {
01483 const SUMMARY_VALUE* value = gvals[j].Value();
01484 if (value) {
01485 OFFSET_SIZE os(gvals[j].Offset(), gvals[j].Size());
01486 ST_IDX st_idx = GLOBAL_ANNOT::Offset_Size_To_ST[i][os];
01487 if (st_idx && TY_mtype(ST_type(st_idx)) == value->Get_mtype()) {
01488
01489
01490 if (IPA_constant_in_array_bounds(*value, pu, ST_ptr(st_idx))) {
01491 need_to_update_array_bounds = TRUE;
01492 }
01493
01494 if (modref_info->Is_def_elmt(modref_key)) {
01495 Generate_Assignment_Stmt(ST_ptr(st_idx),
01496 new_block,
01497 Gen_WN_Const(*value));
01498 }
01499 else {
01500 ST* const_st = Create_Const_ST(*value);
01501 if (const_st) {
01502 Replace_Formal_By_Actual(WN_func_body(pu),st_idx,const_st);
01503 }
01504 }
01505 }
01506 }
01507 }
01508 }
01509 }
01510
01511
01512 if (need_to_update_array_bounds) {
01513 Update_array_bounds(pu);
01514 }
01515
01516
01517 if (WN_first(new_block)) {
01518 LWN_Insert_Block_Before(WN_func_body(pu),
01519 WN_first(WN_func_body(pu)),
01520 new_block);
01521 }
01522
01523 LWN_Parentize(pu);
01524 WN_verifier(pu);
01525 }
01526
01527 #if 0
01528 MEM_POOL_Pop(&Temp_pool);
01529 #endif
01530 }
01531
01532
01533 #if 0
01534
01535
01536
01537 static void
01538 update_whirl(WN* w, ST_IDX_HASH_TABLE *table)
01539 {
01540
01541 OPCODE opc = WN_opcode(w);
01542 if (OPCODE_has_sym(opc) && WN_st(w) && table->Find(WN_st_idx(w))) {
01543 WN_st_idx(w) = table->Find(WN_st_idx(w));
01544 }
01545 if (opc == OPC_BLOCK) {
01546 for (WN* wn = WN_first(w); wn; wn = WN_next(wn)) {
01547 update_whirl(wn, table);
01548 }
01549 }
01550 else {
01551 for (INT kid=0; kid<WN_kid_count(w); kid++) {
01552 update_whirl(WN_kid(w,kid),table);
01553 }
01554 }
01555 }
01556 #endif
01557