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 #define region_bounds_CXX "region_bounds.cxx"
00074 #ifdef _KEEP_RCS_ID
00075 static char *rcs_id = region_bounds_CXX"$Revision: 1.5 $";
00076 #endif
00077
00078 #include "wn.h"
00079 #include "wn_util.h"
00080 #include "ir_reader.h"
00081 #include "region_util.h"
00082 #include "tracing.h"
00083 #include "opt_cfg.h"
00084 #include "opt_main.h"
00085 #include "opt_alias_rule.h"
00086 #include "pragma_weak.h"
00087 #include "opt_points_to.h"
00088 #include "region_alias_templates.h"
00089 #include "data_layout.h"
00090
00091
00092
00093
00094 class REGION_BOUND {
00095 private:
00096 BOOL _trace;
00097 ALIAS_MANAGER *_alias_mgr;
00098 POINTS_TO *_all_alias_pt;
00099 STACK<RID *> _rstack;
00100
00101
00102 void Push(RID *rid) { _rstack.Push(rid); }
00103 RID *Pop(void) { return _rstack.Pop(); }
00104 BOOL Is_Empty(void) { return _rstack.Is_Empty(); }
00105 RID *Top(void) { return _rstack.Top(); }
00106 ALIAS_MANAGER *Am(void) { return _alias_mgr; }
00107 POINTS_TO *All_alias_pt(void) { return _all_alias_pt; }
00108 void Set_all_alias_pt(POINTS_TO *pt) { _all_alias_pt = pt; }
00109
00110 BOOL is_global(ST *);
00111 void GRB_merge_var(RID *, WN *);
00112 void GRB_merge_preg(RID *, WN *);
00113 void GRB_formal_ref(RID *, ST *, TY_IDX);
00114 void GRB_merge_preg(RID *, PREG_NUM, ST *);
00115 void GRB_merge_var(RID *, ST *, TY_IDX);
00116 void Propagate_boundary_up(RID *);
00117 void Convert_ST_list(RID *, WN *);
00118
00119 public:
00120 REGION_BOUND(ALIAS_MANAGER *alias_mgr, MEM_POOL *pool) :
00121 _alias_mgr(alias_mgr), _rstack(pool) {
00122
00123 _trace = Get_Trace(TP_REGION, TT_REGION_CG_DEBUG) ||
00124 Get_Trace(TP_REGION, TT_REGION_BOUND_DEBUG);
00125 _all_alias_pt = NULL;
00126 _rstack.Clear();
00127 Is_True(_alias_mgr != NULL,
00128 ("REGION_BOUND::REGION_BOUND alias manager is NULL"));
00129 }
00130 ~REGION_BOUND(void) { }
00131
00132 BOOL Trace(void) { return _trace; }
00133 void grb(WN *);
00134 void prune(RID *);
00135 };
00136
00137
00138 inline BOOL
00139 REGION_BOUND::is_global(ST *st)
00140 {
00141 switch (ST_sclass(st)) {
00142 case SCLASS_PSTATIC:
00143 case SCLASS_FSTATIC:
00144 case SCLASS_COMMON:
00145 case SCLASS_EXTERN:
00146 case SCLASS_UGLOBAL:
00147 case SCLASS_DGLOBAL:
00148 return TRUE;
00149 default:
00150 return FALSE;
00151 }
00152 }
00153
00154
00155
00156
00157 void
00158 REGION_BOUND::GRB_merge_preg(RID *rid, WN *wn)
00159 {
00160 ST *st = WN_st(wn);
00161
00162
00163 WN_OFFSET off = WN_load_offset(wn);
00164
00165
00166
00167 BOOL added = REGION_add_preg_in(rid, off, ST_btype(st));
00168
00169 Is_True(WN_operator(wn) == OPR_STID || WN_operator(wn) == OPR_LDID,
00170 ("REGION_BOUND::GRB_merge_preg, unknown operator"));
00171 BOOL is_stid = (WN_operator(wn) == OPR_STID);
00172
00173
00174 if (is_stid) {
00175
00176
00177
00178
00179
00180 added = TRUE;
00181 for (INT i=0; i<RID_num_exits(rid) && added; i++)
00182 added = REGION_add_preg_out(rid, i, off, ST_btype(st));
00183 }
00184 Is_Trace(Trace() && added, (TFile,"REGION_BOUND::GRB_merge_preg, RGN %d, "
00185 "adding %s %d\n",RID_id(rid),ST_name(st),off));
00186 }
00187
00188
00189
00190
00191
00192
00193 inline void
00194 REGION_BOUND::GRB_formal_ref(RID *rid, ST *st, TY_IDX ty)
00195 {
00196 Is_True(st != NULL, ("REGION_BOUND::GRB_formal_ref, NULL ST"));
00197 if (ST_sclass(st) == SCLASS_FORMAL_REF) {
00198 ST *base = Get_ST_formal_ref_base(st);
00199 Is_True(base != NULL,
00200 ("REGION_BOUND::GRB_formal_ref, no base for formal ref"));
00201 PREG_NUM preg = Get_ST_formal_preg_num(base);
00202 if (preg != 0)
00203 GRB_merge_preg(rid, preg, base);
00204 else
00205 GRB_merge_var(rid, st, ty);
00206 }
00207 }
00208
00209
00210
00211 void
00212 REGION_BOUND::GRB_merge_preg(RID *rid, PREG_NUM pr, ST *st)
00213 {
00214
00215
00216 BOOL added = REGION_add_preg_in(rid, pr, MTYPE_V);
00217
00218 Is_Trace(Trace() && added, (TFile,"REGION_BOUND::GRB_merge_preg2, RGN %d, "
00219 "adding %s %d\n", RID_id(rid), ST_name(st), pr));
00220 }
00221
00222
00223
00224 void
00225 REGION_BOUND::GRB_merge_var(RID *rid, ST *st, TY_IDX ty)
00226 {
00227 Is_True(st != NULL, ("REGION_BOUND::GRB_merge_var2, NULL ST"));
00228 Is_True(ty != (TY_IDX) 0, ("REGION_BOUND::GRB_merge_var2, NULL TY"));
00229
00230 POINTS_TO pt;
00231 INT64 size = TY_size(ty);
00232 Is_True(size != 0,
00233 ("REGION_BOUND::GRB_merge_var2, ST size is wrong"));
00234 pt.Analyze_ST(st, 0, size, 0, 0,
00235 ty, FALSE);
00236
00237 if (!REGION_search_set(RID_used_in(rid),
00238 comp_same_pt(&pt, Am()->Rule()))) {
00239 REGION_add_points_to(&RID_used_in(rid), &pt, Am());
00240 Is_Trace(Trace(), (TFile,"REGION_BOUND::GRB_merge_var2, RGN %d, "
00241 "adding %s\n", RID_id(rid), ST_name(st)));
00242 }
00243 }
00244
00245
00246
00247
00248 #pragma weak Meet__9POINTS_TOGPC9POINTS_TOP2ST
00249
00250
00251
00252
00253
00254
00255 void
00256 REGION_BOUND::GRB_merge_var(RID *rid, WN *wn)
00257 {
00258 Is_True(Am() != NULL, ("REGION_BOUNDS:GRB_merge_var(), NULL alias manager"));
00259
00260
00261 POINTS_TO pt;
00262 pt.Analyze_WN_expr(wn);
00263
00264
00265
00266
00267 Is_True(WN_operator(wn) == OPR_STID || WN_operator(wn) == OPR_LDID,
00268 ("REGION_BOUND::GRB_merge_var, unknown operator"));
00269 BOOL is_stid = (WN_operator(wn) == OPR_STID);
00270 BOOL added = FALSE;
00271
00272
00273 if (!REGION_search_set(RID_used_in(rid),
00274 comp_same_pt(&pt, Am()->Rule()))) {
00275 REGION_add_wn_points_to(&RID_used_in(rid), wn, Am());
00276 added = TRUE;
00277 }
00278
00279
00280 if (is_stid && !REGION_search_set(RID_def_in_live_out(rid),
00281 comp_same_pt(&pt, Am()->Rule()))) {
00282 REGION_add_wn_points_to(&RID_def_in_live_out(rid), wn, Am());
00283 added = TRUE;
00284 }
00285
00286 Is_Trace(Trace() && added, (TFile,"REGION_BOUND::GRB_merge_var, RGN %d, "
00287 "added variable %s to %s\n", RID_id(rid), ST_name(WN_st(wn)),
00288 is_stid ? "in/out sets" : "in set"));
00289 }
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299 void
00300 REGION_BOUND::Propagate_boundary_up(RID *rid)
00301 {
00302 if ( !Is_Empty() ) {
00303 Is_True(rid != Top(),
00304 ("REGION_BOUND::Propagate_boundary_up, TOS is same as rid"));
00305 Is_True(RID_bounds_exist(rid) == REGION_BOUND_EXISTS,
00306 ("REGION_BOUND::Propagate_boundary_up, bounds do not exist"));
00307 Is_Trace(Trace(), (TFile,"Propagate up: RGN %d to RGN %d\n",
00308 RID_id(rid), RID_id(Top())));
00309
00310
00311 for (POINTS_TO_SET *ptmp=RID_used_in(rid); ptmp; ptmp=ptmp->Next) {
00312 if (!REGION_search_set(RID_used_in(Top()),
00313 comp_same_pt(ptmp->Pt, Am()->Rule()))) {
00314
00315 REGION_add_points_to(&RID_used_in(Top()), ptmp->Pt, Am());
00316 REGION_add_points_to(&RID_def_in_live_out(Top()), ptmp->Pt, Am());
00317 }
00318 }
00319
00320
00321 PREG_LIST *ptmp2;
00322 for (ptmp2=RID_pregs_in(rid); ptmp2;
00323 ptmp2=PREG_LIST_rest(ptmp2)) {
00324 PREG_NUM pr = PREG_LIST_first(ptmp2);
00325
00326 TYPE_ID type = MTYPE_V;
00327 if (REGION_search_preg_set(RID_pregs_quad(rid), pr))
00328 type = MTYPE_FQ;
00329 else if (REGION_search_preg_set(RID_pregs_complex_quad(rid), pr))
00330 type = MTYPE_CQ;
00331
00332 REGION_add_preg_in(Top(), pr, type);
00333 }
00334
00335
00336 for (INT32 j=0; j<RID_num_exits(rid); j++) {
00337 for (ptmp2=RID_pregs_out_i(rid, j); ptmp2;
00338 ptmp2=PREG_LIST_rest(ptmp2)) {
00339 PREG_NUM pr = PREG_LIST_first(ptmp2);
00340
00341 TYPE_ID type = MTYPE_V;
00342 if (REGION_search_preg_set(RID_pregs_quad(rid), pr))
00343 type = MTYPE_FQ;
00344 else if (REGION_search_preg_set(RID_pregs_complex_quad(rid), pr))
00345 type = MTYPE_CQ;
00346
00347 for (INT32 i=0; i<RID_num_exits(Top()); i++)
00348 REGION_add_preg_out(Top(), i, pr, type);
00349 }
00350 }
00351 }
00352 }
00353
00354
00355
00356
00357
00358
00359 void
00360 REGION_BOUND::Convert_ST_list(RID *rid, WN *wn)
00361 {
00362 Is_True(WN_opcode(wn) == OPC_FORWARD_BARRIER ||
00363 WN_opcode(wn) == OPC_BACKWARD_BARRIER,
00364 ("REGION_BOUND::Convert_ST_list, not a barrier"));
00365
00366
00367 if (WN_kid_count(wn) == 0)
00368 RID_contains_barrier(rid) = TRUE;
00369 else {
00370 for (INT i=0; i<WN_kid_count(wn); i++) {
00371
00372 ST *st = WN_st(WN_kid(wn, i));
00373 Is_True(ST_class (st) == CLASS_VAR,
00374 ("OPT_STAB::Create_barrier_defs: barrier contains non-var ST"));
00375 POINTS_TO pt;
00376 Is_True(ST_sclass(st) != SCLASS_UNKNOWN,(""));
00377 INT64 ofst = 0;
00378 TY& ty = Ty_Table[ST_type (st)];
00379 INT64 size = TY_size (ty);
00380 pt.Analyze_ST(st, ofst, size, 0, 0, ST_type(st), TRUE);
00381
00382
00383 if (!REGION_search_set(RID_used_in(rid),
00384 comp_same_pt(&pt, Am()->Rule()))) {
00385 REGION_add_points_to(&RID_used_in(rid), &pt, Am());
00386 Is_True(REGION_search_set(RID_def_in_live_out(rid),
00387 comp_same_pt(&pt, Am()->Rule())),
00388 ("REGION_BOUND::Convert_ST_list, pt not found in used_in "
00389 "but in live_out"));
00390 REGION_add_points_to(&RID_def_in_live_out(rid), &pt, Am());
00391 }
00392 }
00393 }
00394 }
00395
00396
00397
00398 void
00399 REGION_BOUND::grb(WN *wn)
00400 {
00401 WN *wtmp;
00402 RID *rid;
00403 INT i;
00404 BOOL push_rid = FALSE;
00405
00406 Is_True(wn != NULL, ("REGION_BOUND::grb NULL WN"));
00407
00408
00409
00410
00411
00412
00413 if (WN_opcode(wn) == OPC_REGION) {
00414 rid = REGION_get_rid(wn);
00415 Is_True(rid != NULL, ("REGION_BOUND:grb, NULL RID"));
00416
00417 if (RID_TYPE_transparent(rid))
00418 rid = (Is_Empty()) ? NULL : Top();
00419 else
00420 push_rid = TRUE;
00421 } else
00422 rid = (Is_Empty()) ? NULL : Top();
00423
00424 switch (WN_operator(wn)) {
00425
00426
00427
00428
00429 case OPR_LDID:
00430 case OPR_STID:
00431 {
00432 Is_True(rid != NULL && !RID_TYPE_transparent(rid),
00433 ("REGION_BOUND::grb, transparent rgn"));
00434 ST *st = WN_st(wn);
00435 Is_True(st != NULL, ("REGION_BOUND::grb, NULL ST"));
00436 TY_IDX ty = WN_ty(wn);
00437 Is_True(ty != (TY_IDX) 0, ("REGION_BOUND::grb, NULL TY"));
00438
00439
00440
00441
00442 BOOL cond = TY_is_volatile(ty);
00443
00444
00445 cond |= is_global(st) && RID_aliased_to_globals(rid);
00446 if (!cond) {
00447
00448 if (ST_class(st) == CLASS_PREG) {
00449
00450 if (WN_offset(wn) != 32 && WN_offset(wn) != 2)
00451 GRB_merge_preg(rid, wn);
00452 } else
00453 GRB_merge_var(rid, wn);
00454 }
00455
00456
00457
00458 GRB_formal_ref(rid, st, ty);
00459
00460
00461 for (i=0; i<WN_kid_count(wn); i++)
00462 grb(WN_kid(wn,i));
00463 }
00464 break;
00465
00466 case OPR_LDA:
00467
00468 Is_True(rid != NULL && !RID_TYPE_transparent(rid),
00469 ("REGION_BOUND::grb, transparent rgn"));
00470
00471
00472
00473 GRB_formal_ref(rid, WN_st(wn), WN_ty(wn));
00474 break;
00475
00476 case OPR_PARM:
00477 case OPR_ILOAD:
00478 case OPR_MLOAD:
00479 case OPR_ILOADX:
00480 case OPR_ISTORE:
00481 case OPR_MSTORE:
00482 case OPR_ISTOREX:
00483
00484 Is_True(rid != NULL && !RID_TYPE_transparent(rid),
00485 ("REGION_BOUND::grb, transparent rgn"));
00486 {
00487 POINTS_TO pt;
00488 pt.Analyze_WN_expr(wn);
00489 if (pt.Base_is_fixed() || pt.Restricted() || pt.Unique_pt() ||
00490 pt.F_param()) {
00491
00492 if (!REGION_search_set(RID_used_in(rid),
00493 comp_same_pt(&pt, Am()->Rule()))) {
00494
00495 REGION_add_points_to(&RID_used_in(rid), &pt, Am());
00496 REGION_add_points_to(&RID_def_in_live_out(rid), &pt, Am());
00497 }
00498 } else
00499 RID_aliased_to_indirects(rid) = TRUE;
00500 }
00501
00502
00503 for (i=0; i<WN_kid_count(wn); i++)
00504 grb(WN_kid(wn,i));
00505 break;
00506
00507
00508
00509 case OPR_REGION:
00510 { RID *rtmp;
00511
00512
00513 if (push_rid) {
00514 Is_True(rid != NULL && REGION_get_rid(wn) == rid &&
00515 !RID_TYPE_transparent(rid),
00516 ("REGION_BOUND::grb, rid is wrong for region with bounds"));
00517 Is_True(RID_rwn(REGION_get_rid(wn)) == wn,
00518 ("REGION_BOUND::grb, RID <-> WN inconsistency"));
00519
00520
00521 Push(rid);
00522
00523
00524 for (wtmp=WN_first(WN_region_body(wn)); wtmp; wtmp=WN_next(wtmp))
00525 grb(wtmp);
00526
00527 RID *rtmp2 = Pop();
00528 Is_True(rtmp2 == rid, ("REGION_BOUND::grb, stack inconsistency"));
00529
00530
00531
00532 RID_bounds_exist(rid) = REGION_BOUND_EXISTS;
00533 RID_level(rid) = RL_RBI;
00534
00535
00536
00537 Propagate_boundary_up(rid);
00538
00539 } else {
00540
00541
00542
00543 if (rid != NULL) {
00544 Is_True(rid == Top(),("REGION_BOUND::grb, rid != Top()"));
00545
00546
00547 for (wtmp=WN_first(WN_region_body(wn)); wtmp; wtmp=WN_next(wtmp))
00548 grb(wtmp);
00549 } else {
00550
00551
00552
00553 rid = REGION_get_rid(wn);
00554
00555
00556 Is_True(rid != NULL, ("REGION_BOUND:grb, NULL RID"));
00557 Is_True(RID_TYPE_transparent(rid),
00558 ("REGION_BOUND::grb, region is not transparent"));
00559 for (rtmp = RID_first_kid(rid); rtmp != NULL; rtmp=RID_next(rtmp))
00560 grb(RID_rwn(rtmp));
00561 }
00562 }
00563 }
00564 break;
00565
00566 case OPR_FUNC_ENTRY:
00567 { RID *rtmp;
00568 Is_True(rid == NULL, ("REGION_BOUND::grb, rid should be NULL here"));
00569 rid = REGION_get_rid(wn);
00570 Is_True(rid != NULL && RID_TYPE_func_entry(rid),
00571 ("REGION_BOUND::grb, rid messed up for func_entry"));
00572 Is_Trace(Trace(),(TFile,"===== Generate_region_boundaries (GRB) %s\n",
00573 ST_name(WN_st(wn))));
00574
00575
00576
00577
00578
00579 for (rtmp = RID_first_kid(rid); rtmp != NULL; rtmp = RID_next(rtmp))
00580 grb(RID_rwn(rtmp));
00581 }
00582 break;
00583
00584 case OPR_CALL:
00585 RID_aliased_to_globals(rid) = TRUE;
00586 RID_aliased_to_indirects(rid) = TRUE;
00587
00588
00589
00590 if (Is_nested_call(wn, STAB_ADAPTER()))
00591 RID_contains_uplevel(rid) = TRUE;
00592
00593
00594 for (i=0; i<WN_kid_count(wn); i++) {
00595 WN *wtmp2 = WN_kid(wn, i);
00596 Is_True(WN_operator(wtmp2) == OPR_PARM,
00597 ("REGION_BOUND::grb, CALL sequence error"));
00598 grb(wtmp2);
00599 }
00600 break;
00601
00602 case OPR_FORWARD_BARRIER:
00603 case OPR_BACKWARD_BARRIER:
00604 Convert_ST_list(rid, wn);
00605 break;
00606
00607 case OPR_BLOCK:
00608 for (wtmp=WN_first(wn); wtmp; wtmp=WN_next(wtmp))
00609 grb(wtmp);
00610 break;
00611
00612 default:
00613 for (i=0; i<WN_kid_count(wn); i++)
00614 grb(WN_kid(wn, i));
00615 break;
00616 }
00617 }
00618
00619 void
00620 REGION_BOUND::prune(RID *rid)
00621 {
00622 Is_True(rid != NULL, ("REGION_BOUND::prune, NULL RID"));
00623 Is_Trace(Trace(), (TFile, "REGION_BOUND::prune boundary sets called\n"));
00624
00625
00626
00627
00628 }
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649 extern "C"
00650 void Generate_region_boundaries(WN *wn, ALIAS_MANAGER *am)
00651 {
00652 Is_True(wn != NULL && WN_opcode(wn) == OPC_FUNC_ENTRY,
00653 ("Generate_region_boundaries, NULL WN or not a PU"));
00654 RID *root_rid = REGION_get_rid(wn);
00655 Is_True(root_rid != NULL && RID_TYPE_func_entry(root_rid),
00656 ("Generate_region_boundaries, invalid RID type"));
00657
00658
00659 REGION_BOUND rb(am, ®ION_mem_pool);
00660 rb.grb(wn);
00661 rb.prune(REGION_get_rid(wn));
00662
00663 Is_Trace(rb.Trace(),
00664 (TFile,"Generate_region_boundaries (GRB) final sets:\n"));
00665 Is_Trace_cmd(rb.Trace(), RID_set_print(TFile, root_rid));
00666 }
00667
00668
00669
00670
00671
00672
00673
00674 extern "C"
00675 BOOL REGION_search_preg_set(PREG_LIST *pset, PREG_NUM pr)
00676 {
00677 PREG_LIST *ptmp;
00678 for (ptmp = pset; ptmp; ptmp = PREG_LIST_rest(ptmp)) {
00679 if (pr == PREG_LIST_first(ptmp))
00680 return TRUE;
00681 }
00682 return FALSE;
00683 }