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 #define __STDC_LIMIT_MACROS
00041 #include <stdint.h>
00042 #if defined(BUILD_OS_DARWIN)
00043 #include <darwin_elf.h>
00044 #else
00045 #include <elf.h>
00046 #endif
00047 #include <alloca.h>
00048
00049 #include "defs.h"
00050 #include "mempool.h"
00051 #include "tracing.h"
00052 #include "cxx_template.h"
00053 #include "wn.h"
00054 #include "wn_simp.h"
00055 #include "wn_util.h"
00056 #include "lwn_util.h"
00057
00058 #include "ipc_symtab_merge.h"
00059 #include "ipl_summary.h"
00060 #include "ipa_option.h"
00061 #include "ipa_cg.h"
00062 #include "ipa_cprop.h"
00063 #include "ipa_summary.h"
00064 #include "ipaa.h"
00065 #include "ipo_defs.h"
00066
00067 #include "ipa_cprop_annot.h"
00068
00069
00070 enum CONDITION_STATE {
00071 CD_UNKNOWN = 0,
00072 CD_TRUE = 1,
00073 CD_FALSE = 2,
00074 CD_DEAD = 3,
00075 };
00076
00077 CONDITION_STATE *cd_status;
00078
00079
00080 MEM_POOL Ipa_cprop_pool;
00081 MEM_POOL local_cprop_pool;
00082
00083
00084
00085 static IPA_NODE *Current_caller;
00086 static IPA_NODE **callsite_map;
00087
00088
00089
00090 static GLOBAL_ANNOT *current_gannot;
00091
00092 static SUMMARY_PROCEDURE *ipa_proc;
00093 static SUMMARY_CALLSITE *ipa_callsite;
00094 static SUMMARY_FORMAL *ipa_formal;
00095 static SUMMARY_ACTUAL *ipa_actual;
00096 static SUMMARY_VALUE *ipa_value;
00097 static SUMMARY_EXPR *ipa_expr;
00098 static SUMMARY_PHI *ipa_phi;
00099 static SUMMARY_CHI *ipa_chi;
00100 static const SUMMARY_SYMBOL *ipa_symbol;
00101 static SUMMARY_STMT *ipa_stmt;
00102 static SUMMARY_CONTROL_DEPENDENCE *ipa_ctrl_dep;
00103 static SUMMARY_STID *ipa_stid;
00104
00105
00106 static VALUE_DYN_ARRAY *formal_value;
00107
00108
00109 typedef SEGMENTED_ARRAY<SUMMARY_VALUE> VALUE_VECTOR;
00110 static VALUE_VECTOR* eval_value;
00111
00112 struct eval_hasher
00113 {
00114 size_t operator()(const void* s) const {
00115 return reinterpret_cast<size_t>(s);
00116 }
00117 };
00118
00119 typedef __gnu_cxx::hash_map<const void *, UINT32, eval_hasher, std::equal_to<const void *>,
00120 mempool_allocator<pair<const void *, UINT32> > > EVAL_HASH;
00121 static EVAL_HASH *eval_hash;
00122
00123 static void
00124 Evaluate_chi (const SUMMARY_CHI *chi, SUMMARY_VALUE &return_value);
00125
00126 static void
00127 Evaluate_phi (const SUMMARY_PHI *phi, SUMMARY_VALUE &return_value);
00128
00129 static void
00130 Evaluate_expr (const SUMMARY_EXPR *expr, SUMMARY_VALUE &return_value);
00131
00132 #ifdef KEY
00133 static void
00134 Evaluate_value (const SUMMARY_VALUE&, SUMMARY_VALUE&, WN * = NULL);
00135 #else
00136 static void
00137 Evaluate_value (const SUMMARY_VALUE& value, SUMMARY_VALUE &return_value);
00138 #endif
00139
00140
00141
00142
00143
00144 static void
00145 Set_summary_info(const IPA_NODE* node)
00146 {
00147 ipa_proc = node->Summary_Proc();
00148
00149 ipa_callsite = IPA_get_callsite_array (node);
00150 ipa_actual = IPA_get_actual_array (node);
00151 ipa_symbol = IPA_get_symbol_array (node);
00152 ipa_formal = IPA_get_formal_array (node);
00153 ipa_ctrl_dep = IPA_get_ctrl_dep_array (node);
00154 ipa_stmt = IPA_get_stmt_array (node);
00155 ipa_value = IPA_get_value_array (node);
00156 ipa_phi = IPA_get_phi_array (node);
00157 ipa_chi = IPA_get_chi_array (node);
00158 ipa_expr = IPA_get_expr_array (node);
00159 ipa_stid = IPA_get_stid_array (node);
00160 }
00161
00162
00163
00164
00165
00166 static inline BOOL
00167 Values_are_equal(const SUMMARY_VALUE* v1, const SUMMARY_VALUE* v2)
00168 {
00169 if (v1 == v2) {
00170 return TRUE;
00171 }
00172
00173 if (v1->Is_int_const() && v2->Is_int_const()) {
00174 return (v1->Get_int_const_value() == v2->Get_int_const_value());
00175 }
00176
00177 if (v1->Is_const_st() && v2->Is_const_st()) {
00178 Is_True(v1->Is_merged_const_st_idx() && v2->Is_merged_const_st_idx(),
00179 ("const_st values can be compared only after merging"));
00180 return (v1->Get_const_st_idx() == v2->Get_const_st_idx() &&
00181 v1->Get_tcon_idx () == v2->Get_tcon_idx ());
00182 }
00183
00184
00185 return FALSE;
00186 }
00187
00188
00189 static inline BOOL
00190 Compatible_Mtypes (TYPE_ID mtype1, TYPE_ID mtype2)
00191 {
00192 if (mtype1 == mtype2)
00193 return TRUE;
00194 return (MTYPE_is_integral (mtype1) && MTYPE_is_integral (mtype2));
00195 }
00196
00197
00198
00199 static BOOL
00200 Compatible_Parameters (TYPE_ID formal_mtype, BOOL is_ref_param,
00201 const SUMMARY_VALUE& actual)
00202 {
00203 if (!actual.Is_addr_of ()) {
00204 if (is_ref_param)
00205 return MTYPE_is_pointer (actual.Get_mtype ());
00206 else
00207 return Compatible_Mtypes (formal_mtype, actual.Get_mtype ());
00208 } else {
00209 if (is_ref_param)
00210 return Compatible_Mtypes (formal_mtype, actual.Target_mtype ());
00211 else
00212 return MTYPE_is_pointer (formal_mtype);
00213 }
00214 }
00215
00216
00217
00218
00219
00220 static BOOL
00221 Update_node_const (SUMMARY_VALUE& formal, const SUMMARY_VALUE& actual,
00222 BOOL is_ref_parm)
00223 {
00224 BOOL formal_update = TRUE;
00225
00226 Is_True (formal.Is_merged_const_st_idx () &&
00227 actual.Is_merged_const_st_idx (),
00228 ("Invalid ST_IDX for VALUE_CONST"));
00229 if (! formal.Is_addr_of ()) {
00230
00231 if (formal.Get_tcon_idx () == actual.Get_tcon_idx ())
00232 return FALSE;
00233 } else {
00234
00235 if (formal.Get_const_st_idx () != 0 &&
00236 formal.Get_const_st_idx () == actual.Get_const_st_idx ()) {
00237
00238 if (formal.Is_convertible_to_global () &&
00239 !actual.Is_convertible_to_global ()) {
00240 formal.Clear_convertible_to_global ();
00241 return TRUE;
00242 }
00243 return FALSE;
00244 } else if (is_ref_parm) {
00245
00246
00247 if (formal.Get_tcon_idx () == actual.Get_tcon_idx ()) {
00248
00249
00250 if (formal.Is_convertible_to_global () ==
00251 actual.Is_convertible_to_global ()) {
00252
00253 if (formal.Get_const_st_idx () != 0) {
00254 formal.Set_const_st_idx (0, actual.Get_tcon_idx ());
00255 return TRUE;
00256 } else
00257 return FALSE;
00258 }
00259 }
00260 }
00261 }
00262
00263 formal.Set_not_const ();
00264 return TRUE;
00265 }
00266
00267
00268
00269 static BOOL
00270 Same_Global_Value (ST_IDX st_idx1, ST_IDX st_idx2)
00271 {
00272 if (st_idx1 == st_idx2)
00273 return TRUE;
00274
00275 Is_True (ST_IDX_level (st_idx1) == GLOBAL_SYMTAB &&
00276 ST_IDX_level (st_idx2) == GLOBAL_SYMTAB,
00277 ("Expecting global symbols"));
00278
00279 const ST& st1 = St_Table[st_idx1];
00280 const ST& st2 = St_Table[st_idx2];
00281
00282 Is_True (ST_is_const_var (st1) && ST_is_const_var (st2),
00283 ("Variable is not constant"));
00284
00285 if (ST_type (st1) != ST_type (st2))
00286 return FALSE;
00287
00288 BOOL st1_is_zero = !ST_is_initialized (st1) || ST_init_value_zero (st1);
00289 BOOL st2_is_zero = !ST_is_initialized (st2) || ST_init_value_zero (st2);
00290
00291 if (st1_is_zero != st2_is_zero)
00292 return FALSE;
00293
00294 if (st1_is_zero)
00295 return TRUE;
00296
00297
00298 ST_TO_INITO_MAP::const_iterator iter = ST_To_INITO_Map.find (st_idx1);
00299 if (iter == ST_To_INITO_Map.end ())
00300 return FALSE;
00301 INITV_IDX initv1 = INITO_val (Inito_Table[(*iter).second]);
00302
00303 iter = ST_To_INITO_Map.find (st_idx2);
00304 if (iter == ST_To_INITO_Map.end ())
00305 return FALSE;
00306 INITV_IDX initv2 = INITO_val (Inito_Table[(*iter).second]);
00307
00308 return initv1 == initv2;
00309
00310 }
00311
00312
00313
00314
00315
00316 static BOOL
00317 Update_node(SUMMARY_VALUE& formal, const SUMMARY_VALUE& actual,
00318 TYPE_ID formal_type, BOOL is_ref_parm)
00319 {
00320
00321
00322 if (formal.Is_not_const ())
00323 return FALSE;
00324
00325 if (! Compatible_Parameters (formal_type, is_ref_parm, actual)) {
00326 formal.Set_not_const ();
00327 return TRUE;
00328 }
00329
00330 if (formal.Is_unknown ()) {
00331 formal = actual;
00332 return TRUE;
00333 }
00334
00335
00336 if (actual.Is_addr_of () != formal.Is_addr_of () ||
00337 actual.Get_const_type () != formal.Get_const_type ()) {
00338 formal.Set_not_const ();
00339 return TRUE;
00340 }
00341
00342 switch (formal.Get_const_type ()) {
00343 case VALUE_INT_CONST:
00344 if (formal.Get_int_const_value () == actual.Get_int_const_value ())
00345 return FALSE;
00346 break;
00347
00348 case VALUE_CONST:
00349 return Update_node_const (formal, actual, is_ref_parm);
00350
00351 case VALUE_GLOBAL:
00352 if (formal.Get_global_st_idx () == actual.Get_global_st_idx ())
00353 return FALSE;
00354 if (!formal.Is_addr_of () && !is_ref_parm) {
00355
00356 if (Same_Global_Value (formal.Get_global_st_idx (),
00357 actual.Get_global_st_idx ()))
00358 return FALSE;
00359 }
00360 break;
00361
00362 default:
00363 break;
00364 }
00365
00366 formal.Set_not_const ();
00367 return TRUE;
00368 }
00369
00370
00371
00372
00373
00374
00375
00376
00377 extern BOOL
00378 Union_Formal_Cprop_Annot (IPA_NODE* callee, IPA_EDGE *e)
00379 {
00380 VALUE_DYN_ARRAY* formals = callee->Cprop_Annot();
00381 VALUE_DYN_ARRAY* actuals = e->Cprop_Annot();
00382
00383 if (formals == NULL || actuals == NULL) {
00384 return FALSE;
00385 }
00386
00387
00388 Set_summary_info (callee);
00389
00390
00391 UINT32 count = (formals->Elements() < actuals->Elements()) ?
00392 formals->Elements() : actuals->Elements();
00393
00394 BOOL updated = FALSE;
00395 for (UINT32 pos = 0, i = ipa_proc->Get_formal_index();
00396 pos < count;
00397 ++pos, ++i) {
00398 const SUMMARY_FORMAL& sum_formal = ipa_formal[i];
00399 TYPE_ID mtype = ipa_symbol[sum_formal.Get_symbol_index()].Get_btype();
00400 updated |= Update_node ((*formals)[pos], (*actuals)[pos], mtype,
00401 sum_formal.Is_ref_parm ());
00402 }
00403
00404 return updated;
00405 }
00406
00407
00408
00409
00410
00411 extern void
00412 Union_Quasi_Clone_Cprop_Annot (IPA_NODE* origin, IPA_NODE* clone)
00413 {
00414 VALUE_DYN_ARRAY* orig_annots = origin->Cprop_Annot();
00415 VALUE_DYN_ARRAY* clone_annots = clone->Cprop_Annot();
00416
00417 if (orig_annots == NULL || clone_annots == NULL) {
00418 return;
00419 }
00420
00421
00422 Set_summary_info (origin);
00423
00424 UINT32 count = orig_annots->Elements();
00425
00426 for (UINT32 pos = 0, i = ipa_proc->Get_formal_index();
00427 pos < count;
00428 ++pos, ++i) {
00429 const SUMMARY_FORMAL& sum_formal = ipa_formal[i];
00430 TYPE_ID mtype = ipa_symbol[sum_formal.Get_symbol_index()].Get_btype();
00431 Update_node((*orig_annots)[pos], (*clone_annots)[pos], mtype,
00432 sum_formal.Is_ref_parm ());
00433 }
00434 }
00435
00436
00437
00438
00439
00440
00441 static BOOL
00442 Values_are_cprop_equivalent(const SUMMARY_VALUE* val1,
00443 const SUMMARY_VALUE* val2)
00444 {
00445 if (val1 == val2) {
00446 return TRUE;
00447 }
00448
00449 if (val1->Get_const_type () != val2->Get_const_type ()) {
00450 return FALSE;
00451 }
00452
00453 switch (val1->Get_const_type ()) {
00454
00455 case VALUE_INT_CONST:
00456 return (val1->Get_int_const_value() == val2->Get_int_const_value());
00457
00458 case VALUE_CONST:
00459 Is_True(val1->Is_merged_const_st_idx() && val2->Is_merged_const_st_idx(),
00460 ("const_st values can be compared only after merging"));
00461 return (val1->Get_const_st_idx() == val2->Get_const_st_idx() &&
00462 val1->Get_tcon_idx() == val2->Get_tcon_idx());
00463
00464 case VALUE_NOT_CONST:
00465 return TRUE;
00466
00467 case VALUE_FORMAL:
00468 case VALUE_GLOBAL:
00469 case VALUE_SYMBOL:
00470 if (val1->Is_addr_of ()) {
00471 return memcmp (val1, val2, sizeof(SUMMARY_VALUE)) == 0;
00472 }
00473 }
00474
00475 return FALSE;
00476 }
00477
00478
00479
00480
00481
00482
00483
00484 extern BOOL
00485 Edges_Have_Equiv_Cprop_Annots(const IPA_EDGE* e1,
00486 const IPA_EDGE* e2)
00487 {
00488 if (e1 == e2) {
00489 return TRUE;
00490 }
00491
00492 VALUE_DYN_ARRAY* args1 = e1->Cprop_Annot();
00493 VALUE_DYN_ARRAY* args2 = e2->Cprop_Annot();
00494
00495 if (args1 == NULL || args2 == NULL ||
00496 args1 == (void*)-1 || args2 == (void*)-1) {
00497 return FALSE;
00498 }
00499
00500
00501 UINT32 count = args1->Elements();
00502 if (count != args2->Elements()) {
00503 return FALSE;
00504 }
00505
00506 for (UINT32 i = 0; i < count; ++i) {
00507 if (!Values_are_cprop_equivalent(&((*args1)[i]), &((*args2)[i]))) {
00508 return FALSE;
00509 }
00510 }
00511
00512 return TRUE;
00513 }
00514
00515
00516
00517
00518
00519
00520
00521
00522 static IPA_CLONING_ACTION
00523 Precise_int_const_node_update(SUMMARY_VALUE* formal,
00524 SUMMARY_VALUE* actual)
00525 {
00526 if (formal->Is_unknown()) {
00527
00528 *formal = *actual;
00529 return ANNOTATION_CHANGED;
00530 }
00531
00532 if (formal->Is_int_const() &&
00533 formal->Get_int_const_value() == actual->Get_int_const_value()) {
00534 return NO_CHANGE;
00535 }
00536
00537 return NEEDS_CLONING;
00538 }
00539
00540
00541
00542
00543
00544 static IPA_CLONING_ACTION
00545 Precise_const_st_node_update(SUMMARY_VALUE* formal,
00546 SUMMARY_VALUE* actual)
00547 {
00548 if (formal->Is_unknown()) {
00549
00550 *formal = *actual;
00551 return ANNOTATION_CHANGED;
00552 }
00553
00554 if (formal->Is_const_st() &&
00555 formal->Get_const_st_idx() == actual->Get_const_st_idx() &&
00556 formal->Get_tcon_idx() == actual->Get_tcon_idx ()) {
00557 return NO_CHANGE;
00558 }
00559
00560 return NEEDS_CLONING;
00561 }
00562
00563
00564
00565
00566
00567
00568
00569
00570 static IPA_CLONING_ACTION
00571 Precise_node_update (SUMMARY_VALUE* formal,
00572 SUMMARY_VALUE* actual,
00573 TYPE_ID formal_type,
00574 BOOL is_ref_parm)
00575 {
00576 if (MTYPE_is_integral(formal_type)) {
00577 if (actual->Is_int_const()) {
00578 return Precise_int_const_node_update(formal, actual);
00579 }
00580 if (actual->Is_const_st() && MTYPE_is_integral(actual->Get_mtype())) {
00581 return Precise_const_st_node_update(formal, actual);
00582 }
00583 }
00584
00585 if (Update_node (*formal, *actual, formal_type, is_ref_parm)) {
00586 return ANNOTATION_CHANGED;
00587 }
00588
00589 return NO_CHANGE;
00590 }
00591
00592
00593
00594
00595
00596 static BOOL
00597 Clone_for_this_formal(const IPA_NODE* callee,
00598 UINT32 position)
00599 {
00600
00601
00602 if (IPA_Max_Node_Clones_Set) {
00603 return TRUE;
00604 }
00605
00606
00607 INT32 f_idx = callee->Summary_Proc()->Get_formal_index() + position;
00608 INT32 s_idx = IPA_get_formal_array(callee)[f_idx].Get_symbol_index();
00609 return IPA_get_symbol_array(callee)[s_idx].Used_in_array_section();
00610 }
00611
00612
00613
00614
00615
00616
00617
00618 extern IPA_CLONING_ACTION
00619 Union_Formal_Cprop_Annot_With_Cloning (IPA_NODE* callee,
00620 IPA_EDGE* edge)
00621 {
00622 VALUE_DYN_ARRAY* formals = callee->Cprop_Annot();
00623 VALUE_DYN_ARRAY* actuals = edge->Cprop_Annot();
00624
00625 if (formals == NULL || actuals == NULL) {
00626 return NO_CHANGE;
00627 }
00628
00629
00630 UINT32 count = (formals->Elements() < actuals->Elements()) ?
00631 formals->Elements() : actuals->Elements();
00632
00633 Set_summary_info (callee);
00634
00635 IPA_CLONING_ACTION action = NO_CHANGE;
00636 for (UINT32 pos = 0, formal_idx = ipa_proc->Get_formal_index();
00637 pos < count;
00638 ++pos, ++formal_idx) {
00639
00640 const SUMMARY_FORMAL& sum_formal=ipa_formal[formal_idx];
00641 const SUMMARY_SYMBOL& formal_sym=ipa_symbol[sum_formal.Get_symbol_index()];
00642 TYPE_ID mtype = formal_sym.Get_btype();
00643 BOOL is_ref_param = sum_formal.Is_ref_parm();
00644
00645
00646 if (Clone_for_this_formal(callee, pos)) {
00647 IPA_CLONING_ACTION node_action = Precise_node_update(&(*formals)[pos],
00648 &(*actuals)[pos],
00649 mtype,
00650 is_ref_param);
00651
00652 if (node_action == NEEDS_CLONING) {
00653 action = NEEDS_CLONING;
00654 }
00655 else if (action == NO_CHANGE) {
00656 action = node_action;
00657 }
00658 }
00659 else {
00660 if (Update_node((*formals)[pos], (*actuals)[pos], mtype, is_ref_param) &&
00661 action == NO_CHANGE) {
00662 action = ANNOTATION_CHANGED;
00663 }
00664 }
00665 }
00666
00667 return action;
00668
00669 }
00670
00671
00672
00673
00674
00675 static void
00676 Simplify_value (SUMMARY_VALUE& value)
00677 {
00678 if (value.Is_addr_of ())
00679 return;
00680
00681 if (value.Is_global ()) {
00682 const ST& st = St_Table[value.Get_global_st_idx ()];
00683 Is_True (ST_is_const_var (st),
00684 ("Non-constant global variables found in constant propagation"));
00685
00686 const TY& ty = Ty_Table[ST_type (st)];
00687 if (TY_kind (ty) != KIND_SCALAR && TY_kind (ty) != KIND_POINTER)
00688 return;
00689
00690
00691 if (!ST_is_initialized (st) || ST_init_value_zero (st)) {
00692 if (MTYPE_is_integral (value.Get_mtype ())) {
00693 value.Set_int_const ();
00694 value.Set_int_const_value (0);
00695 } else if (value.Get_mtype () != MTYPE_M) {
00696 value.Set_const_st ();
00697 TCON_IDX tcon_idx =
00698 Enter_tcon (Host_To_Targ_Float (value.Get_mtype (), (double) 0));
00699 value.Set_const_st_idx (ST_st_idx (st), tcon_idx);
00700 value.Set_merged_const_st_idx ();
00701 }
00702 return;
00703 }
00704 else {
00705
00706 if (ST_base_idx (st) != ST_st_idx (st))
00707 return;
00708
00709
00710
00711 ST_TO_INITO_MAP::const_iterator iter =
00712 ST_To_INITO_Map.find (ST_st_idx (st));
00713 FmtAssert (iter != ST_To_INITO_Map.end (),
00714 ("Missing value for initialized global variable %s",
00715 ST_name (st)));
00716 const INITO& inito = Inito_Table[(*iter).second];
00717 Is_True (INITO_st_idx (inito) == ST_st_idx (st),
00718 ("Mismatched inito and initialized st"));
00719 const INITV& initv = Initv_Table[INITO_val (inito)];
00720
00721 switch (INITV_kind (initv)) {
00722 case INITVKIND_ZERO:
00723 value.Set_int_const ();
00724 value.Set_int_const_value (0);
00725 return;
00726
00727 case INITVKIND_ONE:
00728 value.Set_int_const ();
00729 value.Set_int_const_value (1);
00730 return;
00731
00732 case INITVKIND_VAL:
00733 value.Set_const_st ();
00734 value.Set_const_st_idx (ST_st_idx (st), INITV_tc (initv));
00735 value.Set_merged_const_st_idx ();
00736
00737 break;
00738
00739 case INITVKIND_SYMOFF:
00740 if (TY_kind (ty) != KIND_POINTER)
00741 return;
00742 if (INITV_ofst (initv) != 0)
00743 return;
00744 value.Set_is_addr_of ();
00745 value.Set_global_st_idx (INITV_st (initv));
00746 break;
00747
00748 default:
00749 return;
00750 }
00751 }
00752 }
00753
00754 if (! MTYPE_is_integral (value.Get_mtype ()))
00755 return;
00756
00757 if (value.Is_const_st ()) {
00758 TCON& tc = Tcon_Table[value.Get_tcon_idx()];
00759 INT64 v = Targ_To_Host (tc);
00760 value.Set_int_const ();
00761 value.Set_int_const_value (v);
00762 }
00763 }
00764
00765
00766
00767
00768
00769 static IPA_NODE *
00770 Get_callee (SUMMARY_CALLSITE *callsite, INT sym_idx, BOOL must_be_an_actual)
00771 {
00772 if (must_be_an_actual) {
00773
00774
00775 SUMMARY_ACTUAL *actuals =&ipa_actual[callsite->Get_actual_index()];
00776 BOOL found = FALSE;
00777 for (INT i = 0; i < callsite->Get_param_count (); i++) {
00778 if (actuals[i].Get_symbol_index () == sym_idx &&
00779 actuals[i].Get_pass_type () == PASS_LDA) {
00780 found = TRUE;
00781 break;
00782 }
00783 }
00784
00785 if (!found) return (IPA_NODE *) -1;
00786 }
00787
00788 static SUMMARY_CALLSITE* base;
00789
00790 if (callsite_map == 0) {
00791
00792 INT size = sizeof(IPA_NODE *) * ipa_proc->Get_callsite_count ();
00793 callsite_map = (IPA_NODE **) MEM_POOL_Alloc (&Ipa_cprop_pool, size);
00794 bzero (callsite_map, size);
00795
00796 base = &ipa_callsite[ipa_proc->Get_callsite_index()];
00797
00798 IPA_SUCC_ITER edge_iter (Current_caller);
00799 for (edge_iter.First (); !edge_iter.Is_Empty(); edge_iter.Next()) {
00800 IPA_EDGE* e = edge_iter.Current_Edge();
00801 if (e) {
00802 INT idx = e->Summary_Callsite() - base;
00803 IPA_NODE* callee = IPA_Call_Graph->Callee(e);
00804 callsite_map[idx] = callee;
00805 }
00806 }
00807 }
00808
00809 Is_True(callsite >= base,
00810 ("Get_callee: negative callsite index %d", callsite - base));
00811
00812 return callsite_map[callsite - base];
00813 }
00814
00815
00816 static void
00817 Get_chi_operand (const SUMMARY_CHI *chi, SUMMARY_VALUE &return_value)
00818 {
00819 if (chi->Is_chi_value ()) {
00820 const SUMMARY_VALUE& value = ipa_value[chi->Get_node_index ()];
00821 Evaluate_value (value, return_value);
00822 } else if (chi->Is_chi_expr ()) {
00823 SUMMARY_EXPR *expr = ipa_expr + chi->Get_node_index ();
00824 Evaluate_expr (expr, return_value);
00825 } else if (chi->Is_chi_phi ()) {
00826 SUMMARY_PHI *phi = ipa_phi + chi->Get_node_index ();
00827 Evaluate_phi (phi, return_value);
00828 } else if (chi->Is_chi_chi ()) {
00829 SUMMARY_CHI *sub_chi = ipa_chi + chi->Get_node_index ();
00830 Evaluate_chi (sub_chi, return_value);
00831 } else {
00832 return_value.Set_not_const ();
00833 (*eval_hash)[chi] = 0;
00834 return;
00835 }
00836
00837 (*eval_hash)[chi] = eval_value->Insert (return_value);
00838 }
00839
00840
00841
00842
00843
00844
00845 static void
00846 Process_formal_imod (const SUMMARY_CALLSITE *callsite,
00847 const IPAA_NODE_INFO *callee_info,
00848 const SUMMARY_CHI *chi,
00849 SUMMARY_VALUE &return_value)
00850 {
00851 SUMMARY_ACTUAL *actuals = ipa_actual + callsite->Get_actual_index ();
00852
00853 INT count = callsite->Get_param_count ();
00854 if (count > callee_info->Get_fcount ())
00855 count = callee_info->Get_fcount ();
00856
00857 while (count--) {
00858 if (chi->Get_symbol_index () == actuals[count].Get_symbol_index () &&
00859 actuals[count].Get_pass_type () == PASS_LDA &&
00860 callee_info->Is_formal_imod_elmt (count)) {
00861
00862 return_value.Set_not_const ();
00863 (*eval_hash)[chi] = 0;
00864 return;
00865 }
00866 }
00867
00868 Get_chi_operand (chi, return_value);
00869 }
00870
00871
00872
00873
00874 static void
00875 Process_reference_parameter (const SUMMARY_CHI *chi,
00876 SUMMARY_VALUE &return_value)
00877 {
00878 SUMMARY_CALLSITE *callsite = ipa_callsite + chi->Get_call_index ();
00879 IPA_NODE *callee = Get_callee (callsite, chi->Get_symbol_index (), TRUE);
00880
00881 if (callee == (IPA_NODE *) -1) {
00882
00883 Get_chi_operand (chi, return_value);
00884 return;
00885 }
00886
00887 if (callee == NULL) {
00888 return_value.Set_not_const ();
00889 (*eval_hash)[chi] = 0;
00890 return;
00891 }
00892
00893 Process_formal_imod (callsite, callee->Mod_Ref_Info(), chi, return_value);
00894
00895 }
00896
00897
00898 static void
00899 Evaluate_chi (const SUMMARY_CHI *chi, SUMMARY_VALUE &return_value)
00900 {
00901 EVAL_HASH::const_iterator idx = eval_hash->find (chi);
00902
00903 if (idx != eval_hash->end ()) {
00904 return_value = (*eval_value)[(*idx).second];
00905 return;
00906 }
00907
00908 if (!IPA_Enable_Addressing ||
00909 !IPA_Enable_Simple_Alias ||
00910 Current_caller->Summary_Proc()->Is_alt_entry()) {
00911 return_value.Set_not_const ();
00912 return;
00913 }
00914
00915 const SUMMARY_SYMBOL &sym = ipa_symbol[chi->Get_symbol_index ()];
00916
00917 if (sym.Is_global ()) {
00918
00919
00920 ST_IDX st_idx = sym.St_idx();
00921 if (ST_is_const_var(ST_ptr(st_idx))) {
00922
00923 if (return_value.Is_addr_of()) {
00924 return_value.Set_not_const ();
00925 (*eval_hash)[chi] = 0;
00926 }
00927 else {
00928 return_value.Set_global ();
00929 return_value.Set_global_st_idx (st_idx);
00930 return_value.Set_global_index (-1);
00931
00932 TYPE_ID mtype = Mtype_comparison (TY_mtype (ST_type (st_idx)));
00933 return_value.Set_mtype (mtype);
00934
00935 Simplify_value (return_value);
00936
00937 (*eval_hash)[chi] = eval_value->Insert (return_value);
00938 }
00939 return;
00940 }
00941 }
00942
00943 if (sym.Is_static() ||
00944 sym.Is_addr_saved ()) {
00945 return_value.Set_not_const ();
00946 return;
00947 }
00948
00949 if (sym.Is_local () && !sym.Is_common ()) {
00950 if (!sym.Is_addr_passed()) {
00951
00952 Get_chi_operand (chi, return_value);
00953 return;
00954 }
00955
00956 #if 0
00957
00958
00959
00960
00961
00962 if (!sym.Is_dmod ()) {
00963
00964 Get_chi_operand (chi, return_value);
00965 return;
00966 }
00967 #endif
00968
00969
00970
00971
00972 Process_reference_parameter (chi, return_value);
00973 return;
00974 } else {
00975
00976
00977 ST* st = &St_Table[sym.St_idx ()];
00978
00979 while (ST_base_idx (st) != ST_st_idx (st))
00980 st = ST_base (st);
00981
00982 if (ST_addr_saved (st)) {
00983 return_value.Set_not_const ();
00984 return;
00985 }
00986
00987
00988
00989 IPA_NODE *callee = Get_callee (ipa_callsite + chi->Get_call_index (),
00990 chi->Get_symbol_index (), FALSE);
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000 if (callee == NULL) {
01001 if (icall_def != NULL &&
01002 ! icall_def->Is_elmt (ST_IDX_index (ST_st_idx (st)))) {
01003 Get_chi_operand (chi, return_value);
01004 return;
01005 }
01006 } else if (! callee->Mod_Ref_Info ()->
01007 Is_def_elmt (ST_IDX_index (ST_st_idx (st)))) {
01008
01009
01010
01011 Process_formal_imod (ipa_callsite + chi->Get_call_index (),
01012 callee->Mod_Ref_Info (), chi, return_value);
01013 return;
01014 }
01015
01016 return_value.Set_not_const ();
01017 (*eval_hash)[chi] = 0;
01018 return;
01019 }
01020
01021 }
01022
01023
01024 static void
01025 Get_phi_operand (const SUMMARY_PHI *phi, INT operand,
01026 SUMMARY_VALUE &return_value)
01027 {
01028 if (phi->Is_value (operand)) {
01029 const SUMMARY_VALUE& value = ipa_value[phi->Get_node_index (operand)];
01030 Evaluate_value (value, return_value);
01031 } else if (phi->Is_expr (operand)) {
01032 SUMMARY_EXPR *expr = ipa_expr + phi->Get_node_index (operand);
01033 Evaluate_expr (expr, return_value);
01034 } else if (phi->Is_phi (operand)) {
01035 SUMMARY_PHI *sub_phi = ipa_phi + phi->Get_node_index (operand);
01036 Evaluate_phi (sub_phi, return_value);
01037 } else if (phi->Is_chi (operand)) {
01038 SUMMARY_CHI *chi = ipa_chi + phi->Get_node_index (operand);
01039 Evaluate_chi (chi, return_value);
01040 } else {
01041
01042 return_value.Set_not_const ();
01043 (*eval_hash)[phi] = 0;
01044 return;
01045 }
01046
01047 (*eval_hash)[phi] = eval_value->Insert (return_value);
01048 }
01049
01050
01051 static void
01052 Evaluate_phi (const SUMMARY_PHI *phi, SUMMARY_VALUE &return_value)
01053 {
01054 if (!IPA_Enable_Flow_Analysis) {
01055 return_value.Set_not_const ();
01056 return;
01057 }
01058
01059 EVAL_HASH::const_iterator idx = eval_hash->find (phi);
01060 if (idx != eval_hash->end ()) {
01061 return_value = (*eval_value)[(*idx).second];
01062 return;
01063 }
01064
01065 INT operand = -1;
01066
01067 INT cd_idx = phi->Get_ctrl_dep_index (0) - ipa_proc->Get_ctrl_dep_index ();
01068
01069 switch (cd_status[cd_idx]) {
01070 case CD_DEAD:
01071 operand = 1;
01072 break;
01073 case CD_FALSE:
01074 if (phi->Get_branch (0))
01075 operand = 1;
01076 break;
01077 case CD_TRUE:
01078 if (!phi->Get_branch (0))
01079 operand = 1;
01080 break;
01081 case CD_UNKNOWN:
01082 break;
01083 }
01084
01085 if (operand == -1) {
01086 cd_idx = phi->Get_ctrl_dep_index (1) - ipa_proc->Get_ctrl_dep_index ();
01087
01088 switch (cd_status[cd_idx]) {
01089 case CD_DEAD:
01090 operand = 0;
01091 break;
01092 case CD_FALSE:
01093 if (phi->Get_branch (1))
01094 operand = 0;
01095 break;
01096 case CD_TRUE:
01097 if (!phi->Get_branch (1))
01098 operand = 0;
01099 break;
01100 case CD_UNKNOWN:
01101 break;
01102 }
01103 }
01104
01105 if (operand == -1) {
01106
01107
01108 SUMMARY_VALUE v1, v2;
01109 v1.Init ();
01110 Get_phi_operand (phi, 0, v1);
01111 if (v1.Is_constant ()) {
01112 v2.Init ();
01113 Get_phi_operand (phi, 1, v2);
01114 if (memcmp (&v1, &v2, sizeof(SUMMARY_VALUE)) == 0) {
01115 return_value = v1;
01116 return;
01117 }
01118 }
01119 return_value.Set_not_const ();
01120 (*eval_hash)[phi] = 0;
01121 return;
01122 }
01123
01124 Get_phi_operand (phi, operand, return_value);
01125
01126 }
01127
01128
01129 static void
01130 Get_expr_operand (const SUMMARY_EXPR *expr, INT operand,
01131 SUMMARY_VALUE &return_value)
01132 {
01133 if (expr->Has_const_operand () && expr->Get_kid () != operand) {
01134 return_value.Set_int_const ();
01135 return_value.Set_int_const_value (expr->Get_const_value ());
01136 return_value.Set_mtype (expr->Get_mtype ());
01137 return;
01138 }
01139
01140 if (expr->Is_expr_value (operand)) {
01141 const SUMMARY_VALUE& value = ipa_value[expr->Get_node_index (operand)];
01142 Evaluate_value (value, return_value);
01143 } else if (expr->Is_expr_expr (operand)) {
01144 SUMMARY_EXPR *sub_expr = ipa_expr + expr->Get_node_index (operand);
01145 Evaluate_expr (sub_expr, return_value);
01146 } else if (expr->Is_expr_phi (operand)) {
01147 SUMMARY_PHI *phi = ipa_phi + expr->Get_node_index (operand);
01148 Evaluate_phi (phi, return_value);
01149 } else if (expr->Is_expr_chi (operand)) {
01150 SUMMARY_CHI *chi = ipa_chi + expr->Get_node_index (operand);
01151 Evaluate_chi (chi, return_value);
01152 } else {
01153 return_value.Set_not_const ();
01154 return;
01155 }
01156
01157 Simplify_value (return_value);
01158
01159 return;
01160 }
01161
01162
01163 static void
01164 Evaluate_expr (const SUMMARY_EXPR *expr, SUMMARY_VALUE &return_value)
01165 {
01166 SUMMARY_VALUE first_operand, second_operand;
01167 WN *kid0, *kid1, *result;
01168 OPCODE op;
01169
01170 EVAL_HASH::const_iterator idx = eval_hash->find (expr);
01171 if (idx != eval_hash->end ()) {
01172 return_value = (*eval_value)[(*idx).second];
01173 return;
01174 }
01175
01176 return_value.Set_mtype (expr->Get_mtype ());
01177
01178 if (expr->Is_expr_unknown ()) {
01179 return_value.Set_not_const ();
01180 (*eval_hash)[expr] = 0;
01181 return;
01182 }
01183
01184 first_operand.Init ();
01185 Get_expr_operand (expr, 0, first_operand);
01186
01187 if (first_operand.Is_not_const ()) {
01188 return_value.Set_not_const ();
01189 (*eval_hash)[expr] = 0;
01190 return;
01191 } else if (!first_operand.Is_int_const ()) {
01192
01193 return_value.Set_not_const ();
01194 (*eval_hash)[expr] = 0;
01195 return;
01196 }
01197
01198 if (OPCODE_nkids (expr->Get_opcode ()) == 2) {
01199 second_operand.Init ();
01200 Get_expr_operand (expr, 1, second_operand);
01201
01202 if (second_operand.Is_not_const ()) {
01203 return_value.Set_not_const ();
01204 (*eval_hash)[expr] = 0;
01205 return;
01206 } else if (!second_operand.Is_int_const ()) {
01207
01208 return_value.Set_not_const ();
01209 (*eval_hash)[expr] = 0;
01210 return;
01211 }
01212 }
01213
01214 op = OPCODE_make_op (OPR_INTCONST, first_operand.Get_mtype (), MTYPE_V);
01215 kid0 = WN_CreateIntconst (op, first_operand.Get_int_const_value ());
01216
01217 if (OPCODE_nkids (expr->Get_opcode ()) == 2) {
01218 op = OPCODE_make_op (OPR_INTCONST, second_operand.Get_mtype (),
01219 MTYPE_V);
01220 kid1 = WN_CreateIntconst (op, second_operand.Get_int_const_value ());
01221
01222 result = WN_SimplifyExp2 (expr->Get_opcode (), kid0, kid1);
01223
01224 } else if (OPCODE_nkids (expr->Get_opcode ()) == 1) {
01225 if (OPCODE_operator (expr->Get_opcode ()) == OPR_CVTL)
01226 result = WN_SimplifyCvtl (expr->Get_opcode (),
01227 expr->Get_const_value (), kid0);
01228 else
01229 result = WN_SimplifyExp1 (expr->Get_opcode (), kid0);
01230 }
01231
01232 if (result != NULL &&
01233 WN_operator(result) == OPR_INTCONST) {
01234 return_value.Set_int_const ();
01235 return_value.Set_int_const_value (WN_const_val (result));
01236 } else
01237 return_value.Set_not_const ();
01238
01239 (*eval_hash)[expr] = eval_value->Insert (return_value);
01240
01241 }
01242
01243
01244
01245
01246
01247
01248 static BOOL
01249 Evaluate_common_const (const SUMMARY_SYMBOL* sym,
01250 const SUMMARY_VALUE& value,
01251 SUMMARY_VALUE& return_value)
01252 {
01253 if (current_gannot && sym && sym->Is_common()) {
01254 const ST& st = St_Table[sym->St_idx()];
01255 const GLOBAL_VALUE* gval =
01256 current_gannot->Find(GLOBAL_ANNOT::Index(ST_base_idx(st)),
01257 ST_ofst(st),
01258 (UINT32) TY_size(ST_type(st)));
01259 if (gval) {
01260 SUMMARY_VALUE* val = gval->Value();
01261 if (val) {
01262 Evaluate_value(*val, return_value);
01263 if (value.Is_addr_of ()) {
01264 return_value.Set_is_addr_of ();
01265 return_value.Set_target_mtype (value.Target_mtype ());
01266 return_value.Set_mtype (value.Get_mtype ());
01267 }
01268 return TRUE;
01269 }
01270 }
01271 }
01272 return FALSE;
01273 }
01274
01275
01276 #ifdef KEY
01277
01278
01279 static BOOL
01280 Var_is_private (ST_IDX idx, WN * region)
01281 {
01282 Is_True (region && (WN_region_kind (region) & REGION_KIND_MP),
01283 ("Var_is_private: Valid MP region expected"));
01284
01285 Is_True (idx, ("Var_is_private: Invalid symbol idx"));
01286
01287 WN * pragmas = WN_first (WN_region_pragmas (region));
01288
01289 while (pragmas)
01290 {
01291 ST_IDX sym = WN_st_idx (pragmas);
01292 if (sym == idx)
01293 {
01294 switch (WN_pragma (pragmas))
01295 {
01296 case WN_PRAGMA_LOCAL:
01297 case WN_PRAGMA_FIRSTPRIVATE:
01298 case WN_PRAGMA_LASTLOCAL:
01299 return TRUE;
01300
01301 default:
01302 break;
01303 }
01304 }
01305
01306 pragmas = WN_next (pragmas);
01307 }
01308
01309 return FALSE;
01310 }
01311
01312
01313
01314 static void
01315 Evaluate_value (const SUMMARY_VALUE& value, SUMMARY_VALUE& return_value,
01316 WN * mp_region)
01317 #else
01318 static void
01319 Evaluate_value (const SUMMARY_VALUE& value, SUMMARY_VALUE &return_value)
01320 #endif // KEY
01321 {
01322 EVAL_HASH::const_iterator idx = eval_hash->find (&value);
01323
01324 if (idx != eval_hash->end ()) {
01325 return_value = (*eval_value)[(*idx).second];
01326 return;
01327 }
01328
01329 return_value = value;
01330
01331 if (value.Is_int_const ())
01332 return;
01333 else if (value.Is_const_st ()) {
01334 ST_IDX st_idx = return_value.Get_const_st_idx ();
01335 if (st_idx == 0)
01336 return;
01337 const ST& st = St_Table[st_idx];
01338 Is_True (ST_sym_class (st) == CLASS_CONST,
01339 ("Inconsistent summary info: symbol should be CLASS_CONST"));
01340 return_value.Set_const_st_idx (st_idx, ST_tcon (st));
01341 return_value.Set_merged_const_st_idx();
01342 Simplify_value (return_value);
01343 return;
01344 } else if (value.Is_formal ()) {
01345 if (formal_value == 0) {
01346 return_value.Set_not_const ();
01347 return;
01348 }
01349
01350 const SUMMARY_FORMAL& sum_formal =
01351 ipa_formal[value.Get_formal_index ()];
01352
01353 if (value.Is_addr_of () && !sum_formal.Is_ref_parm ()) {
01354
01355 return_value.Set_not_const ();
01356 return;
01357 }
01358
01359 INT idx = sum_formal.Get_position ();
01360 const SUMMARY_VALUE& formal = (*formal_value)[idx];
01361
01362 return_value = formal;
01363
01364 if (sum_formal.Is_ref_parm ()) {
01365 if (!value.Is_addr_of ()) {
01366
01367 if (return_value.Is_addr_of () &&
01368 (!return_value.Is_global() ||
01369 ST_is_const_var(ST_ptr(return_value.Get_global_st_idx())))) {
01370
01371 return_value.Clear_is_addr_of ();
01372 return_value.Set_mtype (return_value.Target_mtype ());
01373 Simplify_value (return_value);
01374 } else {
01375 return_value.Set_not_const ();
01376 return;
01377 }
01378 }
01379 } else {
01380
01381 if (value.Is_addr_of ()) {
01382
01383 return_value.Set_not_const ();
01384 return;
01385 }
01386
01387 if (return_value.Is_addr_of ()) {
01388
01389
01390
01391
01392
01393 if (!return_value.Is_convertible_to_global ()) {
01394 switch (return_value.Get_const_type ()) {
01395 case VALUE_INT_CONST:
01396 case VALUE_CONST:
01397 return_value.Set_symbol ();
01398 }
01399 }
01400 }
01401 }
01402
01403 if (return_value.Is_addr_of ()) {
01404 if (return_value.Get_mtype () != Pointer_type)
01405 return_value.Set_not_const ();
01406 return;
01407 }
01408
01409 switch (return_value.Get_const_type ()) {
01410 case VALUE_NOT_CONST:
01411 return_value.Set_not_const ();
01412 break;
01413
01414 case VALUE_INT_CONST:
01415 if (MTYPE_is_integral (return_value.Get_mtype ()) &&
01416 MTYPE_is_integral (value.Get_mtype ()))
01417
01418 return_value.Set_mtype (value.Get_mtype ());
01419 else
01420 return_value.Set_not_const ();
01421 break;
01422
01423 case VALUE_CONST:
01424 case VALUE_GLOBAL:
01425 if (MTYPE_type_class (return_value.Get_mtype ()) !=
01426 MTYPE_type_class (value.Get_mtype ()))
01427 return_value.Set_not_const ();
01428 break;
01429
01430 default:
01431 return_value.Set_not_const ();
01432 break;
01433 }
01434 } else if (value.Is_symbol ()) {
01435 return_value.Set_not_const ();
01436 return;
01437 } else if (value.Is_global ()) {
01438 INT idx = value.Get_global_index ();
01439 ST_IDX st_idx;
01440 const SUMMARY_SYMBOL* sym = NULL;
01441 if (idx != -1) {
01442 sym = ipa_symbol + idx;
01443 st_idx = sym->St_idx ();
01444 } else
01445 st_idx = value.Get_global_st_idx ();
01446 return_value.Set_global_st_idx (st_idx);
01447 return_value.Set_global_index (-1);
01448
01449 #ifdef KEY
01450 if (mp_region && Var_is_private (st_idx, mp_region)) {
01451 return_value.Set_not_const ();
01452 return;
01453 }
01454 #endif // KEY
01455 if (!ST_is_const_var (St_Table[st_idx])) {
01456 if (Evaluate_common_const(sym, value, return_value)) {
01457 return;
01458 }
01459 if (!value.Is_addr_of()) {
01460 return_value.Set_not_const ();
01461 (*eval_hash)[&value] = 0;
01462 return;
01463 }
01464 }
01465 Simplify_value (return_value);
01466
01467 if (return_value.Is_global () &&
01468 return_value.Is_addr_of () &&
01469 ! return_value.Is_convertible_to_global ()) {
01470
01471
01472
01473
01474
01475
01476
01477
01478
01479
01480
01481 return_value.Set_not_const ();
01482 (*eval_hash)[&value] = 0;
01483 return;
01484 }
01485
01486 } else if (value.Is_expr ()) {
01487 SUMMARY_EXPR *expr = ipa_expr + value.Get_expr_index ();
01488 Evaluate_expr (expr, return_value);
01489 } else if (value.Is_phi ()) {
01490 SUMMARY_PHI *phi = ipa_phi + value.Get_phi_index ();
01491 Evaluate_phi (phi, return_value);
01492 } else if (value.Is_chi ()) {
01493 SUMMARY_CHI *chi = ipa_chi + value.Get_chi_index ();
01494 Evaluate_chi (chi, return_value);
01495 }
01496
01497 if (value.Is_addr_of ()) {
01498 return_value.Set_is_addr_of ();
01499 return_value.Set_target_mtype (value.Target_mtype ());
01500 return_value.Set_mtype (value.Get_mtype ());
01501 }
01502
01503 (*eval_hash)[&value] = eval_value->Insert (return_value);
01504 }
01505
01506
01507
01508
01509
01510 static BOOL
01511 PU_is_dead (IPA_NODE *node, BOOL *updated)
01512 {
01513 IPA_EDGE *e;
01514 IPA_PRED_ITER pred_iter (node);
01515
01516 if (node->Is_Externally_Callable () ||
01517 node->Summary_Proc()->Is_alt_entry () ||
01518 node->Summary_Proc()->Has_alt_entry ())
01519 return FALSE;
01520
01521 for (pred_iter.First (); !pred_iter.Is_Empty (); pred_iter.Next ()) {
01522 e = pred_iter.Current_Edge ();
01523 if (e && e->Cprop_Annot() != (void *) -1)
01524 return FALSE;
01525 }
01526
01527
01528
01529 IPA_SUCC_ITER succ_iter (node);
01530
01531 for (succ_iter.First (); !succ_iter.Is_Empty (); succ_iter.Next ()) {
01532 e = succ_iter.Current_Edge ();
01533 if (e == NULL)
01534 continue;
01535 if (e->Cprop_Annot () != (void *) -1) {
01536 e->Set_Cprop_Annot ((VALUE_DYN_ARRAY*) -1);
01537 *updated = TRUE;
01538 }
01539 }
01540
01541 if (node->Cprop_Annot () != (void *) -1) {
01542 if (node->Cprop_Annot () != NULL)
01543 CXX_DELETE (node->Cprop_Annot (), Malloc_Mem_Pool);
01544 node->Set_Cprop_Annot ((VALUE_DYN_ARRAY*) -1);
01545 *updated = TRUE;
01546 }
01547
01548 return TRUE;
01549
01550 }
01551
01552
01553 static void
01554 Delete_stmts (SUMMARY_CONTROL_DEPENDENCE *cd, BOOL branch, BOOL *call_deleted)
01555 {
01556 SUMMARY_STMT *stmts;
01557 INT count;
01558
01559 if (branch) {
01560 stmts = ipa_stmt + cd->Get_true_stmt_index ();
01561 count = cd->Get_true_count ();
01562 } else {
01563 stmts = ipa_stmt + cd->Get_false_stmt_index ();
01564 count = cd->Get_false_count ();
01565 }
01566
01567 for (INT i = 0; i < count; i++) {
01568 INT idx;
01569 if (stmts[i].Is_cond ()) {
01570 idx = stmts[i].Get_cond_index () - ipa_proc->Get_ctrl_dep_index ();
01571 cd_status[idx] = CD_DEAD;
01572 } else if (stmts[i].Is_call ()) {
01573 idx = stmts[i].Get_call_index () - ipa_proc->Get_callsite_index ();
01574 call_deleted[idx] = TRUE;
01575 }
01576 }
01577 }
01578
01579
01580
01581 static void
01582 Process_cond_branches (BOOL *call_deleted)
01583 {
01584 cd_status = (CONDITION_STATE *)
01585 MEM_POOL_Alloc (&Ipa_cprop_pool, sizeof(CONDITION_STATE) *
01586 ipa_proc->Get_ctrl_dep_count ());
01587
01588 bzero (cd_status, sizeof(CONDITION_STATE) * ipa_proc->Get_ctrl_dep_count ());
01589
01590 for (INT i = 0; i < ipa_proc->Get_ctrl_dep_count (); i++) {
01591
01592 SUMMARY_CONTROL_DEPENDENCE *cd;
01593
01594 cd = ipa_ctrl_dep + ipa_proc->Get_ctrl_dep_index () + i;
01595
01596 if (cd_status[i] == CD_DEAD) {
01597 Delete_stmts (cd, TRUE, call_deleted);
01598 Delete_stmts (cd, FALSE, call_deleted);
01599 continue;
01600 }
01601
01602 if (cd->Is_do_loop () || cd->Is_entry ())
01603 continue;
01604
01605 if (cd->Get_expr_index () == -1)
01606 continue;
01607
01608 SUMMARY_EXPR *expr = ipa_expr + cd->Get_expr_index ();
01609 SUMMARY_VALUE value;
01610 value.Init ();
01611
01612 Evaluate_expr (expr, value);
01613
01614 if (!value.Is_int_const ())
01615 continue;
01616
01617 cd_status[i] = value.Get_int_const_value () ? CD_TRUE : CD_FALSE;
01618
01619 Delete_stmts (cd, !value.Get_int_const_value (), call_deleted);
01620
01621 }
01622
01623 }
01624
01625 #ifdef KEY
01626 #include "ipo_parent.h"
01627
01628
01629 static void
01630 Get_enclosing_mp_region (IPA_NODE * c, IPA_EDGE * e)
01631 {
01632 PU caller = c->Get_PU ();
01633
01634 if (!PU_has_mp (caller)) return;
01635
01636
01637 IPA_NODE_CONTEXT context (c);
01638
01639
01640 IPA_Call_Graph->Map_Callsites (c);
01641
01642 WN * call_wn = e->Whirl_Node ();
01643 Is_True (call_wn, ("Get_enclosing_mp_region: NULL callsite in IPA_EDGE"));
01644
01645 WN * parent = WN_Get_Parent (call_wn, Parent_Map, Current_Map_Tab);
01646
01647 for (; parent; parent = WN_Get_Parent (parent, Parent_Map, Current_Map_Tab))
01648 {
01649
01650 if (WN_operator (parent) == OPR_REGION &&
01651 (WN_region_kind (parent) & REGION_KIND_MP))
01652 {
01653 e->Set_MP_Whirl_Node (parent);
01654 break;
01655 }
01656 }
01657 }
01658 #endif // KEY
01659
01660
01661
01662
01663
01664
01665
01666
01667 static VALUE_DYN_ARRAY *
01668 Get_cprop_annot (IPA_NODE *node)
01669 {
01670
01671
01672
01673
01674 if ((node->Is_Externally_Callable() && IPA_Enable_Cloning) ||
01675 node->Summary_Proc()->Is_alt_entry () ||
01676 node->Summary_Proc()->Has_alt_entry ()) {
01677 return NULL;
01678 }
01679
01680 #ifdef KEY
01681 {
01682
01683
01684
01685
01686 IPA_PRED_ITER edge_iter (node);
01687 for (edge_iter.First (); !edge_iter.Is_Empty(); edge_iter.Next()) {
01688 IPA_EDGE *e = edge_iter.Current_Edge();
01689 if (e && e->Is_Recursive()) {
01690 return NULL;
01691 }
01692 }
01693 }
01694 #endif
01695
01696 return node->Cprop_Annot();
01697 }
01698
01699
01700 static void
01701 Evaluate_actuals (IPA_NODE *caller, IPA_NODE *callee, IPA_EDGE *edge)
01702 {
01703 INT count = edge->Summary_Callsite()->Get_param_count ();
01704 VALUE_DYN_ARRAY* annot = edge->Cprop_Annot ();
01705 INT i;
01706 INT actual_idx = edge->Summary_Callsite()->Get_actual_index ();
01707
01708 if (count > callee->Num_Formals())
01709 count = callee->Num_Formals();
01710
01711 if (annot == NULL) {
01712 annot = CXX_NEW (VALUE_DYN_ARRAY (MEM_local_nz_pool_ptr),
01713 MEM_local_nz_pool_ptr);
01714 annot->Force_Alloc_array (count);
01715 annot->Setidx (count - 1);
01716 for (i = 0; i < count; i++)
01717 (*annot)[i].Init ();
01718 edge->Set_Cprop_Annot (annot);
01719 }
01720
01721 const PU& caller_pu = caller->Get_PU ();
01722 const PU& callee_pu = callee->Get_PU ();
01723
01724 BOOL check_for_readonly_ref =
01725 (IPA_Enable_Readonly_Ref && IPA_Enable_Simple_Alias &&
01726 IPA_Enable_Addressing && !PU_f77_lang (caller_pu) &&
01727 !PU_f90_lang (caller_pu));
01728
01729 const IPAA_NODE_INFO *callee_info = check_for_readonly_ref ?
01730 callee->Mod_Ref_Info () : NULL;
01731
01732 const IPAA_NODE_INFO *caller_info = caller->Mod_Ref_Info ();
01733
01734 BOOL Need_to_verify_duplicated = FALSE;
01735
01736 for (i = 0; i < count; i++, actual_idx++) {
01737
01738 const SUMMARY_VALUE* actual;
01739
01740 INT value_idx = ipa_actual[actual_idx].Get_value_index ();
01741 if (value_idx == -1) {
01742
01743 INT symbol_idx = ipa_actual[actual_idx].Get_symbol_index();
01744 if (symbol_idx != -1 && ipa_symbol[symbol_idx].Is_formal()) {
01745 INT position =
01746 ipa_formal[ipa_symbol[symbol_idx].Get_findex()].Get_position();
01747 #ifdef KEY
01748
01749 INT func_st_idx = ipa_symbol[symbol_idx].Get_st_idx_func();
01750 if (func_st_idx != ST_st_idx (caller->Func_ST())) {
01751
01752
01753 NODE_INDEX node_id =
01754 AUX_PU_node (Aux_Pu_Table[ST_pu (St_Table[func_st_idx])]);
01755 IPA_NODE * parent = IPA_Call_Graph->Graph()->Node_User (node_id);
01756
01757 Is_True (PU_ftn_lang (parent->Get_PU()),
01758 ("Nested PUs supported only in Fortran"));
01759
01760 VALUE_DYN_ARRAY * parents_formal_value = Get_cprop_annot (parent);
01761 if (parents_formal_value &&
01762 !parent->Mod_Ref_Info()->Is_formal_dmod_elmt(position) &&
01763 !parent->Mod_Ref_Info()->Is_formal_imod_elmt(position)) {
01764 actual = &(*parents_formal_value)[position];
01765 }
01766 else {
01767 (*annot)[i].Set_not_const ();
01768 continue;
01769 }
01770 } else
01771 #endif
01772 if (formal_value &&
01773 !caller_info->Is_formal_dmod_elmt(position) &&
01774 !caller_info->Is_formal_imod_elmt(position)) {
01775 actual = &(*formal_value)[position];
01776 }
01777 else {
01778 (*annot)[i].Set_not_const ();
01779 continue;
01780 }
01781 }
01782 else {
01783 (*annot)[i].Set_not_const ();
01784 continue;
01785 }
01786 }
01787 else {
01788 actual = &ipa_value[value_idx];
01789 }
01790
01791 #ifdef KEY
01792
01793
01794
01795 if (!edge->MP_Whirl_Node ())
01796 Get_enclosing_mp_region (caller, edge);
01797 WN * mp_region = edge->MP_Whirl_Node ();
01798
01799 Evaluate_value (*actual, (*annot)[i], mp_region);
01800 #else
01801
01802 Evaluate_value (*actual, (*annot)[i]);
01803 #endif // KEY
01804
01805 if (check_for_readonly_ref &&
01806 ipa_actual[actual_idx].Get_pass_type() == PASS_LDID) {
01807
01808 Need_to_verify_duplicated = TRUE;
01809
01810 if ((*annot)[i].Is_global () && (*annot)[i].Is_addr_of ()) {
01811
01812 ST_IDX st_idx = (*annot)[i].Get_global_st_idx ();
01813
01814 if (ST_addr_saved (St_Table[st_idx])) {
01815 edge->Clear_Param_Readonly(i);
01816 edge->Clear_Param_Pass_Not_Saved(i);
01817 continue;
01818 }
01819
01820 if (callee_info->Is_def_elmt (st_idx) ||
01821 callee_info->Is_formal_imod_elmt (i))
01822 edge->Clear_Param_Readonly(i);
01823 else
01824 edge->Set_Param_Readonly(i);
01825
01826 if (callee_info->Is_formal_dref_elmt (i))
01827 edge->Clear_Param_Pass_Not_Saved(i);
01828 else
01829 edge->Set_Param_Pass_Not_Saved (i);
01830
01831 } else {
01832 edge->Clear_Param_Readonly(i);
01833 edge->Clear_Param_Pass_Not_Saved(i);
01834 }
01835 }
01836 }
01837
01838 if (!Need_to_verify_duplicated)
01839 return;
01840
01841 for (i = 0; i < count; ++i) {
01842 if (! ((*annot)[i].Is_global () && (*annot)[i].Is_addr_of ()))
01843 continue;
01844 for (INT j = i + 1; j < count; ++j) {
01845 const SUMMARY_VALUE& value = (*annot)[j];
01846 if (! (value.Is_global () && value.Is_addr_of ()))
01847 continue;
01848 if ((*annot)[i].Get_global_st_idx () != value.Get_global_st_idx ())
01849 continue;
01850 edge->Clear_Param_Readonly(i);
01851 edge->Clear_Param_Readonly(j);
01852 edge->Clear_Param_Pass_Not_Saved(i);
01853 edge->Clear_Param_Pass_Not_Saved(j);
01854 Set_ST_addr_saved (St_Table[value.Get_global_st_idx ()]);
01855 }
01856 }
01857 }
01858
01859
01860 extern BOOL
01861 Intra_PU_Formal_Cprop (IPA_NODE *node)
01862 {
01863 BOOL updated = FALSE;
01864
01865 if (IPA_Enable_DFE && PU_is_dead (node, &updated))
01866 return updated;
01867
01868 current_gannot = node->Global_Annot ();
01869 formal_value = Get_cprop_annot (node);
01870
01871
01872
01873
01874
01875 if ((node->Is_Externally_Callable() && IPA_Enable_Cloning) ||
01876 node->Summary_Proc()->Is_alt_entry () ||
01877 node->Summary_Proc()->Has_alt_entry ()) {
01878 formal_value = 0;
01879 }
01880
01881 #ifdef KEY
01882 {
01883
01884
01885
01886
01887 IPA_PRED_ITER edge_iter (node);
01888 for (edge_iter.First (); !edge_iter.Is_Empty(); edge_iter.Next()) {
01889 IPA_EDGE *e = edge_iter.Current_Edge();
01890 if (e && e->Is_Recursive()) {
01891 formal_value = 0;
01892 break;
01893 }
01894 }
01895 }
01896 #endif
01897
01898 Set_summary_info (node);
01899
01900 WN_mem_pool_ptr = &Ipa_cprop_pool;
01901
01902 eval_value = CXX_NEW (VALUE_VECTOR (&Ipa_cprop_pool), &Ipa_cprop_pool);
01903 eval_hash = CXX_NEW (EVAL_HASH (100, eval_hasher(),
01904 std::equal_to<const void *> (),
01905 &Ipa_cprop_pool),
01906 &Ipa_cprop_pool);
01907
01908 SUMMARY_VALUE value;
01909 value.Init ();
01910 value.Set_not_const ();
01911
01912 eval_value->Insert (value);
01913 Is_True ((*eval_value)[0].Is_not_const (),
01914 ("incorrectly initialized eval_value array"));
01915
01916
01917 INT call_count = ipa_proc->Get_callsite_count ();
01918 BOOL* call_deleted = (BOOL*) alloca (sizeof(BOOL) * call_count);
01919 bzero (call_deleted, sizeof(BOOL) * call_count);
01920
01921 Current_caller = node;
01922 callsite_map = 0;
01923
01924 if (IPA_Enable_Flow_Analysis)
01925 Process_cond_branches (call_deleted);
01926
01927 SUMMARY_CALLSITE* callsite = &ipa_callsite[ipa_proc->Get_callsite_index()];
01928 IPA_SUCC_ITER edge_iter (node);
01929
01930 for (edge_iter.First (); !edge_iter.Is_Empty(); edge_iter.Next()) {
01931 IPA_EDGE *e = edge_iter.Current_Edge();
01932
01933 if (e == NULL)
01934 continue;
01935
01936 INT idx = e->Summary_Callsite() - callsite;
01937
01938 if (call_deleted[idx] && e->Cprop_Annot() != (void *) -1) {
01939 e->Set_Cprop_Annot ((VALUE_DYN_ARRAY*) -1);
01940 updated = TRUE;
01941 } else if (!call_deleted[idx]) {
01942 IPA_NODE *callee = IPA_Call_Graph->Callee (e);
01943 if (e->Cprop_Annot() == (void *) -1) {
01944 e->Set_Cprop_Annot (NULL);
01945 updated = TRUE;
01946
01947 if (callee->Cprop_Annot () == ((void *) -1)) {
01948
01949
01950 Init_Cprop_Annotations (callee);
01951 }
01952 } else {
01953 Evaluate_actuals (node, callee, e);
01954 }
01955 }
01956 }
01957
01958 if (! node->Icall_List().empty ()) {
01959 const IPA_ICALL_LIST& icall_list = node->Icall_List ();
01960
01961 for (IPA_ICALL_LIST::const_iterator icall_iter = icall_list.begin ();
01962 icall_iter != icall_list.end (); ++icall_iter) {
01963
01964 SUMMARY_CALLSITE *call = (*icall_iter)->Callsite();
01965 if (call == NULL)
01966 continue;
01967
01968 if (call_deleted[call - callsite])
01969 continue;
01970
01971 if ((*icall_iter)->Value().Is_not_const ())
01972 continue;
01973
01974 SUMMARY_VALUE return_value;
01975 return_value.Init ();
01976 Evaluate_value(ipa_value[call->Get_value_index()], return_value);
01977
01978 if (Update_node ((*icall_iter)->Value (),
01979 return_value,
01980 ipa_value[call->Get_value_index()].Get_mtype(),
01981 FALSE ))
01982 updated = TRUE;
01983 }
01984 }
01985
01986 return updated;
01987 }
01988
01989
01990
01991
01992
01993
01994
01995
01996
01997
01998
01999
02000
02001
02002
02003
02004
02005
02006
02007
02008 BOOL
02009 GLOBAL_VALUE::Union(SUMMARY_VALUE* value, BOOL overwrite)
02010 {
02011 if (overwrite) {
02012 if (_value != value) {
02013 _value = value;
02014 return TRUE;
02015 }
02016 return FALSE;
02017 }
02018
02019
02020 if (_value == 0) {
02021 return FALSE;
02022 }
02023
02024 if (value == 0 || !Values_are_equal(_value, value)) {
02025 _value = 0;
02026 return TRUE;
02027 }
02028
02029 return FALSE;
02030 }
02031
02032
02033
02034
02035 INT32
02036 GLOBAL_ANNOT::Index (ST_IDX st_idx)
02037 {
02038 for (UINT32 i = 0; i < Size; ++i) {
02039 if (Common_ST[i] == st_idx) {
02040 return i;
02041 }
02042 }
02043 return -1;
02044 }
02045
02046
02047
02048
02049
02050 const GLOBAL_VALUE*
02051 GLOBAL_ANNOT::Find (INT32 idx, UINT64 offset, UINT32 size) const
02052 {
02053 if (idx >= 0 && idx < Size && !Top(idx) && !Bottom(idx)) {
02054 const GLOBAL_DYN_ARRAY& gvals = Global_Value_Array(idx);
02055 for (UINT32 i = 0; i < gvals.Elements(); ++i) {
02056 if (gvals[i].Offset() == offset &&
02057 (size == 0 || gvals[i].Size() == size)) {
02058 return &(gvals[i]);
02059 }
02060 }
02061 }
02062 return 0;
02063 }
02064
02065
02066
02067
02068
02069 static inline BOOL
02070 Overlap (UINT64 start1, UINT32 size1, UINT64 start2, UINT32 size2)
02071 {
02072 UINT64 end1 = start1 + size1;
02073 UINT64 end2 = start2 + size2;
02074
02075 return ((start2 < end1 && end1 <= end2) || (start1 < end2 && end2 <= end1));
02076 }
02077
02078
02079
02080
02081 BOOL
02082 GLOBAL_ANNOT::Union (UINT32 common_idx,
02083 const GLOBAL_VALUE& gval,
02084 BOOL overwrite_when_found,
02085 BOOL add_when_not_found)
02086 {
02087 if (Top(common_idx) || Bottom(common_idx)) {
02088 if (add_when_not_found) {
02089 _gvals_array[common_idx] = CXX_NEW(GLOBAL_DYN_ARRAY(_pool), _pool);
02090 _gvals_array[common_idx]->Force_Alloc_array(8);
02091 _gvals_array[common_idx]->AddElement(gval);
02092 return TRUE;
02093 }
02094 else {
02095 return FALSE;
02096 }
02097 }
02098
02099 UINT64 offset = gval.Offset();
02100 UINT32 size = gval.Size();
02101 GLOBAL_DYN_ARRAY& gvals = *(_gvals_array[common_idx]);
02102
02103 for (UINT32 i = 0; i < gvals.Elements(); ++i) {
02104
02105 if (gvals[i].Offset() == offset && gvals[i].Size() == size) {
02106 return gvals[i].Union(gval.Value(), overwrite_when_found);
02107 }
02108
02109 else if (Overlap(gvals[i].Offset(), gvals[i].Size(), offset, size)) {
02110 Set_Bottom(common_idx);
02111 return TRUE;
02112 }
02113 }
02114
02115
02116 if (add_when_not_found) {
02117 gvals.AddElement(gval);
02118 return TRUE;
02119 }
02120
02121 return FALSE;
02122 }
02123
02124
02125
02126
02127 BOOL
02128 GLOBAL_ANNOT::Union (const GLOBAL_ANNOT* gannot)
02129 {
02130 BOOL change = FALSE;
02131
02132 for (UINT32 i = 0; i < Size; ++i) {
02133 if (Bottom(i) || gannot->Top(i)) {
02134 continue;
02135 }
02136 if (gannot->Bottom(i)) {
02137 Set_Bottom(i);
02138 change = TRUE;
02139 }
02140 else if (Top(i)) {
02141 _gvals_array[i] = CXX_NEW(GLOBAL_DYN_ARRAY(_pool), _pool);
02142 *(_gvals_array[i]) = gannot->Global_Value_Array(i);
02143 change = TRUE;
02144 }
02145 else {
02146 UINT32 j;
02147
02148 const GLOBAL_DYN_ARRAY& lhs = Global_Value_Array(i);
02149 const GLOBAL_DYN_ARRAY& rhs = gannot->Global_Value_Array(i);
02150
02151
02152
02153 for (j = 0; j < lhs.Elements(); ++j) {
02154 GLOBAL_VALUE& lhs_gval = lhs[j];
02155 if (!gannot->Find(i, lhs_gval.Offset(), lhs_gval.Size())) {
02156 new (&lhs_gval) GLOBAL_VALUE(lhs_gval.Offset(), lhs_gval.Size(), 0);
02157 }
02158 }
02159
02160
02161
02162 BOOL overwrite_if_found = FALSE;
02163 BOOL add_if_not_found = TRUE;
02164 for (j = 0; j < rhs.Elements(); ++j) {
02165 change |= Union(i, rhs[j], overwrite_if_found, add_if_not_found);
02166 }
02167 }
02168 }
02169
02170 return change;
02171 }
02172
02173
02174
02175
02176 void
02177 GLOBAL_ANNOT::Print(FILE *fp)
02178 {
02179 for (UINT32 i = 0; i < Size; ++i) {
02180 if (!Top(i) && !Bottom(i)) {
02181 fprintf(fp, " common block %s:\n", ST_name(Common_ST[i]));
02182 const GLOBAL_DYN_ARRAY& gvals = Global_Value_Array(i);
02183 for (UINT32 j = 0; j < gvals.Elements(); ++j) {
02184 if (gvals[j].Value()) {
02185 fprintf(fp, " offset = %lld, element_size = %d, value = ",
02186 gvals[j].Offset(), gvals[j].Size());
02187 gvals[j].Value()->Print_const_value(fp);
02188 fprintf(fp, "\n");
02189 }
02190 }
02191 }
02192 }
02193 }
02194
02195
02196
02197
02198
02199
02200
02201 static INT indent = 0;
02202
02203
02204
02205
02206 static void
02207 Process_stid (const IPA_NODE* node,
02208 const SUMMARY_STID* stid,
02209 BOOL always_executed,
02210 GLOBAL_ANNOT* gannot)
02211 {
02212 const ST& st =
02213 St_Table[IPA_get_symbol_array(node)[stid->Get_symbol_index()].St_idx()];
02214
02215 INT32 common_idx = GLOBAL_ANNOT::Index(ST_base_idx(st));
02216
02217
02218 if (common_idx != -1) {
02219
02220 UINT64 offset;
02221 UINT32 size;
02222
02223 if (stid->Is_array_assignment()) {
02224
02225 if (!stid->Has_constant_subscript()) {
02226 if (!gannot->Bottom(common_idx)) {
02227 gannot->Set_Bottom(common_idx);
02228 }
02229 return;
02230 }
02231 size = TY_size(TY_AR_etype(ST_type(st)));
02232 offset = ST_ofst(st) + stid->Get_array_subscript() * size;
02233 }
02234 else {
02235 size = TY_size(ST_type(st));
02236 offset = ST_ofst(st);
02237 }
02238
02239 SUMMARY_VALUE* value = 0;
02240 INT32 value_index = stid->Get_value_index();
02241 if (value_index != -1) {
02242 value = IPA_get_value_array(node) + value_index;
02243
02244 if (!value->Is_int_const() && !value->Is_const_st()) {
02245 SUMMARY_VALUE tmp_value;
02246 tmp_value.Init();
02247 Evaluate_value(*value, tmp_value);
02248 if (tmp_value.Is_int_const() || tmp_value.Is_const_st()) {
02249
02250 value = CXX_NEW(SUMMARY_VALUE(), Malloc_Mem_Pool);
02251 *value = tmp_value;
02252 }
02253 else {
02254 value = 0;
02255 }
02256 }
02257 }
02258
02259 BOOL overwrite_if_found = always_executed;
02260 BOOL add_if_not_found = always_executed;
02261 gannot->Union (common_idx,
02262 GLOBAL_VALUE(offset, size, value),
02263 overwrite_if_found,
02264 add_if_not_found);
02265
02266
02267
02268 }
02269 }
02270
02271
02272
02273
02274 static BOOL
02275 Propagate_vals_in_unstructured_cflow (IPA_NODE* node, GLOBAL_ANNOT* gannot)
02276
02277 {
02278 if (Get_Trace(TP_IPA, IPA_TRACE_COMMON_CONST)) {
02279 for (INT i = 0; i < indent; ++i) putc(' ', TFile);
02280 fprintf(TFile, "Propagate_vals_in_unstructured_cflow\n");
02281 }
02282 indent += 2;
02283
02284 BOOL change = FALSE;
02285
02286 SUMMARY_PROCEDURE* proc = node->Summary_Proc();
02287 INT num_calls = proc->Get_callsite_count();
02288 SUMMARY_CALLSITE* callsite = &ipa_callsite[proc->Get_callsite_index()];
02289
02290 for (INT i = 0; i < num_calls; ++i, ++callsite) {
02291 if (!callsite->Is_intrinsic()) {
02292 IPA_NODE* callee = Get_callee(callsite, -1, FALSE);
02293 if (callee) {
02294 change |= callee->Global_Annot()->Union(gannot);
02295 }
02296 }
02297 }
02298
02299 indent -= 2;
02300 return change;
02301 }
02302
02303
02304
02305
02306 static void
02307 Update_annot_with_callee_mod (IPA_NODE* callee, GLOBAL_ANNOT* gannot)
02308 {
02309 IPAA_NODE_INFO* modref_info = callee->Mod_Ref_Info();
02310 for (UINT32 i = 0; i < GLOBAL_ANNOT::Size; ++i) {
02311 const char* is_mod = "is NOT";
02312 ST_IDX common_st = GLOBAL_ANNOT::Common_ST[i];
02313 if (modref_info->Is_def_elmt(ST_IDX_index(common_st))) {
02314 gannot->Set_Bottom(i);
02315 is_mod = "IS";
02316 }
02317 if (Get_Trace(TP_IPA, IPA_TRACE_COMMON_CONST)) {
02318 for (INT i = 0; i < indent; ++i) putc(' ', TFile);
02319 fprintf(TFile, "%-10s %s modified\n", ST_name(common_st), is_mod);
02320 }
02321 }
02322 }
02323
02324
02325
02326
02327 static void
02328 Update_annot_with_all_callee_mods (IPA_NODE* node, GLOBAL_ANNOT* gannot)
02329 {
02330 if (Get_Trace(TP_IPA, IPA_TRACE_COMMON_CONST)) {
02331 for (INT i = 0; i < indent; ++i) putc(' ', TFile);
02332 fprintf(TFile, "Update_annot_with_all_callee_mods\n");
02333 }
02334 indent += 2;
02335
02336 SUMMARY_PROCEDURE* proc = node->Summary_Proc();
02337 INT num_calls = proc->Get_callsite_count();
02338 SUMMARY_CALLSITE* callsite = &ipa_callsite[proc->Get_callsite_index()];
02339
02340 for (INT i = 0; i < num_calls; ++i, ++callsite) {
02341 if (!callsite->Is_intrinsic()) {
02342 IPA_NODE* callee = Get_callee(callsite, -1, FALSE);
02343 if (callee && !callee->Is_Externally_Callable()) {
02344 Update_annot_with_callee_mod(callee, gannot);
02345 }
02346 else {
02347
02348 gannot->Set_Bottom();
02349 }
02350 }
02351 }
02352
02353 indent -= 2;
02354 }
02355
02356
02357
02358
02359 static void
02360 Collect_stids_in_unstructured_cflow (IPA_NODE* node,
02361 GLOBAL_ANNOT* gannot)
02362 {
02363 if (Get_Trace(TP_IPA, IPA_TRACE_COMMON_CONST)) {
02364 for (INT i = 0; i < indent; ++i) putc(' ', TFile);
02365 fprintf(TFile, "Propagate_global_unstructured\n");
02366 }
02367 indent += 2;
02368
02369 SUMMARY_PROCEDURE* proc = node->Summary_Proc();
02370 INT cd_count = proc->Get_ctrl_dep_count();
02371 INT cd_index = proc->Get_ctrl_dep_index();
02372
02373 for (INT i = 0; i < cd_count; ++i) {
02374
02375 SUMMARY_CONTROL_DEPENDENCE* cd = &ipa_ctrl_dep[cd_index+i];
02376 INT num_stmt_counts = (cd->Is_if_stmt()) ? 2 : 1;
02377
02378 for (INT j = 0; j < num_stmt_counts; ++j) {
02379
02380 INT stmt_count, stmt_index;
02381 if (cd->Is_if_stmt() && j == 1) {
02382 stmt_count = cd->Get_false_count();
02383 stmt_index = cd->Get_false_stmt_index();
02384 }
02385 else {
02386 stmt_count = cd->Get_true_count();
02387 stmt_index = cd->Get_true_stmt_index();
02388 }
02389
02390 for (INT k = 0; k < stmt_count; ++k) {
02391 SUMMARY_STMT* cur_stmt = &ipa_stmt[stmt_index+k];
02392 if (cur_stmt->Is_stid()) {
02393 const SUMMARY_STID* stid = &ipa_stid[cur_stmt->Get_stid_index()];
02394 Process_stid(node,
02395 stid,
02396 cd->Is_entry() && stid->Is_always_executed(),
02397 gannot);
02398 }
02399 }
02400 }
02401 }
02402
02403 indent -= 2;
02404 }
02405
02406
02407
02408
02409
02410 static BOOL
02411 Process_global_call (SUMMARY_CALLSITE* callsite, GLOBAL_ANNOT* gannot)
02412 {
02413 BOOL change = FALSE;
02414 IPA_NODE* callee = Get_callee(callsite, -1, FALSE);
02415
02416 if (callee && !callee->Is_Externally_Callable()) {
02417
02418 if (Get_Trace(TP_IPA, IPA_TRACE_COMMON_CONST)) {
02419 for (INT i = 0; i < indent; ++i) putc(' ', TFile);
02420 fprintf(TFile, "Process_global_call to %s\n", callee->Name());
02421 }
02422 indent += 2;
02423
02424 if (callsite->Get_loopnest() > 0) {
02425 Update_annot_with_callee_mod(callee, gannot);
02426 change |= callee->Global_Annot()->Union(gannot);
02427 }
02428 else {
02429 change |= callee->Global_Annot()->Union(gannot);
02430 Update_annot_with_callee_mod(callee, gannot);
02431 }
02432
02433 indent -= 2;
02434 }
02435 else {
02436
02437 gannot->Set_Bottom();
02438 }
02439
02440 return change;
02441 }
02442
02443
02444
02445
02446 static BOOL
02447 Propagate_global_vals (IPA_NODE* node,
02448 SUMMARY_CONTROL_DEPENDENCE* cd,
02449 GLOBAL_ANNOT* gannot)
02450 {
02451 if (Get_Trace(TP_IPA, IPA_TRACE_COMMON_CONST)) {
02452 for (INT i = 0; i < indent; ++i) putc(' ', TFile);
02453 fprintf(TFile, "Propagate_global_vals\n");
02454 }
02455 indent += 2;
02456
02457 BOOL change = FALSE;
02458
02459 INT num_cd_counts = (cd->Is_if_stmt()) ? 2 : 1;
02460
02461 for (INT i = 0; i < num_cd_counts; ++i) {
02462
02463 INT stmt_count, stmt_index;
02464
02465 if (cd->Is_if_stmt() && i == 1) {
02466 stmt_count = cd->Get_false_count();
02467 stmt_index = cd->Get_false_stmt_index();
02468 }
02469 else {
02470 stmt_count = cd->Get_true_count();
02471 stmt_index = cd->Get_true_stmt_index();
02472 }
02473
02474 for (INT j = 0; j < stmt_count; ++j) {
02475
02476 const SUMMARY_STMT& cur_stmt = ipa_stmt[j+stmt_index];
02477
02478 if (cur_stmt.Is_stid()) {
02479 Process_stid(node,
02480 &ipa_stid[cur_stmt.Get_stid_index()],
02481 cd->Is_entry(),
02482 gannot);
02483 }
02484 else if (cur_stmt.Is_call()) {
02485 change |=
02486 Process_global_call(&ipa_callsite[cur_stmt.Get_call_index()],
02487 gannot);
02488 }
02489 else if (cur_stmt.Is_cond()) {
02490 change |=
02491 Propagate_global_vals(node,
02492 &ipa_ctrl_dep[cur_stmt.Get_cond_index()],
02493 gannot);
02494 }
02495 }
02496 }
02497 indent -= 2;
02498
02499 return change;
02500 }
02501
02502
02503
02504
02505
02506 static void
02507 Compute_disconnected_graph (SUMMARY_CONTROL_DEPENDENCE* cd,
02508 INT* total_cd_count)
02509 {
02510 INT num_cd_counts = (cd->Is_if_stmt()) ? 2 : 1;
02511
02512 for (INT i = 0; i < num_cd_counts; ++i) {
02513
02514 INT stmt_count, stmt_index;
02515
02516 if (cd->Is_if_stmt() && i == 1) {
02517 stmt_count = cd->Get_false_count();
02518 stmt_index = cd->Get_false_stmt_index();
02519 }
02520 else {
02521 stmt_count = cd->Get_true_count();
02522 stmt_index = cd->Get_true_stmt_index();
02523 }
02524
02525 for (INT j = 0; j < stmt_count; ++j) {
02526 SUMMARY_STMT* cur_stmt = &ipa_stmt[j+stmt_index];
02527 if (cur_stmt->Is_cond()) {
02528 ++(*total_cd_count);
02529 Compute_disconnected_graph(&ipa_ctrl_dep[cur_stmt->Get_cond_index()],
02530 total_cd_count);
02531 }
02532 }
02533 }
02534 }
02535
02536
02537
02538
02539
02540
02541
02542
02543
02544
02545
02546
02547
02548
02549
02550
02551
02552
02553
02554
02555
02556
02557
02558
02559
02560
02561 extern BOOL
02562 Intra_PU_Global_Cprop (IPA_NODE* node)
02563 {
02564 MEM_POOL_Push(&local_cprop_pool);
02565
02566 if (Get_Trace(TP_IPA, IPA_TRACE_COMMON_CONST)) {
02567 fprintf(TFile, "\nIntra_PU_global_cprop in %s\n", node->Name());
02568 }
02569 indent += 2;
02570
02571 BOOL change = FALSE;
02572
02573 #ifdef KEY // bug 2175
02574 if (IPA_Enable_DFE && PU_is_dead(node, &change))
02575 #else
02576 if (PU_is_dead(node, &change))
02577 #endif
02578 {
02579 return change;
02580 }
02581
02582
02583 Set_summary_info (node);
02584
02585
02586 Current_caller = node;
02587 callsite_map = 0;
02588
02589 SUMMARY_PROCEDURE* proc = node->Summary_Proc();
02590 INT num_cds = proc->Get_ctrl_dep_count();
02591 if (num_cds) {
02592
02593 SUMMARY_CONTROL_DEPENDENCE* cd = &ipa_ctrl_dep[proc->Get_ctrl_dep_index()];
02594 INT total_cd_count = 1;
02595
02596 if (!proc->Has_unstructured_cflow()) {
02597 Compute_disconnected_graph(cd, &total_cd_count);
02598 if (total_cd_count != num_cds) {
02599 proc->Set_has_unstructured_cflow();
02600 }
02601 }
02602
02603
02604 GLOBAL_ANNOT gannot (node->Global_Annot(), &local_cprop_pool);
02605
02606 if (!proc->Has_unstructured_cflow()) {
02607 change |= Propagate_global_vals(node, cd, &gannot);
02608 }
02609 else {
02610 Collect_stids_in_unstructured_cflow(node, &gannot);
02611 Update_annot_with_all_callee_mods(node, &gannot);
02612 change |= Propagate_vals_in_unstructured_cflow(node, &gannot);
02613 }
02614 }
02615
02616 MEM_POOL_Pop(&local_cprop_pool);
02617 indent -= 2;
02618
02619 return change;
02620 }
02621
02622
02623
02624
02625
02626
02627 extern void
02628 Map_Global_Constants (IPA_NODE *n)
02629 {
02630 GLOBAL_ANNOT* gannot = n->Global_Annot();
02631 for (UINT32 i = 0; i < GLOBAL_ANNOT::Size; ++i) {
02632 if (!gannot->Top(i) && !gannot->Bottom(i)) {
02633 const GLOBAL_DYN_ARRAY& gvals = gannot->Global_Value_Array(i);
02634 for (UINT32 j = 0; j < gvals.Elements(); ++j) {
02635 if (gvals[j].Value()) {
02636 n->Set_Propagated_Const();
02637 return;
02638 }
02639 }
02640 }
02641 }
02642 }