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
00087 #ifdef USE_PCH
00088 #include "opt_pch.h"
00089 #endif // USE_PCH
00090 #pragma hdrstop
00091
00092
00093 #define __STDC_LIMIT_MACROS
00094 #include <stdint.h>
00095 #include "defs.h"
00096
00097 #include "opt_defs.h"
00098 #include "opt_config.h"
00099 #include "stab.h"
00100 #include "targ_sim.h"
00101 #include "tracing.h"
00102 #include "wn_util.h"
00103 #include "optimizer.h"
00104 #include "errors.h"
00105 #include "erbe.h"
00106 #include "stblock.h"
00107 #include "config.h"
00108 #include "config_opt.h"
00109 #include "config_ipa.h"
00110 #include "region_util.h"
00111 #include "srcpos.h"
00112 #include "pu_info.h"
00113 #include "opt_base.h"
00114 #include "opt_util.h"
00115 #include "opt_sym.h"
00116 #include "opt_ssa.h"
00117 #include "opt_htable.h"
00118 #include "opt_cfg.h"
00119 #include "opt_mu_chi.h"
00120 #include "opt_points_to.h"
00121 #include "opt_alias_class.h"
00122 #include "opt_alias_rule.h"
00123 #include "opt_points_to_summary.h"
00124 #include "region_alias_templates.h"
00125 #include "opt_dbg.h"
00126 #include "opt_main.h"
00127 #include "opt_alias_analysis.h"
00128 #include "intrn_info.h"
00129
00130 extern "C" {
00131 #include "bitset.h"
00132 }
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158 void OPT_STAB::Analyze_Range(WN *wn_arr, POINTS_TO *pt)
00159 {
00160 Is_True(WN_operator(wn_arr) == OPR_ARRAY, ("WN operator is not ARRAY."));
00161
00162 Is_True(pt->Bit_Size() == 0, ("OPR_ARRAY should not address bit fields"));
00163
00164
00165 if (pt->Ofst_kind() != OFST_IS_FIXED || !pt->Is_pointer())
00166 return;
00167
00168 mINT64 product = WN_element_size(wn_arr);
00169
00170 if (product < 0) {
00171
00172
00173
00174 pt->Set_byte_ofst(0);
00175 pt->Set_byte_size(0);
00176 pt->Set_ofst_kind( OFST_IS_UNKNOWN );
00177 return;
00178 }
00179
00180
00181 mINT64 upper = WN_element_size(wn_arr);
00182 mINT64 lower = 0;
00183 INT32 n_dim = WN_num_dim(wn_arr);
00184
00185
00186
00187 for (INT32 i = n_dim; i >= 1; i--) {
00188 WN *wn_dim = WN_kid(wn_arr,i);
00189 WN *wn_index = WN_kid(wn_arr, i + n_dim);
00190
00191 if ( WN_operator(wn_dim) != OPR_INTCONST ||
00192 WN_const_val(wn_dim) == 1 ||
00193 WN_const_val(wn_dim) == 0) {
00194
00195 pt->Set_byte_ofst(0);
00196 pt->Set_byte_size(0);
00197 pt->Set_ofst_kind( OFST_IS_UNKNOWN );
00198 return;
00199 }
00200 if ( WN_operator(wn_index) == OPR_INTCONST) {
00201 lower = product * WN_const_val(wn_index) + lower;
00202 upper = product * WN_const_val(wn_index) + upper;
00203 } else {
00204
00205
00206 lower = 0;
00207 upper = product * WN_const_val(wn_dim);
00208 }
00209 product *= WN_const_val(wn_dim);
00210 }
00211
00212
00213
00214
00215
00216
00217 upper = upper - WN_element_size(wn_arr);
00218 Is_True(upper >= lower, ("range error in OPT_STAB::Analyze_Range."));
00219
00220 pt->Set_byte_ofst( pt->Byte_Ofst() + lower );
00221
00222
00223
00224 pt->Set_byte_size( upper - lower );
00225 pt->Set_ofst_kind( OFST_IS_FIXED );
00226 return;
00227 }
00228
00229
00230
00231
00232
00233
00234
00235 void OPT_STAB::Simplify_Pointer_Arith(WN *wn_expr, POINTS_TO *ai)
00236 {
00237 OPERATOR opr = WN_operator(wn_expr);
00238 switch (opr) {
00239 #if defined(TARG_SL)
00240 case OPR_INTRINSIC_OP:
00241 if( INTRN_copy_addr(WN_intrinsic(wn_expr)) )
00242 Simplify_Pointer( WN_kid0(WN_kid0(wn_expr)), ai );
00243 else {
00244 ai->Set_expr_kind(EXPR_IS_UNKNOWN);
00245 ai->Set_base_kind(BASE_IS_UNKNOWN);
00246 ai->Set_ofst_kind(OFST_IS_UNKNOWN);
00247 ai->Invalidate_ptr_info ();
00248 }
00249 CHECK_POINTS_TO(ai);
00250 break;
00251 #endif
00252 case OPR_INTCONST:
00253 ai->Set_expr_kind(EXPR_IS_INT);
00254 ai->Set_const_val(WN_const_val(wn_expr));
00255 ai->Invalidate_ptr_info ();
00256 CHECK_POINTS_TO(ai);
00257 break;
00258
00259 case OPR_LDBITS:
00260 case OPR_ILDBITS:
00261 case OPR_LDID:
00262 case OPR_ILOAD:
00263 {
00264 TY_IDX ty = WN_object_ty(wn_expr);
00265 if (TY_kind(ty) == KIND_POINTER) {
00266 Simplify_Pointer(wn_expr, ai);
00267 } else {
00268 ai->Set_expr_kind(EXPR_IS_INT);
00269 ai->Invalidate_ptr_info ();
00270 }
00271 }
00272 CHECK_POINTS_TO(ai);
00273 break;
00274
00275 case OPR_LDA:
00276 case OPR_ARRAY:
00277 Simplify_Pointer(wn_expr, ai);
00278 CHECK_POINTS_TO(ai);
00279 break;
00280
00281 case OPR_PAREN:
00282 Simplify_Pointer_Arith(WN_kid0(wn_expr), ai);
00283 break;
00284
00285 case OPR_NEG:
00286 {
00287 POINTS_TO alias0;
00288 alias0.Init();
00289 Simplify_Pointer_Arith(WN_kid0(wn_expr), &alias0);
00290 if (alias0.Expr_kind() == EXPR_IS_INT)
00291 ai->Copy_fully(alias0);
00292 else {
00293 ai->Set_expr_kind(EXPR_IS_UNKNOWN);
00294 ai->Set_base_kind(BASE_IS_UNKNOWN);
00295 ai->Set_ofst_kind(OFST_IS_UNKNOWN);
00296 }
00297 ai->Invalidate_ptr_info ();
00298 break;
00299 }
00300
00301 case OPR_ADD:
00302 {
00303 POINTS_TO alias0;
00304 POINTS_TO alias1;
00305
00306 alias0.Init();
00307 alias1.Init();
00308 alias0.Set_expr_kind(EXPR_IS_UNKNOWN);
00309 alias1.Set_expr_kind(EXPR_IS_UNKNOWN);
00310
00311 Simplify_Pointer_Arith(WN_kid0(wn_expr), &alias0);
00312 Simplify_Pointer_Arith(WN_kid1(wn_expr), &alias1);
00313
00314 ai->Set_expr_kind(EXPR_IS_UNKNOWN);
00315 if (alias0.Expr_kind() == EXPR_IS_BEING_PROCESSED) {
00316 ai->Copy_fully(alias0);
00317 ai->Invalidate_ptr_info ();
00318 } else if (alias0.Expr_kind() == EXPR_IS_ADDR) {
00319 if (alias1.Expr_kind() == EXPR_IS_INT) {
00320 ai->Copy_fully(alias0);
00321
00322 if ((alias0.Ofst_kind() == OFST_IS_FIXED ||
00323 alias0.Iofst_kind() == OFST_IS_FIXED) && alias1.Int_is_constant()) {
00324 ai->Shift_ofst( alias1.Int_const_val());
00325 }
00326 else
00327 #ifdef KEY
00328 if (!ai->Is_field()) {
00329 #endif
00330 ai->Set_ofst_kind(OFST_IS_UNKNOWN);
00331 ai->Set_iofst_kind(OFST_IS_UNKNOWN);
00332 }
00333 } else if (alias1.Expr_kind() == EXPR_IS_ADDR) {
00334 ai->Copy_fully(alias0);
00335 ai->Meet(&alias1, (ST *) wn_expr);
00336 }
00337 } else if (alias0.Expr_kind() == EXPR_IS_INT) {
00338 if (alias1.Expr_kind() == EXPR_IS_ADDR) {
00339 ai->Copy_fully(alias1);
00340 if ((alias1.Ofst_kind() == OFST_IS_FIXED ||
00341 alias1.Iofst_kind() == OFST_IS_FIXED) && alias0.Int_is_constant()) {
00342 ai->Shift_ofst( alias0.Int_const_val());
00343 }
00344 else
00345 #ifdef KEY
00346 if (!ai->Is_field()) {
00347 #endif
00348 ai->Set_ofst_kind(OFST_IS_UNKNOWN);
00349 ai->Set_iofst_kind(OFST_IS_UNKNOWN);
00350 }
00351 } else if (alias1.Expr_kind() == EXPR_IS_INT) {
00352 ai->Set_expr_kind(EXPR_IS_INT);
00353 ai->Invalidate_ptr_info ();
00354 }
00355 }
00356 if (ai->Expr_kind() == EXPR_IS_UNKNOWN) {
00357 ai->Set_base_kind(BASE_IS_UNKNOWN);
00358 ai->Set_ofst_kind(OFST_IS_UNKNOWN);
00359 ai->Invalidate_ptr_info ();
00360 }
00361 CHECK_POINTS_TO(ai);
00362 }
00363 break;
00364
00365 case OPR_SUB:
00366 {
00367 POINTS_TO alias0;
00368 POINTS_TO alias1;
00369
00370 alias0.Init();
00371 alias1.Init();
00372 alias0.Set_expr_kind(EXPR_IS_UNKNOWN);
00373 alias1.Set_expr_kind(EXPR_IS_UNKNOWN);
00374
00375 Simplify_Pointer_Arith(WN_kid0(wn_expr), &alias0);
00376 Simplify_Pointer_Arith(WN_kid1(wn_expr), &alias1);
00377
00378 ai->Set_expr_kind(EXPR_IS_UNKNOWN);
00379 if (alias0.Expr_kind() == EXPR_IS_BEING_PROCESSED) {
00380 ai->Copy_fully(alias0);
00381 ai->Invalidate_ptr_info ();
00382 } else if (alias0.Expr_kind() == EXPR_IS_ADDR) {
00383 if (alias1.Expr_kind() == EXPR_IS_INT) {
00384 ai->Copy_fully(alias0);
00385 if ((alias0.Ofst_kind() == OFST_IS_FIXED ||
00386 alias0.Iofst_kind() == OFST_IS_FIXED) && alias1.Int_is_constant()) {
00387 ai->Shift_ofst( - alias1.Int_const_val());
00388 } else {
00389 ai->Set_ofst_kind(OFST_IS_UNKNOWN);
00390 ai->Set_iofst_kind(OFST_IS_UNKNOWN);
00391 }
00392 } else if (alias1.Expr_kind() == EXPR_IS_ADDR) {
00393 ai->Copy_fully(alias0);
00394 ai->Meet(&alias1, (ST *) wn_expr);
00395 }
00396 } else if (alias0.Expr_kind() == EXPR_IS_INT) {
00397 if (alias1.Expr_kind() == EXPR_IS_INT) {
00398 ai->Set_expr_kind(EXPR_IS_INT);
00399 }
00400 ai->Invalidate_ptr_info ();
00401 }
00402 if (ai->Expr_kind() == EXPR_IS_UNKNOWN) {
00403 ai->Set_base_kind(BASE_IS_UNKNOWN);
00404 ai->Set_ofst_kind(OFST_IS_UNKNOWN);
00405 ai->Invalidate_ptr_info ();
00406 }
00407 CHECK_POINTS_TO(ai);
00408 }
00409 break;
00410
00411
00412 case OPR_ABS:
00413 case OPR_SQRT:
00414 case OPR_RSQRT:
00415 case OPR_RECIP:
00416 case OPR_REALPART:
00417 case OPR_IMAGPART:
00418 case OPR_RND:
00419 case OPR_TRUNC:
00420 case OPR_CEIL:
00421 case OPR_FLOOR:
00422 case OPR_BNOT:
00423 case OPR_LNOT:
00424 case OPR_COMPLEX:
00425 case OPR_MPY:
00426 case OPR_DIV:
00427 case OPR_MOD:
00428 case OPR_REM:
00429 case OPR_MAX:
00430 case OPR_MIN:
00431 case OPR_EQ:
00432 case OPR_NE:
00433 case OPR_GE:
00434 case OPR_GT:
00435 case OPR_LE:
00436 case OPR_LT:
00437 case OPR_BAND:
00438 case OPR_BIOR:
00439 case OPR_BXOR:
00440 case OPR_LAND:
00441 case OPR_LIOR:
00442 case OPR_SHL:
00443 case OPR_ASHR:
00444 case OPR_LSHR:
00445 case OPR_MADD:
00446 case OPR_MSUB:
00447 case OPR_NMADD:
00448 case OPR_NMSUB:
00449 case OPR_CVT:
00450 case OPR_CVTL:
00451 ai->Set_expr_kind(EXPR_IS_INT);
00452 ai->Set_base_kind(BASE_IS_UNKNOWN);
00453 ai->Set_ofst_kind(OFST_IS_UNKNOWN);
00454 ai->Invalidate_ptr_info ();
00455 CHECK_POINTS_TO(ai);
00456 break;
00457
00458 default:
00459
00460 ai->Set_expr_kind(EXPR_IS_UNKNOWN);
00461 ai->Set_base_kind(BASE_IS_UNKNOWN);
00462 ai->Set_ofst_kind(OFST_IS_UNKNOWN);
00463 ai->Invalidate_ptr_info ();
00464 CHECK_POINTS_TO(ai);
00465 break;
00466 }
00467 }
00468
00469
00470
00471
00472
00473 BOOL OPT_STAB::Its_ret_val_of_malloc (VER_ID ver_id) {
00474
00475 VER_STAB_ENTRY* ver = Ver_stab_entry (ver_id);
00476 if (ver->Type () != CHI_STMT) { return FALSE; }
00477
00478
00479 AUX_STAB_ENTRY* aux = Aux_stab_entry(ver->Aux_id());
00480 if (!aux->Is_dedicated_preg ()) { return FALSE; }
00481
00482
00483 WN* call = ver->Chi_wn();
00484 if (WN_operator (call) != OPR_CALL) { return FALSE; }
00485
00486
00487 ST* call_st = WN_st(call);
00488 if (!PU_has_attr_malloc(Pu_Table[ST_pu(call_st)])) {
00489 return FALSE;
00490 }
00491
00492
00493 if (WHIRL_Return_Info_On) {
00494 RETURN_INFO return_info =
00495 Get_Return_Info (MTYPE_To_TY(WN_rtype(call)),
00496 Allow_sim_type() ? Use_Simulated :
00497 Complex_Not_Simulated
00498 #ifdef TARG_X8664
00499 ,call_st ? PU_ff2c_abi(Pu_Table[ST_pu(call_st)]) : FALSE
00500 #endif
00501 );
00502
00503 if (RETURN_INFO_count(return_info) == 1 &&
00504 RETURN_INFO_preg (return_info, 0) == aux->St_ofst()) {
00505 return TRUE;
00506 }
00507 }
00508
00509 return FALSE;
00510 }
00511
00512
00513
00514
00515 void OPT_STAB::Simplify_Pointer_Ver(VER_ID ver, POINTS_TO *ai)
00516 {
00517 PT_MEMOP_ANNOT_STIKER mem_annot_stiker(ai);
00518
00519 INT32 vtype = Ver_stab_entry(ver)->Type();
00520 POINTS_TO *pt = Ver_stab_entry(ver)->Points_to();
00521 AUX_ID aux_id = Ver_stab_entry(ver)->Aux_id();
00522 ST* st = Aux_stab_entry (aux_id)->St ();
00523
00524
00525
00526 if (pt) {
00527 ai->Copy_fully(pt);
00528 CHECK_POINTS_TO(ai);
00529 return;
00530 }
00531
00532
00533
00534 switch (vtype) {
00535 case ENTRY_STMT:
00536 {
00537 ai->Invalidate_ptr_info ();
00538 if ( Is_volatile(Ver_stab_entry(ver)->Aux_id()) ) {
00539
00540
00541 ai->Set_expr_kind(EXPR_IS_ADDR);
00542 ai->Set_base_kind(BASE_IS_DYNAMIC);
00543 ai->Set_ofst_kind(OFST_IS_FIXED);
00544 ai->Set_byte_ofst(0);
00545 ai->Set_byte_size(0);
00546 ai->Set_bit_ofst_size(0, 0);
00547 ai->Set_base((ST*)(INTPTR)ver);
00548 ai->Invalidate_ptr_info ();
00549 }
00550 else {
00551 ai->Set_expr_kind(EXPR_IS_ADDR);
00552 ai->Set_base_kind(BASE_IS_DYNAMIC);
00553 ai->Set_ofst_kind(OFST_IS_FIXED);
00554 ai->Set_byte_ofst(0);
00555 ai->Set_byte_size(0);
00556 ai->Set_bit_ofst_size(0, 0);
00557 ai->Set_global();
00558 ai->Set_base((ST*)(INTPTR)ver);
00559 if (st) {
00560 if (ST_class(st) != CLASS_PREG){
00561 ai->Set_pointer (st);
00562 } else {
00563 ai->Set_pointer_as_aux_id (aux_id);
00564 }
00565 ai->Set_pointer_ver (ver);
00566 ai->Set_iofst_kind (OFST_IS_FIXED);
00567 }
00568 }
00569 }
00570 break;
00571 case WHIRL_STMT:
00572 {
00573 WN *def = Ver_stab_entry(ver)->Wn();
00574 if (def) {
00575 FmtAssert ( WN_operator(def) == OPR_STID,
00576 ("Simplify_Pointer_Ver: def must be STID.") );
00577 pt = CXX_NEW(POINTS_TO, &_ver_pool);
00578 pt->Init();
00579 pt->Set_expr_kind(EXPR_IS_BEING_PROCESSED);
00580 Ver_stab_entry(ver)->Set_points_to(pt);
00581 Simplify_Pointer(WN_kid0(def), ai);
00582 pt->Copy_fully(ai);
00583
00584 if (pt->Expr_kind() == EXPR_IS_BEING_PROCESSED) {
00585 pt->Set_expr_kind(EXPR_IS_UNKNOWN);
00586 CHECK_POINTS_TO(pt);
00587 }
00588 }
00589 }
00590 break;
00591 case PHI_STMT:
00592 {
00593
00594
00595 INT32 in_degree = Ver_stab_entry(ver)->Bb()->Pred()->Len();
00596 BB_NODE *bb = Ver_stab_entry(ver)->Bb();
00597 PHI_NODE *phi = Ver_stab_entry(ver)->Phi();
00598 VER_ID opnd_vid;
00599 POINTS_TO *opnd_pt, pt2;
00600 POINTS_TO summary_pt;
00601
00602
00603 pt = CXX_NEW(POINTS_TO, &_ver_pool);
00604 pt->Init();
00605 pt->Set_expr_kind(EXPR_IS_BEING_PROCESSED);
00606 Ver_stab_entry(ver)->Set_points_to(pt);
00607
00608
00609 summary_pt.Init();
00610 summary_pt.Set_expr_kind(EXPR_IS_ANY);
00611 BB_NODE *pred;
00612 BB_LIST_ITER bb_iter;
00613 INT32 i = -1;
00614 FOR_ALL_ELEM(pred, bb_iter, Init(bb->Pred())) {
00615 i++;
00616 opnd_vid = phi->Opnd(i);
00617 opnd_pt = Ver_stab_entry(opnd_vid)->Points_to();
00618 if (opnd_pt == NULL) {
00619 pt2.Init();
00620 Simplify_Pointer_Ver(opnd_vid, &pt2);
00621 opnd_pt = &pt2;
00622 }
00623
00624
00625
00626
00627
00628
00629 if (opnd_pt->Expr_kind() == EXPR_IS_BEING_PROCESSED &&
00630 ! bb->Dominates(pred)) {
00631 opnd_pt->Set_expr_kind(EXPR_IS_UNKNOWN);
00632 opnd_pt->Set_base_kind(BASE_IS_UNKNOWN);
00633 opnd_pt->Set_ofst_kind(OFST_IS_UNKNOWN);
00634 opnd_pt->Reset_attr();
00635 }
00636
00637 summary_pt.Meet(opnd_pt, (ST *) phi);
00638
00639
00640
00641 if (summary_pt.Expr_kind() != EXPR_IS_ANY &&
00642 (summary_pt.Expr_kind() != EXPR_IS_ADDR ||
00643 (summary_pt.Expr_kind() == EXPR_IS_ADDR
00644 && summary_pt.Base_kind() == BASE_IS_UNKNOWN))) {
00645 summary_pt.Reset_attr();
00646 break;
00647 }
00648 }
00649 if (summary_pt.Expr_kind() == EXPR_IS_ANY ||
00650 summary_pt.Expr_kind() == EXPR_IS_BEING_PROCESSED) {
00651 Warn_todo("analyze why it is EXPR_IS_ANY / EXPR_IS_BEING_PROCESSED.");
00652 summary_pt.Set_expr_kind(EXPR_IS_UNKNOWN);
00653 summary_pt.Set_base_kind(BASE_IS_UNKNOWN);
00654 summary_pt.Set_ofst_kind(OFST_IS_UNKNOWN);
00655 summary_pt.Reset_attr();
00656 }
00657
00658 if (summary_pt.Expr_kind () == EXPR_IS_ADDR &&
00659 (summary_pt.Base_kind () == BASE_IS_UNKNOWN ||
00660 summary_pt.Ofst_kind () != OFST_IS_FIXED) &&
00661 WOPT_Enable_Pt_Keep_Track_Ptr) {
00662 if (Get_Trace(TP_GLOBOPT, ALIAS_DUMP_FLAG)) {
00663 fprintf (TFile, "phi result ver %d BB %d aux %d: ", ver, bb->Id(),
00664 Ver_stab_entry(ver)->Aux_id());
00665 summary_pt.Print(TFile);
00666 fprintf(TFile, "this result is not very useful, and is changed into: ");
00667 }
00668 PT_MEM_ANNOT mem_annot_saved = summary_pt.Mem_annot();
00669
00670 summary_pt.Init ();
00671 summary_pt.Set_expr_kind(EXPR_IS_ADDR);
00672 summary_pt.Set_base_kind(BASE_IS_DYNAMIC);
00673 summary_pt.Set_ofst_kind(OFST_IS_FIXED);
00674 summary_pt.Set_byte_ofst(0);
00675 summary_pt.Set_byte_size(0);
00676 summary_pt.Set_bit_ofst_size(0, 0);
00677 summary_pt.Set_base((ST *)phi);
00678 if (st) {
00679 if (ST_class(st) != CLASS_PREG){
00680 summary_pt.Set_pointer (st);
00681 } else {
00682 summary_pt.Set_pointer_as_aux_id (aux_id);
00683 }
00684 }
00685 summary_pt.Set_pointer_ver (ver);
00686 summary_pt.Set_iofst_kind (OFST_IS_FIXED);
00687 if (mem_annot_saved.Has_annotation ()) {
00688 PT_MEM_ANNOT& t = summary_pt.Mem_annot();
00689 t = mem_annot_saved ;
00690 }
00691 if (Get_Trace(TP_GLOBOPT, ALIAS_DUMP_FLAG)) {
00692 summary_pt.Print (TFile);
00693 }
00694 }
00695
00696
00697 pt->Copy_fully(summary_pt);
00698 ai->Copy_fully(summary_pt);
00699
00700 if ( Get_Trace(TP_GLOBOPT, ALIAS_DUMP_FLAG)) {
00701 BB_NODE *pred;
00702 BB_LIST_ITER bb_iter;
00703 INT32 i = -1;
00704 FOR_ALL_ELEM(pred, bb_iter, Init(bb->Pred())) {
00705 i++;
00706 fprintf(TFile, " phi opnd %d BB %d ver %d: ",
00707 i, pred->Id(), phi->Opnd(i));
00708 if (Ver_stab_entry(phi->Opnd(i))->Points_to())
00709 Ver_stab_entry(phi->Opnd(i))->Points_to()->Print(TFile);
00710 else
00711 fprintf(TFile, " no points to.\n");
00712 }
00713 fprintf(TFile, "phi result ver %d BB %d aux %d: ", ver, bb->Id(),
00714 Ver_stab_entry(ver)->Aux_id());
00715 ai->Print(TFile);
00716 }
00717 }
00718 break;
00719 case CHI_STMT:
00720
00721 if (Ver_stab_entry(ver)->Synonym()) {
00722 Simplify_Pointer_Ver( Ver_stab_entry(ver)->Synonym(), ai);
00723 } else {
00724 CHI_NODE *chi = Ver_stab_entry(ver)->Chi();
00725
00726 if (WOPT_Enable_Pt_Summary && st && ST_class(st) != CLASS_PREG) {
00727 WN* stmt = Ver_stab_entry(ver)->Chi_wn();
00728 if (WN_operator(stmt) == OPR_CALL) {
00729
00730 } else if (OPERATOR_is_scalar_istore (WN_operator(stmt))) {
00731
00732 POINTS_TO* ptr = Aux_stab_entry(aux_id)->Points_to();
00733 POINTS_TO* istore = Get_occ(stmt)->Points_to();
00734
00735 if (ptr && istore && !Rule()->Aliased_Memop (ptr, istore)) {
00736
00737 Simplify_Pointer_Ver(chi->Opnd(), ai);
00738 break;
00739 }
00740 }
00741 }
00742
00743 ai->Set_expr_kind(EXPR_IS_ADDR);
00744 ai->Set_base_kind(BASE_IS_DYNAMIC);
00745 ai->Set_ofst_kind(OFST_IS_FIXED);
00746 ai->Set_byte_ofst(0);
00747 ai->Set_byte_size(0);
00748 ai->Set_bit_ofst_size(0, 0);
00749 ai->Set_base( (ST *) chi );
00750 if (st) {
00751 if (ST_class(st) != CLASS_PREG){
00752 ai->Set_pointer (st);
00753 } else {
00754 ai->Set_pointer_as_aux_id (aux_id);
00755 if (Its_ret_val_of_malloc (ver)) {
00756 VER_STAB_ENTRY* verent = Ver_stab_entry(ver);
00757 ai->Set_malloc_id (WN_linenum(verent->Chi_wn()));
00758 }
00759 }
00760 ai->Set_pointer_ver (ver);
00761 ai->Set_iofst_kind (OFST_IS_FIXED);
00762
00763 pt = CXX_NEW(POINTS_TO, &_ver_pool);
00764 pt->Init();
00765 pt->Copy_fully(ai);
00766 Ver_stab_entry(ver)->Set_points_to(pt);
00767 }
00768 }
00769 break;
00770 default:
00771 Warn_todo("unknown ver type");
00772 }
00773
00774 if ( Get_Trace(TP_GLOBOPT, ALIAS_DUMP_FLAG)) {
00775 fprintf(TFile, "ver %d aux %d: ", ver, Ver_stab_entry(ver)->Aux_id());
00776 ai->Print(TFile);
00777 }
00778 CHECK_POINTS_TO(ai);
00779 }
00780
00781
00782
00783
00784 void OPT_STAB::Simplify_Pointer(WN *wn_addr, POINTS_TO *ai)
00785 {
00786 OPERATOR opr = WN_operator(wn_addr);
00787
00788 PT_MEMOP_ANNOT_STIKER t(ai);
00789
00790 switch (opr) {
00791
00792 case OPR_ARRAY:
00793 Simplify_Pointer(WN_kid0(wn_addr), ai);
00794 Analyze_Range(wn_addr, ai);
00795 ai->Invalidate_ptr_info ();
00796 break;
00797 case OPR_LDA:
00798 ai->Analyze_Lda_Base( wn_addr, *this);
00799 break;
00800 case OPR_LDBITS:
00801 case OPR_LDID:
00802 if (FSA()) {
00803 VER_ID ver = WN_ver(wn_addr);
00804 AUX_ID aux = Ver_stab_entry(ver)->Aux_id();
00805 ST *st = Aux_stab_entry(aux)->St();
00806 TY_IDX ty = ST_type(st);
00807
00808
00809
00810 if (TY_is_restrict(ty)) {
00811 ai->Analyze_ST_as_base(st, WN_offset(wn_addr), WN_ty(wn_addr));
00812 ai->Set_ofst_kind(OFST_IS_UNKNOWN);
00813 } else {
00814 Simplify_Pointer_Ver(ver, ai);
00815 }
00816 } else if (FFA()) {
00817 ai->Analyze_Ldid_Base(wn_addr, *this);
00818 }
00819 break;
00820 case OPR_ADD:
00821 case OPR_SUB:
00822 case OPR_NEG:
00823 Simplify_Pointer_Arith(wn_addr, ai);
00824 break;
00825 case OPR_CVT:
00826 case OPR_PAREN:
00827 Simplify_Pointer(WN_kid0(wn_addr), ai);
00828 break;
00829 case OPR_ILOAD:
00830 case OPR_ILDBITS:
00831 ai->Set_expr_kind(EXPR_IS_ADDR);
00832 ai->Set_base_kind(BASE_IS_DYNAMIC);
00833 ai->Set_ofst_kind(OFST_IS_FIXED);
00834 ai->Set_byte_ofst(0);
00835 ai->Set_byte_size(0);
00836 ai->Set_bit_ofst_size(0, 0);
00837 ai->Set_base( (ST *) wn_addr );
00838 break;
00839 #if defined(TARG_SL)
00840 case OPR_INTRINSIC_OP:
00841 if( INTRN_copy_addr(WN_intrinsic(wn_addr)) ) {
00842 Simplify_Pointer( WN_kid0(WN_kid0(wn_addr)), ai );
00843 } else {
00844 ai->Set_expr_kind(EXPR_IS_UNKNOWN);
00845 ai->Set_base_kind(BASE_IS_UNKNOWN);
00846 ai->Set_ofst_kind(OFST_IS_UNKNOWN);
00847 }
00848 break;
00849 #endif
00850 default:
00851 ai->Set_expr_kind(EXPR_IS_UNKNOWN);
00852 ai->Set_base_kind(BASE_IS_UNKNOWN);
00853 ai->Set_ofst_kind(OFST_IS_UNKNOWN);
00854 break;
00855 }
00856
00857
00858 CHECK_POINTS_TO(ai);
00859 }
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879 void
00880 OPT_STAB::Collect_f90_pointer_info(POINTS_TO *pt, const WN *wn)
00881 {
00882 Is_True(OPERATOR_is_scalar_iload (WN_operator(wn)) ||
00883 WN_operator(wn) == OPR_MLOAD ||
00884 OPERATOR_is_scalar_istore (WN_operator(wn)) ||
00885 WN_operator(wn) == OPR_MSTORE,
00886 ("OPT_STAB::Collect_f90_pointer_info: "
00887 "illegal opcode"));
00888
00889 TY_IDX addr_ty;
00890
00891 switch (WN_operator(wn)) {
00892 case OPR_ILOAD:
00893 case OPR_ILDBITS:
00894 addr_ty = WN_load_addr_ty(wn);
00895 break;
00896 default:
00897 addr_ty = WN_ty(wn);
00898 break;
00899 }
00900 if (TY_is_f90_pointer(Ty_Table[addr_ty])) {
00901 pt->Set_known_f90_pointer();
00902 }
00903 else {
00904 pt->Set_known_not_f90_pointer();
00905 }
00906 }
00907
00908
00909
00910
00911 void OPT_STAB::Analyze_Base_Flow_Free(POINTS_TO *pt, WN *wn)
00912 {
00913 pt->Set_expr_kind(EXPR_IS_ADDR);
00914 pt->Set_base_kind(BASE_IS_UNKNOWN);
00915 pt->Set_ofst_kind(OFST_IS_UNKNOWN);
00916 pt->Reset_attr();
00917 switch (WN_operator(wn)) {
00918 case OPR_ILDBITS:
00919 case OPR_ILOAD:
00920 case OPR_MLOAD:
00921 case OPR_ILOADX:
00922 Simplify_Pointer(WN_kid0(wn), pt);
00923 break;
00924 case OPR_ISTORE:
00925 case OPR_ISTBITS:
00926 case OPR_MSTORE:
00927 case OPR_ISTOREX:
00928 Simplify_Pointer(WN_kid1(wn), pt);
00929 break;
00930 }
00931 pt->Shift_ofst(WN_offset(wn));
00932 pt->Lower_to_base(wn);
00933 pt->Set_ty(WN_object_ty(wn));
00934 TY_IDX hl_ty = 0;
00935 UINT32 fld_id = 0;
00936 WN_hl_object_ty (wn, hl_ty, fld_id);
00937 pt->Set_hl_ty (hl_ty);
00938 pt->Set_field_id (fld_id);
00939 Collect_f90_pointer_info(pt, wn);
00940 Update_From_Restricted_Map(wn, pt);
00941 }
00942
00943
00944
00945
00946
00947 void OPT_STAB::Analyze_Base_Flow_Sensitive(POINTS_TO *pt, WN *wn)
00948 {
00949 POINTS_TO ai;
00950 ai.Init();
00951 ai.Set_expr_kind(EXPR_IS_ADDR);
00952 ai.Set_base_kind(BASE_IS_UNKNOWN);
00953 ai.Set_ofst_kind(OFST_IS_UNKNOWN);
00954
00955 switch (WN_operator(wn)) {
00956 case OPR_ILDBITS:
00957 case OPR_ILOAD:
00958 case OPR_MLOAD:
00959 Simplify_Pointer(WN_kid0(wn), &ai);
00960 if (ai.Expr_kind() == EXPR_IS_ADDR) {
00961 if (ai.Base_kind() != BASE_IS_UNKNOWN) {
00962 pt->Set_expr_kind(EXPR_IS_ADDR);
00963 pt->Set_base_kind(ai.Base_kind());
00964 pt->Set_ofst_kind(ai.Ofst_kind());
00965 pt->Set_base(ai.Base());
00966 pt->Set_byte_ofst(ai.Byte_Ofst());
00967 pt->Set_byte_size(ai.Byte_Size());
00968
00969 pt->Set_bit_ofst_size(ai.Bit_Ofst(), ai.Bit_Size());
00970 pt->Set_attr(ai.Attr());
00971 pt->Shift_ofst(WN_offset(wn));
00972 pt->Lower_to_base(wn);
00973 pt->Copy_pointer_info (&ai);
00974 } else if (ai.Restricted()) {
00975 pt->Set_expr_kind(EXPR_IS_ADDR);
00976 pt->Set_restricted();
00977 pt->Set_based_sym(ai.Based_sym());
00978 }
00979 if (ai.Malloc_id()) {
00980 pt->Set_malloc_id (ai.Malloc_id());
00981 }
00982 }
00983 break;
00984 #if defined(TARG_SL)
00985 case OPR_PARM:
00986 if( WN_Parm_Dereference(wn) ) {
00987 Simplify_Pointer( WN_kid0(wn), &ai );
00988 if ( ai.Expr_kind() == EXPR_IS_ADDR ) {
00989 if ( ai.Base_kind() != BASE_IS_UNKNOWN ) {
00990 pt->Set_expr_kind(EXPR_IS_ADDR);
00991 pt->Set_base_kind(ai.Base_kind());
00992 pt->Set_ofst_kind(ai.Ofst_kind());
00993 pt->Set_base(ai.Base());
00994 pt->Set_byte_ofst(ai.Byte_Ofst());
00995 pt->Set_byte_size(ai.Byte_Size());
00996 pt->Set_bit_ofst_size(ai.Bit_Ofst(), ai.Bit_Size());
00997 pt->Set_attr(ai.Attr());
00998 pt->Shift_ofst(0);
00999 pt->Lower_to_base(NULL);
01000 pt->Copy_pointer_info (&ai);
01001 } else if ( ai.Restricted() ) {
01002 pt->Set_expr_kind(EXPR_IS_ADDR);
01003 pt->Set_restricted();
01004 pt->Set_based_sym(ai.Based_sym());
01005 }
01006 if ( ai.Malloc_id() ) {
01007 pt->Set_malloc_id(ai.Malloc_id());
01008 }
01009 }
01010 break;
01011 }
01012 #endif
01013
01014 case OPR_ISTORE:
01015 case OPR_ISTBITS:
01016 case OPR_MSTORE:
01017 Simplify_Pointer(WN_kid1(wn), &ai);
01018 if (ai.Expr_kind() == EXPR_IS_ADDR) {
01019 if (ai.Base_kind() != BASE_IS_UNKNOWN) {
01020 pt->Set_expr_kind(EXPR_IS_ADDR);
01021 pt->Set_base_kind(ai.Base_kind());
01022 pt->Set_ofst_kind(ai.Ofst_kind());
01023 pt->Set_base(ai.Base());
01024 pt->Set_byte_ofst(ai.Byte_Ofst());
01025 pt->Set_byte_size(ai.Byte_Size());
01026 pt->Set_bit_ofst_size(ai.Bit_Ofst(), ai.Bit_Size());
01027 pt->Set_attr(ai.Attr());
01028 pt->Shift_ofst(WN_offset(wn));
01029 pt->Lower_to_base(wn);
01030 pt->Copy_pointer_info (&ai);
01031 } else if (ai.Restricted()) {
01032 pt->Set_expr_kind(EXPR_IS_ADDR);
01033 pt->Set_restricted();
01034 pt->Set_based_sym(ai.Based_sym());
01035 }
01036 if (ai.Malloc_id()) {
01037 pt->Set_malloc_id (ai.Malloc_id());
01038 }
01039 }
01040 break;
01041 case OPR_ILOADX:
01042 case OPR_ISTOREX:
01043 break;
01044 }
01045 CHECK_POINTS_TO(pt);
01046 }
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065 ST *
01066 OPT_STAB::Find_Based_Pointer(WN *wn, INT *depth)
01067 {
01068 OPERATOR opr = WN_operator(wn);
01069 switch (opr) {
01070
01071 case OPR_ARRAY:
01072 return Find_Based_Pointer(WN_kid0(wn), depth);
01073
01074 case OPR_LDA:
01075 return NULL;
01076
01077 case OPR_LDBITS:
01078 case OPR_LDID:
01079
01080 if (WN_offset(wn) == 0) {
01081 TY_IDX ty = WN_ty(wn);
01082 if (TY_kind(ty) == KIND_POINTER) {
01083 VER_ID ver_id = WN_ver(wn);
01084 AUX_ID aux_id = Ver_stab_entry(ver_id)->Aux_id();
01085 ST *st = St(aux_id);
01086 if (ST_sclass(st) != SCLASS_REG) {
01087 *depth = 0;
01088 return st;
01089 }
01090 }
01091 } else {
01092 VER_ID ver_id = WN_ver(wn);
01093 AUX_ID aux_id = Ver_stab_entry(ver_id)->Aux_id();
01094 ST *st = St(aux_id);
01095 if (ST_sclass(st) == SCLASS_REG &&
01096 FSA() &&
01097 WHIRL_STMT == Ver_stab_entry(ver_id)->Type()) {
01098 WN *def = Ver_stab_entry(ver_id)->Wn();
01099 if (def) {
01100 FmtAssert ( OPERATOR_is_scalar_store (WN_operator(def)),
01101 ("Find_Based_Pointer: def must be STID.") );
01102 return Find_Based_Pointer(WN_kid0(def),depth);
01103 }
01104 }
01105 }
01106 return NULL;
01107
01108 case OPR_ILOAD:
01109 case OPR_ILDBITS:
01110 if (Alias_Pointer_Disjoint) {
01111 ST *tmp_st = Find_Based_Pointer(WN_kid0(wn),depth);
01112 *depth = *depth + 1;
01113 return tmp_st;
01114 }
01115 return NULL;
01116
01117 case OPR_ADD:
01118 case OPR_SUB:
01119 ST *based_pointer0, *based_pointer1;
01120 INT depth0, depth1;
01121 based_pointer0 = Find_Based_Pointer(WN_kid0(wn), &depth0);
01122 based_pointer1 = Find_Based_Pointer(WN_kid1(wn), &depth1);
01123 if (based_pointer0 && !based_pointer1) {
01124 *depth = depth0;
01125 return based_pointer0;
01126 }
01127 if (based_pointer1 && !based_pointer0) {
01128 *depth = depth1;
01129 return based_pointer1;
01130 }
01131 return NULL;
01132
01133 default:
01134 return NULL;
01135 }
01136 }
01137
01138
01139
01140
01141
01142
01143
01144 void OPT_STAB::Analyze_Based_Pointer(POINTS_TO *pt, WN *addr_wn)
01145 {
01146 Is_True(FSA(), ("Analyze_Based_Pointer is FSA-specific"));
01147
01148 if (!Rule()->Rule_enabled(RAG_RESTRICTED_RULE) &&
01149 !Rule()->Rule_enabled(RAG_PARMS_RULE))
01150 return;
01151
01152
01153 if (
01154 pt->F_param() ||
01155 pt->Restricted() ||
01156 pt->Unique_pt())
01157 return;
01158
01159 INT depth = 0;
01160
01161 ST *st = Find_Based_Pointer(addr_wn, &depth);
01162 if (st != NULL && !ST_is_temp_var(st))
01163 if (Rule()->Rule_enabled(RAG_RESTRICTED_RULE) ||
01164 Rule()->Rule_enabled(IBM_DISJOINT_RULE) ||
01165 Rule()->Rule_enabled(RAG_UNNAMED_RULE) ||
01166 ST_is_value_parm(st)) {
01167 pt->Set_based_sym(st);
01168 pt->Set_based_sym_depth(depth);
01169 }
01170 }
01171
01172
01173
01174
01175
01176
01177 POINTS_TO_LIST*
01178 OPT_STAB::Create_barrier_defs( WN *wn )
01179 {
01180 INT32 is_dealloca = WN_operator(wn) == OPR_DEALLOCA;
01181 if (WN_kid_count(wn) == 0) return NULL;
01182 if (is_dealloca && WN_kid_count(wn) == 1) return NULL;
01183
01184 POINTS_TO_LIST *ptl = CXX_NEW(POINTS_TO_LIST,mem_pool);
01185
01186 for (INT i = is_dealloca; i < WN_kid_count(wn); i++) {
01187 POINTS_TO *points_to = CXX_NEW(POINTS_TO,mem_pool);
01188 points_to->Init();
01189 Simplify_Pointer(WN_kid(wn,i), points_to);
01190 points_to->Lower_to_base(NULL);
01191 ptl->Prepend( points_to, mem_pool );
01192 }
01193 return ptl;
01194 }
01195
01196
01197
01198
01199
01200 static void Add_to_mu_chi(OCC_TAB_ENTRY *occ, AUX_ID aux_id,
01201 MEM_POOL *mem_pool, BOOL no_dups,
01202 BOOL generate_mu, BOOL generate_chi)
01203 {
01204 if (no_dups) {
01205 if (generate_mu)
01206 occ->Stmt_mu_list()->New_mu_node_no_dups(aux_id, mem_pool);
01207 if (generate_chi)
01208 occ->Stmt_chi_list()->New_chi_node_no_dups(aux_id, mem_pool);
01209 } else {
01210 if (generate_mu)
01211 occ->Stmt_mu_list()->New_mu_node(aux_id, mem_pool);
01212 if (generate_chi)
01213 occ->Stmt_chi_list()->New_chi_node(aux_id, mem_pool);
01214 }
01215 }
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227
01228
01229
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285 BOOL
01286 OPT_STAB::Not_affected_by_barrier(AUX_ID aux, BB_NODE *bb)
01287 {
01288 AUX_STAB_ENTRY *psym = &aux_stab[aux];
01289
01290 if (IS_FORTRAN && Var_is_loop_index(aux, bb))
01291 return TRUE;
01292
01293
01294
01295
01296 if (IS_FORTRAN && psym->St() &&
01297 ST_sclass(psym->St()) == SCLASS_FORMAL)
01298 return TRUE;
01299
01300
01301 if (psym->Is_volatile() && !psym->Is_virtual() )
01302 return TRUE;
01303
01304 if (psym->Is_preg())
01305 return TRUE;
01306
01307 POINTS_TO *pt = psym->Points_to();
01308 if (pt->Const())
01309 return TRUE;
01310
01311 return FALSE;
01312 }
01313
01314
01315
01316
01317 void
01318 OPT_STAB::Compute_barrier_mu_chi( OCC_TAB_ENTRY *occ, POINTS_TO_LIST *defs,
01319 BB_NODE *bb, BOOL no_dups,
01320 BOOL generate_mu, BOOL generate_chi,
01321 BOOL is_mp_barrier)
01322 {
01323 AUX_STAB_ITER aux_stab_iter(this);
01324 AUX_ID auxid;
01325
01326
01327
01328
01329
01330
01331 if (WOPT_Enable_Strong_Barrier) {
01332
01333
01334
01335 FOR_ALL_NODE(auxid, aux_stab_iter, Init()) {
01336
01337 if (Not_affected_by_barrier(auxid, bb))
01338 continue;
01339
01340 Add_to_mu_chi(occ, auxid, mem_pool, no_dups, generate_mu, generate_chi);
01341 }
01342 } else if (defs != NULL) {
01343
01344
01345 FOR_ALL_NODE(auxid, aux_stab_iter, Init()) {
01346
01347 if (Not_affected_by_barrier(auxid, bb))
01348 continue;
01349
01350 AUX_STAB_ENTRY *psym = &aux_stab[auxid];
01351 POINTS_TO *aux_pt = psym->Points_to();
01352
01353 if (!is_mp_barrier) {
01354
01355 if (aux_pt->Named())
01356 continue;
01357 }
01358
01359
01360 POINTS_TO_ITER def_iter;
01361 POINTS_TO_NODE *defn;
01362 FOR_ALL_NODE( defn, def_iter, Init(defs)) {
01363 if ( Rule()->Aliased_Memop( aux_pt, defn->Pt() ) ) {
01364 Add_to_mu_chi(occ, auxid, mem_pool, no_dups, generate_mu, generate_chi);
01365 break;
01366 }
01367 }
01368 }
01369 } else {
01370 FOR_ALL_NODE(auxid, aux_stab_iter, Init()) {
01371
01372 if (Not_affected_by_barrier(auxid, bb))
01373 continue;
01374
01375 AUX_STAB_ENTRY *psym = &aux_stab[auxid];
01376 POINTS_TO *aux_pt = psym->Points_to();
01377
01378 if (!is_mp_barrier) {
01379
01380 if (aux_pt->Named())
01381 continue;
01382 } else {
01383 if (aux_pt->Local() &&
01384 (psym->St() && !ST_is_shared_auto(*psym->St())) &&
01385 (psym->St() && ST_sclass(psym->St()) != SCLASS_FORMAL_REF))
01386 continue;
01387 }
01388
01389 Add_to_mu_chi(occ, auxid, mem_pool, no_dups, generate_mu, generate_chi);
01390 }
01391 }
01392 }
01393
01394
01395
01396
01397
01398
01399
01400
01401 void OPT_STAB::Compute_black_box_mu_chi( const WN *wn, OCC_TAB_ENTRY *occ)
01402 {
01403 const OPCODE opc = WN_opcode(wn);
01404
01405 Is_True( OPCODE_is_black_box(opc),
01406 ("OPT_STAB::Compute_black_box_mu_chi: Bad opcode: %s",
01407 OPCODE_name(opc)) );
01408
01409
01410 POINTS_TO_LIST *refs = Black_box_refs( wn );
01411 POINTS_TO_LIST *defs = Black_box_defs( wn );
01412 POINTS_TO_ITER ref_iter;
01413 POINTS_TO_ITER def_iter;
01414 POINTS_TO_NODE *refn, *defn;
01415 AUX_STAB_ITER aux_stab_iter(this);
01416 AUX_ID auxid;
01417
01418 FOR_ALL_NODE(auxid, aux_stab_iter, Init()) {
01419
01420 AUX_STAB_ENTRY *psym = &aux_stab[auxid];
01421 if ((psym->Is_real_var() && !psym->Is_volatile()) ||
01422 psym->Is_virtual()) {
01423
01424 POINTS_TO *aux_pt = psym->Points_to();
01425
01426 if (aux_pt->Not_addr_saved()) {
01427
01428 if ( refs != NULL ) FOR_ALL_NODE( refn, ref_iter, Init(refs)) {
01429 if ( Rule()->Aliased_Memop( aux_pt, refn->Pt() ) ) {
01430 occ->Stmt_mu_list()->New_mu_node(auxid, mem_pool);
01431 break;
01432 }
01433 }
01434
01435 if ( defs != NULL ) FOR_ALL_NODE( defn, def_iter, Init(defs)) {
01436 if ( Rule()->Aliased_Memop( aux_pt, defn->Pt() ) ) {
01437 occ->Stmt_chi_list()->New_chi_node(auxid, mem_pool);
01438 break;
01439 }
01440 }
01441 } else {
01442
01443
01444
01445 occ->Stmt_mu_list()->New_mu_node(auxid, mem_pool);
01446 occ->Stmt_chi_list()->New_chi_node(auxid, mem_pool);
01447 }
01448 }
01449 }
01450 }
01451
01452
01453
01454
01455
01456
01457
01458
01459
01460
01461
01462
01463
01464
01465 WN *OPT_STAB::Create_entry_chi_stmt(BB_NODE *bb)
01466 {
01467 STMT_CONTAINER stmt_con( bb->Firststmt(), bb->Laststmt());
01468 Is_True(bb->Kind() == BB_ENTRY || bb->Kind() == BB_REGIONSTART,
01469 ("OPT_STAB::Create_entry_chi_stmt: not a ENTRY_BB"));
01470
01471 OPCODE opc = OPCODE_make_op(OPR_OPT_CHI, MTYPE_V, MTYPE_V );
01472 WN *wn = WN_Create(opc, 0);
01473 WN_Set_Linenum(wn, bb->Linenum());
01474 Enter_occ_tab(wn, 0);
01475 stmt_con.Prepend(wn);
01476
01477 bb->Set_firststmt(stmt_con.Head());
01478 bb->Set_laststmt(stmt_con.Tail());
01479 return wn;
01480 }
01481
01482
01483 void
01484 OPT_STAB::Create_entry_chi(void)
01485 {
01486 CFG_ITER cfg_iter;
01487 BB_NODE *bb;
01488
01489 FOR_ALL_ELEM (bb, cfg_iter, Init(Cfg())) {
01490 if ((bb->Kind() == BB_ENTRY && bb->Entrywn()) ||
01491 bb->Kind() == BB_REGIONSTART) {
01492
01493
01494
01495
01496
01497
01498
01499
01500 if (bb->Kind() == BB_REGIONSTART) {
01501 RID *rid = bb->Regioninfo()->Rid();
01502 if (rid != Cfg()->Rid())
01503 continue;
01504 }
01505
01506 WN *chi_stmt = Create_entry_chi_stmt(bb);
01507 CHI_LIST *chi = Get_stmt_chi_list(chi_stmt);
01508 AUX_STAB_ITER aux_stab_iter(this);
01509 AUX_ID auxid;
01510 FOR_ALL_NODE(auxid, aux_stab_iter, Init()) {
01511 AUX_STAB_ENTRY *sym = Aux_stab_entry(auxid);
01512 if ( !sym->Is_volatile() ) {
01513 CHI_NODE *cnode = chi->New_chi_node(auxid, Occ_pool());
01514 cnode->Set_opnd(auxid);
01515 cnode->Set_result(auxid);
01516 cnode->Set_live(TRUE);
01517 }
01518 }
01519 }
01520 }
01521 }
01522
01523
01524
01525
01526
01527
01528
01529
01530
01531
01532
01533
01534 void
01535 OPT_STAB::Compute_region_mu_chi(WN *wn, RID *rid, BOOL mu_and_chi, BB_NODE *bb)
01536 {
01537 OCC_TAB_ENTRY *occ = Get_occ(wn);
01538
01539 Is_True(occ != NULL, ("OPT_STAB::Compute_region_mu_chi, NULL occ"));
01540 Is_True(rid, ("OPT_STAB::Compute_region_mu_chi, NULL rid"));
01541 Is_True(!RID_TYPE_transparent(rid),
01542 ("OPT_STAB::Compute_region_mu_chi, transparent region, RGN %d",
01543 RID_id(rid)));
01544 if (mu_and_chi) {
01545 Is_True(REGION_consistency_check(wn), ("OPT_STAB::Compute_region_mu_chi"));
01546 Is_True(rid == REGION_get_rid(wn),
01547 ("OPT_STAB::Compute_region_mu_chi, wrong RID"));
01548 }
01549 if (RID_bounds_exist(rid) == REGION_BOUND_UNKNOWN)
01550 return;
01551
01552 Is_Trace(_rgn_trace, (TFile,
01553 "===== OPT_STAB::Compute_region_mu_chi, RGN %d %s\n",
01554 RID_id(rid), mu_and_chi ? "(mu and chi)":"(mu only)"));
01555 Is_Trace_cmd(_rgn_trace, RID_set_print(TFile, rid));
01556
01557
01558 POINTS_TO_SET *pt_tmp;
01559 for (pt_tmp=RID_used_in(rid); pt_tmp; pt_tmp=pt_tmp->Next)
01560 pt_tmp->Pt->Lower_to_base(NULL);
01561 for (pt_tmp=RID_def_in_live_out(rid); pt_tmp; pt_tmp=pt_tmp->Next)
01562 pt_tmp->Pt->Lower_to_base(NULL);
01563
01564
01565 AUX_STAB_ITER aux_stab_iter(this);
01566 AUX_ID aux_id;
01567 FOR_ALL_NODE(aux_id, aux_stab_iter, Init()) {
01568
01569 AUX_STAB_ENTRY *psym = &aux_stab[aux_id];
01570
01571
01572 if ((psym->Is_real_var() && !psym->Is_volatile()) || psym->Is_virtual()) {
01573
01574 BOOL aliased = FALSE;
01575
01576 POINTS_TO *pt = Points_to(aux_id);
01577 Is_True(pt == psym->Points_to(),
01578 ("Compute_region_mu_chi, POINTS_TO problem"));
01579 ST *st = aux_stab[aux_id].St();
01580
01581 if (st && ST_class(st) == CLASS_PREG) {
01582
01583 if (REGION_search_preg_set(RID_pregs_in(rid),
01584 aux_stab[aux_id].St_ofst())) {
01585 aliased = TRUE;
01586 } else {
01587 for (INT i=0; i<RID_num_exits(rid); i++) {
01588 if (REGION_search_preg_set(RID_pregs_out_i(rid, i),
01589 aux_stab[aux_id].St_ofst())) {
01590 aliased = TRUE;
01591 break;
01592 }
01593 }
01594 }
01595
01596 }
01597 else {
01598
01599 if (!(pt->Restricted() || pt->Unique_pt() || pt->F_param())) {
01600 aliased = (RID_aliased_to_indirects(rid) &&
01601 Rule()->Aliased_with_Indirect(pt)) ||
01602 (RID_aliased_to_globals(rid) &&
01603 Rule()->Aliased_with_Global(pt)) ||
01604 (RID_contains_uplevel(rid) && st &&
01605 Is_up_level_var(st));
01606 }
01607 if (!aliased) {
01608
01609 if (mu_and_chi &&
01610 REGION_search_set(RID_used_in(rid), comp_aliased(pt, Rule())))
01611 aliased = TRUE;
01612 if ((!aliased || !mu_and_chi) &&
01613 REGION_search_set(RID_def_in_live_out(rid),
01614 comp_aliased(pt, Rule())))
01615 aliased = TRUE;
01616 }
01617
01618 }
01619
01620
01621 if (aliased) {
01622 aux_stab[aux_id].Set_disable_local_rvi();
01623
01624 Is_True(occ->Stmt_mu_list()->Search_mu_node(aux_id) == NULL,
01625 ("Compute_region_mu_chi, duplicate mu node"));
01626 occ->Stmt_mu_list()->New_mu_node(aux_id, mem_pool);
01627
01628 if (mu_and_chi) {
01629 Is_True(occ->Stmt_chi_list()->Search_chi_node(aux_id) == NULL,
01630 ("Compute_region_mu_chi, duplicate chi node"));
01631 occ->Stmt_chi_list()->New_chi_node(aux_id, mem_pool);
01632 }
01633
01634 Is_Trace(_rgn_trace, (TFile,
01635 "===== Compute_region_mu_chi, RGN %d, adding "
01636 "aux_id %d to %s\n", RID_id(rid), aux_id,
01637 mu_and_chi ? "mu and chi" : "mu"));
01638 }
01639
01640 }
01641
01642 }
01643
01644
01645
01646 if (RID_contains_barrier(rid)) {
01647 Is_Trace(_rgn_trace, (TFile,
01648 "OPT_STAB::Compute_region_mu_chi, found a barrier"));
01649 Compute_barrier_mu_chi(occ, NULL, bb, TRUE, TRUE, mu_and_chi, TRUE);
01650 }
01651
01652
01653 if (mu_and_chi && RID_has_return(rid))
01654 Generate_exit_mu(wn);
01655
01656 if (_rgn_trace) {
01657 Print(TFile);
01658 fprintf(TFile,"===== OPT_STAB::Compute_region_mu_chi, RGN %d, "
01659 "mu result\n",RID_id(rid));
01660 occ->Stmt_mu_list()->Print(TFile);
01661 if (mu_and_chi) {
01662 fprintf(TFile,"===== OPT_STAB::Compute_region_mu_chi, RGN %d, "
01663 "chi result\n",RID_id(rid));
01664 occ->Stmt_chi_list()->Print(TFile);
01665 }
01666 }
01667 }
01668
01669
01670
01671
01672
01673
01674
01675
01676 void
01677 OPT_STAB::REGION_add_to_bound(RID *rid, AUX_ID aux_id, BOOL empty)
01678 {
01679
01680 if (aux_id == Return_vsym())
01681 return;
01682
01683 ST *st = Points_to(aux_id)->Base();
01684 if (st == NULL)
01685 return;
01686 Is_True(st != NULL,
01687 ("OPT_STAB::REGION_add_to_bound, NULL st"));
01688
01689 if (st && ST_class(st) == CLASS_PREG) {
01690
01691
01692 BOOL ret = REGION_add_preg_in(rid, Points_to(aux_id)->Byte_Ofst(),
01693 ST_btype(st));
01694 for (INT i=0; i<RID_num_exits(rid); i++)
01695 ret |= REGION_add_preg_out(rid, i, Points_to(aux_id)->Byte_Ofst(),
01696 ST_btype(st));
01697 Is_Trace(_rgn_trace && ret,(TFile,"===== OPT_STAB::REGION_add_to_bound "
01698 "(RGN %d), adding preg aux_id %d\n",RID_id(rid),aux_id));
01699 } else {
01700 if (empty) {
01701 REGION_add_aux_id_points_to(&RID_used_in(rid), aux_id);
01702 REGION_add_aux_id_points_to(&RID_def_in_live_out(rid), aux_id);
01703 Is_Trace(_rgn_trace,(TFile,
01704 "===== OPT_STAB::REGION_add_to_bound (RGN %d, empty=T), "
01705 "adding vir var aux_id %d\n",RID_id(rid),aux_id));
01706 } else {
01707 BOOL ret = REGION_merge_aux_id_points_to(&RID_used_in(rid), aux_id);
01708 ret |= REGION_merge_aux_id_points_to(&RID_def_in_live_out(rid), aux_id);
01709 Is_Trace(_rgn_trace && ret, (TFile,
01710 "===== OPT_STAB::REGION_add_to_bound (RGN %d, empty=F), "
01711 "adding vir var aux_id %d\n",RID_id(rid),aux_id));
01712 }
01713 }
01714 }
01715
01716
01717
01718
01719
01720
01721 BOOL
01722 OPT_STAB::REGION_verify_bound(RID *rid, AUX_ID aux_id)
01723 {
01724
01725 if (!RID_bounds_exist(rid))
01726 return TRUE;
01727
01728
01729 if (RID_aliased_to_indirects(rid) || RID_aliased_to_globals(rid))
01730 return TRUE;
01731
01732
01733 AUX_STAB_ENTRY *psym = Aux_stab_entry(aux_id);
01734 if (!psym->Is_real_var())
01735 return TRUE;
01736
01737 ST *st = Points_to(aux_id)->Base();
01738 if (st == NULL)
01739 return TRUE;
01740 Is_True(st != NULL, ("OPT_STAB::REGION_verify_bound, NULL st"));
01741
01742 if (st && ST_class(st) == CLASS_PREG) {
01743 #if 1
01744
01745 return TRUE;
01746 #else
01747 PREG_NUM pr = psym->St_ofst();
01748
01749
01750 if (pr < 72)
01751 return TRUE;
01752
01753 Is_True(REGION_search_preg_set(RID_pregs_in(rid), pr),
01754 ("OPT_STAB::REGION_verify_bound, PREG %d not in preg-in set, RGN %d",
01755 pr,RID_id(rid)));
01756 if (RID_pregs_out(rid)) {
01757 for (INT i=0; i<RID_num_exits(rid); i++)
01758 Is_True(REGION_search_preg_set(RID_pregs_out_i(rid, i), pr),
01759 ("OPT_STAB::REGION_verify_bound, PREG %d not in preg-in set, RGN %d",
01760 pr,RID_id(rid)));
01761 }
01762 #endif
01763 } else {
01764
01765
01766 if (Points_to(aux_id)->Const())
01767 return TRUE;
01768
01769
01770 if (Points_to(aux_id)->Global() && RID_aliased_to_globals(rid))
01771 return TRUE;
01772
01773
01774 Is_True(REGION_search_set(RID_used_in(rid),
01775 comp_same_pt(Points_to(aux_id), Rule())),
01776 ("OPT_STAB::REGION_verify_bound, AUX_ID %d not in live-in set, RGN %d",
01777 aux_id, RID_id(rid)));
01778 Is_True(REGION_search_set(RID_def_in_live_out(rid),
01779 comp_same_pt(Points_to(aux_id), Rule())),
01780 ("OPT_STAB::REGION_verify_bound, AUX_ID %d not in live-out set, RGN %d",
01781 aux_id, RID_id(rid)));
01782 }
01783 return TRUE;
01784 }
01785
01786
01787
01788 void
01789 OPT_STAB::REGION_add_aux_id_points_to(POINTS_TO_SET **pset, AUX_ID aux_id)
01790 {
01791 POINTS_TO_SET *ptr = TYPE_OPT_POOL_ALLOC(POINTS_TO_SET,®ION_mem_pool,-1);
01792 ptr->Pt = Points_to_copy(Points_to(aux_id), ®ION_mem_pool);
01793 ptr->Next = *pset;
01794 *pset = ptr;
01795 }
01796
01797
01798
01799
01800 BOOL
01801 OPT_STAB::REGION_merge_aux_id_points_to(POINTS_TO_SET **pset, AUX_ID aux_id)
01802 {
01803
01804 if (REGION_search_set(*pset, comp_same_pt(Points_to(aux_id), Rule())))
01805 return FALSE;
01806
01807
01808 REGION_add_aux_id_points_to(pset, aux_id);
01809 return TRUE;
01810 }
01811
01812
01813
01814
01815
01816
01817
01818 void
01819 OPT_STAB::Update_aux_id_list(AUX_ID vp_idx)
01820 {
01821
01822
01823 const BS *alias_set = Rule()->Alias_Set_Indirect(this);
01824 AUX_ID_LIST *alist = CXX_NEW(AUX_ID_LIST, mem_pool);
01825 alist->Clear();
01826 aux_stab[vp_idx].Set_aux_id_list(alist);
01827 for (AUX_ID idx = BS_Choose( alias_set );
01828 idx != (AUX_ID) BS_CHOOSE_FAILURE;
01829 idx = BS_Choose_Next ( alias_set, idx )) {
01830
01831 if ( ! Is_real_var(idx) ) continue;
01832
01833 if (Rule()->Aliased_Memop(aux_stab[vp_idx].Points_to(),
01834 aux_stab[idx].Points_to()))
01835 alist->New_aux_id_node(idx, mem_pool);
01836 }
01837 }
01838
01839 #ifdef KEY
01840 extern BOOL ST_Has_Dope_Vector(ST *);
01841
01842
01843
01844
01845
01846
01847
01848
01849
01850
01851
01852 AUX_ID
01853 OPT_STAB::Allocate_vsym(WN * memop_wn, POINTS_TO *memop_pt)
01854 {
01855 AUX_ID vp_idx = 0;
01856 POINTS_TO scratch_pt;
01857 scratch_pt.Init();
01858 if (Update_From_Restricted_Map(memop_wn, &scratch_pt)) {
01859
01860
01861 Is_True(scratch_pt.Based_sym() != NULL,
01862 ("Based symbol must be set for restricted map entry"));
01863
01864
01865 if (scratch_pt.Unique_pt() ||
01866 scratch_pt.Restricted()) {
01867 AUX_ID var = Find_vsym_with_base(scratch_pt.Based_sym());
01868 if (var == 0) {
01869 var = Create_vsym(EXPR_IS_ANY);
01870 AUX_STAB_ENTRY *vsym = Aux_stab_entry(var);
01871 vsym->Points_to()->Copy_fully(scratch_pt);
01872 vsym->Set_stype(VT_UNIQUE_VSYM);
01873 }
01874 else {
01875 Is_True(Aux_stab_entry(var)->Stype() == VT_UNIQUE_VSYM ||
01876 Aux_stab_entry(var)->Stype() == VT_SPECIAL_VSYM,
01877 ("vsym based on unique/restrict pointer must be unique "
01878 "or special"));
01879 }
01880 if (Get_Trace(TP_GLOBOPT, ALIAS_DUMP_FLAG)) {
01881 fprintf(TFile, "Allocate_vsym: Returning aux_id %u as unique "
01882 "based on\n", var);
01883 Print_ST(TFile, Aux_stab_entry(var)->Points_to()->Based_sym(), TRUE);
01884 }
01885 vp_idx = var;
01886 }
01887 }
01888
01889 if (vp_idx == 0)
01890 {
01891 OPERATOR opr = WN_operator(memop_wn);
01892 WN *addr_wn = ((OPERATOR_is_scalar_istore (opr) ||
01893 opr == OPR_MSTORE) ? WN_kid1(memop_wn) : WN_kid0(memop_wn));
01894 INT64 offset = (opr == OPR_PARM || opr == OPR_ASM_INPUT ? (INT64) 0
01895 : WN_offset(memop_wn));
01896
01897
01898 BOOL direct_use = ((addr_wn != NULL) &&
01899 (WN_operator(addr_wn) == OPR_LDID) &&
01900 (offset == 0));
01901
01902 addr_wn = Find_addr_recur(addr_wn, *this);
01903
01904 if (addr_wn != NULL) {
01905 switch (WN_operator(addr_wn)) {
01906 case OPR_LDA:
01907 AUX_ID var;
01908 var = WN_aux(addr_wn);
01909 Is_True(var != 0, ("lda not entered into aux_stab."));
01910 vp_idx = var;
01911 break;
01912 case OPR_LDID:
01913 {
01914 ST *st = aux_stab[WN_aux(addr_wn)].St();
01915 AUX_ID vsym_id;
01916
01917 if (ST_sclass(st) == SCLASS_FORMAL&&
01918 IS_FORTRAN &&
01919 Alias_Pointer_Parms &&
01920 ! ST_is_value_parm(st)) {
01921 vsym_id = Find_vsym_with_base(st);
01922 if (vsym_id == 0) {
01923 vsym_id = Create_vsym(EXPR_IS_ANY);
01924 AUX_STAB_ENTRY *vsym = Aux_stab_entry(vsym_id);
01925 vsym->Points_to()->Set_based_sym(st);
01926 if (direct_use) {
01927 vsym->Set_stype(VT_UNIQUE_VSYM);
01928 }
01929 }
01930 else {
01931 if (! direct_use) {
01932 AUX_STAB_ENTRY *vsym = Aux_stab_entry(vsym_id);
01933 vsym->Set_stype(VT_SPECIAL_VSYM);
01934 }
01935 }
01936 vp_idx = vsym_id;
01937 break;
01938 }
01939 if (WOPT_Enable_Unique_Pt_Vsym &&
01940 ST_class(st) == CLASS_VAR &&
01941 (ST_pt_to_unique_mem(st) ||
01942 TY_is_restrict(ST_type(st)))) {
01943 vsym_id = Find_vsym_with_base(st);
01944 if (vsym_id == 0) {
01945 vsym_id = Create_vsym(EXPR_IS_ANY);
01946 AUX_STAB_ENTRY *vsym = Aux_stab_entry(vsym_id);
01947 if (ST_pt_to_unique_mem(st)) {
01948 vsym->Points_to()->Set_unique_pt();
01949 }
01950 if (TY_is_restrict(ST_type(st))) {
01951 vsym->Points_to()->Set_restricted();
01952 }
01953 vsym->Points_to()->Set_based_sym(st);
01954 if (direct_use) {
01955 vsym->Set_stype(VT_UNIQUE_VSYM);
01956 }
01957 }
01958 else {
01959 if (! direct_use) {
01960 AUX_STAB_ENTRY *vsym = Aux_stab_entry(vsym_id);
01961 vsym->Set_stype(VT_SPECIAL_VSYM);
01962 }
01963 }
01964 vp_idx = vsym_id;
01965 break;
01966 }
01967
01968 if (WOPT_Enable_Vsym_Unique && !ST_Has_Dope_Vector(st)) {
01969 vsym_id = Find_vsym_with_st(st, !direct_use, memop_pt);
01970 if (vsym_id == 0) {
01971 vsym_id = Create_vsym(EXPR_IS_ANY);
01972 AUX_STAB_ENTRY *vsym = Aux_stab_entry(vsym_id);
01973 vsym->Points_to()->Set_based_sym(NULL);
01974 vsym->Set_st(st);
01975 if (direct_use) {
01976 vsym->Set_stype(VT_UNIQUE_VSYM);
01977 }
01978 else {
01979 Is_True (vsym->Special_vsym(),
01980 ("Allocate_vsym: Expected VT_SPECIAL_VSYM"));
01981 vsym->Set_indirect_access();
01982 }
01983 }
01984 else {
01985
01986 AUX_STAB_ENTRY *vsym = Aux_stab_entry(vsym_id);
01987
01988 FmtAssert (direct_use == !vsym->Indirect_access(),
01989 ("Allocate_vsym: incompatible access flag in vsym"));
01990 if (!direct_use)
01991
01992 FmtAssert (vsym->Special_vsym(),
01993 ("Allocate_vsym: Expected VT_SPECIAL_VSYM"));
01994
01995
01996 }
01997 vp_idx = vsym_id;
01998 break;
01999 }
02000 }
02001 default:
02002 addr_wn = NULL;
02003 }
02004 }
02005
02006 if (vp_idx == 0) {
02007
02008 if (Default_vsym() == 0) {
02009
02010 Set_default_vsym(Create_vsym(EXPR_IS_ANY));
02011
02012 Aux_stab_entry(Default_vsym())->Points_to()->Set_default_vsym();
02013 }
02014
02015 vp_idx = Default_vsym();
02016 }
02017 }
02018
02019 Is_True (vp_idx, ("OPT_STAB::Allocate_vsym: Unallocated vsym"));
02020 POINTS_TO *pt = aux_stab[vp_idx].Points_to();
02021 BOOL use_default_vsym = FALSE;
02022
02023
02024
02025
02026
02027 if ((WOPT_Enable_Unique_Pt_Vsym &&
02028 memop_pt->Unique_pt()) ||
02029 memop_pt->Restricted()) {
02030 Is_True(vp_idx != Default_vsym(),
02031 ("Adjust_vsym: Default vsym must not be vsym for "
02032 "Unique_pt() or Restricted()"));
02033 Is_True(pt->Based_sym() == memop_pt->Based_sym(),
02034 ("Adjust_vsym: unique vsym should have been set up by "
02035 "Indentify_vsym"));
02036 if (pt->Based_sym() == memop_pt->Based_sym()) {
02037 return vp_idx;
02038 }
02039 else {
02040 #if 0
02041 vp_idx = Find_vsym_with_base(occ->Based_sym());
02042 if (vp_idx == NULL) {
02043 vp_idx = Create_vsym(EXPR_IS_ANY);
02044 AUX_STAB_ENTRY *vsym = Aux_stab_entry(vp_idx);
02045 vsym->Points_to()->Set_based_sym(occ->Based_sym());
02046
02047 }
02048 #else
02049
02050
02051
02052 pt->Set_based_sym(memop_pt->Based_sym());
02053 #endif
02054 return vp_idx;
02055 }
02056 }
02057
02058 if (vp_idx != Default_vsym()) {
02059 if (pt->Expr_kind() != EXPR_IS_ANY &&
02060 pt->Base_kind() != memop_pt->Base_kind() &&
02061 (pt->Based_sym() == NULL ||
02062 pt->Based_sym() != memop_pt->Based_sym()))
02063 use_default_vsym = TRUE;
02064 else if (aux_stab[vp_idx].Is_real_var()) {
02065
02066 POINTS_TO tmp_pt;
02067 tmp_pt.Init();
02068 tmp_pt.Copy_fully(pt);
02069 tmp_pt.Meet(memop_pt, NULL);
02070 if (tmp_pt.Expr_kind() != EXPR_IS_ADDR ||
02071 tmp_pt.Base_kind() != BASE_IS_FIXED ||
02072 tmp_pt.Ofst_kind() != OFST_IS_FIXED ||
02073 tmp_pt.Base() != pt->Base() ||
02074 tmp_pt.Byte_Ofst() != pt->Byte_Ofst() ||
02075 tmp_pt.Byte_Size() != pt->Byte_Size() ||
02076 tmp_pt.Bit_Ofst() != pt->Bit_Ofst() ||
02077 tmp_pt.Bit_Size() != pt->Bit_Size())
02078 use_default_vsym = TRUE;
02079 }
02080 if (use_default_vsym) {
02081 if (Default_vsym() == 0) {
02082 Set_default_vsym(Create_vsym(EXPR_IS_ANY));
02083
02084 Aux_stab_entry(Default_vsym())->Points_to()->Set_default_vsym();
02085 }
02086 vp_idx = Default_vsym();
02087
02088
02089 pt = aux_stab[vp_idx].Points_to();
02090 }
02091 }
02092
02093
02094 pt->Meet(memop_pt, NULL);
02095
02096
02097 if (vp_idx == Default_vsym())
02098 pt->Set_default_vsym();
02099
02100 Is_True(WOPT_Enable_Vsym_Unique || vp_idx == Default_vsym() ||
02101 pt->Base_is_fixed() || pt->Based_sym() ||
02102 aux_stab[vp_idx].Unique_vsym(),
02103 ("OPT_STAB::Adjust_vsym: base is disrupted."));
02104
02105 return vp_idx;
02106 }
02107 #endif
02108
02109
02110
02111
02112
02113
02114
02115
02116
02117
02118
02119
02120
02121
02122
02123
02124 AUX_ID
02125 OPT_STAB::Adjust_vsym(AUX_ID vp_idx, OCC_TAB_ENTRY *occ)
02126 {
02127 POINTS_TO *pt = aux_stab[vp_idx].Points_to();
02128 BOOL use_default_vsym = FALSE;
02129
02130
02131
02132
02133
02134 if ((WOPT_Enable_Unique_Pt_Vsym &&
02135 occ->Points_to()->Unique_pt()) ||
02136 occ->Points_to()->Restricted()) {
02137 Is_True(vp_idx != Default_vsym(),
02138 ("Adjust_vsym: Default vsym must not be vsym for "
02139 "Unique_pt() or Restricted()"));
02140 Is_True(pt->Based_sym() == occ->Points_to()->Based_sym(),
02141 ("Adjust_vsym: unique vsym should have been set up by "
02142 "Indentify_vsym"));
02143 if (pt->Based_sym() == occ->Points_to()->Based_sym()) {
02144 return vp_idx;
02145 }
02146 else {
02147 #if 0
02148 vp_idx = Find_vsym_with_base(occ->Based_sym());
02149 if (vp_idx == NULL) {
02150 vp_idx = Create_vsym(EXPR_IS_ANY);
02151 AUX_STAB_ENTRY *vsym = Aux_stab_entry(vp_idx);
02152 vsym->Points_to()->Set_based_sym(occ->Based_sym());
02153
02154 }
02155 #else
02156
02157
02158
02159 pt->Set_based_sym(occ->Points_to()->Based_sym());
02160 #endif
02161 return vp_idx;
02162 }
02163 }
02164
02165 if (vp_idx != Default_vsym()) {
02166 if (pt->Expr_kind() != EXPR_IS_ANY &&
02167 pt->Base_kind() != occ->Points_to()->Base_kind() &&
02168 (pt->Based_sym() == NULL ||
02169 pt->Based_sym() != occ->Points_to()->Based_sym()))
02170 use_default_vsym = TRUE;
02171 else if (aux_stab[vp_idx].Is_real_var()) {
02172
02173 POINTS_TO tmp_pt;
02174 tmp_pt.Init();
02175 tmp_pt.Copy_fully(pt);
02176 tmp_pt.Meet(occ->Points_to(), NULL);
02177 if (tmp_pt.Expr_kind() != EXPR_IS_ADDR ||
02178 tmp_pt.Base_kind() != BASE_IS_FIXED ||
02179 tmp_pt.Ofst_kind() != OFST_IS_FIXED ||
02180 tmp_pt.Base() != pt->Base() ||
02181 tmp_pt.Byte_Ofst() != pt->Byte_Ofst() ||
02182 tmp_pt.Byte_Size() != pt->Byte_Size() ||
02183 tmp_pt.Bit_Ofst() != pt->Bit_Ofst() ||
02184 tmp_pt.Bit_Size() != pt->Bit_Size())
02185 use_default_vsym = TRUE;
02186 }
02187 if (use_default_vsym) {
02188 if (Default_vsym() == 0) {
02189 Set_default_vsym(Create_vsym(EXPR_IS_ANY));
02190
02191 Aux_stab_entry(Default_vsym())->Points_to()->Set_default_vsym();
02192 }
02193 vp_idx = Default_vsym();
02194 occ->Set_aux_id(vp_idx);
02195 pt = aux_stab[vp_idx].Points_to();
02196 }
02197 }
02198
02199
02200 pt->Meet(occ->Points_to(), NULL);
02201
02202
02203 if (vp_idx == Default_vsym())
02204 pt->Set_default_vsym();
02205
02206 #ifdef KEY
02207 Is_True(WOPT_Enable_Vsym_Unique || vp_idx == Default_vsym() ||
02208 pt->Base_is_fixed() || pt->Based_sym() ||
02209 (pt->Expr_kind() == EXPR_IS_ADDR && pt->Ofst_kind() == OFST_IS_UNKNOWN) ||
02210 aux_stab[vp_idx].Unique_vsym(),
02211 ("OPT_STAB::Adjust_vsym: base is disrupted."));
02212
02213 #else
02214 Is_True(vp_idx == Default_vsym() || pt->Base_is_fixed() ||
02215 pt->Based_sym() || aux_stab[vp_idx].Unique_vsym(),
02216 ("OPT_STAB::Adjust_vsym: base is disrupted."));
02217 #endif
02218
02219 return vp_idx;
02220 }
02221
02222
02223
02224
02225 void OPT_STAB::Allocate_mu_chi_and_virtual_var(WN *wn, BB_NODE *bb)
02226 {
02227 if (wn == NULL)
02228 return;
02229
02230 const OPCODE opc = WN_opcode(wn);
02231 const OPERATOR opr = OPCODE_operator(opc);
02232 Is_True(!OPCODE_is_scf(opc) || opc == OPC_REGION,
02233 ("OPT_STAB::Allocate_mu_chi_and_virtual_var: Wn is SCF %s",
02234 OPCODE_name(opc)));
02235 Is_True(opc != OPC_BLOCK, ("Wn is a OPR_BLOCK."));
02236
02237 AUX_ID vp_idx;
02238 OCC_TAB_ENTRY *occ;
02239
02240 switch ( opr ) {
02241 case OPR_LDBITS:
02242 case OPR_LDID:
02243 break;
02244
02245 case OPR_STID:
02246 case OPR_STBITS:
02247 if (!aux_stab[WN_aux(wn)].Points_to()->No_alias()) {
02248 occ = Enter_occ_tab(wn, WN_aux(wn));
02249
02250 occ->Points_to()->Copy_fully(aux_stab[WN_aux(wn)].Points_to());
02251 }
02252 break;
02253
02254
02255
02256
02257
02258
02259
02260
02261 case OPR_ILOAD:
02262 case OPR_ILDBITS:
02263 case OPR_MLOAD:
02264 case OPR_ILOADX:
02265 #ifdef KEY
02266 if (WOPT_Enable_New_Vsym_Allocation) {
02267 POINTS_TO pt;
02268 pt.Init();
02269 pt.Set_base_kind(BASE_IS_UNKNOWN);
02270 pt.Set_ofst_kind(OFST_IS_INVALID);
02271 Analyze_Base_Flow_Free(&pt, wn);
02272
02273 IDTYPE alias_class = Alias_classification()->Alias_class(wn);
02274 pt.Set_alias_class(alias_class);
02275
02276 IDTYPE ip_alias_class = WN_MAP32_Get(WN_MAP_ALIAS_CLASS, wn);
02277 pt.Set_ip_alias_class(ip_alias_class);
02278 vp_idx = Allocate_vsym(wn, &pt);
02279 occ = Enter_occ_tab(wn , vp_idx, &pt);
02280 } else
02281 #endif
02282 {
02283 vp_idx = Identify_vsym(wn);
02284 occ = Enter_occ_tab(wn, vp_idx);
02285 Analyze_Base_Flow_Free(occ->Points_to(), wn);
02286 vp_idx = Adjust_vsym(vp_idx, occ);
02287 if (occ->Points_to()->Pointer () != NULL) {
02288
02289
02290 if (WN_desc (wn) != MTYPE_BS) {
02291 occ->Points_to()->Set_byte_size (WN_object_size(wn));
02292 } else {
02293 occ->Points_to()->Invalidate_ptr_info ();
02294 }
02295 }
02296 }
02297 break;
02298
02299 case OPR_ISTORE:
02300 case OPR_ISTBITS:
02301 case OPR_MSTORE:
02302 case OPR_ISTOREX:
02303 #ifdef KEY
02304 if (WOPT_Enable_New_Vsym_Allocation) {
02305 POINTS_TO pt;
02306 pt.Init();
02307 pt.Set_base_kind(BASE_IS_UNKNOWN);
02308 pt.Set_ofst_kind(OFST_IS_INVALID);
02309 Analyze_Base_Flow_Free(&pt, wn);
02310
02311 IDTYPE alias_class = Alias_classification()->Alias_class(wn);
02312 pt.Set_alias_class(alias_class);
02313
02314 IDTYPE ip_alias_class = WN_MAP32_Get(WN_MAP_ALIAS_CLASS, wn);
02315 pt.Set_ip_alias_class(ip_alias_class);
02316 vp_idx = Allocate_vsym(wn, &pt);
02317 occ = Enter_occ_tab(wn , vp_idx, &pt);
02318 } else
02319 #endif
02320 {
02321 vp_idx = Identify_vsym(wn);
02322 occ = Enter_occ_tab(wn, vp_idx);
02323 Analyze_Base_Flow_Free(occ->Points_to(), wn);
02324 vp_idx = Adjust_vsym(vp_idx, occ);
02325 if (occ->Points_to()->Pointer () != NULL) {
02326
02327
02328 if (WN_desc (wn) != MTYPE_BS) {
02329 occ->Points_to()->Set_byte_size (WN_object_size(wn));
02330 } else {
02331 occ->Points_to()->Invalidate_ptr_info ();
02332 }
02333 }
02334 }
02335 break;
02336
02337 case OPR_ICALL:
02338 case OPR_CALL:
02339 case OPR_INTRINSIC_CALL:
02340 Enter_occ_tab(wn, 0);
02341 break;
02342
02343 case OPR_INTRINSIC_OP:
02344 #ifdef KEY
02345 case OPR_PURE_CALL_OP:
02346 #endif
02347
02348 break;
02349
02350 case OPR_PARM:
02351 #if defined(TARG_SL)
02352 if ( WN_Parm_By_Reference(wn) || WN_Parm_Dereference(wn) ) {
02353 #else
02354 if ( WN_Parm_By_Reference(wn) ) {
02355 #endif
02356 #ifdef KEY
02357 if (WOPT_Enable_New_Vsym_Allocation) {
02358 POINTS_TO pt;
02359 pt.Init();
02360 pt.Set_base_kind(BASE_IS_UNKNOWN);
02361 pt.Set_ofst_kind(OFST_IS_INVALID);
02362
02363 #if 0 // This is "HACK" from Enter_occ_tab, so we disable it until
02364
02365 if (WN_operator(wn) == OPR_PARM && aux_id == _default_vsym)
02366 occ->Points_to()->Set_expr_kind(EXPR_IS_ANY);
02367 #endif
02368 pt.Analyze_Parameter_Base(WN_kid0(wn), *this);
02369 Update_From_Restricted_Map(wn, &pt);
02370 Is_True(pt.Alias_class() == OPTIMISTIC_AC_ID ||
02371 pt.Alias_class() == Alias_classification()->Alias_class(wn) ||
02372 (pt.Alias_class() == PESSIMISTIC_AC_ID &&
02373 WOPT_Alias_Class_Limit != UINT32_MAX),
02374 ("Allocate_mu_chi_and_virtual_var: Alias class %ld for PARM "
02375 "not consistent (%ld).",
02376 pt.Alias_class(),
02377 Alias_classification()->Alias_class(wn)));
02378 pt.Set_alias_class(Alias_classification()->Alias_class(wn));
02379 vp_idx = Allocate_vsym(wn, &pt);
02380 occ = Enter_occ_tab(wn , vp_idx, &pt);
02381 } else
02382 #endif
02383 {
02384 vp_idx = Identify_vsym(wn);
02385 occ = Enter_occ_tab(wn, vp_idx);
02386 Is_True(WN_kid0(wn) != NULL, ("bad OPR_PARM node."));
02387 occ->Points_to()->Analyze_Parameter_Base(WN_kid0(wn), *this);
02388 Update_From_Restricted_Map(wn, occ->Points_to());
02389
02390
02391 Is_True(occ->Points_to()->Alias_class() == OPTIMISTIC_AC_ID ||
02392 occ->Points_to()->Alias_class() == Alias_classification()->Alias_class(wn) ||
02393 (occ->Points_to()->Alias_class() == PESSIMISTIC_AC_ID &&
02394 WOPT_Alias_Class_Limit != UINT32_MAX),
02395 ("Allocate_mu_chi_and_virtual_var: Alias class %ld for PARM "
02396 "not consistent (%ld).",
02397 occ->Points_to()->Alias_class(),
02398 Alias_classification()->Alias_class(wn)));
02399 occ->Points_to()->Set_alias_class(Alias_classification()->Alias_class(wn));
02400 vp_idx = Adjust_vsym(vp_idx, occ);
02401 }
02402 } else {
02403 Is_True( WN_Parm_By_Value(wn),
02404 ("OPT_STAB::Allocate_mu_chi_and_virtual_var: not by value") );
02405 }
02406 break;
02407
02408 case OPR_IO:
02409 case OPR_FORWARD_BARRIER:
02410 case OPR_BACKWARD_BARRIER:
02411 case OPR_DEALLOCA:
02412 case OPR_PREFETCH:
02413 case OPR_RETURN:
02414 case OPR_RETURN_VAL:
02415 #ifdef KEY
02416 case OPR_GOTO_OUTER_BLOCK:
02417 #endif
02418 Enter_occ_tab(wn, 0);
02419 break;
02420
02421 case OPR_REGION:
02422 RID *rid;
02423 rid = REGION_get_rid(wn);
02424 if (RID_level(rid) >= Rgn_level()) {
02425 Enter_occ_tab(wn, 0);
02426 return;
02427 }
02428 break;
02429
02430 case OPR_REGION_EXIT:
02431 Enter_occ_tab(wn,0);
02432 break;
02433
02434 case OPR_ASM_STMT:
02435 Enter_occ_tab(wn,0);
02436 break;
02437
02438 default:
02439 break;
02440 }
02441
02442
02443 if ( opc == OPC_COMPGOTO ) {
02444
02445 Allocate_mu_chi_and_virtual_var(WN_kid(wn,0),bb);
02446 }
02447 else if (!OPCODE_is_black_box(opc)) {
02448 INT32 i = (opr == OPR_ASM_STMT ? 2 : 0);
02449 for (; i < WN_kid_count(wn); i++)
02450 Allocate_mu_chi_and_virtual_var(WN_kid(wn,i),bb);
02451 }
02452 }
02453
02454
02455
02456
02457
02458
02459
02460
02461
02462
02463
02464
02465
02466
02467
02468
02469
02470
02471
02472
02473
02474
02475
02476
02477
02478
02479
02480
02481
02482
02483 BOOL OPT_STAB::Var_is_loop_index(AUX_ID idx, BB_NODE *bb)
02484 {
02485
02486 if (!IS_FORTRAN)
02487 return FALSE;
02488
02489
02490 if (!aux_stab[idx].Loop_index())
02491 return FALSE;
02492
02493 BB_LOOP *loop = bb->Innermost();
02494
02495 while (loop != NULL) {
02496 if (loop->Index() != NULL && St(idx) == WN_sym(loop->Index()))
02497 return TRUE;
02498 loop = loop->Parent();
02499 }
02500 return FALSE;
02501 }
02502
02503
02504
02505 void
02506 OPT_STAB::Generate_call_mu_chi_by_ref(WN *wn, ST *call_st,
02507 MU_LIST *mu, CHI_LIST *chi,
02508 INT32 num_parms, BB_NODE *bb)
02509 {
02510 AUX_ID idx;
02511 const BS *alias_set;
02512
02513 alias_set = Rule()->Alias_Set_Call_By_Ref(this);
02514 for (idx = BS_Choose( alias_set );
02515 idx != (AUX_ID) BS_CHOOSE_FAILURE;
02516 idx = BS_Choose_Next ( alias_set, idx )) {
02517
02518
02519 if (Aux_stab_entry(idx)->Is_volatile() &&
02520 !Aux_stab_entry(idx)->Is_virtual() )
02521 continue;
02522
02523 READ_WRITE how = Rule()->Aliased_with_Call(call_st,
02524 WN_call_flag(wn),
02525 aux_stab[idx].Points_to());
02526
02527
02528 if (how != READ_AND_WRITE)
02529 for (INT32 i = 0; i < num_parms; i++) {
02530 WN *actual = WN_actual(wn,i);
02531 if ( WN_Parm_By_Reference(actual) ) {
02532 OCC_TAB_ENTRY *p_occ = Get_occ(actual);
02533 POINTS_TO *pt = p_occ->Points_to();
02534 if (Rule()->Aliased_Memop(pt, aux_stab[idx].Points_to())) {
02535 how = READ_AND_WRITE;
02536 break;
02537 }
02538 }
02539 }
02540 #ifdef KEY // bug 8607
02541 if (WN_operator(wn) == OPR_CALL)
02542 if (WN_st(wn) && strcmp(ST_name(WN_st(wn)), "_Copyin" ) == 0) {
02543 {
02544 if (how == READ_AND_WRITE)
02545 how = READ;
02546 else if (how == WRITE)
02547 how = NO_READ_NO_WRITE;
02548 }
02549 }
02550 else if (WN_st(wn) && strcmp(ST_name(WN_st(wn)), "_Copyout" ) == 0) {
02551 {
02552 if (how == READ_AND_WRITE)
02553 how = WRITE;
02554 else if (how == READ)
02555 how = NO_READ_NO_WRITE;
02556 }
02557 }
02558 #endif
02559 #ifdef KEY
02560
02561 if ( Aux_stab_entry(idx)->St() && IS_FORTRAN && (idx != Return_vsym() || idx != Default_vsym())){
02562
02563 if (strncmp(Aux_stab_entry(idx)->St_name(), "cray_fcd_", 8) ==0 ||
02564 strncmp(Aux_stab_entry(idx)->St_name(), "_cray_", 6) ==0 )
02565 continue;
02566
02567 if ((WN_operator(wn) == OPR_INTRINSIC_CALL &&
02568 WN_intrinsic(wn) == INTRN_CASSIGNSTMT) ||
02569 (WN_operator(wn) == OPR_CALL &&
02570 (WN_st(wn) && strcmp(ST_name(WN_st(wn)), "_OPEN" ) ==0 ||
02571 WN_st(wn) && strcmp(ST_name(WN_st(wn)), "_CLOSE" ) ==0) )){
02572
02573 BOOL idx_is_accessed_by_call = FALSE;
02574
02575 for (INT32 i = 0; i < WN_kid_count(wn); i++) {
02576 OCC_TAB_ENTRY *occ = Get_occ(WN_kid(wn, i));
02577
02578 if (occ != NULL &&
02579 (occ->Aux_id() == idx ||
02580 Aux_stab_entry(idx)->St()==Aux_stab_entry(occ->Aux_id())->St() ||
02581 occ->Aux_id() == Default_vsym() ||
02582 occ->Aux_id() == Return_vsym()) ) {
02583 idx_is_accessed_by_call = TRUE;
02584 break;
02585 }
02586 }
02587 if (!idx_is_accessed_by_call &&
02588 strncmp(Aux_stab_entry(idx)->St_name(), ".preg_I", 7) != 0)
02589 continue;
02590 }
02591
02592 }
02593 #endif
02594 if (how & READ)
02595 mu->New_mu_node(idx, Occ_pool());
02596
02597 if ((how & WRITE) && IS_FORTRAN && !Var_is_loop_index(idx, bb))
02598 chi->New_chi_node(idx, Occ_pool());
02599 }
02600 }
02601
02602
02603
02604
02605 BOOL
02606 OPT_STAB::Has_read_only_parm(AUX_ID idx, WN *wn, INT32 num_parms)
02607 {
02608 if (!OPT_IPA_addr_analysis)
02609 return FALSE;
02610
02611 if (!PU_ipa_addr_analysis(Get_Current_PU()))
02612 return FALSE;
02613
02614 for (INT32 i = 0; i < num_parms; i++) {
02615 WN *actual = WN_actual(wn,i);
02616 Is_True(WN_operator(actual) == OPR_PARM,
02617 ("OPT_STAB::Has_read_only_parm: not a PARM node."));
02618
02619 WN *lda = WN_kid0(actual);
02620 if (WN_operator(lda) != OPR_LDA)
02621 continue;
02622 AUX_ID lda_idx = WN_aux(lda);
02623
02624 if (WN_Parm_Read_Only(actual)) {
02625 if (idx == lda_idx) return TRUE;
02626 if (Is_real_var(idx) || Lda_vsym(idx)) {
02627 ST *st = Aux_stab_entry(idx)->St();
02628 INT64 ofst = Aux_stab_entry(idx)->St_ofst();
02629 INT64 size = Aux_stab_entry(idx)->Byte_size();
02630 ST *parm_st = Aux_stab_entry(lda_idx)->St();
02631 INT64 parm_ofst = Aux_stab_entry(lda_idx)->St_ofst();
02632 INT64 parm_size = Aux_stab_entry(lda_idx)->Byte_size();
02633
02634 if (st == parm_st &&
02635 ofst >= parm_ofst &&
02636 size > 0 &&
02637 parm_size > 0 &&
02638 (ofst + size) <= (parm_ofst + parm_size)) {
02639 return TRUE;
02640 }
02641 }
02642 }
02643 }
02644 return FALSE;
02645 }
02646
02647 #ifdef KEY
02648 #include "be_ipa_util.h"
02649
02650
02651 static void
02652 check_ipa_mod_ref_info (const ST * call_st, const ST * st, INT * mod, INT * ref)
02653 {
02654 PU_IDX idx = ST_pu (call_st);
02655
02656 *mod = *ref = 1;
02657
02658 for (INT i=0; i<Mod_Ref_Info_Table_Size(); i++)
02659 {
02660 if (Mod_Ref_Info_Table[i].pu_idx != idx) continue;
02661 else
02662 {
02663 mUINT8 * mod_info = Mod_Ref_Info_Table[i].mod;
02664 mUINT8 * ref_info = Mod_Ref_Info_Table[i].ref;
02665 *mod = *ref = 0;
02666
02667 INT index = ST_IDX_index (ST_st_idx (st));
02668
02669
02670 if (index >= Mod_Ref_Info_Table[i].size * 8) return;
02671
02672 *mod = (*(mod_info + index/8) >> (8 - 1 - (index % 8))) & 0x1;
02673 *ref = (*(ref_info + index/8) >> (8 - 1 - (index % 8))) & 0x1;
02674 return;
02675 }
02676 }
02677 }
02678 #endif
02679
02680
02681
02682 void
02683 OPT_STAB::Generate_call_mu_chi_by_value(WN *wn, ST *call_st,
02684 MU_LIST *mu, CHI_LIST *chi,
02685 INT32 num_parms)
02686 {
02687 AUX_ID idx;
02688 const BS *alias_set;
02689
02690 alias_set = Rule()->Alias_Set_Call_By_Value(this);
02691 for (idx = BS_Choose( alias_set );
02692 idx != (AUX_ID) BS_CHOOSE_FAILURE;
02693 idx = BS_Choose_Next ( alias_set, idx )) {
02694
02695
02696 if (Aux_stab_entry(idx)->Is_volatile() &&
02697 !Aux_stab_entry(idx)->Is_virtual() )
02698 continue;
02699
02700 POINTS_TO *pt = aux_stab[idx].Points_to();
02701 READ_WRITE how = Rule()->Aliased_with_Call(call_st,
02702 WN_call_flag(wn),
02703 pt);
02704
02705 if ((how & WRITE) &&
02706 pt->Not_addr_saved()) {
02707
02708 if (Has_read_only_parm(idx, wn, num_parms)) {
02709 how = READ;
02710 if (Get_Trace(TP_GLOBOPT, ALIAS_DUMP_FLAG)) {
02711 fprintf(TFile, "<alias> Remove the chi node with aux id %d"
02712 " due to PARM_READ_ONLY.\n", idx);
02713 }
02714 }
02715 }
02716
02717 if( WN_operator(wn)==OPR_INTRINSIC_CALL &&
02718 INTRN_has_no_side_effects(WN_intrinsic(wn)) &&
02719 (!pt->Dedicated())) {
02720 if(how == WRITE)
02721 how = NO_READ_NO_WRITE;
02722 else if(how==READ_AND_WRITE)
02723 how = READ;
02724 }
02725
02726 #ifdef KEY
02727
02728
02729
02730
02731 ST * st = aux_stab[idx].St();
02732
02733 if (WOPT_Enable_IP_Mod_Ref && how != NO_READ_NO_WRITE && call_st && st
02734 && ST_class (st) == CLASS_VAR && Is_Global_Symbol (st))
02735 {
02736 INT mod, ref;
02737
02738 check_ipa_mod_ref_info (call_st, st, &mod, &ref);
02739
02740 if ((mod == 0) && (how & WRITE))
02741 {
02742 if (how == WRITE)
02743 how = NO_READ_NO_WRITE;
02744 else
02745 how = READ;
02746 if (Get_Trace(TP_GLOBOPT, ALIAS_DUMP_FLAG))
02747 fprintf(TFile, "<alias> Remove the chi node with aux id %d"
02748 " due to IPA MOD information.\n", idx);
02749 }
02750
02751 if ((ref == 0) && (how & READ))
02752 {
02753 if (how == READ)
02754 how = NO_READ_NO_WRITE;
02755 else
02756 how = WRITE;
02757 if (Get_Trace(TP_GLOBOPT, ALIAS_DUMP_FLAG))
02758 fprintf(TFile, "<alias> Remove the mu node with aux id %d"
02759 " due to IPA REF information.\n", idx);
02760 }
02761 }
02762 #endif
02763
02764 if (how & READ)
02765 mu->New_mu_node(idx, Occ_pool());
02766 if (how & WRITE)
02767 chi->New_chi_node(idx, Occ_pool());
02768 }
02769 }
02770
02771
02772 void
02773 OPT_STAB::Add_nested_call_mu_chi(WN *wn, ST *call_st,
02774 MU_LIST *mu, CHI_LIST *chi)
02775 {
02776 ST *nested_func = Is_nested_call(wn, *this);
02777
02778 if ( nested_func != NULL ) {
02779 WN *pragma_list = Get_MP_accessed_id_list(nested_func);
02780 AUX_ID idx;
02781 AUX_STAB_ITER aux_stab_iter(this);
02782
02783 FOR_ALL_NODE(idx, aux_stab_iter, Init()) {
02784
02785 if (Aux_stab_entry(idx)->Is_volatile() &&
02786 !Aux_stab_entry(idx)->Is_virtual() )
02787 continue;
02788
02789
02790 if (!aux_stab[idx].Points_to()->Local() &&
02791 !aux_stab[idx].Points_to()->F_param())
02792 continue;
02793
02794 if ( pragma_list != NULL && WOPT_Enable_MP_varref) {
02795 READ_WRITE how =
02796 (READ_WRITE) Get_MP_modref(pragma_list,
02797 aux_stab[idx].Points_to(), Rule());
02798 if (how & READ) {
02799 mu->New_mu_node_no_dups(idx, Occ_pool());
02800 aux_stab[idx].Set_has_nested_ref();
02801 }
02802 if (how & WRITE) {
02803 chi->New_chi_node_no_dups(idx, Occ_pool());
02804 aux_stab[idx].Set_has_nested_ref();
02805 }
02806 } else {
02807
02808
02809
02810 if ( Aux_stab_entry(idx)->Has_nested_ref() ) {
02811 mu->New_mu_node_no_dups(idx, Occ_pool());
02812 chi->New_chi_node_no_dups(idx, Occ_pool());
02813 } else if ( aux_stab[idx].Points_to()->F_param() ) {
02814
02815 mu->New_mu_node_no_dups(idx, Occ_pool());
02816 chi->New_chi_node_no_dups(idx, Occ_pool());
02817 }
02818 }
02819 }
02820 }
02821 }
02822
02823
02824
02825
02826
02827
02828
02829
02830
02831 void
02832 OPT_STAB::Generate_asm_mu_chi(WN *wn, MU_LIST *mu, CHI_LIST *chi)
02833 {
02834 AUX_ID idx;
02835
02836
02837
02838 BOOL asm_clobbers_mem = WN_Asm_Clobbers_Mem(wn);
02839
02840 AUX_STAB_ITER aux_stab_iter(this);
02841 FOR_ALL_NODE(idx, aux_stab_iter, Init()) {
02842
02843 if (Aux_stab_entry(idx)->Is_volatile() &&
02844 !Aux_stab_entry(idx)->Is_virtual()) {
02845 continue;
02846 }
02847
02848 READ_WRITE how = NO_READ_NO_WRITE;
02849
02850
02851
02852 if (Aux_stab_entry(idx)->Is_preg())
02853 continue;
02854 #ifdef KEY //Bug 607 && bug 1672 and bug 5022
02855 if (idx == Return_vsym()){
02856 how = READ_AND_WRITE;
02857 goto label_how;
02858 }
02859
02860 if (Asm_Memory || asm_clobbers_mem)
02861 #if 0 // bug 10016
02862 if (Addr_saved(idx) || Addr_passed(idx) || Addr_used_locally(idx) ||
02863 idx == Default_vsym())
02864 #endif
02865 {
02866 how = READ_AND_WRITE;
02867 goto label_how;
02868 }
02869
02870 for (INT kid = 2; kid < WN_kid_count(wn); ++kid) {
02871 WN* asm_input = WN_kid(wn, kid);
02872 const char* constraint = WN_asm_input_constraint(asm_input);
02873 if (WN_operator(WN_kid0(asm_input)) == OPR_LDA ||
02874 strncmp(constraint, "=m", 2) == 0 ||
02875 strstr(constraint, "m") != NULL) {
02876 AUX_ID vp_idx = Identify_vsym(asm_input);
02877 if (vp_idx == idx ||
02878 Rule()->Aliased_Memop(Aux_stab_entry(vp_idx)->Points_to(),
02879 Aux_stab_entry(idx)->Points_to())) {
02880 if (strncmp(constraint, "=m", 2) == 0) {
02881 how = READ_AND_WRITE;
02882 goto label_how;
02883 }
02884 else how = READ;
02885 }
02886 }
02887 }
02888
02889 #if defined(TARG_NVISA)
02890
02891
02892 if (!asm_clobbers_mem && !WN_Asm_Volatile(wn))
02893 continue;
02894 #endif
02895 #else
02896 if (!asm_clobbers_mem)
02897 continue;
02898
02899 how |= Rule()->Aliased_with_Asm(wn, aux_stab[idx].Points_to());
02900 #endif //KEY
02901
02902 label_how:
02903 if (how & READ) {
02904 mu->New_mu_node(idx, Occ_pool());
02905 }
02906 if (how & WRITE) {
02907 chi->New_chi_node(idx, Occ_pool());
02908 }
02909
02910 Aux_stab_entry(idx)->Set_disable_local_rvi();
02911 }
02912
02913 WN *prag = WN_first(WN_asm_constraints(wn));
02914 while (prag != NULL) {
02915 chi->New_chi_node_no_dups(WN_aux(prag), Occ_pool());
02916 prag = WN_next(prag);
02917
02918 }
02919 }
02920
02921
02922
02923
02924 void
02925 OPT_STAB::Generate_exit_mu(WN *wn)
02926 {
02927
02928 AUX_ID idx, vp_idx = Return_vsym();
02929 MU_LIST *mu = Get_stmt_mu_list(wn);
02930 mu->New_mu_node(vp_idx, Occ_pool());
02931
02932
02933 if (aux_stab[vp_idx].Aux_id_list() == NULL)
02934 Update_aux_id_list(vp_idx);
02935
02936
02937
02938
02939 AUX_STAB_ITER aux_stab_iter(this);
02940 FOR_ALL_NODE(idx, aux_stab_iter, Init()) {
02941 AUX_STAB_ENTRY *psym = Aux_stab_entry(idx);
02942
02943
02944
02945
02946 if (psym->Is_volatile()) continue;
02947 if (idx == Default_vsym()) continue;
02948
02949 ST *st;
02950 if (!psym->Points_to()->Local()) {
02951 mu->New_mu_node(idx, mem_pool);
02952 }
02953
02954
02955 else if ((st = psym->Points_to()->Based_sym()) != NULL
02956 && ST_sclass(st) == SCLASS_FORMAL
02957 && !ST_is_value_parm(st)) {
02958 mu->New_mu_node(idx, mem_pool);
02959 }
02960
02961
02962
02963 else if ((st = psym->St()) != NULL
02964 && (ST_sclass(st) == SCLASS_FORMAL_REF
02965 || (ST_sclass(st) == SCLASS_FORMAL
02966 && PU_has_syscall_linkage(Get_Current_PU())))) {
02967 mu->New_mu_node(idx, mem_pool);
02968 }
02969
02970
02971 else if (Local_static(idx)) {
02972 mu->New_mu_node(idx, mem_pool);
02973 }
02974 }
02975 }
02976
02977 #if defined(TARG_SL)
02978 void
02979 OPT_STAB::Generate_call_mu_chi_by_intrninfo(WN *intrn_wn, MU_LIST *mu, CHI_LIST *chi)
02980 {
02981 INTRINSIC intrinsic = WN_intrinsic(intrn_wn);
02982 FmtAssert( INTRN_is_sl(intrinsic), ("OPT_STAB::Generate_call_mu_chi_by_intrninfo:input intrinsic is not sl intrinsic") );
02983
02984 OCC_TAB_ENTRY *occ[SL_MAX_MEMOP_COUNT]={NULL};
02985
02986 INT memop_count = INTRN_get_memop_count(intrinsic);
02987 FmtAssert(memop_count <= SL_MAX_MEMOP_COUNT && (memop_count <= 0 || (memop_count >0 && INTRN_carry_memop(intrinsic))),
02988 ("OPT_STAB::Generate_call_mu_chi_by_intrninfo: too many memop"));
02989
02990 for(INT m_id = 0; m_id < memop_count; m_id++) {
02991 WN *addr_parm = WN_kid( intrn_wn, INTRN_get_addr_parm(intrinsic, m_id) );
02992 occ[m_id] = Get_occ(addr_parm);
02993 }
02994
02995 const BS *alias_set = Rule()->Alias_Set_Call_By_Value(this);
02996 for (AUX_ID idx = BS_Choose( alias_set );
02997 idx != (AUX_ID) BS_CHOOSE_FAILURE;
02998 idx = BS_Choose_Next ( alias_set, idx )) {
02999
03000 if (!Aux_stab_entry(idx)->Is_volatile() ||
03001 Aux_stab_entry(idx)->Is_virtual() ) {
03002 if (aux_stab[idx].Points_to()->Dedicated())
03003 chi->New_chi_node(idx, Occ_pool());
03004 else {
03005 for(INT o_id = 0; o_id < memop_count; o_id++ ) {
03006 if(Rule()->Aliased_Memop(occ[o_id]->Points_to(), aux_stab[idx].Points_to())) {
03007 if(INTRN_like_store(intrinsic)) {
03008 chi->New_chi_node(idx, Occ_pool());
03009 break;
03010 }
03011 else {
03012 mu->New_mu_node(idx, Occ_pool());
03013 break;
03014 }
03015 }
03016 }
03017 }
03018 }
03019 }
03020 return;
03021 }
03022
03023 #endif
03024
03025
03026
03027
03028 void
03029 OPT_STAB::Generate_mu_and_chi_list(WN *wn, BB_NODE *bb)
03030 {
03031 if (wn == NULL)
03032 return;
03033
03034 const OPCODE opc = WN_opcode(wn);
03035 const OPERATOR opr = OPCODE_operator(opc);
03036 Is_True(!OPCODE_is_scf(opc) || opc == OPC_REGION,
03037 ("OPT_STAB::Generate_mu_and_chi_list: Wn is SCF %s",
03038 OPCODE_name(opc)));
03039 Is_True(opc != OPC_BLOCK, ("Wn is a OPR_BLOCK."));
03040
03041 AUX_ID cur, idx, vp_idx, st_idx;
03042 CHI_LIST *chi;
03043 MU_LIST *mu;
03044 const BS *alias_set;
03045 OCC_TAB_ENTRY *occ;
03046 TY_IDX wn_ty;
03047 RID *rid;
03048
03049 switch ( opr ) {
03050 case OPR_LDID:
03051 case OPR_LDBITS:
03052 break;
03053
03054 case OPR_STBITS:
03055 case OPR_STID:
03056
03057 {
03058 st_idx = WN_aux(wn);
03059 POINTS_TO *pt = aux_stab[st_idx].Points_to();
03060 if (pt->No_alias())
03061 break;
03062
03063 chi = Get_mem_chi_list(wn);
03064 if (cur = aux_stab[st_idx].St_group()) {
03065 while (cur && cur != st_idx) {
03066
03067 if (!Aux_stab_entry(cur)->Is_volatile() &&
03068 Aux_stab_entry(cur)->Is_real_var()) {
03069 if (Rule()->Aliased_Ofst_Rule(aux_stab[st_idx].Points_to(),
03070 aux_stab[cur].Points_to()))
03071 chi->New_chi_node(cur, Occ_pool());
03072 }
03073 cur = aux_stab[cur].St_group();
03074 }
03075 }
03076
03077 alias_set = Virtual_var();
03078 for (idx = BS_Choose( alias_set );
03079 idx != (AUX_ID) BS_CHOOSE_FAILURE;
03080 idx = BS_Choose_Next ( alias_set, idx )) {
03081 if (!Aux_stab_entry(idx)->Is_real_var() &&
03082 Rule()->Aliased_Memop(aux_stab[st_idx].Points_to(),
03083 aux_stab[idx].Points_to()))
03084 chi->New_chi_node(idx, Occ_pool());
03085 }
03086
03087 if (aux_stab[st_idx].Points_to()->Weak() ||
03088 aux_stab[st_idx].Points_to()->Weak_base()) {
03089 AUX_ID auxid;
03090 AUX_STAB_ITER aux_stab_iter(this);
03091 FOR_ALL_NODE(auxid, aux_stab_iter, Init()) {
03092 if (auxid == st_idx) continue;
03093 AUX_STAB_ENTRY *psym = &aux_stab[auxid];
03094 if ((psym->Is_real_var() && !psym->Is_volatile()) ||
03095 psym->Is_virtual()) {
03096 POINTS_TO *aux_pt = psym->Points_to();
03097 if (Rule()->Aliased_Memop( aux_stab[st_idx].Points_to(), aux_pt))
03098 chi->New_chi_node_no_dups(auxid, Occ_pool());
03099 }
03100 }
03101 }
03102
03103 break;
03104 }
03105
03106 case OPR_ILDBITS:
03107 case OPR_ILOAD:
03108 case OPR_MLOAD:
03109 case OPR_ILOADX:
03110 occ = Get_occ(wn);
03111 Is_True(!WOPT_Enable_Alias_Classification ||
03112 REGION_has_black_regions(g_comp_unit->Rid()) ||
03113 occ->Points_to()->Alias_class() != OPTIMISTIC_AC_ID,
03114 ("indirect load has OPTIMISTIC_AC_ID"));
03115 Is_True(!WOPT_Enable_Alias_Classification ||
03116 (WOPT_Alias_Class_Limit != UINT32_MAX) ||
03117 REGION_has_black_regions(g_comp_unit->Rid()) ||
03118 occ->Points_to()->Alias_class() != PESSIMISTIC_AC_ID,
03119 ("indirect load has PESSIMISTIC_AC_ID"));
03120 vp_idx = occ->Aux_id();
03121 occ->New_mem_mu_node(vp_idx, Occ_pool());
03122
03123
03124 if (aux_stab[vp_idx].Aux_id_list() == NULL)
03125 Update_aux_id_list(vp_idx);
03126
03127 break;
03128
03129 case OPR_ISTORE:
03130 case OPR_ISTBITS:
03131 case OPR_MSTORE:
03132 case OPR_ISTOREX:
03133 occ = Get_occ(wn);
03134 Is_True(!WOPT_Enable_Alias_Classification ||
03135 REGION_has_black_regions(g_comp_unit->Rid()) ||
03136 occ->Points_to()->Alias_class() != OPTIMISTIC_AC_ID,
03137 ("indirect store has OPTIMISTIC_AC_ID"));
03138 Is_True(!WOPT_Enable_Alias_Classification ||
03139 (WOPT_Alias_Class_Limit != UINT32_MAX) ||
03140 REGION_has_black_regions(g_comp_unit->Rid()) ||
03141 occ->Points_to()->Alias_class() != PESSIMISTIC_AC_ID,
03142 ("indirect store has PESSIMISTIC_AC_ID"));
03143 vp_idx = occ->Aux_id();
03144 chi = occ->Mem_chi_list();
03145
03146
03147 if (aux_stab[vp_idx].Aux_id_list() == NULL)
03148 Update_aux_id_list(vp_idx);
03149
03150 alias_set = Rule()->Alias_Set_Indirect(this);
03151 wn_ty = WN_object_ty(wn);
03152 for (idx = BS_Choose( alias_set );
03153 idx != (AUX_ID) BS_CHOOSE_FAILURE;
03154 idx = BS_Choose_Next ( alias_set, idx )) {
03155
03156
03157 if (!Aux_stab_entry(idx)->Is_volatile() ||
03158 Aux_stab_entry(idx)->Is_virtual() ) {
03159
03160 if (idx == vp_idx)
03161 chi->New_chi_node(idx, Occ_pool());
03162 else if (Rule()->Aliased_Memop(occ->Points_to(),
03163 aux_stab[idx].Points_to(),
03164 wn_ty,
03165 aux_stab[idx].Points_to()->Ty())) {
03166 if (!IS_FORTRAN || !Var_is_loop_index(idx, bb))
03167 chi->New_chi_node(idx, Occ_pool());
03168 }
03169 }
03170 }
03171 break;
03172
03173 case OPR_INTRINSIC_OP:
03174 #ifdef KEY
03175 case OPR_PURE_CALL_OP:
03176 #endif
03177 {
03178 for (INT32 i = 0; i < WN_kid_count(wn); i++) {
03179 occ = Get_occ(WN_kid(wn, i));
03180 if (occ != NULL) {
03181 vp_idx = occ->Aux_id();
03182 occ->New_mem_mu_node(vp_idx, Occ_pool());
03183 if (aux_stab[vp_idx].Aux_id_list() == NULL)
03184 Update_aux_id_list(vp_idx);
03185 }
03186 }
03187 break;
03188 }
03189
03190 case OPR_ICALL:
03191 case OPR_CALL:
03192 case OPR_INTRINSIC_CALL:
03193 {
03194 ST *call_st = NULL;
03195 INT32 num_parms = WN_kid_count(wn);
03196
03197 if (opr == OPR_CALL)
03198 call_st = WN_sym(wn);
03199 else if (opr == OPR_ICALL)
03200 num_parms--;
03201
03202 occ = Get_occ(wn);
03203 mu = Get_stmt_mu_list(wn);
03204 chi = Get_stmt_chi_list(wn);
03205
03206 #if defined(TARG_SL)
03207 if(opr==OPR_INTRINSIC_CALL && INTRN_is_sl(WN_intrinsic(wn)) &&
03208 INTRN_has_no_side_effects(WN_intrinsic(wn)) ) {
03209 Generate_call_mu_chi_by_intrninfo(wn, mu, chi);
03210 break;
03211 }
03212 #endif
03213
03214 if (Rule()->Call_by_reference())
03215 Generate_call_mu_chi_by_ref(wn, call_st, mu, chi, num_parms, bb);
03216 else
03217 Generate_call_mu_chi_by_value(wn, call_st, mu, chi, num_parms);
03218
03219
03220 Add_nested_call_mu_chi(wn, call_st, mu, chi);
03221 break;
03222 }
03223
03224 case OPR_PARM:
03225
03226 if ( WN_Parm_By_Reference(wn)
03227 #if defined(TARG_SL)
03228 || WN_Parm_Dereference(wn)
03229 #endif
03230 ) {
03231 occ = Get_occ(wn);
03232 AUX_ID vp_idx = occ->Aux_id();
03233
03234 occ->New_mem_mu_node(vp_idx, Occ_pool());
03235
03236 if (!aux_stab[vp_idx].Is_real_var() &&
03237 aux_stab[vp_idx].Aux_id_list() == NULL)
03238 Update_aux_id_list(vp_idx);
03239 }
03240 else {
03241 Is_True( WN_Parm_By_Value(wn),
03242 ("OPT_STAB::Generate_mu_and_chi_list: not by value") );
03243 }
03244
03245 break;
03246
03247 case OPR_IO:
03248
03249 Is_True( OPCODE_is_black_box(opc), ("OPR_IO is not black box opr."));
03250 occ = Get_occ(wn);
03251 Compute_black_box_mu_chi(wn, occ);
03252 break;
03253
03254 case OPR_REGION:
03255 Is_True(PU_has_region(Get_Current_PU()),
03256 ("OPT_STAB::Generate_mu_and_chi_list, region encountered"));
03257 rid = REGION_get_rid(wn);
03258 if (RID_level(rid) >= Rgn_level()) {
03259
03260
03261 Compute_region_mu_chi(wn, rid, TRUE, bb);
03262 return;
03263 }
03264 break;
03265
03266 case OPR_REGION_EXIT:
03267
03268
03269
03270
03271
03272
03273
03274 if (bb->Kind() == BB_REGIONEXIT) {
03275 RID *rid2 = bb->Regioninfo()->Rid();
03276 rid = Cfg()->Rid();
03277 if (rid == rid2 && !RID_TYPE_transparent(rid)) {
03278
03279 Compute_region_mu_chi(wn, rid, FALSE, bb);
03280 }
03281 }
03282 break;
03283
03284 case OPR_RETURN:
03285 case OPR_RETURN_VAL:
03286 #ifdef KEY
03287 case OPR_GOTO_OUTER_BLOCK:
03288 #endif
03289 Generate_exit_mu(wn);
03290 break;
03291
03292 case OPR_FORWARD_BARRIER:
03293 case OPR_BACKWARD_BARRIER:
03294 case OPR_DEALLOCA:
03295 {
03296 occ = Get_occ(wn);
03297 POINTS_TO_LIST *ptl = Create_barrier_defs(wn);
03298 occ->Set_pt_list(ptl);
03299 Compute_barrier_mu_chi(Get_occ(wn), ptl, bb,
03300 FALSE,
03301 opr != OPR_DEALLOCA, TRUE, opr != OPR_DEALLOCA);
03302 CHI_LIST *chi_list = Get_stmt_chi_list(wn);
03303 CHI_NODE *cnode;
03304 CHI_LIST_ITER chi_iter;
03305 if (chi_list) {
03306 FOR_ALL_NODE( cnode, chi_iter, Init(chi_list) ) {
03307 AUX_ID v = cnode->Aux_id();
03308 aux_stab[v].Set_disable_local_rvi();
03309 }
03310 }
03311 }
03312 break;
03313
03314 case OPR_ASM_STMT:
03315 {
03316 mu = Get_stmt_mu_list(wn);
03317 chi = Get_stmt_chi_list(wn);
03318 Generate_asm_mu_chi(wn, mu, chi);
03319 }
03320 break;
03321
03322 default:
03323 break;
03324 }
03325
03326 if ( opc == OPC_COMPGOTO ) {
03327
03328 Generate_mu_and_chi_list(WN_kid(wn,0), bb);
03329 }
03330 else if ( ! OPCODE_is_black_box( opc )) {
03331 INT32 i = (opr == OPR_ASM_STMT ? 2 : 0);
03332 for (; i < WN_kid_count(wn); i++)
03333 Generate_mu_and_chi_list(WN_kid(wn,i), bb);
03334 }
03335 }
03336
03337
03338
03339
03340
03341
03342
03343
03344
03345
03346
03347
03348
03349
03350
03351
03352
03353
03354
03355
03356
03357
03358
03359
03360
03361
03362
03363
03364
03365
03366 BOOL
03367 OPT_STAB::Transfer_alias_class_to_occ_and_aux(RID *const rid,
03368 WN *const wn)
03369 {
03370 BOOL found_ip_alias_class_info = FALSE;
03371 OPCODE opc = WN_opcode(wn);
03372
03373
03374
03375
03376 if (!OPCODE_is_black_box(opc)) {
03377 OPERATOR opr = OPCODE_operator(opc);
03378 if (OPCODE_is_load(opc) ||
03379 OPCODE_is_store(opc) ||
03380 opr == OPR_LDA ||
03381 #if defined(TARG_SL)
03382 (opr == OPR_PARM && (WN_Parm_By_Reference(wn) || WN_Parm_Dereference(wn)))) {
03383 #else
03384 (opr == OPR_PARM && WN_Parm_By_Reference(wn))) {
03385 #endif
03386 if (OPERATOR_is_scalar_load (opr) || OPERATOR_is_scalar_store (opr) ||
03387 opr == OPR_LDA) {
03388 POINTS_TO *sym_pt = Aux_stab_entry(WN_aux(wn))->Points_to();
03389
03390
03391
03392 sym_pt->Set_not_alloca_mem();
03393 if (WOPT_Enable_Alias_Classification &&
03394 !REGION_has_black_regions(rid)) {
03395 if (sym_pt->Alias_class() == OPTIMISTIC_AC_ID) {
03396 Is_True(WOPT_Enable_Tail_Recur ||
03397 (opr == OPR_LDA &&
03398 ST_class(Aux_stab_entry(WN_aux(wn))->st) == CLASS_FUNC) ||
03399 Aux_stab_entry(WN_aux(wn))->Is_dedicated_preg(),
03400 ("Transfer_alias_class_to_occ_and_aux: class should have "
03401 "been set during Classify_memops"));
03402
03403 }
03404 else {
03405 Is_True((WOPT_Alias_Class_Limit != UINT32_MAX) ||
03406 (sym_pt->Alias_class() ==
03407 Alias_classification()->Alias_class(wn)) ||
03408
03409
03410
03411 (Alias_classification()->Alias_class(wn) ==
03412 OPTIMISTIC_AC_ID),
03413 ("Transfer_alias_class_to_occ_and_aux: Inconsistent alias class"));
03414 }
03415 }
03416 if (sym_pt->Ip_alias_class() == OPTIMISTIC_AC_ID) {
03417 #if Is_True_On
03418 if (Get_Trace(TP_GLOBOPT, ALIAS_DUMP_FLAG)) {
03419 fprintf(TFile, "IP alias class %d for ",
03420 WN_MAP32_Get(WN_MAP_ALIAS_CLASS, wn));
03421 fdump_tree_no_st(TFile, wn);
03422 }
03423 #endif
03424 IDTYPE ip_alias_class = (IDTYPE) WN_MAP32_Get(WN_MAP_ALIAS_CLASS, wn);
03425 sym_pt->Set_ip_alias_class(ip_alias_class);
03426 if (ip_alias_class != OPTIMISTIC_AC_ID) {
03427 found_ip_alias_class_info = TRUE;
03428 }
03429 }
03430 else {
03431
03432
03433
03434
03435
03436
03437
03438
03439
03440
03441
03442
03443
03444
03445
03446
03447
03448
03449
03450
03451
03452
03453
03454
03455
03456
03457
03458
03459
03460 Is_True(!WOPT_Enable_Debug_Inconsistent_Ip_Class ||
03461 (WOPT_Ip_Alias_Class_Limit != UINT32_MAX) ||
03462 (sym_pt->Ip_alias_class() ==
03463 (IDTYPE) WN_MAP32_Get(WN_MAP_ALIAS_CLASS, wn)) ||
03464 (WN_MAP32_Get(WN_MAP_ALIAS_CLASS, wn) == OPTIMISTIC_AC_ID),
03465 ("Transfer_alias_class_to_occ_and_aux: Inconsistent IP alias class: %lu vs. %lu\n"
03466 "Someone (LNO:Equivalence_arrays?) forgot to call Note_Invalid_IP_Alias_Class?",
03467 sym_pt->Ip_alias_class(), WN_MAP32_Get(WN_MAP_ALIAS_CLASS, wn)));
03468
03469
03470
03471
03472 if ((sym_pt->Ip_alias_class() != PESSIMISTIC_AC_ID) &&
03473 (sym_pt->Ip_alias_class() !=
03474 (IDTYPE) WN_MAP32_Get(WN_MAP_ALIAS_CLASS, wn)) &&
03475 (WN_MAP32_Get(WN_MAP_ALIAS_CLASS, wn) != OPTIMISTIC_AC_ID)) {
03476
03477
03478
03479
03480
03481
03482
03483
03484 DevWarn("Transfer_alias_class_to_occ_and_aux: Inconsistent IP alias class: %u vs. %u",
03485 sym_pt->Ip_alias_class(), WN_MAP32_Get(WN_MAP_ALIAS_CLASS, wn));
03486
03487
03488 sym_pt->Set_ip_alias_class(PESSIMISTIC_AC_ID);
03489 }
03490 }
03491 }
03492 else {
03493 Is_True(Get_occ(wn) != NULL,
03494 ("Transfer_alias_class_to_occ_and_aux: Indirect memop should have "
03495 "OCC_TAB_ENTRY"));
03496 }
03497
03498
03499
03500 OCC_TAB_ENTRY *occ = Get_occ(wn);
03501 if (occ != NULL) {
03502 POINTS_TO *occ_pt = occ->Points_to();
03503 IDTYPE alias_class = Alias_classification()->Alias_class(wn);
03504 #ifdef KEY
03505 Is_True (!WOPT_Enable_New_Vsym_Allocation ||
03506 occ_pt->Alias_class() == alias_class ||
03507 (opr != OPR_ILOAD && opr != OPR_ISTORE),
03508 ("Transfer_alias_class_to_occ_and_aux: Alias class "
03509 "mismatch at -WOPT:new_vsym=on"));
03510 #endif
03511 occ_pt->Set_alias_class(alias_class);
03512
03513 IDTYPE ip_alias_class = WN_MAP32_Get(WN_MAP_ALIAS_CLASS, wn);
03514 #ifdef KEY
03515 Is_True (!WOPT_Enable_New_Vsym_Allocation ||
03516 occ_pt->Ip_alias_class() == ip_alias_class ||
03517 (opr != OPR_ILOAD && opr != OPR_ISTORE),
03518 ("Transfer_alias_class_to_occ_and_aux: IP alias class "
03519 "mismatch at -WOPT:new_vsym=on"));
03520 #endif
03521 occ_pt->Set_ip_alias_class(ip_alias_class);
03522 if (ip_alias_class != OPTIMISTIC_AC_ID) {
03523 found_ip_alias_class_info = TRUE;
03524 }
03525
03526 if ((Alias_classification()->Non_alloca_memop(alias_class)) &&
03527 (alias_class <= WOPT_Alias_Class_Limit)) {
03528 occ_pt->Set_not_alloca_mem();
03529 }
03530
03531 POINTS_TO *vsym_pt = Aux_stab_entry(occ->Aux_id())->Points_to();
03532
03533
03534
03535
03536
03537
03538
03539
03540
03541
03542
03543
03544
03545
03546
03547
03548
03549
03550
03551
03552
03553
03554
03555
03556
03557
03558 if (vsym_pt->Unique_pt()) {
03559 Is_True(Aux_stab_entry(occ->Aux_id())->Is_virtual(),
03560 ("Transfer_alias_class_to_occ_and_aux: Robert thought "
03561 "Unique_pt POINTS_TO would be virtual"));
03562
03563
03564
03565
03566
03567
03568
03569
03570
03571
03572
03573
03574
03575
03576
03577
03578
03579
03580
03581
03582
03583
03584
03585
03586
03587
03588
03589
03590
03591
03592
03593
03594
03595
03596
03597
03598 #if 0
03599 Is_True((vsym_pt->Alias_class() == OPTIMISTIC_AC_ID) ||
03600 (vsym_pt->Alias_class() == alias_class),
03601 ("Transfer_alias_class_to_occ_and_aux: Inconsistent alias "
03602 "class for vsym"));
03603 #endif
03604
03605 if (alias_class != OPTIMISTIC_AC_ID &&
03606 alias_class != PESSIMISTIC_AC_ID &&
03607 !Alias_classification()->Writable_by_call(alias_class) &&
03608 alias_class <= WOPT_Alias_Class_Limit) {
03609
03610
03611
03612
03613
03614
03615
03616 Set_inaccessible_to_callees(BS_Union1D(Inaccessible_to_callees(),
03617 occ->Aux_id(), mem_pool));
03618
03619
03620
03621
03622
03623 vsym_pt->Set_local();
03624 if (Get_Trace(TP_GLOBOPT, ALIAS_DUMP_FLAG)) {
03625 fprintf(TFile, "Xfer_ac: Aux ID %d is local unique_pt vsym\n",
03626 occ->Aux_id());
03627 }
03628 if (WOPT_Alias_Class_Limit != UINT32_MAX) {
03629 Lmt_DevWarn(1,
03630 ("Alias class used to set Inaccessible_to_callees"));
03631 }
03632 }
03633
03634
03635 #if 0
03636 Is_True((vsym_pt->Ip_alias_class() == OPTIMISTIC_AC_ID) ||
03637 (vsym_pt->Ip_alias_class() ==
03638 WN_MAP32_Get(WN_MAP_ALIAS_CLASS, wn)) ||
03639 (WN_MAP32_Get(WN_MAP_ALIAS_CLASS, wn) == OPTIMISTIC_AC_ID),
03640 ("Transfer_alias_class_to_occ_and_aux: Inconsistent IP alias "
03641 "class for vsym"));
03642 #endif
03643 #if Is_True_On
03644 if ((WOPT_Ip_Alias_Class_Limit == UINT32_MAX) &&
03645 (WN_MAP32_Get(WN_MAP_ALIAS_CLASS, wn) ==
03646 OPTIMISTIC_AC_ID) &&
03647 (vsym_pt->Ip_alias_class() != OPTIMISTIC_AC_ID)) {
03648 DevWarn("Someone (LNO?) introduced a WN without setting "
03649 "its IP alias class");
03650 }
03651 #endif
03652 }
03653
03654
03655
03656
03657
03658
03659
03660
03661
03662 vsym_pt->Meet_info_from_alias_class(occ_pt);
03663 }
03664 }
03665 for (UINT i = 0; i < WN_kid_count(wn); ++i) {
03666 found_ip_alias_class_info |= Transfer_alias_class_to_occ_and_aux(rid, WN_kid(wn, i));
03667 }
03668 }
03669 return found_ip_alias_class_info;
03670 }
03671
03672 #if defined(TARG_SL)
03673 void OPT_STAB::Refine_intrn_alias_info( WN* intrn_wn )
03674 {
03675 FmtAssert( intrn_wn != NULL, ("OPT_STAB::Refine_intrn_alias_info: input NULL") );
03676
03677 OPERATOR opr = WN_operator( intrn_wn );
03678 FmtAssert( (opr == OPR_INTRINSIC_OP || opr == OPR_INTRINSIC_CALL),
03679 ("OPT_STAB::Refine_intrn_alias_info: input not intrinsic wn") );
03680
03681 INTRINSIC intrinsic = WN_intrinsic(intrn_wn);
03682 FmtAssert( INTRN_specify_memop(intrinsic),
03683 ("OPT_STAB::Refine_intrn_alias_info: input intrinsic has no memop") );
03684
03685 for(INT ma_count=0;ma_count++;ma_count<INTRN_get_memop_count(intrinsic)) {
03686 WN *addr_parm = WN_kid( intrn_wn, INTRN_get_addr_parm(intrinsic, ma_count) );
03687 OCC_TAB_ENTRY *occ = Get_occ(addr_parm);
03688 POINTS_TO *pt = occ->Points_to();
03689 if ( pt->Base_kind() == BASE_IS_FIXED && pt->Ofst_kind() == OFST_IS_FIXED ) {
03690
03691 BOOL is_sw_mode = FALSE;
03692 INT32 sw_id = INTRN_get_sw_parm( intrinsic );
03693 if( sw_id != INVALID_PID ) {
03694 WN *sw = WN_kid0( WN_kid(intrn_wn, sw_id) );
03695 FmtAssert(WN_operator(sw) == OPR_INTCONST,
03696 ("OPT_STAB::Refine_intrn_alias_info: cannot get sw mode"));
03697 if( WN_const_val(sw) > 0 )
03698 is_sw_mode = TRUE;
03699 }
03700
03701
03702 POINTS_TO ai;
03703 WN *addr_wn = WN_kid0( addr_parm );
03704 Simplify_Pointer( addr_wn, &ai );
03705 FmtAssert(ai.Base_kind() == BASE_IS_FIXED && ai.Base() == pt->Base(),
03706 ("OPT_STAB::Refine_intrn_alias_info: conflict base kind"));
03707
03708 if(ai.Ofst_kind() == OFST_IS_FIXED) {
03709 mINT64 byte_ofst = ai.Byte_Ofst();
03710 INT32 byte_size;
03711 FmtAssert( byte_ofst >= pt->Byte_Ofst(),
03712 ("OPT_STAB::Refine_intrn_alias_info: wrong offset"));
03713 if(!is_sw_mode)
03714 pt->Set_byte_ofst( byte_ofst );
03715
03716
03717 INT32 macro_id=INTRN_get_macro_parm( intrinsic );
03718 if( macro_id != INVALID_PID ) {
03719 WN *macro = WN_kid0(WN_kid(intrn_wn, macro_id));
03720 if( WN_operator( macro ) == OPR_INTCONST && WN_const_val(macro) > 0 )
03721 return;
03722 }
03723
03724
03725 if( is_sw_mode ) {
03726 ST *base_st = pt->Base();
03727 if( base_st != NULL && ST_in_vbuf( base_st )) {
03728 if( pt->Ofst_kind() == OFST_IS_FIXED) {
03729 INT32 sw_acc_hint = byte_ofst & ( 1 << INTRN_vbuf_sw_crossline_hintbofs()-1 );
03730 if(sw_acc_hint <= INTRN_vbuf_sw_crossline_hinthrd()) {
03731 pt->Set_byte_ofst( byte_ofst );
03732 if(sw_acc_hint == 0)
03733 byte_size = INTRN_vbuf_linesize();
03734 else
03735 byte_size = INTRN_vbuf_sw_crossline_size();
03736
03737 FmtAssert( byte_size <= pt->Byte_Size(),
03738 ("OPT_STAB::Refine_intrn_alias_info:wrong size"));
03739 pt->Set_byte_size( byte_size );
03740 return;
03741 }
03742 }
03743 }
03744 return;
03745 }
03746
03747
03748 INT32 size_id = INTRN_get_size_parm( intrinsic );
03749 if(size_id != INVALID_PID ) {
03750 WN *size = WN_kid0 ( WN_kid( intrn_wn, size_id ) );
03751 FmtAssert( WN_operator(size) == OPR_INTCONST,
03752 ("OPT_STAB::Refine_intrn_alias_info:data size unknown "));
03753
03754 INT32 size_base = INTRN_get_size( WN_const_val( size ) );
03755 if( INTRN_maybe_stride( intrinsic ) && size_base > 1) {
03756
03757 INT32 size_stride = INTRN_get_size_stride( intrinsic );
03758 byte_size = (size_base-1) * size_stride + 1;
03759 } else {
03760 INT32 size_coeff = INTRN_get_size_coeff( intrinsic );
03761 byte_size = size_base * size_coeff;
03762 }
03763
03764 FmtAssert( byte_size <= pt->Byte_Size(),
03765 ("OPT_STAB::Refine_intrn_alias_info:wrong size"));
03766 pt->Set_byte_size( byte_size );
03767 }else {
03768 pt->Set_byte_size( INTRN_get_max_scalar_size() );
03769 }
03770 }
03771 }
03772 }
03773 return;
03774 }
03775
03776 void OPT_STAB::Refine_intrn_mu_chi_list(WN *intrn_wn)
03777 {
03778 FmtAssert( intrn_wn != NULL, ("OPT_STAB::Refine_intrn_mu_chi_list: input NULL") );
03779
03780 OPERATOR opr = WN_operator( intrn_wn );
03781 FmtAssert( (opr == OPR_INTRINSIC_CALL), ("OPT_STAB::Refine_intrn_mu_chi_list: input not intrinsic wn") );
03782
03783 INTRINSIC intrinsic = WN_intrinsic(intrn_wn);
03784 FmtAssert( INTRN_carry_memop(intrinsic), ("OPT_STAB::Refine_intrn_mu_chi_list: input intrinsic has no memop") );
03785
03786 OCC_TAB_ENTRY *occ[SL_MAX_MEMOP_COUNT]={NULL};
03787
03788 INT memop_count = INTRN_get_memop_count(intrinsic);
03789 FmtAssert( memop_count > 0 && memop_count <= SL_MAX_MEMOP_COUNT, ("OPT_STAB::Refine_intrn_mu_chi_list: too many memop"));
03790
03791 for(INT m_id = 0; m_id < memop_count; m_id++) {
03792 WN *addr_parm = WN_kid( intrn_wn, INTRN_get_addr_parm(intrinsic, m_id) );
03793 occ[m_id] = Get_occ(addr_parm);
03794 }
03795
03796 if(INTRN_like_store(intrinsic)) {
03797 CHI_LIST *chi_list = Get_stmt_chi_list(intrn_wn);
03798 FmtAssert(chi_list !=NULL, ("OPT_STAB::Refine_intrn_mu_chi_list: chi_list=NULL"));
03799 CHI_NODE *prev_cnode = NULL;
03800 CHI_NODE *cnode = chi_list->Head();
03801 while (cnode != NULL) {
03802 AUX_ID v = cnode->Aux_id();
03803
03804 BOOL can_remove=TRUE;
03805 if (aux_stab[v].Points_to()->Dedicated())
03806 can_remove=FALSE;
03807 if(can_remove) {
03808 for(INT p_id = 0; p_id < memop_count; p_id++) {
03809 if(Rule()->Aliased_Memop(occ[p_id]->Points_to(), aux_stab[v].Points_to()))
03810 can_remove=FALSE;
03811 }
03812 }
03813
03814 if(can_remove) {
03815 Ver_stab_entry(cnode->Result())->Set_synonym( cnode->Opnd());
03816 if (Get_Trace(TP_GLOBOPT, ALIAS_DUMP_FLAG))
03817 fprintf(TFile, "<alias> Remove the chi node that defines %d.\n", cnode->Result());
03818 chi_list->Remove(prev_cnode, cnode);
03819 if (prev_cnode != NULL)
03820 cnode = prev_cnode->Next();
03821 else
03822 cnode = chi_list->Head();
03823 } else {
03824 prev_cnode = cnode;
03825 cnode = prev_cnode->Next();
03826 }
03827 }
03828 } else {
03829 MU_LIST *mu_list = Get_stmt_mu_list(intrn_wn);
03830 FmtAssert(mu_list !=NULL, ("OPT_STAB::Refine_intrn_mu_chi_list: mu_list=NULL"));
03831 MU_NODE *prev_cnode = NULL;
03832 MU_NODE *mnode = mu_list->Head();
03833 while (mnode != NULL) {
03834 AUX_ID v = mnode->Aux_id();
03835
03836 BOOL can_remove=TRUE;
03837 for(INT p_id = 0; p_id < memop_count; p_id++) {
03838 if(Rule()->Aliased_Memop(occ[p_id]->Points_to(), aux_stab[v].Points_to()))
03839 can_remove=FALSE;
03840 }
03841
03842 if(can_remove) {
03843 if (Get_Trace(TP_GLOBOPT, ALIAS_DUMP_FLAG))
03844 fprintf(TFile, "<alias> Remove the mu node that use %d.\n", mnode->Opnd());
03845 mu_list->Remove(prev_cnode, mnode);
03846 if (prev_cnode != NULL)
03847 mnode = prev_cnode->Next();
03848 else
03849 mnode = mu_list->Head();
03850 } else {
03851 prev_cnode = mnode;
03852 mnode = prev_cnode->Next();
03853 }
03854 }
03855 }
03856
03857 return;
03858 }
03859
03860 #endif
03861
03862
03863
03864
03865
03866
03867
03868
03869
03870 void OPT_STAB::Compute_FFA(RID *const rid)
03871 {
03872 CFG_ITER cfg_iter;
03873 STMT_ITER stmt_iter;
03874 BB_NODE *bb;
03875 WN *wn;
03876 BOOL found_ip_alias_class_info = FALSE;
03877
03878
03879 Set_FFA();
03880
03881 FOR_ALL_ELEM (bb, cfg_iter, Init(_cfg)) {
03882 FOR_ALL_ELEM (wn, stmt_iter, Init(bb->Firststmt(), bb->Laststmt())) {
03883 Allocate_mu_chi_and_virtual_var(wn, bb);
03884 found_ip_alias_class_info |= Transfer_alias_class_to_occ_and_aux(rid, wn);
03885 }
03886 }
03887
03888
03889
03890
03891
03892
03893 #ifndef NOT_73_BETA
03894
03895
03896
03897
03898
03899
03900
03901
03902
03903
03904
03905
03906
03907
03908
03909
03910
03911
03912
03913
03914
03915
03916
03917
03918
03919
03920 AUX_STAB_REVERSE_ITER aux_stab_reverse_iter(this);
03921 AUX_ID chain_head;
03922
03923
03924
03925 typedef pair<AUX_ID , AUX_STAB_ENTRY *> CHAIN_HEAD_VIRTUAL_PAIR;
03926 typedef vector<CHAIN_HEAD_VIRTUAL_PAIR,
03927 mempool_allocator<CHAIN_HEAD_VIRTUAL_PAIR> > IP_ALIAS_CLASS_VIRTUALS;
03928 IP_ALIAS_CLASS_VIRTUALS ip_alias_class_virtuals;
03929
03930 FOR_ALL_NODE(chain_head, aux_stab_reverse_iter, Init()) {
03931 AUX_STAB_ENTRY *chain_head_sym = Aux_stab_entry(chain_head);
03932 if (!chain_head_sym->Prop_chain_seen()) {
03933 AUX_ID aux_id = chain_head;
03934 if (chain_head_sym->St_chain() != (AUX_ID) 0) {
03935 while (aux_id != 0) {
03936 AUX_STAB_ENTRY *chain_sym = Aux_stab_entry(aux_id);
03937 if (chain_sym->Is_virtual() &&
03938 (chain_sym->Points_to()->Ip_alias_class() != OPTIMISTIC_AC_ID)) {
03939 ip_alias_class_virtuals.
03940 push_back(CHAIN_HEAD_VIRTUAL_PAIR(chain_head, chain_sym));
03941 }
03942 chain_sym->Set_prop_chain_seen();
03943 aux_id = chain_sym->St_chain();
03944 }
03945 }
03946 }
03947 }
03948
03949 IP_ALIAS_CLASS_VIRTUALS::iterator chain_head_virtual_pair;
03950 for (chain_head_virtual_pair = ip_alias_class_virtuals.begin();
03951 chain_head_virtual_pair != ip_alias_class_virtuals.end();
03952 ++chain_head_virtual_pair) {
03953 AUX_STAB_ENTRY *chain_head_sym;
03954 AUX_STAB_ENTRY *virtual_sym = chain_head_virtual_pair->second;
03955 AUX_ID next = chain_head_virtual_pair->first;
03956
03957 do {
03958 chain_head_sym = Aux_stab_entry(next);
03959 if (Rule()->Aliased_Ofst_Rule(chain_head_sym->Points_to(),
03960 virtual_sym->Points_to())) {
03961 IDTYPE sym_alias_class =
03962 chain_head_sym->Points_to()->Ip_alias_class();
03963 IDTYPE virtual_sym_alias_class =
03964 virtual_sym->Points_to()->Ip_alias_class();
03965 Is_True((virtual_sym_alias_class == PESSIMISTIC_AC_ID) ||
03966 (virtual_sym_alias_class == sym_alias_class) ||
03967 (sym_alias_class == OPTIMISTIC_AC_ID) ||
03968
03969
03970
03971
03972
03973
03974 (sym_alias_class == PESSIMISTIC_AC_ID),
03975 ("IP alias class info inconsistent for %s",
03976 ST_name(chain_head_sym->St())));
03977 if (sym_alias_class == OPTIMISTIC_AC_ID) {
03978
03979
03980 DevWarn("IP alias class info lost and restored for part of %s",
03981 ST_name(chain_head_sym->St()));
03982 chain_head_sym->Points_to()->Set_ip_alias_class(virtual_sym_alias_class);
03983 }
03984 else if (sym_alias_class == PESSIMISTIC_AC_ID) {
03985
03986
03987
03988 DevWarn("IP alias class info discarded by overlap for %s",
03989 ST_name(chain_head_sym->St()));
03990 virtual_sym->Points_to()->Set_ip_alias_class(PESSIMISTIC_AC_ID);
03991 }
03992 }
03993 next = chain_head_sym->St_chain();
03994 } while (next != (AUX_ID) 0);
03995 }
03996 #endif // NOT_73_BETA
03997
03998
03999 if (Default_vsym() != 0) {
04000 Aux_stab_entry(Default_vsym())->Points_to()->Set_ty(0);
04001 Aux_stab_entry(Default_vsym())->Points_to()->Set_hl_ty(0);
04002 }
04003
04004 if (Return_vsym() != 0) {
04005 Aux_stab_entry(Return_vsym())->Points_to()->Set_ty(0);
04006 Aux_stab_entry(Return_vsym())->Points_to()->Set_hl_ty(0);
04007 }
04008
04009
04010 Update_alias_set_with_virtual_var();
04011
04012 FOR_ALL_ELEM (bb, cfg_iter, Init(_cfg)) {
04013 FOR_ALL_ELEM (wn, stmt_iter, Init(bb->Firststmt(), bb->Laststmt())) {
04014 Generate_mu_and_chi_list(wn, bb);
04015 }
04016 }
04017
04018 if (Get_Trace(TP_GLOBOPT, ALIAS_DUMP_FLAG)) {
04019 fprintf(TFile, "%sPOINTS_TO after flow free alias analysis\n%s",
04020 DBar,DBar);
04021 Print_alias_info(TFile);
04022 fprintf( TFile, "%sOcc table after flow free alias analysis\n%s", DBar, DBar );
04023 #ifdef KEY
04024 FOR_ALL_ELEM (bb, cfg_iter, Init(_cfg)) {
04025 FOR_ALL_ELEM (wn, stmt_iter, Init(bb->Firststmt(), bb->Laststmt())) {
04026 Print_occ_tab(TFile,wn);
04027 }
04028 }
04029 #endif
04030 Cr_sr_annot_mgr()->Print (TFile);
04031 }
04032 }
04033
04034
04035
04036
04037
04038 void OPT_STAB::Compute_FFA_for_copy( WN *wn, BB_NODE *bb, BOOL complete_list )
04039 {
04040
04041 Set_FFA();
04042 Allocate_mu_chi_and_virtual_var(wn, bb);
04043 if (complete_list)
04044 Generate_mu_and_chi_list(wn, bb);
04045 else {
04046 CHI_LIST *chi = Get_mem_chi_list(wn);
04047 chi->New_chi_node(Default_vsym(), Occ_pool());
04048 }
04049 }
04050
04051
04052
04053
04054
04055
04056
04057
04058
04059
04060
04061
04062
04063
04064
04065
04066
04067
04068
04069
04070
04071
04072
04073 void
04074 OPT_STAB::Compute_FSA_stmt_or_expr(WN *wn)
04075 {
04076 if (wn == NULL)
04077 return;
04078
04079 const OPCODE opc = WN_opcode(wn);
04080 const OPERATOR opr = OPCODE_operator(opc);
04081 if (opc == OPC_REGION)
04082 return;
04083 Is_True(!OPCODE_is_scf(opc),
04084 ("OPT_STAB::Compute_FSA_stmt_or_expr: Wn is SCF %s",
04085 OPCODE_name(opc)));
04086
04087 OCC_TAB_ENTRY *occ;
04088 #if defined(TARG_SL)
04089 if (OPERATOR_is_scalar_iload (opr) || opr == OPR_MLOAD ||
04090 (opr == OPR_PARM && WN_Parm_Dereference(wn))) {
04091 #else
04092 if (OPERATOR_is_scalar_iload (opr) || opr == OPR_MLOAD) {
04093 #endif
04094
04095 occ = Get_occ(wn);
04096
04097 if (Phase() == MAINOPT_PHASE) {
04098
04099
04100
04101 Verify_Restricted_Map(wn, occ->Points_to());
04102 }
04103
04104 if (occ->Points_to()->Base_kind() == BASE_IS_UNKNOWN &&
04105 !occ->Points_to()->F_param()) {
04106
04107 BOOL is_unique_pt = occ->Points_to()->Unique_pt();
04108 BOOL is_restricted = occ->Points_to()->Restricted();
04109 ST *based_sym = occ->Points_to()->Based_sym();
04110
04111 Analyze_Base_Flow_Sensitive(occ->Points_to(), wn);
04112 Is_True(Rule()->Aliased_Memop(occ->Points_to(), occ->Points_to())
04113 || occ->Points_to()->Const(),
04114 ("iload not aliased to itself!"));
04115
04116
04117 if (is_unique_pt) {
04118 occ->Points_to()->Set_unique_pt();
04119 occ->Points_to()->Set_based_sym(based_sym);
04120 }
04121 if (is_restricted) {
04122 occ->Points_to()->Set_restricted();
04123 occ->Points_to()->Set_based_sym(based_sym);
04124 }
04125
04126 if (WOPT_Enable_Update_Vsym)
04127 Update_iload_vsym(occ);
04128 }
04129
04130 if (occ->Points_to()->Based_sym() == NULL)
04131 Analyze_Based_Pointer(occ->Points_to(), WN_kid0(wn));
04132 }
04133
04134 if (OPERATOR_is_scalar_istore (opr) || opr == OPR_MSTORE) {
04135 BOOL need_update_chi = FALSE;
04136 CHI_LIST_ITER chi_iter;
04137 CHI_NODE *cnode;
04138 occ = Get_occ(wn);
04139
04140
04141
04142
04143
04144 if (Update_From_Restricted_Map(wn, occ->Points_to()))
04145 need_update_chi = TRUE;
04146
04147 if (occ->Points_to()->Base_kind() == BASE_IS_UNKNOWN &&
04148 !occ->Points_to()->F_param()) {
04149
04150 BOOL is_unique_pt = occ->Points_to()->Unique_pt();
04151 BOOL is_restricted = occ->Points_to()->Restricted();
04152 ST *based_sym = occ->Points_to()->Based_sym();
04153
04154 Analyze_Base_Flow_Sensitive(occ->Points_to(), wn);
04155
04156 if (is_unique_pt) {
04157 occ->Points_to()->Set_unique_pt();
04158 occ->Points_to()->Set_based_sym(based_sym);
04159 }
04160 if (is_restricted) {
04161 occ->Points_to()->Set_restricted();
04162 occ->Points_to()->Set_based_sym(based_sym);
04163 }
04164
04165 if (occ->Points_to()->Const()) {
04166 USRCPOS srcpos;
04167 USRCPOS_srcpos(srcpos) = WN_Get_Linenum(wn);
04168 ErrMsgLine(EC_Store_Const, USRCPOS_linenum(srcpos));
04169 } else {
04170 Is_True(Rule()->Aliased_Memop(occ->Points_to(), occ->Points_to()),
04171 ("istore not aliased to itself!"));
04172 }
04173
04174 if (WOPT_Enable_Update_Vsym)
04175 Update_istore_vsym(occ);
04176
04177 need_update_chi = TRUE;
04178 }
04179
04180 if (occ->Points_to()->Based_sym() == NULL) {
04181 Analyze_Based_Pointer(occ->Points_to(), WN_kid1(wn));
04182 if (occ->Points_to()->Based_sym() != NULL)
04183 need_update_chi = TRUE;
04184 }
04185
04186
04187
04188
04189 if (need_update_chi) {
04190 CHI_LIST *chi_list = occ->Mem_chi_list();
04191 CHI_NODE *prev_cnode = NULL;
04192 cnode = chi_list->Head();
04193 while (cnode != NULL) {
04194 AUX_ID v = cnode->Aux_id();
04195 #ifdef KEY // work around bug 7421: return_vsym aliases with a fixed global var
04196 if (v == Return_vsym() &&
04197 occ->Points_to()->Base_kind() == BASE_IS_FIXED &&
04198 occ->Points_to()->Not_addr_saved() && occ->Points_to()->Global()) {
04199 prev_cnode = cnode;
04200 cnode = prev_cnode->Next();
04201 }
04202 else
04203 #endif
04204
04205 if (aux_stab[v].Stype() != VT_UNIQUE_VSYM &&
04206 !Rule()->Aliased_Memop(occ->Points_to(),
04207 aux_stab[v].Points_to())) {
04208 Ver_stab_entry(cnode->Result())->Set_synonym( cnode->Opnd());
04209 if (Get_Trace(TP_GLOBOPT, ALIAS_DUMP_FLAG))
04210 fprintf(TFile, "<alias> Remove the chi node that defines %d.\n",
04211 cnode->Result());
04212 chi_list->Remove(prev_cnode, cnode);
04213 if (prev_cnode != NULL)
04214 cnode = prev_cnode->Next();
04215 else
04216 cnode = chi_list->Head();
04217 } else {
04218 prev_cnode = cnode;
04219 cnode = prev_cnode->Next();
04220 }
04221 }
04222 }
04223 }
04224
04225
04226 if ( opc == OPC_COMPGOTO ) {
04227
04228 Compute_FSA_stmt_or_expr(WN_kid(wn, 0));
04229 }
04230 else if ( ! OPCODE_is_black_box( opc ) ) {
04231 INT32 i = (opr == OPR_ASM_STMT ? 2 : 0);
04232 for (; i < WN_kid_count(wn); i++)
04233 Compute_FSA_stmt_or_expr(WN_kid(wn, i));
04234 }
04235 #if defined(TARG_SL)
04236 if( WOPT_Enable_Alias_Intrn ) {
04237 if( opr == OPR_INTRINSIC_OP || opr == OPR_INTRINSIC_CALL ) {
04238 INTRINSIC intrn = WN_intrinsic(wn);
04239
04240 if( INTRN_specify_memop(intrn) )
04241 Refine_intrn_alias_info(wn);
04242
04243 if(opr == OPR_INTRINSIC_CALL && INTRN_carry_memop(intrn)){
04244 Refine_intrn_mu_chi_list(wn);
04245 }
04246 }
04247 }
04248 #endif
04249 }
04250
04251
04252
04253
04254 void OPT_STAB::Compute_FSA_dominator_order(BB_NODE *bb)
04255 {
04256 BB_NODE *dom_bb;
04257 BB_LIST_ITER dom_bb_iter;
04258 STMT_ITER stmt_iter;
04259 WN *wn;
04260
04261 FOR_ALL_ELEM(dom_bb, dom_bb_iter, Init(bb->Dom_bbs()))
04262 Compute_FSA_dominator_order(dom_bb);
04263
04264 FOR_ALL_ELEM (wn, stmt_iter, Init(bb->Firststmt(), bb->Laststmt())) {
04265 Compute_FSA_stmt_or_expr(wn);
04266 }
04267 }
04268
04269
04270
04271
04272
04273
04274 void OPT_STAB::Compute_FSA(void)
04275 {
04276 Set_FSA();
04277 Compute_FSA_dominator_order(_cfg->Entry_bb());
04278 }
04279
04280
04281
04282
04283
04284 void OPT_STAB::Update_return_mu(void)
04285 {
04286
04287
04288
04289
04290
04291 BS *use_before_def = BS_Create_Empty(aux_stab.Lastidx()+1, mem_pool);
04292 if (Cfg()->Fake_entry_bb() != NULL) {
04293 BB_NODE *bb;
04294 BB_LIST_ITER bb_iter;
04295 FOR_ALL_ELEM (bb, bb_iter, Init(Cfg()->Fake_entry_bb()->Succ())) {
04296 if (bb->Kind() == BB_ENTRY) {
04297 WN *entry_chi = bb->Firststmt();
04298 Is_True(WN_operator(entry_chi) == OPR_OPT_CHI, ("cannot find entry chi."));
04299 CHI_LIST *chi_list = Get_generic_chi_list(entry_chi);
04300 CHI_NODE *cnode;
04301 CHI_LIST_ITER chi_iter;
04302 FOR_ALL_NODE( cnode, chi_iter, Init(chi_list) ) {
04303 if (cnode->Live())
04304 use_before_def = BS_Union1D(use_before_def, cnode->Aux_id(), mem_pool);
04305 }
04306 }
04307 }
04308 } else {
04309 BB_NODE *bb = Cfg()->Entry_bb();
04310 WN *entry_chi = bb->Firststmt();
04311 Is_True(WN_operator(entry_chi) == OPR_OPT_CHI, ("cannot find entry chi."));
04312 CHI_LIST *chi_list = Get_generic_chi_list(entry_chi);
04313 CHI_NODE *cnode;
04314 CHI_LIST_ITER chi_iter;
04315 FOR_ALL_NODE( cnode, chi_iter, Init(chi_list) ) {
04316 if (cnode->Live())
04317 use_before_def = BS_Union1D(use_before_def, cnode->Aux_id(), mem_pool);
04318 }
04319 }
04320 if (Cfg()->Fake_exit_bb() != NULL) {
04321 BB_NODE *bb = Cfg()->Exit_bb();
04322 WN *wn = bb->Laststmt();
04323 if (wn != NULL &&
04324 (WN_operator(wn) == OPR_RETURN || WN_operator(wn) == OPR_RETURN_VAL)) {
04325 MU_LIST *mu_list = Get_stmt_mu_list(wn);
04326 MU_NODE *prev_mnode = NULL;
04327 MU_NODE *mnode = mu_list->Head();
04328 while (mnode != NULL) {
04329 AUX_ID idx = mnode->Aux_id();
04330 if (Local_static(idx) && !BS_MemberP(use_before_def, idx)) {
04331 if (Get_Trace(TP_GLOBOPT, ALIAS_DUMP_FLAG))
04332 fprintf(TFile, "<alias> Remove the mu node with aux id %d.\n", idx);
04333 mu_list->Remove(prev_mnode, mnode);
04334 if (prev_mnode != NULL)
04335 mnode = prev_mnode->Next();
04336 else
04337 mnode = mu_list->Head();
04338 } else {
04339 prev_mnode = mnode;
04340 mnode = prev_mnode->Next();
04341 }
04342 }
04343 }
04344 } else {
04345 BB_NODE *bb = Cfg()->Exit_bb();
04346 WN *wn = bb->Laststmt();
04347 if (wn != NULL &&
04348 (WN_operator(wn) == OPR_RETURN || WN_operator(wn) == OPR_RETURN_VAL)) {
04349 MU_LIST *mu_list = Get_stmt_mu_list(wn);
04350 MU_NODE *prev_mnode = NULL;
04351 MU_NODE *mnode = mu_list->Head();
04352 while (mnode != NULL) {
04353 AUX_ID idx = mnode->Aux_id();
04354 if (Local_static(idx) && !Addr_saved(idx) && !BS_MemberP(use_before_def, idx)) {
04355 if (Get_Trace(TP_GLOBOPT, ALIAS_DUMP_FLAG))
04356 fprintf(TFile, "<alias> Remove the mu node with aux id %d.\n", idx);
04357 mu_list->Remove(prev_mnode, mnode);
04358 if (prev_mnode != NULL)
04359 mnode = prev_mnode->Next();
04360 else
04361 mnode = mu_list->Head();
04362 } else {
04363 prev_mnode = mnode;
04364 mnode = prev_mnode->Next();
04365 }
04366 }
04367 }
04368 }
04369 }
04370
04371
04372
04373
04374
04375
04376
04377
04378
04379
04380
04381
04382
04383
04384 const BS *ALIAS_RULE::Alias_Set_Indirect(const OPT_STAB *aux_stab) const
04385 {
04386 return aux_stab->Indirect();
04387 }
04388
04389
04390
04391
04392
04393 const BS *ALIAS_RULE::Alias_Set_Call_By_Value(const OPT_STAB *aux_stab) const
04394 {
04395 return aux_stab->Call_by_value();
04396 }
04397
04398
04399
04400
04401
04402 const BS *ALIAS_RULE::Alias_Set_Call_By_Ref(const OPT_STAB *aux_stab) const
04403 {
04404 return aux_stab->Call_by_ref();
04405 }
04406
04407
04408 const BS *ALIAS_RULE::Alias_Set_Asm(const OPT_STAB *aux_stab) const
04409 {
04410 return aux_stab->Asm_alias();
04411 }
04412
04413
04414
04415
04416 void
04417 OPT_STAB::Update_alias_set_with_virtual_var(void)
04418 {
04419 IDX_32 idx;
04420
04421 if (Default_vsym() != 0) {
04422 BS *vv = Virtual_var();
04423 vv = BS_Union1D(vv, Default_vsym(), mem_pool);
04424 Set_virtual_var(vv);
04425 }
04426
04427 if (Return_vsym() != 0) {
04428 BS *vv = Virtual_var();
04429 vv = BS_Union1D(vv, Return_vsym(), mem_pool);
04430 Set_virtual_var(vv);
04431 }
04432
04433 BS *call_by_value = Call_by_value();
04434 call_by_value = BS_UnionD(call_by_value, Virtual_var(), mem_pool);
04435 call_by_value = BS_DifferenceD(call_by_value,
04436 Inaccessible_to_callees());
04437 Set_call_by_value(call_by_value);
04438
04439 BS *call_by_ref = Call_by_ref();
04440
04441 #if Is_True_On
04442 if (Get_Trace(TP_GLOBOPT, ALIAS_DUMP_FLAG)) {
04443 fprintf(TFile, "Update_alias_set_with_virtual_var: call_by_ref: ");
04444 BS_Print(call_by_ref, TFile);
04445 }
04446 #endif // Is_True_On
04447
04448 call_by_ref = BS_UnionD(call_by_ref, Virtual_var(), mem_pool);
04449
04450 #if Is_True_On
04451 if (Get_Trace(TP_GLOBOPT, ALIAS_DUMP_FLAG)) {
04452 fprintf(TFile, "\nafter adding virtual vars: ");
04453 BS_Print(call_by_ref, TFile);
04454 }
04455 #endif // Is_True_On
04456
04457 call_by_ref = BS_DifferenceD(call_by_ref,
04458 Inaccessible_to_callees());
04459
04460 #if Is_True_On
04461 if (Get_Trace(TP_GLOBOPT, ALIAS_DUMP_FLAG)) {
04462 fprintf(TFile, "\n");
04463 }
04464 #endif // Is_True_On
04465
04466 Set_call_by_ref(call_by_ref);
04467
04468 BS *asm_alias_set = Asm_alias();
04469 asm_alias_set = BS_UnionD(asm_alias_set, Virtual_var(), mem_pool);
04470 Set_asm_alias(asm_alias_set);
04471
04472 BS *indirect = Indirect();
04473 indirect = BS_UnionD(indirect, Virtual_var(), mem_pool);
04474 Set_indirect(indirect);
04475
04476 if (Get_Trace(TP_GLOBOPT, ALIAS_DUMP_FLAG)) {
04477 fprintf(TFile, "Return vsym is %d\n", Return_vsym());
04478 fprintf(TFile, "\nAddr_saved bitset: ");
04479 BS_Print(Addr_saved(),TFile);
04480 fprintf(TFile, "\nAddr_passed bitset: ");
04481 BS_Print(Addr_passed(),TFile);
04482 fprintf(TFile, "\nAddr_used bitset: ");
04483 BS_Print(Addr_used_locally(),TFile);
04484 fprintf(TFile, "\nExternal bitset: ");
04485 BS_Print(External(),TFile);
04486 fprintf(TFile, "\nIndirect bitset: ");
04487 BS_Print(Indirect(),TFile);
04488 fprintf(TFile, "\nCall_by_value bitset: ");
04489 BS_Print(Call_by_value(),TFile);
04490 fprintf(TFile, "\nCall_by_ref bitset: ");
04491 BS_Print(Call_by_ref(),TFile);
04492 fprintf(TFile, "\n");
04493 }
04494 }
04495
04496
04497
04498
04499 void
04500 OPT_PU_POINTS_TO_SUMMARIZER::Bind_callee_points_to_summary
04501 (UNIFORM_NAME* ptr, PT_SET_MGR* pt_mgr, PT_SET_MGR* bound_pt_mgr) {
04502
04503 PT_SET* pt_set = pt_mgr->Points_to_set (ptr);
04504
04505 Is_True (ptr->Type () == UN_NAMED_GLOBAL,
04506 ("Currently we only handle global named pointer"));
04507 Is_True (!pt_set->Has_unknown_pt(),
04508 ("Currently we can handle only points-to pointing to"
04509 "named objects"));
04510
04511 UNAME_SPACE* bound_name_space = bound_pt_mgr->Name_space ();
04512
04513
04514 UNIFORM_NAME* bound_ptr =
04515 bound_name_space->Add_global(ptr->ST_for_named_global());
04516
04517
04518 PT_SET* bound_pt_set = CXX_NEW(PT_SET(*pt_set, Mem_pool()), Mem_pool());
04519 bound_pt_mgr->Associate (bound_ptr, bound_pt_set);
04520 }
04521
04522
04523
04524
04525
04526
04527
04528
04529 void
04530 OPT_PU_POINTS_TO_SUMMARIZER::Bind_callee_points_to_summary (WN* entry_wn) {
04531
04532 if (WOPT_Enable_Pt_Summary) {
04533 if (Tracing()) {
04534 fprintf (TFile, "\nBegin backward points-to binding\n");
04535 }
04536
04537 INT idx = 0;
04538 for (WN_ITER* wni = WN_WALK_StmtIter (entry_wn);
04539 wni != NULL; wni = WN_WALK_StmtNext (wni)) {
04540 WN* call = WN_ITER_wn(wni);
04541 if (WN_operator (call) != OPR_CALL) {
04542 continue;
04543 }
04544
04545 if (Tracing()) {
04546 fprintf (TFile, "CALL SITE %2d: ", idx++);
04547 fdump_wn (TFile, call);
04548 }
04549
04550 PU_POINTS_TO_SUMMARY* sum = Get_points_to_summary (WN_st(call));
04551 if (!sum) {
04552 if (Tracing()) {
04553 fprintf (TFile, "points-to summary is not found\n");
04554 }
04555 continue;
04556 }
04557
04558 PT_SET_MGR& pt_mgr = sum->Out_set ();
04559 UNAME_SPACE* ptrs = pt_mgr.Name_space();
04560 if (ptrs->Cardinality () == 0) {
04561
04562 continue;
04563 }
04564
04565 PU_POINTS_TO_SUMMARY* bound_sum =
04566 CXX_NEW(PU_POINTS_TO_SUMMARY(Mem_pool()), Mem_pool());
04567 Set_bound_pt_sum (call, bound_sum);
04568
04569 UNAME_SPACE* bound_name_space = bound_sum->Out_set().Name_space();
04570
04571
04572 for (UNAME_VECTOR_ITER ptr_iter = ptrs->All_names().begin ();
04573 ptr_iter != ptrs->All_names().end (); ptr_iter ++) {
04574
04575 UNIFORM_NAME* ptr = *ptr_iter;
04576 Bind_callee_points_to_summary (ptr, &pt_mgr, &bound_sum->Out_set());
04577 }
04578
04579 if (Tracing()) {
04580 bound_sum->Print (TFile);
04581 }
04582
04583 }
04584
04585 if (Tracing()) {
04586 fprintf (TFile, "End of backward points-to binding\n\n");
04587 }
04588 }
04589 }
04590
04591
04592
04593
04594 void
04595 OPT_PU_POINTS_TO_SUMMARIZER::Annotate_points_to_summary
04596 (UNIFORM_NAME* ptr, PT_SET_MGR* pt_set_mgr, CHI_LIST* chi_list) {
04597
04598 if (ptr->Type () == UN_NAMED_GLOBAL) {
04599 POINTS_TO pt;
04600 pt_set_mgr->Points_to_set (ptr)->Meet (&pt);
04601
04602 if (pt.Expr_kind() != EXPR_IS_INVALID) {
04603 ST* st = ptr->ST_for_named_global ();
04604 CHI_NODE* cnode;
04605 CHI_LIST_ITER chi_iter;
04606
04607 FOR_ALL_NODE (cnode, chi_iter, Init(chi_list)) {
04608 if (Opt_stab()->St(cnode->Aux_id()) == st) {
04609 POINTS_TO* new_pt = CXX_NEW(POINTS_TO, Opt_stab()->Ver_pool());
04610 new_pt->Copy_fully (pt);
04611
04612 VER_ID ver = cnode->Result();
04613 Opt_stab()->Ver_stab_entry(ver)->Set_points_to(new_pt);
04614
04615 if (Tracing()) {
04616 const char* indent = " ";
04617 fprintf (TFile, "%schi(%s) v%d<=%d\n%s", indent,
04618 ST_name(st), cnode->Result(), cnode->Opnd(), indent);
04619 new_pt->Print(TFile);
04620 }
04621 }
04622 }
04623 }
04624 }
04625 }
04626
04627
04628
04629
04630
04631
04632
04633
04634
04635 void
04636 OPT_PU_POINTS_TO_SUMMARIZER::Annotate_points_to_summary (void) {
04637
04638 CFG_ITER cfg_iter;
04639 BB_NODE* bb;
04640
04641 if (Tracing()) {
04642 fprintf (TFile, "\nBegin annotating points-to summary\n%s", DBar);
04643 }
04644
04645 FOR_ALL_ELEM (bb, cfg_iter, Init(Opt_stab()->Cfg())) {
04646 WN* stmt;
04647 STMT_ITER stmt_iter;
04648
04649 FOR_ALL_ELEM (stmt, stmt_iter, Init(bb->Firststmt(), bb->Laststmt())) {
04650 if (WN_operator(stmt) != OPR_CALL) continue;
04651
04652 if (Tracing()) {
04653 fprintf (TFile, "CALL SITE ");
04654 fdump_wn (TFile, stmt);
04655 }
04656
04657 PU_POINTS_TO_SUMMARY* sum = Get_bound_pt_sum (stmt);
04658 if (!sum) continue;
04659 UNAME_VECTOR& ptrs = sum->Out_set().Name_space()->All_names();
04660
04661 CHI_LIST* chi_list = Opt_stab()->Get_generic_chi_list (stmt);
04662
04663
04664 for (UNAME_VECTOR_ITER pt_iter = ptrs.begin ();
04665 pt_iter != ptrs.end (); pt_iter++) {
04666 Annotate_points_to_summary (*pt_iter, &sum->Out_set(), chi_list);
04667 }
04668 }
04669 }
04670
04671 if (Tracing()) {
04672 fprintf (TFile, "\nEnd annotating points-to summary\n%s", DBar);
04673 }
04674 }
04675
04676
04677
04678
04679 void
04680 OPT_PU_POINTS_TO_SUMMARIZER::Summarize_points_to
04681 (VER_ID ver, OPT_PU_POINTS_TO_SUMMARIZER::VER_ID_VISIT_CNT& visited,
04682 PT_SET& pt_set) {
04683
04684 POINTS_TO *pt = Opt_stab()->Ver_stab_entry(ver)->Points_to();
04685 if (pt && PU_POINTS_TO_SUMMARY::Pt_known_obj (pt)) {
04686 pt_set.Add_points_to (pt, PTC_DEFINITE, PT_MUST_POINTS_TO);
04687 return;
04688 }
04689
04690
04691 STMT_TYPE vtype = Opt_stab()->Ver_stab_entry(ver)->Type();
04692 AUX_ID aux_id = Opt_stab()->Ver_stab_entry(ver)->Aux_id();
04693 ST* st = Opt_stab()->Aux_stab_entry (aux_id)->St ();
04694
04695
04696 visited.Set_visited(ver);
04697
04698 switch (vtype) {
04699 case ENTRY_STMT:
04700 {
04701
04702 break;
04703 }
04704
04705 case WHIRL_STMT:
04706 {
04707 POINTS_TO* pt = Opt_stab()->Ver_stab_entry(ver)->Points_to();
04708 if (!pt) {
04709 POINTS_TO points_to;
04710 points_to.Init ();
04711 Opt_stab()->Simplify_Pointer_Ver (ver, &points_to);
04712 pt = Opt_stab()->Ver_stab_entry(ver)->Points_to();
04713 }
04714
04715 Is_True (pt != NULL, ("points-to for version %d is NULL", ver));
04716 if (PU_POINTS_TO_SUMMARY::Pt_known_obj (pt)) {
04717 pt_set.Add_points_to (pt, PTC_DEFINITE, PT_MUST_POINTS_TO);
04718 return;
04719 }
04720 }
04721 break;
04722
04723 case PHI_STMT:
04724 {
04725 BB_NODE *pred;
04726 BB_LIST_ITER bb_iter;
04727 BB_NODE *bb = Opt_stab()->Ver_stab_entry(ver)->Bb();
04728 PHI_NODE *phi = Opt_stab()->Ver_stab_entry(ver)->Phi();
04729
04730 INT i=0;
04731 FOR_ALL_ELEM (pred, bb_iter, Init(bb->Pred())) {
04732 VER_ID opnd_vid = phi->Opnd(i++);
04733 if (visited.Visited(opnd_vid)) {
04734 continue;
04735 }
04736 Summarize_points_to (opnd_vid, visited, pt_set);
04737 if (pt_set.Has_unknown_pt ()) {
04738 break;
04739 }
04740 }
04741 }
04742 return;
04743
04744 case CHI_STMT:
04745
04746
04747 if (!Opt_stab()->Ver_stab_entry(ver)->Synonym()) {
04748 VER_STAB_ENTRY* ver_ent = Opt_stab()->Ver_stab_entry(ver);
04749 WN* chi_wn = ver_ent->Chi_wn();
04750 if (WN_operator(chi_wn) == OPR_CALL) {
04751 ST* call_st = WN_st (chi_wn);
04752 if (call_st) {
04753 const char* st_name = ST_name(call_st);
04754 if (!strcmp (st_name, "exit")) {
04755
04756 return;
04757 } else if (!strcmp (st_name, "malloc") ||
04758 !strcmp (st_name, "fprintf") ||
04759 !strcmp (st_name, "printf")) {
04760
04761
04762
04763 Summarize_points_to (ver_ent->Chi()->Opnd(), visited, pt_set);
04764 return;
04765 }
04766 }
04767 } else if (OPERATOR_is_scalar_istore (WN_operator(chi_wn))) {
04768
04769 POINTS_TO* ptr =
04770 Opt_stab()->Aux_stab_entry(ver_ent->Aux_id())->Points_to();
04771 POINTS_TO* istore = Opt_stab()->Get_occ(chi_wn)->Points_to();
04772
04773 if (ptr && istore &&
04774 !Opt_stab()->Rule()->Aliased_Memop (ptr, istore)) {
04775
04776 Summarize_points_to (ver_ent->Chi()->Opnd(), visited, pt_set);
04777 return;
04778 }
04779 }
04780 } else {
04781 VER_ID synonym = Opt_stab()->Ver_stab_entry(ver)->Synonym();
04782 if (!visited.Visited (ver)) {
04783 Summarize_points_to (synonym, visited, pt_set);
04784 return;
04785 }
04786 }
04787 break;
04788 default:
04789 Warn_todo("unknown ver type");
04790 }
04791
04792 pt_set.Set_has_unkown_pt ();
04793 }
04794
04795 void
04796 OPT_PU_POINTS_TO_SUMMARIZER::Summarize_points_to (void) {
04797
04798 MEM_POOL_Popper popper(&MEM_local_pool);
04799
04800 BB_NODE* exit_bb = Opt_stab()->Cfg()->Fake_exit_bb() ?
04801 Opt_stab()->Cfg()->Fake_exit_bb() :
04802 Opt_stab()->Cfg()->Exit_bb ();
04803
04804 WN* wn = exit_bb->Laststmt ();
04805 if (wn == NULL ||
04806 WN_operator (wn) != OPR_RETURN && WN_operator (wn) != OPR_RETURN_VAL) {
04807 return;
04808 }
04809
04810 MU_LIST_ITER mu_iter;
04811 MU_NODE* mnode;
04812
04813
04814
04815
04816
04817
04818
04819
04820
04821 FOR_ALL_NODE (mnode, mu_iter, Init(Opt_stab()->Get_stmt_mu_list(wn))) {
04822 ST* st = Opt_stab()->St(mnode->Aux_id());
04823
04824
04825 if (!st || TY_kind(ST_type(st)) != KIND_POINTER ||
04826 ST_sclass (st) == SCLASS_PSTATIC) {
04827 continue;
04828 }
04829 VER_ID ver = mnode->Opnd();
04830
04831 PT_SET pt_set(popper.Pool());
04832 OPT_PU_POINTS_TO_SUMMARIZER::VER_ID_VISIT_CNT visited (popper.Pool());
04833 Summarize_points_to (ver, visited, pt_set);
04834
04835 if (pt_set.Has_unknown_pt () || pt_set.Certainty() != PTC_DEFINITE) {
04836
04837 continue;
04838 }
04839
04840 PT_SET_MGR& pt_set_mgr = Pu_summary()->Out_set ();
04841 UNIFORM_NAME* uname = pt_set_mgr.Add_global(st);
04842 PT_SET* old_pt_set = pt_set_mgr.Points_to_set (uname);
04843 if (old_pt_set == NULL) {
04844 PT_SET* t = CXX_NEW (PT_SET(pt_set, pt_set_mgr.Mem_pool()),
04845 pt_set_mgr.Mem_pool());
04846 pt_set_mgr.Associate (uname, t);
04847 } else {
04848 old_pt_set->Copy (pt_set);
04849 }
04850 }
04851 }
04852
04853 void
04854 OPT_STAB::Summarize_points_to (void) {
04855
04856 PU_POINTS_TO_SUMMARY* sum = _pt_sum.Pu_summary ();
04857 if (sum == NULL) {
04858 sum = Allocate_PU_Points_To_Summary ();
04859 FmtAssert (sum != NULL,
04860 ("fail to allocate data structure for points-to summary"));
04861 _pt_sum.Set_pu_summary (sum);
04862 }
04863
04864 _pt_sum.Summarize_points_to ();
04865 if (Get_Trace (TP_WOPT2, PT_SUMMARY_FLAG)) {
04866 fprintf (TFile, "Points-to summary for PU %s\n%s",
04867 ST_name(PU_Info_proc_sym(Current_PU_Info)), DBar);
04868 sum->Print (TFile);
04869 fprintf (TFile, DBar);
04870 }
04871 }
04872
04873
04874
04875
04876
04877 void OPT_STAB::Print_alias_info(FILE *fp)
04878 {
04879 AUX_ID i;
04880 AUX_STAB_ITER aux_stab_iter(this);
04881
04882 FOR_ALL_NODE(i, aux_stab_iter, Init()) {
04883 AUX_STAB_ENTRY *psym = &aux_stab[i];
04884 if (psym->Is_real_var() || psym->Is_virtual()) {
04885 fprintf(fp, "aux_id=%d ", i);
04886 psym->Points_to()->Print(fp);
04887 }
04888 }
04889 }
04890
04891
04892 void Print_points_to(FILE *fp, POINTS_TO *ptmp)
04893 {
04894 if (ptmp)
04895 ptmp->Print(fp);
04896 else
04897 fprintf(fp,"<NULL>\n");
04898 }
04899
04900