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
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086 #define __STDC_LIMIT_MACROS
00087 #include <stdint.h>
00088 #include <set>
00089 #include <math.h>
00090
00091 #ifdef USE_PCH
00092 #include "opt_pch.h"
00093 #endif // USE_PCH
00094 #pragma hdrstop
00095
00096 #include "opt_points_to.h"
00097 #include "opt_base.h"
00098 #include "opt_config.h"
00099 #include "opt_sym.h"
00100 #include "opt_alias_class.h"
00101 #include "opt_alias_mgr.h"
00102 #include "wintrinsic.h"
00103
00104 extern "C" {
00105 #include "bitset.h"
00106 }
00107 #ifdef KEY
00108 extern BOOL ST_Has_Dope_Vector(ST *st);
00109 #endif
00110
00111 IDTYPE ALIAS_CLASS_REP::_last_id_used;
00112 BOOL ALIAS_CLASS_REP::_structure_not_frozen;
00113
00114
00115 #if Is_True_On
00116 static const int num_acr_table_entries = 100;
00117 ALIAS_CLASS_REP *acr_table[num_acr_table_entries];
00118
00119 static const int num_acm_table_entries = 100;
00120 ALIAS_CLASS_MEMBER *acm_table[num_acm_table_entries];
00121 static int next_acm_idx = 0;
00122
00123
00124 void print_table(void)
00125 {
00126 UINT i;
00127 INT acr_size = Min(ALIAS_CLASS_REP::_last_id_used + 1,
00128 num_acr_table_entries);
00129 for (i = 0; i < acr_size; ++i) {
00130 if (acr_table[i] != NULL) {
00131 fprintf(TFile, "acr_table[%2u]: ", i);
00132 acr_table[i]->Print(TFile);
00133 }
00134 }
00135 INT acm_size = Min(next_acm_idx, num_acm_table_entries);
00136 for (i = 0; i < acm_size; ++i) {
00137 fprintf(TFile, "acm_table[%2u]: ", i);
00138 if (acm_table[i] == acm_table[i]->Alias_class()->Representative()) {
00139 fprintf(TFile, "self");
00140 }
00141 else {
00142 acm_table[i]->Print(TFile);
00143 }
00144 fprintf(TFile, " in ");
00145 if (acm_table[i]->Alias_class() == NULL) {
00146 fprintf(TFile, "no class\n");
00147 }
00148 else {
00149 acm_table[i]->Alias_class()->Print(TFile);
00150 }
00151 }
00152 }
00153 #endif
00154
00155
00156 class BASE_ID_MAP_ENTRY {
00157 private:
00158 const ST *_st;
00159 ALIAS_CLASS_REP _base_lda_class;
00160 public:
00161 #if Is_True_On
00162 BASE_ID_MAP_ENTRY(void)
00163 {
00164 if (_base_lda_class.Id() < num_acr_table_entries) {
00165 acr_table[_base_lda_class.Id()] = &_base_lda_class;
00166 }
00167 }
00168 #endif
00169
00170 void Set_st(const ST *st) { _st = st; }
00171 const ST *St(void) const { return _st; }
00172 ALIAS_CLASS_REP &Lda_class(void) { return _base_lda_class; }
00173 };
00174
00175
00176 ALIAS_CLASSIFICATION::ALIAS_CLASSIFICATION(OPT_STAB *opt_stab,
00177 AC_DESTINATION destination,
00178 MEM_POOL *pool) :
00179 _opt_stab(opt_stab), _destination(destination), _pool(pool),
00180 _pending_list_home(pool), _base_id_map(pool),
00181 _collapsed_nested_references(FALSE),
00182 _preg_num_base_id_map(128, (IDTYPE) 0, pool, FALSE),
00183 _st_idx_to_base_id_map(256, (IDTYPE) 0, pool, FALSE),
00184 _ac_id_to_acr_map(256, NULL, pool, FALSE),
00185 _altered_non_points_to_parms(pool), _alloca_memory_members(pool),
00186 _memops_classified(FALSE), _mem_pool_valid(TRUE)
00187 {
00188 OPT_POOL_Push(_pool, MEM_DUMP_FLAG+20);
00189 _tracing = Get_Trace(TP_GLOBOPT, ALIAS_DUMP_FLAG);
00190 ALIAS_CLASS_REP::_last_id_used = PESSIMISTIC_AC_ID;
00191 ALIAS_CLASS_REP::_structure_not_frozen = TRUE;
00192
00193
00194 _member_of_global_class = New_alias_class_member();
00195 ALIAS_CLASS_REP *dummy_acr = New_alias_class(_member_of_global_class);
00196 dummy_acr->Set_class_pointed_to(Global_class());
00197
00198
00199 ALIAS_CLASS_MEMBER *dummy_acm = New_alias_class_member();
00200 _const_addr_class = New_alias_class(dummy_acm);
00201 _const_addr_class->Set_class_pointed_to(Global_class());
00202
00203
00204 _base_id_map.Initidx(0);
00205 }
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226 ALIAS_CLASS_REP *
00227 ALIAS_CLASSIFICATION::New_alias_class(ALIAS_CLASS_MEMBER *const acm)
00228 {
00229 ALIAS_CLASS_REP *retval = CXX_NEW(ALIAS_CLASS_REP, Pool());
00230 #if Is_True_On
00231 if (retval->Id() < num_acr_table_entries) {
00232 acr_table[retval->Id()] = retval;
00233 }
00234 #endif
00235 acm->Put_in_set(retval);
00236 if (Tracing() && WOPT_Enable_Verbose) {
00237 fprintf(TFile, "Creating ");
00238 retval->Print(TFile, Global_class());
00239 }
00240 return retval;
00241 }
00242
00243
00244
00245 ALIAS_CLASS_MEMBER *
00246 ALIAS_CLASSIFICATION::New_alias_class_member(void)
00247 {
00248 ALIAS_CLASS_MEMBER *acm = CXX_NEW(ALIAS_CLASS_MEMBER, Pool());
00249 #if Is_True_On
00250 if (next_acm_idx < num_acm_table_entries) {
00251 acm_table[next_acm_idx++] = acm;
00252 }
00253 #endif
00254
00255 return acm;
00256 }
00257
00258
00259 ALIAS_CLASS_MEMBER *
00260 ALIAS_CLASSIFICATION::New_alias_class_member(const IDTYPE base_id)
00261 {
00262 ALIAS_CLASS_MEMBER *acm = CXX_NEW(ALIAS_CLASS_MEMBER(base_id), Pool());
00263
00264 #if Is_True_On
00265 if (next_acm_idx < num_acm_table_entries) {
00266 acm_table[next_acm_idx++] = acm;
00267 }
00268 #endif
00269
00270 return acm;
00271 }
00272
00273
00274 ALIAS_CLASS_MEMBER *
00275 ALIAS_CLASSIFICATION::New_alias_class_member(WN *wn)
00276 {
00277 ALIAS_CLASS_MEMBER *acm = CXX_NEW(ALIAS_CLASS_MEMBER(wn), Pool());
00278
00279 #if Is_True_On
00280 if (next_acm_idx < num_acm_table_entries) {
00281 acm_table[next_acm_idx++] = acm;
00282 }
00283 #endif
00284
00285 return acm;
00286 }
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299 inline ST *
00300 ALIAS_CLASSIFICATION::ST_of_wn(const WN *const wn) const
00301 {
00302 return (_destination == AC_DESTINATION_OPT_STAB ?
00303 Opt_stab()->St(WN_aux(wn)) :
00304 WN_st(wn));
00305 }
00306
00307
00308 inline BOOL
00309 ALIAS_CLASSIFICATION::Is_LDA_of_variable(const WN *const wn) const
00310 {
00311 ST *st = ST_of_wn(wn);
00312
00313 Is_True(ST_class(st) != CLASS_PREG, ("Is_LDA_of_variable: CLASS_PREG"));
00314
00315 return (ST_class(st) == CLASS_UNK ||
00316 ST_class(st) == CLASS_VAR ||
00317
00318 ST_class(st) == CLASS_CONST ||
00319 ST_class(st) == CLASS_BLOCK);
00320 }
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369 IDTYPE
00370 ALIAS_CLASSIFICATION::New_base_id(const ST *st, TY_IDX ty)
00371 {
00372 BOOL weird_class = FALSE;
00373 IDTYPE id = _base_id_map.Newidx();
00374
00375 if (Tracing()) {
00376 fprintf(TFile, "Allocating base ID %u\n", id);
00377 }
00378
00379
00380
00381
00382
00383
00384 if (ST_sclass(st) != SCLASS_REG) {
00385 ST_IDX st_idx = ST_st_idx(st);
00386 _st_idx_to_base_id_map.Insert(st_idx, id);
00387 }
00388
00389
00390
00391
00392
00393
00394
00395
00396 _base_id_map[id] = CXX_NEW(BASE_ID_MAP_ENTRY, Pool());
00397 New_alias_class_member()->Put_in_set(&(_base_id_map[id]->Lda_class()));
00398 _base_id_map[id]->Lda_class().Representative()->Set_lda_kind();
00399 _base_id_map[id]->Set_st(st);
00400
00401 if (Tracing()) {
00402 fprintf(TFile, "Base ID %3u is ", id);
00403 }
00404
00405 ST_SCLASS storage_class = ST_sclass(st);
00406
00407
00408
00409 if ((storage_class == SCLASS_AUTO &&
00410 ST_IDX_level(ST_st_idx(st)) == CURRENT_SYMTAB) ||
00411 storage_class == SCLASS_FORMAL ||
00412 storage_class == SCLASS_FORMAL_REF ||
00413 storage_class == SCLASS_REG) {
00414
00415 ALIAS_CLASS_MEMBER *ldid_item = New_alias_class_member(id);
00416 ALIAS_CLASS_REP *ldid_class = New_alias_class(ldid_item);
00417 _base_id_map[id]->Lda_class().Set_class_pointed_to(ldid_class);
00418
00419
00420
00421 if (storage_class == SCLASS_FORMAL ||
00422 storage_class == SCLASS_FORMAL_REF) {
00423 BOOL cannot_be_pointer = FALSE;
00424
00425 if ((ST_class(st) == CLASS_VAR) ||
00426 (ST_class(st) == CLASS_CONST) ||
00427 (ST_class(st) == CLASS_NAME)) {
00428 TY_IDX st_ty = ST_type(st);
00429
00430 while (TY_kind(st_ty) == KIND_ARRAY) {
00431 st_ty = TY_etype(st_ty);
00432 }
00433
00434 UINT64 lang = PU_src_lang(Get_Current_PU());
00435
00436
00437
00438
00439 cannot_be_pointer = (WOPT_Enable_Alias_Class_Fortran_Rule &&
00440 (lang == PU_F77_LANG ||
00441 lang == PU_F90_LANG) &&
00442 (TY_kind(st_ty) == KIND_SCALAR));
00443
00444
00445
00446 if (cannot_be_pointer) {
00447 while (TY_kind(ty) == KIND_ARRAY) {
00448 ty = TY_etype(ty);
00449 }
00450 Is_True(ty == (TY_IDX) 0 ||
00451 TY_kind(ty) == KIND_SCALAR,
00452 ("Non-pointer ST type, but possibly pointer WN type"));
00453 }
00454 }
00455
00456 if (cannot_be_pointer) {
00457 if (Tracing()) {
00458 fprintf(TFile, "nonptr: ");
00459 }
00460 }
00461 else {
00462 if (Tracing()) {
00463 fprintf(TFile, " parm: ");
00464 }
00465 _base_id_map[id]->Lda_class().Class_pointed_to()->
00466 Set_class_pointed_to(Global_class());
00467 }
00468 }
00469 else {
00470 if (Tracing()) {
00471 fprintf(TFile, " local: ");
00472 }
00473 }
00474 }
00475
00476 else if (storage_class == SCLASS_PSTATIC ||
00477
00478
00479
00480
00481
00482 storage_class == SCLASS_FSTATIC ||
00483 storage_class == SCLASS_COMMON ||
00484 storage_class == SCLASS_UGLOBAL ||
00485 storage_class == SCLASS_DGLOBAL ||
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497 storage_class == SCLASS_AUTO ||
00498
00499
00500
00501
00502
00503 storage_class == SCLASS_UNKNOWN ||
00504 (storage_class == SCLASS_EXTERN &&
00505 ST_class(st) != CLASS_FUNC)) {
00506
00507
00508
00509 if (Tracing()) {
00510 fprintf(TFile, "global: ");
00511 }
00512 _base_id_map[id]->Lda_class().Set_class_pointed_to(Global_class());
00513 }
00514 else {
00515
00516
00517 Is_True(_base_id_map[id]->Lda_class().Class_pointed_to() == NULL,
00518 ("ALIAS_CLASSIFICATION::New_base_id: non-variable LDA must "
00519 "not point"));
00520 if (Tracing()) {
00521 fprintf(TFile, " other: ");
00522 weird_class = TRUE;
00523 }
00524 }
00525 if (Tracing()) {
00526 Print_ST(TFile, st, WOPT_Enable_Verbose || weird_class);
00527 }
00528 return id;
00529 }
00530
00531
00532 IDTYPE
00533 ALIAS_CLASSIFICATION::ST_base_id(ST *st, const TY_IDX ty)
00534 {
00535 IDTYPE base_id = _st_idx_to_base_id_map.Lookup(ST_st_idx(st));
00536 if (base_id == (IDTYPE) 0) {
00537 base_id = New_base_id(st, ty);
00538 }
00539 return base_id;
00540 }
00541
00542
00543 IDTYPE
00544 ALIAS_CLASSIFICATION::Base_id( ST *const base_st,
00545 const INT64 base_ofst,
00546 const TY_IDX ty)
00547 {
00548
00549
00550
00551
00552 if (ST_sclass(base_st) == SCLASS_REG) {
00553
00554 IDTYPE base_id = Preg_num_base_id_map().Lookup(base_ofst);
00555 if (base_id == (IDTYPE) 0) {
00556 base_id = New_base_id(base_st, ty);
00557 if (Tracing()) {
00558 fprintf(TFile, "base_ofst is %lld\n", base_ofst);
00559 }
00560 Preg_num_base_id_map().Insert(base_ofst, base_id);
00561 }
00562 return base_id;
00563 }
00564 else {
00565 return ST_base_id(base_st, ty);
00566 }
00567 }
00568
00569
00570 IDTYPE
00571 ALIAS_CLASSIFICATION::Base_id(const AUX_ID aux_id, const TY_IDX ty)
00572 {
00573 ST *base_st = Opt_stab()->Base(aux_id);
00574 INT64 base_ofst = Opt_stab()->Base_ofst(aux_id);
00575
00576 return Base_id(base_st, base_ofst, ty);
00577 }
00578
00579
00580 void
00581 ALIAS_CLASSIFICATION::Find_declared_base_and_offset(ST_IDX st_idx,
00582 ST_IDX &declared_base_idx,
00583 INT64 &declared_offset)
00584 {
00585 ST *st = &St_Table[st_idx];
00586 ST_IDX base_st_idx = ST_base_idx(st);
00587 ST *base_st;
00588
00589
00590 declared_base_idx = st_idx;
00591
00592 while (st_idx != base_st_idx &&
00593 (base_st = &St_Table[base_st_idx], TRUE) &&
00594 (ST_class(base_st) != CLASS_BLOCK ||
00595 !STB_compiler_layout(base_st))) {
00596 declared_offset += ST_ofst(st);
00597 declared_base_idx = ST_base_idx(st);
00598 st = base_st;
00599 st_idx = base_st_idx;
00600 }
00601 }
00602
00603
00604 IDTYPE
00605 ALIAS_CLASSIFICATION::WN_base_id(const WN *wn)
00606 {
00607 TY_IDX ty;
00608 if (WN_operator(wn) == OPR_LDA ||
00609 WN_operator(wn) == OPR_LDMA) {
00610 if (TY_kind(WN_ty(wn)) == KIND_POINTER) {
00611 ty = TY_pointed(WN_ty(wn));
00612 }
00613 else {
00614
00615
00616
00617
00618 ty = (TY_IDX) 0;
00619 }
00620 }
00621 else {
00622 ty = WN_ty(wn);
00623 }
00624 if (_destination == AC_DESTINATION_OPT_STAB) {
00625 return Base_id(WN_aux(wn), ty);
00626 }
00627 else {
00628 Is_True(_destination == AC_DESTINATION_ALIAS_MANAGER,
00629 ("ALIAS_CLASSIFICATION: Someone added a new "
00630 "destination"));
00631 ST_IDX base_st_idx;
00632 INT64 base_offset = WN_offset(wn);
00633 Find_declared_base_and_offset(WN_st_idx(wn), base_st_idx,
00634 base_offset);
00635 return Base_id(&St_Table[base_st_idx], base_offset, ty);
00636 }
00637 }
00638
00639
00640 ALIAS_CLASS_REP *
00641 ALIAS_CLASSIFICATION::Class_of_base_id_LDA(const IDTYPE base_id) const
00642 {
00643 return &_base_id_map[base_id]->Lda_class();
00644 }
00645
00646
00647 ALIAS_CLASS_REP *
00648 ALIAS_CLASSIFICATION::Class_of_base_id_LDID(const IDTYPE base_id) const
00649 {
00650 return Class_of_base_id_LDA(base_id)->Class_pointed_to();
00651 }
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681 void
00682 ALIAS_CLASS_REP::Add_pending(ALIAS_CLASS_REP *item,
00683 ALIAS_CLASSIFICATION &ac)
00684 {
00685 Is_True(item != NULL && item->Representative() != NULL,
00686 ("ALIAS_CLASSIFICATION: Cannot add <NULL> to pending list"));
00687 _pending = ac.Alloc_pending(item->Representative(), _pending);
00688 }
00689
00690
00691 void
00692 ALIAS_CLASS_REP::Process_pending(ALIAS_CLASSIFICATION &ac)
00693 {
00694
00695
00696 Is_True(Is_pointer_class(),
00697 ("ACR::Process_pending: Must be pointer class"));
00698
00699 #if 0
00700 fprintf(TFile, "Process pending for ");
00701 Print(TFile);
00702 #endif
00703
00704 while (_pending != NULL) {
00705 ALIAS_CLASS_REP *item = _pending->Node()->Alias_class();
00706 _pending = ac.Release_pending(_pending);
00707 Join_object_class(*item, ac);
00708 }
00709 }
00710
00711 #ifdef KEY
00712 BOOL
00713 ALIAS_CLASS_REP::Pending_rep_match(ALIAS_CLASS_REP *rep)
00714 {
00715 PENDING_LIST lst = _pending;
00716 while (lst != NULL) {
00717 ALIAS_CLASS_REP *item = lst->Node()->Alias_class();
00718 if (item == rep)
00719 return TRUE;
00720 lst = lst->Next();
00721 }
00722 return FALSE;
00723 }
00724 #endif
00725 void
00726 ALIAS_CLASS_REP::Merge_pending(ALIAS_CLASS_REP &that)
00727 {
00728
00729 _pending = _pending->Merge(that.Pending());
00730 }
00731
00732
00733 void
00734 ALIAS_CLASS_REP::Join_object_class(ALIAS_CLASS_REP &that,
00735 ALIAS_CLASSIFICATION &ac)
00736 {
00737 ALIAS_CLASS_REP *cpt = Class_pointed_to();
00738 ALIAS_CLASS_REP *that_cpt = that.Class_pointed_to();
00739
00740 if (cpt == NULL && that_cpt == NULL) {
00741
00742 Merge_pending(that);
00743 }
00744 else if (cpt == NULL) {
00745 Set_class_pointed_to(that_cpt);
00746 Process_pending(ac);
00747 }
00748 else if (that_cpt == NULL) {
00749 that.Set_class_pointed_to(cpt);
00750 that.Process_pending(ac);
00751 }
00752 else {
00753 Is_True(!cpt->Representative()->Is_LDA_kind(),
00754 ("ALIAS_CLASSIFICATION: Cannot join LDA class"));
00755 cpt->Union(*that_cpt);
00756 }
00757
00758 if (cpt != NULL && that_cpt != NULL && cpt != that_cpt) {
00759 cpt->Join_object_class(*that_cpt, ac);
00760 Is_True(cpt->Class_pointed_to() == that_cpt->Class_pointed_to(),
00761 ("ACR::Join: Inconsistent join"));
00762 }
00763 }
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773 void
00774 ALIAS_CLASS_REP::Print(FILE *fp, ALIAS_CLASS_REP *global_class) const
00775 {
00776 fprintf(fp, "class %u ", Id());
00777 FmtAssert(Id() != 0 || global_class == NULL || global_class == this,
00778 ("Class of ID 1 must be global"));
00779 if (global_class != NULL &&
00780 global_class == this) {
00781 fprintf(fp, "(global)");
00782 }
00783 else {
00784 if (_representative->Null_parent()) {
00785 fprintf(fp, "represented by ");
00786 if (Representative() == NULL) {
00787 fprintf(fp, "<null> ");
00788 }
00789 else {
00790 Representative()->Print(fp);
00791 }
00792 }
00793 else {
00794 fprintf(fp, "[stale] ");
00795 }
00796 }
00797 fprintf(fp, " -->");
00798 if (Is_pointer_class()) {
00799 fprintf(fp, " class %u ", Class_pointed_to()->Id());
00800 if (global_class != NULL &&
00801 Class_pointed_to() == global_class) {
00802 fprintf(fp, "(global)");
00803 }
00804 else {
00805 fprintf(fp, "(containing ");
00806 _member_of_class_pointed_to->Print(fp);
00807 fprintf(fp, ")");
00808 }
00809 }
00810 else {
00811 fprintf(fp, " <NULL>");
00812 }
00813 fprintf(fp, "\n");
00814 }
00815
00816
00817 void
00818 ALIAS_CLASS_MEMBER::Print(FILE *fp) const
00819 {
00820 if (_kind == ACM_BASE) {
00821 fprintf(fp, "base ID %u", Base_id());
00822 }
00823 else if (_kind == ACM_WN) {
00824 fprintf(fp, "wn ");
00825 fdump_wn_no_st(fp, Wn());
00826 }
00827 else if (_kind == ACM_LDA) {
00828 fprintf(fp, "LDA");
00829 }
00830 else {
00831 fprintf(fp, "unknown <0x%p>", this);
00832 }
00833 }
00834
00835
00836
00837
00838
00839 void
00840 ALIAS_CLASSIFICATION::Merge_conditional(AC_PTR_OBJ_PAIR lhs,
00841 AC_PTR_OBJ_PAIR rhs)
00842 {
00843 if (Tracing()) {
00844 fprintf(TFile, "Conditional merge of ");
00845 if (lhs.Obj_class() == NULL) {
00846 fprintf(TFile, "<NULL> ");
00847 }
00848 else {
00849 lhs.Obj_class()->Print(TFile);
00850 }
00851 fprintf(TFile, "with ");
00852 if (rhs.Obj_class() == NULL) {
00853 fprintf(TFile, "<NULL>\n");
00854 }
00855 else {
00856 rhs.Obj_class()->Print(TFile);
00857 }
00858 }
00859
00860
00861 if (rhs.Obj_class() != NULL) {
00862 lhs.Ref_class()->Join_object_class(*rhs.Ref_class(), *this);
00863 }
00864 else {
00865 FmtAssert(lhs.Ref_class() != NULL,
00866 ("AC::Merge_conditional: Cannot merge deref(LDA) class"));
00867
00868
00869
00870 if (rhs.Ref_class() != NULL) {
00871 rhs.Ref_class()->Add_pending(lhs.Ref_class(), *this);
00872 }
00873 }
00874 }
00875
00876
00877 static BOOL
00878 Is_fortran_reference_parm(WN *expr)
00879 {
00880 if (WN_operator(expr) != OPR_PARM) {
00881 return FALSE;
00882 }
00883 return WN_Parm_By_Reference(expr);
00884 }
00885
00886
00887
00888
00889
00890
00891 static BOOL
00892 Opcode_cannot_be_pointer_value(const OPERATOR opr,
00893 const OPCODE opc)
00894 {
00895 switch (opr) {
00896 case OPR_LAND:
00897 case OPR_LIOR:
00898 case OPR_CAND:
00899 case OPR_CIOR:
00900 case OPR_LT:
00901 case OPR_GT:
00902 case OPR_LE:
00903 case OPR_GE:
00904 case OPR_EQ:
00905 case OPR_NE:
00906 return TRUE;
00907 case OPR_MPY:
00908 case OPR_DIV:
00909 case OPR_MOD:
00910 case OPR_ADD:
00911 case OPR_SUB:
00912 case OPR_NEG:
00913 return MTYPE_is_float(OPCODE_rtype(opc));
00914 default:
00915 return FALSE;
00916 }
00917 }
00918
00919
00920
00921
00922
00923
00924
00925
00926 AC_PTR_OBJ_PAIR
00927 ALIAS_CLASSIFICATION::Classify_deref_of_expr(WN *const expr,
00928 BOOL expr_must_point)
00929 {
00930 OPCODE opc = WN_opcode(expr);
00931 OPERATOR opr = OPCODE_operator(opc);
00932
00933 if (WOPT_Enable_Verbose && Tracing()) {
00934 fprintf(TFile, "cdoe: analyzing ");
00935 Dump_wn(TFile, expr);
00936 }
00937 if (OPCODE_is_leaf(opc)) {
00938 if ((_destination == AC_DESTINATION_OPT_STAB) &&
00939 OPERATOR_has_aux(opr)) {
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952 std::set<AUX_ID> processed_ids;
00953
00954 AUX_ID lhs_aux_id = WN_aux(expr);
00955 ST *lhs_st = Opt_stab()->Aux_stab_entry(lhs_aux_id)->St();
00956 while (lhs_st != NULL && ST_is_initialized(lhs_st)) {
00957 INITV_IDX initv;
00958 if ((initv = ST_has_initv(lhs_st)) &&
00959 INITV_kind(Initv_Table[initv]) == INITVKIND_SYMOFF) {
00960 ST *rhs_st = &St_Table[INITV_st(Initv_Table[initv])];
00961 AUX_ID rhs_aux_id =
00962 Opt_stab()->Find_sym_with_st_and_ofst(rhs_st,
00963 INITV_ofst(Initv_Table[initv]));
00964 if (Tracing()) {
00965 fprintf(TFile, "ALIAS_CLASSIFICATION: process initialization lhs=%d rhs=%d\n",
00966 lhs_aux_id, rhs_aux_id);
00967 }
00968
00969 if (processed_ids.find(lhs_aux_id) == processed_ids.end())
00970 processed_ids.insert(lhs_aux_id);
00971
00972
00973
00974
00975
00976
00977
00978 if (rhs_aux_id != 0) {
00979 IDTYPE lhs_base_id = Base_id(lhs_aux_id, WN_ty(expr));
00980 ALIAS_CLASS_REP *lhs_acr = Class_of_base_id_LDID(lhs_base_id);
00981 AC_PTR_OBJ_PAIR lhs_class(lhs_acr, lhs_acr->Class_pointed_to());
00982
00983 IDTYPE rhs_base_id =
00984 Base_id(rhs_aux_id,
00985 Opt_stab()->Aux_stab_entry(rhs_aux_id)->Ty());
00986 ALIAS_CLASS_REP *rhs_lda_acr = Class_of_base_id_LDA(rhs_base_id);
00987 AC_PTR_OBJ_PAIR rhs_class(rhs_lda_acr,
00988 rhs_lda_acr->Class_pointed_to());
00989 Merge_conditional(lhs_class, rhs_class);
00990
00991
00992 if (processed_ids.find(rhs_aux_id) != processed_ids.end())
00993 lhs_st = NULL;
00994 else {
00995
00996 lhs_aux_id = rhs_aux_id;
00997 lhs_st = Opt_stab()->Aux_stab_entry(lhs_aux_id)->St();
00998 #if Is_True_On
00999
01000
01001 INT64 dummy_offset;
01002 ST_IDX lhs_base_idx;
01003 Find_declared_base_and_offset(ST_st_idx(lhs_st),
01004 lhs_base_idx,
01005 dummy_offset);
01006 ST_IDX rhs_base_idx;
01007 Find_declared_base_and_offset(ST_st_idx(rhs_st),
01008 rhs_base_idx,
01009 dummy_offset);
01010 FmtAssert(lhs_base_idx == rhs_base_idx,
01011 ("ALIAS_CLASSIFICATION: Inconsistent bases for "
01012 "initializer ST's"));
01013 #endif
01014 }
01015 } else {
01016 lhs_st = NULL;
01017 }
01018 } else {
01019 lhs_st = NULL;
01020 }
01021 }
01022 }
01023 switch (opr) {
01024 case OPR_LDA:
01025 case OPR_LDMA:
01026 {
01027 ALIAS_CLASS_REP *lda_class = Class_of_base_id_LDA(WN_base_id(expr));
01028 ALIAS_CLASS_REP *ldid_class = Class_of_base_id_LDID(WN_base_id(expr));
01029 if (expr_must_point &&
01030 (ldid_class == NULL)) {
01031
01032
01033
01034 if (WOPT_Enable_Verbose && Tracing()) {
01035 fprintf(TFile, " --- Expression is indirect load of code\n");
01036 }
01037 lda_class->Set_class_pointed_to(New_alias_class(New_alias_class_member()));
01038 ldid_class = lda_class->Class_pointed_to();
01039 }
01040 return AC_PTR_OBJ_PAIR(lda_class, ldid_class);
01041 }
01042 case OPR_INTCONST:
01043
01044
01045
01046
01047 if (expr_must_point) {
01048
01049
01050 return AC_PTR_OBJ_PAIR(Const_addr_class(), Global_class());
01051 }
01052 return AC_PTR_OBJ_PAIR(NULL, NULL);
01053 case OPR_LDID:
01054 case OPR_LDBITS:
01055 {
01056 ALIAS_CLASS_REP *ref = Class_of_base_id_LDID(WN_base_id(expr));
01057 if (ref == NULL) {
01058
01059
01060
01061 if (WOPT_Enable_Verbose && Tracing()) {
01062 fprintf(TFile, " --- Expression is direct load of code\n");
01063 }
01064 Class_of_base_id_LDA(WN_base_id(expr))->
01065 Set_class_pointed_to(New_alias_class(New_alias_class_member()));
01066 ref = Class_of_base_id_LDID(WN_base_id(expr));
01067 Is_True(ref != NULL,
01068 ("ALIAS_CLASSIFICATION: Unable to make function pointer "
01069 "point to data"));
01070 }
01071 if (expr_must_point && !ref->Is_pointer_class()) {
01072 ALIAS_CLASS_MEMBER *obj_dummy = New_alias_class_member();
01073 ref->Set_class_pointed_to(New_alias_class(obj_dummy));
01074 #ifdef KEY
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087 #endif
01088 ref->Process_pending(*this);
01089 }
01090 if (WOPT_Enable_Verbose && Tracing()) {
01091 fprintf(TFile, " --- After analyzing expression ");
01092 Dump_wn(TFile, expr);
01093 fprintf(TFile, " ref is ");
01094 ref->Print(TFile, Global_class());
01095 Print(TFile);
01096 #if Is_True_On
01097 print_table();
01098 #endif
01099 }
01100 return AC_PTR_OBJ_PAIR(ref, ref->Class_pointed_to());
01101 }
01102 default:
01103
01104
01105 FmtAssert(!expr_must_point,
01106 ("ALIAS_CLASSIFICATION::Classify_deref_of_expr: "
01107 "non-pointer expression must point"));
01108 return AC_PTR_OBJ_PAIR(NULL, NULL);
01109 }
01110 }
01111
01112
01113
01114
01115 else if (OPCODE_is_load(opc) ||
01116 #if defined (TARG_SL)
01117 (opr == OPR_PARM && WN_Parm_Dereference(expr)) ||
01118 #endif
01119 Is_fortran_reference_parm(expr)) {
01120 FmtAssert(OPERATOR_is_scalar_iload (opr) ||
01121 opr == OPR_MLOAD ||
01122 opr == OPR_ILOADX ||
01123 opr == OPR_PARM,
01124 ("ALIAS_CLASSIFICATION: Indirect load: unexpected opcode"));
01125
01126
01127
01128 AC_PTR_OBJ_PAIR t = Classify_deref_of_expr(WN_kid0(expr), TRUE);
01129
01130 ALIAS_CLASS_MEMBER *wn_member = New_alias_class_member(expr);
01131 if (!t.Ref_class()->Is_pointer_class()) {
01132 if (Tracing() && WOPT_Enable_Verbose) {
01133 fprintf(TFile, "Ref class is not pointer. Ref is ");
01134 t.Ref_class()->Print(TFile, Global_class());
01135 }
01136
01137
01138
01139
01140
01141
01142
01143
01144
01145
01146
01147 ALIAS_CLASS_REP *wn_class = New_alias_class(wn_member);
01148
01149 t.Ref_class()->Set_class_pointed_to(wn_class);
01150 t.Ref_class()->Process_pending(*this);
01151 t.Set_ref_class(t.Ref_class()->Representative()->Alias_class());
01152 t.Set_obj_class(t.Ref_class()->Class_pointed_to());
01153 }
01154 else {
01155 wn_member->Put_in_set(t.Obj_class());
01156 }
01157
01158 WN_MAP_Set(Indir_classification_map(), expr,
01159 (void *) t.Obj_class()->Representative());
01160
01161 if (expr_must_point && !t.Obj_class()->Is_pointer_class()) {
01162 t.Obj_class()->Set_class_pointed_to(New_alias_class(New_alias_class_member()));
01163 t.Obj_class()->Process_pending(*this);
01164 t.Set_ref_class(t.Ref_class()->Representative()->Alias_class());
01165 t.Set_obj_class(t.Ref_class()->Class_pointed_to());
01166 }
01167 if (WOPT_Enable_Verbose && Tracing()) {
01168 fprintf(TFile, " --- After analyzing expression ");
01169 Dump_wn(TFile, expr);
01170 fprintf(TFile, " t.Obj_class() is ");
01171 t.Obj_class()->Print(TFile, Global_class());
01172 fprintf(TFile, " t.Ref_class() is ");
01173 t.Ref_class()->Print(TFile, Global_class());
01174 Print(TFile);
01175 #if Is_True_On
01176 print_table();
01177 #endif
01178 }
01179 if (opr == OPR_PARM) {
01180 return t;
01181 }
01182 else {
01183 return AC_PTR_OBJ_PAIR(t.Obj_class(),
01184 t.Obj_class()->Class_pointed_to());
01185 }
01186 }
01187 else if (opr == OPR_ARRAY) {
01188 for (INT i = 1; i < WN_kid_count(expr); i++) {
01189 (void) Classify_deref_of_expr(WN_kid(expr, i), FALSE);
01190 }
01191 if (WOPT_Enable_Verbose && Tracing()) {
01192 fprintf(TFile, " --- After analyzing expression ");
01193 Dump_wn(TFile, expr);
01194 Print(TFile);
01195 }
01196 return Classify_deref_of_expr(WN_kid0(expr), expr_must_point);
01197 }
01198 else if (opr == OPR_ALLOCA) {
01199 for (INT i = 0; i < WN_kid_count(expr); i++) {
01200 (void) Classify_deref_of_expr(WN_kid(expr, i), FALSE);
01201 }
01202 if (WOPT_Enable_Verbose && Tracing()) {
01203 fprintf(TFile, " --- After analyzing ALLOCA kids ");
01204 Dump_wn(TFile, expr);
01205 Print(TFile);
01206 }
01207 ALIAS_CLASS_MEMBER *alloca_mem_acm = New_alias_class_member();
01208 ALIAS_CLASS_REP *alloca_mem_acr = New_alias_class(alloca_mem_acm);
01209 ALIAS_CLASS_MEMBER *return_acm = New_alias_class_member(expr);
01210 ALIAS_CLASS_REP *return_acr = New_alias_class(return_acm);
01211 return_acr->Set_class_pointed_to(alloca_mem_acr);
01212 _alloca_memory_members.push_front(alloca_mem_acm);
01213 return AC_PTR_OBJ_PAIR(return_acr, alloca_mem_acr);
01214 }
01215 else {
01216
01217
01218
01219
01220
01221
01222
01223 ALIAS_CLASS_MEMBER *t_member = New_alias_class_member(expr);
01224 (void) New_alias_class(t_member);
01225
01226 BOOL expr_maybe_point = Expr_may_contain_pointer (expr);
01227 for (INT i = 0; i < WN_kid_count(expr); i++) {
01228
01229
01230 AC_PTR_OBJ_PAIR u = Classify_deref_of_expr(WN_kid(expr, i),
01231 FALSE);
01232
01233 if (expr_maybe_point &&
01234 Expr_may_contain_pointer (WN_kid(expr, i))) {
01235 AC_PTR_OBJ_PAIR t(t_member->Alias_class(),
01236 t_member->Alias_class()->Class_pointed_to());
01237 Merge_conditional(t, u);
01238 }
01239 }
01240 AC_PTR_OBJ_PAIR t(t_member->Alias_class(),
01241 t_member->Alias_class()->Class_pointed_to());
01242
01243 if (expr_must_point && t.Obj_class() == NULL) {
01244 ALIAS_CLASS_MEMBER *dummy_acm = New_alias_class_member();
01245 ALIAS_CLASS_REP *obj_acr = New_alias_class(dummy_acm);
01246 t.Set_obj_class(obj_acr);
01247 t.Ref_class()->Set_class_pointed_to(obj_acr);
01248 #ifdef KEY
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259 #endif
01260 t.Ref_class()->Process_pending(*this);
01261 }
01262 if (WOPT_Enable_Verbose && Tracing()) {
01263 fprintf(TFile, " --- After analyzing expression ");
01264 Dump_wn(TFile, expr);
01265 Print(TFile);
01266 }
01267 if (Opcode_cannot_be_pointer_value(opr, opc)) {
01268
01269
01270
01271 FmtAssert(!expr_must_point,
01272 ("ALIAS_CLASSIFICATION::Classify_deref_of_expr: "
01273 "non-pointer expression must point"));
01274 return AC_PTR_OBJ_PAIR(NULL, NULL);
01275 }
01276 else {
01277 return t;
01278 }
01279 }
01280 }
01281
01282
01283 AC_PTR_OBJ_PAIR
01284 ALIAS_CLASSIFICATION::Classify_lhs_of_store(WN *const stmt)
01285 {
01286 AC_PTR_OBJ_PAIR lhs_class;
01287 OPERATOR opr = WN_operator(stmt);
01288
01289 if (OPERATOR_is_scalar_store (opr)) {
01290
01291 lhs_class.Set_ref_class(Class_of_base_id_LDID(WN_base_id(stmt)));
01292 lhs_class.Set_obj_class(lhs_class.Ref_class()->Class_pointed_to());
01293 }
01294 else if (OPERATOR_is_scalar_istore (opr) || opr == OPR_MSTORE) {
01295 AC_PTR_OBJ_PAIR lhs_ptr_class =
01296 Classify_deref_of_expr(WN_kid1(stmt), TRUE);
01297 lhs_class.Set_ref_class(lhs_ptr_class.Obj_class());
01298 lhs_class.Set_obj_class(lhs_ptr_class.Obj_class()->Class_pointed_to());
01299 if (Tracing()) {
01300 fprintf(TFile, "Setting ISTORE Indir map to 0x%p\n",
01301 lhs_class.Ref_class());
01302 }
01303 WN_MAP_Set(Indir_classification_map(), stmt,
01304 lhs_class.Ref_class()->Representative());
01305 }
01306 else {
01307 FmtAssert(FALSE, ("AC::Classify_lhs_of_store: Other stores "
01308 "not handled"));
01309 }
01310 return lhs_class;
01311 }
01312
01313
01314
01315
01316 BOOL
01317 ALIAS_CLASSIFICATION::Expr_may_contain_pointer (WN* const expr) {
01318
01319 if (!WOPT_Enable_Aggressive_Alias_Classification || !Alias_Pointer_Types) {
01320 return TRUE;
01321 }
01322
01323 TYPE_ID res = WN_rtype (expr);
01324 if (MTYPE_byte_size (res) == 0) {
01325
01326
01327
01328
01329
01330
01331 return TRUE;
01332 }
01333
01334 if (MTYPE_byte_size (res) < Pointer_Size ||
01335 (MTYPE_is_void (res) || MTYPE_is_float (res) ||
01336 MTYPE_is_complex (res) || MTYPE_is_vector (res) ||
01337 MTYPE_is_boolean (res))) {
01338 return FALSE;
01339 }
01340
01341 switch (WN_operator (expr)) {
01342 case OPR_MPY:
01343 return FALSE;
01344
01345 case OPR_LDBITS:
01346 case OPR_ILDBITS:
01347 return WN_bit_size (expr) < Pointer_Size * 8;
01348
01349 case OPR_LDID:
01350 {
01351 ST* sym = ST_of_wn (expr);
01352 return ST_class(sym) != CLASS_PREG &&
01353 TY_kind(WN_object_ty (expr)) == KIND_POINTER ||
01354 WN_object_size (expr) >= Pointer_Size;
01355 }
01356 case OPR_ILOAD:
01357 return TY_kind(WN_object_ty (expr)) == KIND_POINTER ||
01358 WN_object_size (expr) >= Pointer_Size;
01359
01360 case OPR_NEG: case OPR_ABS:
01361 return Expr_may_contain_pointer (WN_kid0(expr));
01362
01363 case OPR_RND:
01364 case OPR_TRUNC:
01365 case OPR_CEIL:
01366 case OPR_FLOOR:
01367 case OPR_BNOT:
01368 case OPR_LNOT:
01369 return FALSE;
01370 }
01371
01372 return TRUE;
01373 }
01374
01375 BOOL
01376 ALIAS_CLASSIFICATION::Assignment_may_xfer_pointer (WN* const stmt) {
01377
01378 if (!WOPT_Enable_Aggressive_Alias_Classification || !Alias_Pointer_Types) {
01379 return TRUE;
01380 }
01381
01382 if (!Expr_may_contain_pointer (WN_kid0(stmt))) {
01383 return FALSE;
01384 }
01385
01386 TY_IDX obj_ty = WN_object_ty (stmt);
01387 switch (TY_kind(obj_ty)) {
01388 case KIND_SCALAR:
01389 return WN_object_size(stmt) >= Pointer_Size;
01390
01391 case KIND_STRUCT:
01392
01393
01394 case KIND_POINTER:
01395 return TRUE;
01396
01397 case KIND_ARRAY:
01398 return TRUE;
01399
01400 case KIND_VOID:
01401 return WN_object_size (stmt) && (WN_object_size (stmt) >= Pointer_Size);
01402
01403 default:
01404 Is_True (FALSE, ("Unexected results returned from WN_object_ty ()"));
01405 }
01406
01407 return TRUE;
01408 }
01409
01410 WN *
01411 ALIAS_CLASSIFICATION::Handle_assignment(WN *const stmt)
01412 {
01413 AC_PTR_OBJ_PAIR lhs_class = Classify_lhs_of_store(stmt);
01414
01415 WN *rhs = WN_kid0(stmt);
01416
01417 ALIAS_CLASS_MEMBER *lhs_ref_member =
01418 lhs_class.Ref_class()->Representative();
01419
01420
01421
01422
01423
01424 TY_IDX rhs_obj_ty = WN_object_ty (rhs);
01425 AC_PTR_OBJ_PAIR rhs_class = Classify_deref_of_expr(rhs,
01426 #if defined(TARG_SL)
01427
01428 TY_kind(WN_object_ty(stmt))==KIND_POINTER ||
01429 #endif
01430 TY_kind(rhs_obj_ty) == KIND_POINTER);
01431
01432 lhs_class.
01433 Set_ref_class(lhs_ref_member->Alias_class());
01434 lhs_class.
01435 Set_obj_class(lhs_ref_member->Alias_class()->Class_pointed_to());
01436
01437 Is_True(lhs_class.Ref_class()->Class_pointed_to() ==
01438 lhs_class.Obj_class(),
01439 ("ALIAS_CLASSIFICATION::Handle_assignment: "
01440 "RHS classification changed LHS points-to relation"));
01441
01442 if (WN_operator(stmt) == OPR_MSTORE) {
01443 (void) Classify_deref_of_expr(WN_kid2(stmt), FALSE);
01444 }
01445
01446 if (rhs_class.Ref_class() != NULL &&
01447 Assignment_may_xfer_pointer (stmt)) {
01448
01449 Merge_conditional(lhs_class, rhs_class);
01450 }
01451 else {
01452
01453 }
01454
01455 if (WOPT_Enable_Verbose && Tracing()) {
01456 fprintf(TFile, " after handling assignment:\n");
01457 #if Is_True_On
01458 print_table();
01459 #endif
01460 if (OPERATOR_is_scalar_istore (WN_operator(stmt)) ||
01461 WN_operator(stmt) == OPR_MSTORE) {
01462 fprintf(TFile, " (M/I)STORE placed in ");
01463 ((ALIAS_CLASS_MEMBER *) WN_MAP_Get(Indir_classification_map(),
01464 stmt))->Alias_class()->
01465 Print(TFile, Global_class());
01466 }
01467 else if (OPERATOR_is_scalar_store (WN_operator(stmt))) {
01468 fprintf(TFile, " %s placed in ", WN_operator(stmt) == OPR_STID ?
01469 "STID" : "STBITS");
01470 Class_of_base_id_LDID(WN_base_id(stmt))->Print(TFile, Global_class());
01471 }
01472 Print(TFile);
01473 }
01474
01475 return WN_next(stmt);
01476 }
01477
01478
01479
01480
01481
01482 BOOL
01483 ALIAS_CLASSIFICATION::Stmt_stores_return_value(const WN *const stmt)
01484 {
01485 WN *rhs = WN_kid0(stmt);
01486
01487 return (OPCODE_is_store(WN_opcode(stmt)) &&
01488 (WN_operator(rhs) == OPR_LDID) &&
01489 (ST_sclass(ST_of_wn(rhs)) == SCLASS_REG) &&
01490 Preg_Is_Dedicated(WN_offset(rhs)));
01491 }
01492
01493
01494 BOOL
01495 ALIAS_CLASSIFICATION::Uses_no_return_value(const WN *const stmt)
01496 {
01497 return TRUE;
01498 }
01499
01500
01501 BOOL
01502 ALIAS_CLASSIFICATION::Callee_changes_no_points_to(const WN *const call_wn,
01503 const WN *const parm_wn)
01504 {
01505 #if defined(TARG_SL)
01506 if(WN_operator(call_wn) == OPR_INTRINSIC_CALL) {
01507 if(INTRN_has_no_side_effects(WN_intrinsic(call_wn)))
01508 return TRUE;
01509 }
01510 #endif
01511 if (WN_Call_Never_Return(call_wn)) {
01512 return TRUE;
01513 }
01514 else if (WN_Call_Does_Mem_Free(call_wn)) {
01515 return TRUE;
01516 }
01517 #if 1
01518 else if ((WN_operator(call_wn) == OPR_CALL) &&
01519 (strcmp("free", ST_name(WN_st(call_wn))) == 0)) {
01520 return TRUE;
01521 }
01522 #endif
01523 else if (Callee_returns_new_memory(call_wn)) {
01524 return TRUE;
01525 }
01526 else if (WOPT_Enable_Alias_Class_Fortran_Rule &&
01527 WN_Call_Fortran_Pointer_Rule(call_wn)) {
01528 const TY_IDX ty = WN_ty(parm_wn);
01529 if ((TY_kind(ty) == KIND_POINTER) &&
01530 (TY_kind(TY_pointed(ty)) != KIND_POINTER) &&
01531 !TY_is_f90_pointer(ty)) {
01532 const WN *const parm_kid = WN_kid0(parm_wn);
01533 if ((WN_operator(parm_kid) == OPR_LDA) ||
01534 (WN_operator(parm_kid) == OPR_LDMA)) {
01535 const ST *const st = ST_of_wn(parm_kid);
01536 if (!ST_is_f90_target(st)) {
01537 return TRUE;
01538 }
01539 }
01540 else {
01541 return TRUE;
01542 }
01543 }
01544 }
01545 return FALSE;
01546 }
01547
01548
01549 BOOL
01550 ALIAS_CLASSIFICATION::WN_is_alloca_intrinsic(const WN *const call_wn)
01551 {
01552 if ((WN_operator(call_wn) == OPR_INTRINSIC_CALL) &&
01553 ((WN_intrinsic(call_wn) == INTRN_U4I4ALLOCA) ||
01554 (WN_intrinsic(call_wn) == INTRN_U8I8ALLOCA) ||
01555 (WN_intrinsic(call_wn) == INTRN_F90_STACKTEMPALLOC))) {
01556 return TRUE;
01557 }
01558 else {
01559 #ifdef KEY
01560 return Callee_returns_new_memory(call_wn);
01561 #else
01562 return FALSE;
01563 #endif
01564 }
01565 }
01566
01567
01568 BOOL
01569 ALIAS_CLASSIFICATION::Callee_returns_new_memory(const WN *const call_wn)
01570 {
01571 #ifndef KEY
01572 return WN_Call_Does_Mem_Alloc(call_wn);
01573 #else
01574 if (WN_Call_Does_Mem_Alloc(call_wn))
01575 return TRUE;
01576 if (WN_operator(call_wn) == OPR_CALL) {
01577 const ST *const st = WN_st(call_wn);
01578
01579
01580
01581 if ((strcmp("malloc", ST_name(st)) == 0) ||
01582 (strcmp("alloca", ST_name(st)) == 0) ||
01583 (strcmp("calloc", ST_name(st)) == 0) ||
01584 (strcmp("_F90_ALLOCATE", ST_name(st)) == 0) ||
01585 WOPT_Enable_Disambiguate_Heap_Obj && PU_has_attr_malloc (Pu_Table[ST_pu(st)])) {
01586 return TRUE;
01587 }
01588 }
01589 else if (WN_operator(call_wn) == OPR_INTRINSIC_CALL) {
01590 if ((WN_intrinsic(call_wn) == INTRN_U4I4ALLOCA) ||
01591 (WN_intrinsic(call_wn) == INTRN_U8I8ALLOCA) ||
01592 (WN_intrinsic(call_wn) == INTRN_U4I4MALLOC) ||
01593 (WN_intrinsic(call_wn) == INTRN_U8I8MALLOC)) {
01594 return TRUE;
01595 }
01596 }
01597 return FALSE;
01598 #endif
01599 }
01600
01601
01602 BOOL
01603 ALIAS_CLASSIFICATION::May_icall_nested_PU(const WN *const call_wn,
01604 ST * *callee_st)
01605 {
01606 if (PU_uplevel(Get_Current_PU())) {
01607
01608
01609
01610
01611
01612 *callee_st = NULL;
01613 return TRUE;
01614 }
01615 else {
01616 return FALSE;
01617 }
01618 }
01619
01620
01621 struct MERGE_NEST_REF_CLASSES {
01622 ALIAS_CLASSIFICATION *_ac;
01623 AC_PTR_OBJ_PAIR _globals;
01624
01625 MERGE_NEST_REF_CLASSES(ALIAS_CLASSIFICATION *ac,
01626 AC_PTR_OBJ_PAIR globals) :
01627 _ac(ac), _globals(globals)
01628 { }
01629
01630 void operator() (UINT32, const ST *st) const {
01631 IDTYPE base_id;
01632 if (ST_sym_class(st) == CLASS_VAR && ST_has_nested_ref(st)) {
01633 base_id = _ac->Base_id(ST_base(st), ST_ofst(st), (TY_IDX) 0);
01634
01635 AC_PTR_OBJ_PAIR
01636 nested_ref_var_class(_ac->Class_of_base_id_LDA(base_id),
01637 _ac->Class_of_base_id_LDID(base_id));
01638 _ac->Merge_conditional(_globals, nested_ref_var_class);
01639 }
01640 }
01641 };
01642
01643
01644 void
01645 ALIAS_CLASSIFICATION::Handle_call_of_nested_PU(ST *const callee_st)
01646 {
01647 if (Tracing()) {
01648 fprintf(TFile, "Handling nested call of %s", callee_st ? "" : "(NULL)");
01649 if (callee_st) Print_ST(TFile, callee_st, FALSE);
01650 fflush(TFile);
01651 }
01652
01653 WN *pragma_list = (callee_st != NULL ?
01654 Get_MP_accessed_id_list(callee_st) :
01655 NULL);
01656
01657 if (pragma_list != NULL && WOPT_Enable_MP_varref) {
01658
01659
01660
01661
01662
01663
01664
01665
01666
01667
01668
01669
01670 for (WN *wn_read = WN_first(pragma_list);
01671 wn_read != NULL;
01672 wn_read = WN_next(wn_read)) {
01673 ST *read_st = WN_st(wn_read);
01674 if (read_st != NULL &&
01675 (WN_pragma_arg2(wn_read) & ACCESSED_LOAD)) {
01676 if (Tracing()) {
01677 fprintf(TFile, "Read (%s%s) by nested callee : ",
01678 (WN_pragma_arg2(wn_read) & ACCESSED_LOAD ? "d" : ""),
01679 (WN_pragma_arg2(wn_read) & ACCESSED_ILOAD ? "i" : ""));
01680 Print_ST(TFile, read_st, FALSE);
01681 fflush(TFile);
01682 }
01683
01684 ST *read_base_st;
01685 INT64 read_base_ofst;
01686 Expand_ST_into_base_and_ofst(read_st, (INT64) 0,
01687 &read_base_st, &read_base_ofst);
01688
01689 IDTYPE read_base_id = Base_id(read_base_st, read_base_ofst,
01690 (TY_IDX) 0);
01691
01692 ALIAS_CLASS_MEMBER *read_member =
01693 Class_of_base_id_LDID(read_base_id)->Representative();
01694
01695 for (WN *wn_written = WN_first(pragma_list);
01696 wn_written != NULL;
01697 wn_written = WN_next(wn_written)) {
01698 Is_True(WN_pragma(wn_written) == WN_PRAGMA_ACCESSED_ID,
01699 ("ALIAS_CLASSIFICATION::Handle_call_of_nested_PU: "
01700 "pragma must be WN_PRAGMA_ACCESSED_ID."));
01701 ST *written_st = WN_st(wn_written);
01702 if (written_st != NULL &&
01703 (WN_pragma_arg2(wn_written) &
01704 (ACCESSED_STORE | ACCESSED_ISTORE))) {
01705 if (Tracing()) {
01706 fprintf(TFile, "Written (%s%s) by nested callee : ",
01707 (WN_pragma_arg2(wn_written) & ACCESSED_STORE ?
01708 "d" : ""),
01709 (WN_pragma_arg2(wn_written) & ACCESSED_ISTORE ?
01710 "i" : ""));
01711 Print_ST(TFile, written_st, FALSE);
01712 fflush(TFile);
01713 }
01714
01715 ST *written_base_st;
01716 INT64 written_base_ofst;
01717 Expand_ST_into_base_and_ofst(written_st, (INT64) 0,
01718 &written_base_st,
01719 &written_base_ofst);
01720 IDTYPE written_base_id = Base_id(written_base_st,
01721 written_base_ofst,
01722 (TY_IDX) 0);
01723
01724 if ((WN_pragma_arg2(wn_written) & ACCESSED_STORE) &&
01725 (WN_pragma_arg2(wn_read) & ACCESSED_LOAD) &&
01726 read_base_id != written_base_id) {
01727
01728 ALIAS_CLASS_REP *read_rep = read_member->Alias_class();
01729
01730 AC_PTR_OBJ_PAIR read_class(read_rep,
01731 read_rep->Class_pointed_to());
01732
01733 ALIAS_CLASS_REP *written_rep =
01734 Class_of_base_id_LDID(written_base_id);
01735
01736 AC_PTR_OBJ_PAIR written_class(written_rep,
01737 written_rep->Class_pointed_to());
01738
01739
01740
01741 Merge_conditional(written_class, read_class);
01742 }
01743 if ((WN_pragma_arg2(wn_written) & ACCESSED_STORE) &&
01744 (WN_pragma_arg2(wn_read) & ACCESSED_ILOAD)) {
01745
01746
01747 ALIAS_CLASS_REP *read_rep = read_member->Alias_class();
01748 if (!read_rep->Is_pointer_class()) {
01749
01750
01751 read_rep->Set_class_pointed_to(New_alias_class(New_alias_class_member()));
01752 read_rep->Process_pending(*this);
01753 }
01754 read_rep = read_rep->Class_pointed_to();
01755
01756 AC_PTR_OBJ_PAIR read_class(read_rep,
01757 read_rep->Class_pointed_to());
01758
01759 ALIAS_CLASS_REP *written_rep =
01760 Class_of_base_id_LDID(written_base_id);
01761
01762 AC_PTR_OBJ_PAIR written_class(written_rep,
01763 written_rep->Class_pointed_to());
01764
01765
01766
01767 Merge_conditional(written_class, read_class);
01768 }
01769 if ((WN_pragma_arg2(wn_written) & ACCESSED_ISTORE) &&
01770 (WN_pragma_arg2(wn_read) & ACCESSED_LOAD)) {
01771
01772
01773 ALIAS_CLASS_REP *read_rep = read_member->Alias_class();
01774
01775 ALIAS_CLASS_REP *written_rep =
01776 Class_of_base_id_LDID(written_base_id);
01777
01778 if (!written_rep->Is_pointer_class()) {
01779
01780
01781 written_rep->Set_class_pointed_to(New_alias_class(New_alias_class_member()));
01782 written_rep->Process_pending(*this);
01783 }
01784 written_rep = written_rep->Class_pointed_to();
01785
01786 AC_PTR_OBJ_PAIR read_class(read_rep,
01787 read_rep->Class_pointed_to());
01788 AC_PTR_OBJ_PAIR written_class(written_rep,
01789 written_rep->Class_pointed_to());
01790
01791
01792
01793 Merge_conditional(written_class, read_class);
01794 }
01795 if ((WN_pragma_arg2(wn_written) & ACCESSED_ISTORE) &&
01796 (WN_pragma_arg2(wn_read) & ACCESSED_ILOAD) &&
01797 read_base_id != written_base_id) {
01798
01799
01800 ALIAS_CLASS_REP *read_rep = read_member->Alias_class();
01801 if (!read_rep->Is_pointer_class()) {
01802
01803
01804 read_rep->Set_class_pointed_to(New_alias_class(New_alias_class_member()));
01805 read_rep->Process_pending(*this);
01806 }
01807 read_rep = read_rep->Class_pointed_to();
01808
01809 AC_PTR_OBJ_PAIR read_class(read_rep,
01810 read_rep->Class_pointed_to());
01811
01812 ALIAS_CLASS_REP *written_rep =
01813 Class_of_base_id_LDID(written_base_id);
01814
01815 if (!written_rep->Is_pointer_class()) {
01816
01817
01818 written_rep->Set_class_pointed_to(New_alias_class(New_alias_class_member()));
01819 written_rep->Process_pending(*this);
01820 }
01821 written_rep = written_rep->Class_pointed_to();
01822
01823 AC_PTR_OBJ_PAIR written_class(written_rep,
01824 written_rep->Class_pointed_to());
01825
01826
01827
01828 Merge_conditional(written_class, read_class);
01829 }
01830 }
01831 }
01832 }
01833 }
01834 }
01835 else {
01836
01837
01838
01839
01840
01841 if (!Collapsed_nested_references()) {
01842 AC_PTR_OBJ_PAIR globals(Global_class(), Global_class());
01843
01844 ST *st;
01845
01846 For_all(*Scope_tab[CURRENT_SYMTAB].st_tab,
01847 MERGE_NEST_REF_CLASSES(this, globals));
01848
01849 Set_collapsed_nested_references();
01850 }
01851 }
01852 }
01853
01854
01855
01856
01857
01858
01859
01860
01861
01862 WN *
01863 ALIAS_CLASSIFICATION::Handle_call(WN *call_wn)
01864 {
01865 OPCODE opc = WN_opcode(call_wn);
01866 OPERATOR opr = OPCODE_operator(opc);
01867
01868 Is_True(opr == OPR_CALL ||
01869 opr == OPR_ICALL ||
01870 opr == OPR_INTRINSIC_CALL,
01871 ("AC::Handle_call: Can handle only calls"));
01872
01873 if (opr == OPR_CALL) {
01874 ST *callee_st = WN_st(call_wn);
01875 if (PU_is_nested_func(Pu_Table[ST_pu(*callee_st)])) {
01876
01877 Handle_call_of_nested_PU(callee_st);
01878 }
01879 }
01880
01881
01882
01883
01884
01885 UINT n_parms;
01886
01887 if (opr == OPR_ICALL) {
01888 n_parms = WN_kid_count(call_wn) - 1;
01889 (void) Classify_deref_of_expr(WN_kid(call_wn,
01890 WN_kid_count(call_wn) - 1),
01891 FALSE);
01892
01893
01894 ST *callee_st;
01895 if (May_icall_nested_PU(call_wn, &callee_st)) {
01896 Handle_call_of_nested_PU(callee_st);
01897 }
01898 }
01899 else {
01900 n_parms = WN_kid_count(call_wn);
01901 }
01902
01903 WN *parm_wn;
01904
01905 #if defined(TARG_SL)
01906 if (WN_operator(call_wn)==OPR_INTRINSIC_CALL &&
01907 INTRN_copy_addr(WN_intrinsic(call_wn))) {
01908
01909
01910 if (WN_kid_count(call_wn)>1)
01911 DevWarn("Handle_call: intrinsic_call which copy addr has more than 1 parms");
01912 WN *rhs = WN_kid0(WN_kid0(call_wn));
01913 TY_IDX rhs_obj_ty = WN_object_ty (rhs);
01914 AC_PTR_OBJ_PAIR rhs_class = Classify_deref_of_expr(rhs,
01915 TRUE);
01916
01917
01918 WN* stmt = WN_next(call_wn);
01919 if (stmt != NULL && Stmt_stores_return_value(stmt)) {
01920 AC_PTR_OBJ_PAIR lhs_class = Classify_lhs_of_store(stmt);
01921
01922 ALIAS_CLASS_MEMBER *lhs_ref_member =
01923 lhs_class.Ref_class()->Representative();
01924
01925
01926
01927
01928
01929
01930 lhs_class.Set_ref_class(lhs_ref_member->Alias_class());
01931 lhs_class.Set_obj_class(lhs_ref_member->Alias_class()->Class_pointed_to());
01932
01933 Is_True(lhs_class.Ref_class()->Class_pointed_to() ==
01934 lhs_class.Obj_class(),
01935 ("ALIAS_CLASSIFICATION::Handle_call:"
01936 "dealing with intrinsic_copy_addr, RHS classification changed LHS points-to relation"));
01937
01938 if (rhs_class.Ref_class() != NULL &&
01939 Assignment_may_xfer_pointer (stmt)) {
01940
01941 Merge_conditional(lhs_class, rhs_class);
01942 }
01943
01944 stmt = WN_next(stmt);
01945 FmtAssert(!(stmt != NULL && Stmt_stores_return_value(stmt)),
01946 ("Handle_call: multiple stmt store return value after call"));
01947 }
01948
01949
01950 if (WOPT_Enable_Verbose && Tracing()) {
01951 fprintf(TFile, " after handling call:\n");
01952 Print(TFile);
01953 }
01954 return stmt;
01955 }
01956 #endif
01957
01958 for (UINT i = 0; i < n_parms; ++i) {
01959 parm_wn = WN_kid(call_wn, i);
01960 Is_True(WN_operator(parm_wn) == OPR_PARM,
01961 ("AC::Handle_call: Can't handle non-PARM parameter"));
01962 WN *actual = WN_kid0(parm_wn);
01963 if ((WN_operator(actual) == OPR_LDA) ||
01964 (WN_operator(actual) == OPR_LDMA)) {
01965 ST *lda_st = ST_of_wn(actual);
01966 if (ST_class(lda_st) == CLASS_FUNC &&
01967 PU_is_nested_func(Pu_Table[ST_pu(lda_st)])) {
01968
01969
01970 Handle_call_of_nested_PU(lda_st);
01971 }
01972 }
01973 AC_PTR_OBJ_PAIR rhs_class = Classify_deref_of_expr(parm_wn,
01974 TY_kind (WN_ty(parm_wn)) == KIND_POINTER);
01975
01976
01977
01978
01979
01980
01981
01982
01983
01984
01985
01986
01987
01988
01989
01990
01991
01992
01993
01994
01995
01996
01997 if (!Callee_changes_no_points_to(call_wn, parm_wn)) {
01998 AC_PTR_OBJ_PAIR lhs_class(Global_class(), Global_class());
01999 Merge_conditional(lhs_class, rhs_class);
02000 }
02001 else if (rhs_class.Ref_class() != NULL) {
02002
02003
02004
02005 Add_to_altered_non_points_to_parms(rhs_class.Ref_class());
02006 }
02007 }
02008
02009 WN *stmt;
02010
02011 stmt = WN_next(call_wn);
02012 while (stmt != NULL && Stmt_stores_return_value(stmt)) {
02013 if (Tracing()) {
02014 fprintf(TFile, "Store of return value:\n");
02015 Dump_wn_tree(TFile, stmt);
02016 }
02017 AC_PTR_OBJ_PAIR lhs_class = Classify_lhs_of_store(stmt);
02018 if (!Callee_returns_new_memory(call_wn)) {
02019
02020
02021
02022
02023 Merge_conditional(lhs_class,
02024 AC_PTR_OBJ_PAIR(Global_class(),
02025 Global_class()));
02026 }
02027 else {
02028
02029
02030
02031
02032 if (!lhs_class.Ref_class()->Is_pointer_class()) {
02033 ALIAS_CLASS_MEMBER *return_acm = New_alias_class_member();
02034 ALIAS_CLASS_REP *return_acr = New_alias_class(return_acm);
02035 lhs_class.Ref_class()->Set_class_pointed_to(return_acr);
02036 lhs_class.Ref_class()->Process_pending(*this);
02037 lhs_class.Set_obj_class(return_acr);
02038 }
02039 if (WN_is_alloca_intrinsic(call_wn)) {
02040 _alloca_memory_members.
02041 push_front(lhs_class.Obj_class()->Representative());
02042 }
02043 }
02044 stmt = WN_next(stmt);
02045 }
02046 Is_True(Uses_no_return_value(stmt),
02047 ("ALIAS_CLASSIFICATION: General use of return value illegal"));
02048
02049 if (WOPT_Enable_Verbose && Tracing()) {
02050 fprintf(TFile, " after handling call:\n");
02051 Print(TFile);
02052 }
02053 return stmt;
02054 }
02055
02056
02057
02058
02059
02060
02061
02062
02063
02064 WN *
02065 ALIAS_CLASSIFICATION::Classify_wn_and_kids(WN *const wn)
02066 {
02067 OPCODE opc = WN_opcode(wn);
02068
02069 #if Is_True_On
02070 if (opc == OPC_REGION) {
02071 RID *rid = REGION_get_rid(wn);
02072 Is_True(rid != NULL, ("ALIAS_CLASSIFICATION::Classify_wn_and_kids: "
02073 "rid must not be NULL"));
02074
02075
02076
02077 FmtAssert((RID_level(rid) <
02078 (Opt_stab()->Rgn_level() +
02079 (_destination == AC_DESTINATION_ALIAS_MANAGER))),
02080 ("ALIAS_CLASSIFICATION: Cannot perform alias classification "
02081 "in the presence of black-box regions"));
02082 }
02083 #endif
02084
02085 if (opc == OPC_BLOCK) {
02086 for (WN *wn2 = WN_first(wn); wn2 != NULL; ) {
02087 wn2 = Classify_wn_and_kids(wn2);
02088 }
02089 return NULL;
02090 }
02091 else if (OPCODE_is_store(opc)) {
02092 if (WOPT_Enable_Verbose && Tracing()) {
02093 fprintf(TFile, "cwnk: Handling assignment:\n");
02094 Dump_wn_tree(TFile, wn);
02095 }
02096 return Handle_assignment(wn);
02097 }
02098 else if (OPCODE_is_call(opc)) {
02099 if (WOPT_Enable_Verbose && Tracing()) {
02100 fprintf(TFile, "cwnk: Handling call:\n");
02101 Dump_wn_tree(TFile, wn);
02102 }
02103 return Handle_call(wn);
02104 }
02105 else if (OPCODE_is_expression(opc)) {
02106
02107
02108 (void) Classify_deref_of_expr(wn, FALSE);
02109 return NULL;
02110 }
02111 else if (opc == OPC_IO) {
02112 Warn_todo("ALIAS_CLASSIFICATION: Handle %s", OPCODE_name(opc));
02113 return WN_next(wn);
02114 }
02115 else if ( ! OPCODE_is_black_box( opc )) {
02116 for (INT i = 0; i < WN_kid_count(wn); i++) {
02117 WN *kid_i = WN_kid(wn, i);
02118 Classify_wn_and_kids(kid_i);
02119 }
02120 return WN_next(wn);
02121 }
02122 else {
02123 return WN_next(wn);
02124 }
02125 }
02126
02127
02128
02129
02130
02131 void
02132 ALIAS_CLASSIFICATION::Finalize_ac_map_wn(WN *wn)
02133 {
02134 OPCODE opc = WN_opcode(wn);
02135 OPERATOR opr = OPCODE_operator(opc);
02136
02137 if (Tracing()) {
02138 fprintf(TFile, "Finalizing : ");
02139 Dump_wn(TFile, wn);
02140 fflush(TFile);
02141 }
02142
02143 if (OPCODE_is_call(opc)) {
02144
02145 }
02146 else if (OPCODE_is_load(opc) ||
02147 OPCODE_is_store(opc) ||
02148 #if defined (TARG_SL)
02149 (opr==OPR_PARM && WN_Parm_Dereference(wn)) ||
02150 #endif
02151 Is_fortran_reference_parm(wn) ||
02152 ((opr == OPR_LDA || opr == OPR_LDMA) &&
02153 Is_LDA_of_variable(wn))) {
02154 if (Tracing()) {
02155 fprintf(TFile, " placed in ");
02156 }
02157 if (OPERATOR_is_scalar_load (opr) ||
02158 OPERATOR_is_scalar_store (opr) ||
02159 opr == OPR_LDA || opr == OPR_LDMA) {
02160
02161 ALIAS_CLASS_REP *acr = Class_of_base_id_LDID(WN_base_id(wn));
02162 IDTYPE class_id = acr->Id();
02163
02164 WN_MAP32_Set(Memop_classification_map(), wn, class_id);
02165 if (_ac_id_to_acr_map.Lookup(class_id) == NULL) {
02166 _ac_id_to_acr_map.Insert(class_id, acr);
02167 }
02168
02169 if (Tracing()) {
02170 Class_of_base_id_LDID(WN_base_id(wn))->Print(TFile, Global_class());
02171 }
02172
02173 if (_destination == AC_DESTINATION_OPT_STAB) {
02174
02175
02176
02177
02178
02179
02180
02181 POINTS_TO *pt = Opt_stab()->Aux_stab_entry(WN_aux(wn))->Points_to();
02182
02183 if (pt->Alias_class() == OPTIMISTIC_AC_ID) {
02184 pt->Set_alias_class(class_id);
02185 }
02186 else {
02187 Is_True(((WOPT_Alias_Class_Limit != UINT32_MAX) &&
02188 (pt->Alias_class() == PESSIMISTIC_AC_ID)) ||
02189 (pt->Alias_class() == class_id),
02190 ("ALIAS_CLASSIFICATION: Inconsistent alias class "
02191 "for base ID %u, aux ID %u", WN_base_id(wn), WN_aux(wn)));
02192
02193
02194 if ((pt->Alias_class() != class_id) &&
02195 (pt->Alias_class() != PESSIMISTIC_AC_ID)) {
02196
02197
02198 DevWarn("ALIAS_CLASSIFICATION: Inconsistent alias class "
02199 "for base ID %u, aux ID %u", WN_base_id(wn), WN_aux(wn));
02200 pt->Set_alias_class(PESSIMISTIC_AC_ID);
02201 }
02202 }
02203 }
02204 }
02205 else {
02206
02207
02208 ALIAS_CLASS_MEMBER *acm =
02209 (ALIAS_CLASS_MEMBER *) WN_MAP_Get(Indir_classification_map(), wn);
02210 #if 0
02211 if (Tracing()) {
02212 fprintf(TFile, "Got 0x%p from indir map %u on\n", acm,
02213 Indir_classification_map());
02214 Dump_wn_tree(TFile, wn);
02215 }
02216 #endif
02217 ALIAS_CLASS_REP *acr = acm->Alias_class();
02218
02219 if (Tracing()) {
02220 acr->Print(TFile, Global_class());
02221 }
02222
02223 IDTYPE class_id = acr->Id();
02224 WN_MAP32_Set(Memop_classification_map(), wn, class_id);
02225 if (_ac_id_to_acr_map.Lookup(class_id) == NULL) {
02226 _ac_id_to_acr_map.Insert(class_id, acr);
02227 }
02228 }
02229 }
02230 }
02231
02232
02233 void
02234 ALIAS_CLASSIFICATION::Finalize_ac_map(WN *const wn)
02235 {
02236 OPCODE opc = WN_opcode(wn);
02237 OPERATOR opr = OPCODE_operator(opc);
02238
02239 #if Is_True_On
02240 if (opc == OPC_REGION) {
02241 RID *rid = REGION_get_rid(wn);
02242 Is_True(rid != NULL, ("ALIAS_CLASSIFICATION::Finalize_ac_map: "
02243 "rid must not be NULL"));
02244
02245
02246
02247 FmtAssert((RID_level(rid) <
02248 (Opt_stab()->Rgn_level() +
02249 (_destination == AC_DESTINATION_ALIAS_MANAGER))),
02250 ("ALIAS_CLASSIFICATION: Cannot perform alias classification "
02251 "in the presence of black-box regions"));
02252 }
02253 #endif
02254
02255 if (opc == OPC_BLOCK) {
02256 for (WN *wn2 = WN_first(wn); wn2 != NULL; wn2 = WN_next(wn2)) {
02257 Finalize_ac_map(wn2);
02258 }
02259 }
02260 else if (!OPCODE_is_black_box(opc)) {
02261 INT rhs_idx;
02262 if (OPCODE_is_store(opc)) {
02263 rhs_idx = 0;
02264 }
02265 else {
02266 rhs_idx = -1;
02267 }
02268 for (INT i = 0; i < WN_kid_count(wn); i++) {
02269
02270
02271 if (!OPCODE_is_store(opc) ||
02272 !Stmt_stores_return_value(wn) ||
02273 i != rhs_idx) {
02274 Finalize_ac_map(WN_kid(wn, i));
02275 }
02276 }
02277 Finalize_ac_map_wn(wn);
02278 }
02279 }
02280
02281
02282
02283
02284
02285
02286
02287 void
02288 ALIAS_CLASSIFICATION::Classify_memops(WN *entry_wn)
02289 {
02290 #if Is_True_On
02291 next_acm_idx = 0;
02292 #endif
02293
02294
02295 Preg_num_base_id_map().Init();
02296 _st_idx_to_base_id_map.Init();
02297
02298 if (Tracing()) {
02299 fprintf(TFile, "%sBeginning alias classification for %s\n%s",
02300 DBar,
02301 (_destination == AC_DESTINATION_OPT_STAB ?
02302 "OPT_STAB" :
02303 "alias manager"),
02304 DBar);
02305 Dump_wn_tree(TFile, entry_wn);
02306 if (_destination == AC_DESTINATION_OPT_STAB) {
02307 Opt_stab()->Print(TFile);
02308 }
02309 }
02310
02311 if (Tracing()) {
02312 fprintf(TFile, "----------\nBefore program analysis:\n");
02313 Print(TFile);
02314 fprintf(TFile, "----------\n");
02315 }
02316
02317 _memop_classification_map = WN_MAP32_Create(Pool());
02318 _indir_classification_map = WN_MAP_Create(Pool());
02319
02320 if (Tracing()) {
02321 fprintf(TFile, "indir map is %u\n", _indir_classification_map);
02322 }
02323
02324 Classify_wn_and_kids(entry_wn);
02325
02326
02327
02328 ALIAS_CLASS_REP::_structure_not_frozen = FALSE;
02329
02330 if (Tracing()) {
02331 fprintf(TFile, "----------\nAfter program analysis:\n");
02332 Print(TFile);
02333 fprintf(TFile, "----------\n");
02334 }
02335
02336 if (_destination == AC_DESTINATION_OPT_STAB) {
02337
02338
02339
02340
02341
02342
02343
02344
02345
02346
02347
02348
02349
02350
02351
02352
02353
02354
02355
02356
02357 ALIAS_CLASS_MEMBER_LIST::iterator p;
02358 for (p = Altered_non_points_to_parms().begin();
02359 p != Altered_non_points_to_parms().end();
02360 ++p) {
02361
02362
02363
02364 for (ALIAS_CLASS_REP *acr = (*p)->Alias_class()->Class_pointed_to();
02365 acr != NULL && !acr->Writable_by_call();
02366 acr = acr->Class_pointed_to()) {
02367 acr->Set_writable_by_call();
02368 }
02369 }
02370
02371 for (p = _alloca_memory_members.begin();
02372 p != _alloca_memory_members.end();
02373 ++p) {
02374 (*p)->Alias_class()->Set_alloca_class();
02375 }
02376
02377
02378
02379 Global_class()->Set_writable_by_call();
02380
02381
02382
02383 AUX_STAB_ITER aux_stab_iter(Opt_stab());
02384 AUX_ID aux_id;
02385 BS *inaccessible_to_callees;
02386
02387 inaccessible_to_callees = BS_Create_Empty(Opt_stab()->Lastidx(),
02388 Pool());
02389
02390 FOR_ALL_NODE(aux_id, aux_stab_iter, Init()) {
02391
02392
02393
02394 AUX_STAB_ENTRY *aux_stab_entry = Opt_stab()->Aux_stab_entry(aux_id);
02395 if (aux_stab_entry->St() != NULL &&
02396 !aux_stab_entry->Is_dedicated_preg() &&
02397
02398
02399 Class_of_base_id_LDID(Base_id(aux_id, (TY_IDX) 0)) != NULL &&
02400 !Class_of_base_id_LDID(Base_id(aux_id, (TY_IDX) 0))->Writable_by_call()) {
02401 inaccessible_to_callees =
02402 BS_Union1D(inaccessible_to_callees, aux_id, Pool());
02403 }
02404 }
02405
02406
02407
02408
02409 Set_inaccessible_to_callees(inaccessible_to_callees);
02410
02411 if (Tracing()) {
02412 fprintf(TFile, "----------\nAux ID's that can't be touched by callees:\n");
02413 BS_Print(Inaccessible_to_callees(), TFile);
02414 fprintf(TFile, "----------\n");
02415 }
02416 }
02417
02418
02419
02420
02421
02422 _ac_id_to_acr_map.Init();
02423
02424 Finalize_ac_map(entry_wn);
02425
02426 WN_MAP_Delete(_indir_classification_map);
02427
02428 _memops_classified = TRUE;
02429 }
02430
02431
02432
02433
02434
02435 IDTYPE
02436 ALIAS_CLASSIFICATION::Alias_class(const WN *const wn) const
02437 {
02438 Is_True(OPCODE_is_store(WN_opcode(wn)) ||
02439 OPCODE_is_load(WN_opcode(wn)) ||
02440 WN_operator(wn) == OPR_LDA ||
02441 WN_operator(wn) == OPR_LDMA ||
02442 WN_operator(wn) == OPR_PARM,
02443 ("ALIAS_CLASSIFICATION: WN must be memop"));
02444
02445 if (_memops_classified) {
02446 FmtAssert(_mem_pool_valid,
02447 ("ALIAS_CLASSIFICATION: Our memory is gone."));
02448 return WN_MAP32_Get(Memop_classification_map(), wn);
02449 }
02450 else {
02451 return PESSIMISTIC_AC_ID;
02452 }
02453 }
02454
02455
02456 void
02457 ALIAS_CLASSIFICATION::Copy_alias_class(const WN *const srcwn, WN *const targwn)
02458 {
02459 Is_True(OPCODE_is_store(WN_opcode(srcwn)) ||
02460 OPCODE_is_load(WN_opcode(srcwn)) ||
02461 WN_operator(srcwn) == OPR_LDA ||
02462 WN_operator(srcwn) == OPR_LDMA ||
02463 WN_operator(srcwn) == OPR_PARM,
02464 ("ALIAS_CLASSIFICATION: WN must be memop"));
02465
02466 if (_memops_classified) {
02467 FmtAssert(_mem_pool_valid,
02468 ("ALIAS_CLASSIFICATION: Our memory is gone."));
02469 IDTYPE class_id = WN_MAP32_Get(Memop_classification_map(), srcwn);
02470 WN_MAP32_Set(Memop_classification_map(), targwn, class_id);
02471 }
02472 }
02473
02474 BOOL
02475 ALIAS_CLASSIFICATION::Non_alloca_memop(const IDTYPE class_id) const
02476 {
02477 if (_memops_classified &&
02478 class_id != OPTIMISTIC_AC_ID &&
02479 class_id != PESSIMISTIC_AC_ID) {
02480 FmtAssert(_mem_pool_valid,
02481 ("ALIAS_CLASSIFICATION: Our memory is gone."));
02482 const ALIAS_CLASS_REP *const acr = _ac_id_to_acr_map.Lookup(class_id);
02483 FmtAssert(acr != NULL,
02484 ("ALIAS_CLASSIFICATION::Non_alloca_memop: ACR with ID "
02485 "%lu not found", class_id));
02486 return !acr->Alloca_class();
02487 }
02488 else {
02489
02490 return FALSE;
02491 }
02492 }
02493
02494
02495 BOOL
02496 ALIAS_CLASSIFICATION::Writable_by_call(const IDTYPE class_id) const
02497 {
02498 if (_memops_classified &&
02499 class_id != OPTIMISTIC_AC_ID &&
02500 class_id != PESSIMISTIC_AC_ID) {
02501 FmtAssert(_mem_pool_valid,
02502 ("ALIAS_CLASSIFICATION: Our memory is gone."));
02503 const ALIAS_CLASS_REP *const acr = _ac_id_to_acr_map.Lookup(class_id);
02504 FmtAssert(acr != NULL,
02505 ("ALIAS_CLASSIFICATION::Writable_by_call: ACR with ID "
02506 "%lu not found", class_id));
02507 return acr->Writable_by_call();
02508 }
02509 else {
02510 return TRUE;
02511 }
02512 }
02513
02514
02515 void
02516 ALIAS_CLASSIFICATION::Release_resources(void)
02517 {
02518 _base_id_map.Free_array();
02519 if (_memops_classified) {
02520 WN_MAP_Delete(Memop_classification_map());
02521
02522 (&_preg_num_base_id_map)->~ID_MAP();
02523 (&_st_idx_to_base_id_map)->~ID_MAP();
02524 (&_ac_id_to_acr_map)->~ID_MAP();
02525 (&_altered_non_points_to_parms)->~ALIAS_CLASS_MEMBER_LIST();
02526 (&_alloca_memory_members)->~ALIAS_CLASS_MEMBER_LIST();
02527 }
02528
02529 OPT_POOL_Pop(_pool, MEM_DUMP_FLAG+20);
02530 _mem_pool_valid = FALSE;
02531 OPT_POOL_Delete(_pool, MEM_DUMP_FLAG+20);
02532 _pool = NULL;
02533 }
02534
02535
02536
02537
02538
02539
02540
02541 void
02542 ALIAS_CLASSIFICATION::Print(FILE *fp) const
02543 {
02544
02545
02546
02547 fprintf(fp, "Global class: ");
02548 Global_class()->Print(fp);
02549 for (INT i = 1; i <= _base_id_map.Lastidx(); i++) {
02550 fprintf(fp, "LDA class for base ID %u is ", i);
02551 _base_id_map[i]->Lda_class().Print(fp, Global_class());
02552 if (_base_id_map[i]->Lda_class().Class_pointed_to() != NULL) {
02553 fprintf(fp, "Class containing base ID %u is ", i);
02554 _base_id_map[i]->Lda_class().Class_pointed_to()->
02555 Print(fp, Global_class());
02556 }
02557 }
02558 }
02559
02560
02561
02562
02563
02564
02565
02566 void
02567 ALIAS_MANAGER::Transfer_alias_class_to_alias_manager(const
02568 ALIAS_CLASSIFICATION &ac,
02569 WN *wn)
02570 {
02571 IDTYPE alias_id = Id(wn);
02572 OPERATOR opr = WN_operator(wn);
02573 if (alias_id != 0 &&
02574 alias_id != Preg_id() &&
02575 opr != OPR_FORWARD_BARRIER &&
02576 opr != OPR_BACKWARD_BARRIER &&
02577 opr != OPR_DEALLOCA) {
02578
02579
02580
02581 IDTYPE wn_alias_class = ac.Alias_class(wn);
02582 POINTS_TO *pt = Pt(alias_id);
02583 if (pt->Alias_class() == OPTIMISTIC_AC_ID) {
02584 pt->Set_alias_class(wn_alias_class);
02585 }
02586 else if (pt->Alias_class() != wn_alias_class) {
02587
02588 DevWarn("New alias ID on second pass");
02589 alias_id = Cross_dso_new_alias_id();
02590 Cross_dso_set_id(wn, alias_id);
02591 POINTS_TO *npt = Pt(alias_id);
02592 npt->Copy_fully(pt);
02593 npt->Set_alias_class(wn_alias_class);
02594 }
02595 }
02596 if (WN_opcode(wn) == OPC_BLOCK) {
02597 for (WN *wn2 = WN_first(wn); wn2 != NULL; wn2 = WN_next(wn2)) {
02598 Transfer_alias_class_to_alias_manager(ac, wn2);
02599 }
02600 }
02601 else {
02602 for (INT i = 0; i < WN_kid_count(wn); i++) {
02603 Transfer_alias_class_to_alias_manager(ac, WN_kid(wn, i));
02604 }
02605 }
02606 }
02607
02608
02609 void
02610 ALIAS_MANAGER::Forget_alias_class_info(void)
02611 {
02612 for (IDTYPE alias_id = 1; alias_id <= _last_alias_id; ++alias_id) {
02613 if (alias_id != Preg_id()) {
02614 Pt(alias_id)->Set_alias_class(OPTIMISTIC_AC_ID);
02615 }
02616 }
02617 }
02618
02619
02620