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 #ifdef USE_PCH
00058 #include "opt_pch.h"
00059 #endif // USE_PCH
00060 #pragma hdrstop
00061
00062
00063 #ifdef _KEEP_RCS_ID
00064 #define opt_region_emit_CXX "opt_region_emit.cxx"
00065 static char *rcs_id = opt_region_emit_CXX"$Revision$";
00066 #endif
00067
00068 #include "defs.h"
00069 #include "tracing.h"
00070
00071 #include "region_util.h"
00072
00073 #include "opt_base.h"
00074 #include "opt_bb.h"
00075 #include "opt_cfg.h"
00076 #include "opt_htable.h"
00077 #include "opt_region_emit.h"
00078 #include "opt_mu_chi.h"
00079 #include "config.h"
00080
00081 #include "bitset.h"
00082
00083
00084
00085
00086
00087 static BOOL
00088 Required_pragmas_for_region( WN * region_pragma_list )
00089 {
00090 Is_True( WN_operator(region_pragma_list) == OPR_BLOCK,
00091 ("Required_pragmas_for_region: not a block") );
00092
00093 for ( WN *stmt = WN_first(region_pragma_list);
00094 stmt != NULL;
00095 stmt = WN_next(stmt) )
00096 {
00097 const OPERATOR opr = WN_operator(stmt);
00098
00099 if ( opr == OPR_PRAGMA || opr == OPR_XPRAGMA ) {
00100 WN_PRAGMA_ID pragma = (WN_PRAGMA_ID)WN_pragma(stmt);
00101
00102 switch ( pragma ) {
00103 case WN_PRAGMA_COPYIN:
00104 return TRUE;
00105
00106 default:
00107 break;
00108 }
00109 }
00110 }
00111
00112
00113 return FALSE;
00114 }
00115
00116
00117
00118
00119
00120 void
00121 Push_region(STACK<E_REGION *> *stk, BB_NODE *start_region, MEM_POOL *pool)
00122 {
00123 Is_True(start_region->Kind() == BB_REGIONSTART,
00124 ("Push_region, region start not found"));
00125 BB_REGION *bb_region = start_region->Regioninfo();
00126 BB_NODE *end_region = bb_region->Region_end();
00127
00128 E_REGION *e_region = CXX_NEW(E_REGION(start_region, end_region), pool);
00129
00130 stk->Push(e_region);
00131 }
00132
00133 WN*
00134 Pop_region(STACK<E_REGION *> *stk, WN *first_wn, WN *last_wn,
00135 REGION_LEVEL rgn_level, OPT_STAB *opt_stab )
00136 {
00137 E_REGION *e_region = stk->Pop();
00138 BB_REGION *bb_region = e_region->Region_start()->Regioninfo();
00139 WN *region_wn = NULL;
00140
00141
00142 if (RID_TYPE_guard(bb_region->Rid()) && first_wn == NULL && last_wn == NULL){
00143 first_wn = last_wn = WN_CreateComment("EH GUARD REGION");
00144 }
00145
00146
00147 if ( first_wn == NULL && last_wn == NULL &&
00148 Required_pragmas_for_region(bb_region->Region_pragma_list()) )
00149 {
00150 first_wn = last_wn = WN_CreateComment("REQUIRED PRAGMAS FOR REGION");
00151 }
00152
00153
00154
00155 if ( first_wn != NULL ) {
00156
00157 WN *region_body = WN_CreateBlock();
00158 Is_True(first_wn != NULL,("EMITTER::Pop_region, null first statement"));
00159 WN_first(region_body) = first_wn;
00160 Is_True(last_wn != NULL,("EMITTER::Pop_region, null last statement"));
00161 WN_last(region_body) = last_wn;
00162 region_wn = WN_CreateRegion(REGION_type_to_kind(bb_region->Rid()),
00163 region_body,
00164 bb_region->Region_pragma_list(),
00165 bb_region->Region_exit_list(),
00166 RID_id(bb_region->Rid()),
00167 bb_region->Ereg_supp());
00168 WN_COPY_All_Maps(region_wn, bb_region->Orig_wn());
00169
00170
00171 if (REGION_is_EH(region_wn))
00172 opt_stab->Convert_EH_pragmas(region_wn);
00173
00174
00175 REGION_emit(bb_region->Rid(), region_wn, rgn_level,
00176 bb_region->Region_num_exits(), bb_region->Region_line_num());
00177 }
00178 return region_wn;
00179 }
00180
00181
00182
00183
00184
00185
00186 void
00187 REGION_live_in_from_chi(RID *rid,
00188 CHI_LIST *clist,
00189 OPT_STAB *opt_stab,
00190 ALIAS_MANAGER *alias_mgr)
00191 {
00192 Is_True(PU_has_region(Get_Current_PU()),
00193 ("REGION_live_in_from_chi, regions are off"));
00194
00195 if (Get_Trace(TP_REGION,TT_REGION_ALL)) {
00196 fprintf(TFile,"===== REGION_live_in_from_chi, RGN#%d\n",
00197 RID_id(rid));
00198 clist->Print(TFile);
00199 }
00200
00201 CHI_LIST_ITER chi_iter;
00202 CHI_NODE *cnode;
00203 FOR_ALL_NODE(cnode, chi_iter, Init(clist)) {
00204 if (cnode->Live()) {
00205 AUX_STAB_ENTRY *psym = opt_stab->Aux_stab_entry(cnode->Aux_id());
00206 if ((psym->Is_real_var() && !psym->Is_volatile()) ||
00207 psym->Is_virtual()) {
00208 POINTS_TO *aux_pt = psym->Points_to();
00209 ST *st = opt_stab->St(cnode->Aux_id());
00210 if (st && ST_class(st) == CLASS_PREG) {
00211 PREG_NUM pnum = opt_stab->St_ofst(cnode->Aux_id());
00212 REGION_add_preg_in(rid, pnum, ST_btype(st));
00213 } else {
00214 POINTS_TO *pt = opt_stab->Points_to(cnode->Aux_id());
00215 REGION_add_points_to(&RID_used_in(rid), pt, alias_mgr);
00216 }
00217 }
00218 }
00219 }
00220 RID_bounds_exist(rid) = REGION_BOUND_EXISTS;
00221 }
00222
00223
00224 void
00225 REGION_live_out_from_mu(RID *rid,
00226 MU_LIST *mlist,
00227 OPT_STAB *opt_stab,
00228 ALIAS_MANAGER *alias_mgr)
00229 {
00230 Is_True(PU_has_region(Get_Current_PU()),
00231 ("REGION_live_out_from_mu, regions are off"));
00232
00233 if (Get_Trace(TP_REGION,TT_REGION_ALL)) {
00234 fprintf(TFile,"===== REGION_live_out_from_mu, RGN#%d\n",
00235 RID_id(rid));
00236 mlist->Print(TFile);
00237 }
00238
00239 MU_LIST_ITER mu_iter;
00240 MU_NODE *mnode;
00241 FOR_ALL_NODE(mnode, mu_iter, Init(mlist)) {
00242 AUX_STAB_ENTRY *psym = opt_stab->Aux_stab_entry(mnode->Aux_id());
00243 if ((psym->Is_real_var() && !psym->Is_volatile()) ||
00244 psym->Is_virtual()) {
00245 POINTS_TO *aux_pt = psym->Points_to();
00246 ST *st = opt_stab->St(mnode->Aux_id());
00247 if (st && ST_class(st) == CLASS_PREG) {
00248
00249
00250 PREG_NUM pnum = opt_stab->St_ofst(mnode->Aux_id());
00251 REGION_add_preg_out(rid, 0 ,
00252 pnum, ST_btype(st));
00253 } else {
00254 POINTS_TO *pt = opt_stab->Points_to(mnode->Aux_id());
00255 REGION_add_points_to(&RID_def_in_live_out(rid), pt, alias_mgr);
00256 }
00257 }
00258 }
00259 RID_bounds_exist(rid) = REGION_BOUND_EXISTS;
00260 }
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270 void
00271 PRUNE_BOUND::Useset_expr(CODEREP *cr)
00272 {
00273 switch (cr->Kind()) {
00274 case CK_LDA:
00275 case CK_CONST:
00276 case CK_RCONST:
00277 break;
00278
00279 case CK_VAR:
00280 {
00281
00282 AUX_ID aux_id = cr->Aux_id();
00283 ST *st = _opt_stab->St(aux_id);
00284 if (st && ST_class(st) == CLASS_PREG) {
00285 Is_Trace(Trace(), (TFile, "Useset_expr, adding Aux_id %d, "
00286 "PREG %d\n", aux_id,
00287 (PREG_NUM) _opt_stab->St_ofst(aux_id)));
00288 FBS_Union1D(_useset, aux_id);
00289 }
00290 }
00291 break;
00292
00293 case CK_IVAR:
00294 Useset_expr(cr->Ilod_base());
00295 if (cr->Opr() == OPR_MLOAD)
00296 Useset_expr(cr->Mload_size());
00297 else if (cr->Opr() == OPR_ILOADX)
00298 Useset_expr(cr->Index());
00299 break;
00300
00301 case CK_OP:
00302 {
00303 for (INT32 i=0; i<cr->Kid_count(); i++)
00304 Useset_expr(cr->Opnd(i));
00305 }
00306 break;
00307
00308 default:
00309 Is_True(FALSE, ("PRUNE_BOUND::Useset_expr: unexpected CK_KIND"));
00310 break;
00311 }
00312 }
00313
00314
00315
00316 void
00317 PRUNE_BOUND::Useset_stmt(STMTREP *stmt)
00318 {
00319 if (stmt->Rhs())
00320 Useset_expr(stmt->Rhs());
00321 switch (stmt->Opr()) {
00322 case OPR_ISTORE:
00323 case OPR_ISTBITS:
00324 Useset_expr(stmt->Lhs()->Istr_base());
00325 break;
00326 case OPR_MSTORE:
00327 {
00328 Useset_expr(stmt->Lhs()->Istr_base());
00329 CODEREP *num_bytes = (CODEREP *)stmt->Lhs()->Mstore_size();
00330 Useset_expr(num_bytes);
00331 }
00332 break;
00333 default:
00334 ;
00335 }
00336 }
00337
00338
00339 void
00340 PRUNE_BOUND::Collect_mod_use_sets(BB_NODE *bb)
00341 {
00342
00343 STMTREP_ITER stmt_iter(bb->Stmtlist());
00344 STMTREP *stmt;
00345 FOR_ALL_NODE(stmt, stmt_iter, Init()) {
00346
00347 if (OPERATOR_is_scalar_store (stmt->Opr()))
00348 FBS_Union1D(_modset, stmt->Lhs()->Aux_id());
00349
00350 Useset_stmt(stmt);
00351 }
00352
00353 BB_NODE *dom_bb;
00354 BB_LIST_ITER dom_bb_iter;
00355 FOR_ALL_ELEM(dom_bb, dom_bb_iter, Init(bb->Dom_bbs()))
00356 Collect_mod_use_sets(dom_bb);
00357 }
00358
00359
00360 #if 0
00361
00362
00363
00364 void REGION_remove_aux_id_points_to(POINTS_TO_SET *pset, AUX_ID aux_id,
00365 OPT_STAB *opt_stab)
00366 {
00367 POINTS_TO_REF *tmp, *prev = NULL;
00368
00369 for (tmp=pset->Elements; tmp!=NULL; tmp=tmp->Next) {
00370 if (Compare_points_to(opt_stab->Points_to(aux_id), tmp->Pt)) {
00371 if (prev == NULL)
00372 pset->Elements = tmp->Next;
00373 else
00374 prev->Next = tmp->Next;
00375 return;
00376 }
00377 prev = tmp;
00378 }
00379 }
00380
00381
00382 BOOL
00383 PRUNE_BOUND::Compare_points_to(POINTS_TO *p1, POINTS_TO *p2)
00384 {
00385 if (p1->Base() == p2->Base() && p1->Ofst() == p2->Ofst() &&
00386 p1->Size() == p2->Size())
00387 return TRUE;
00388 return FALSE;
00389 }
00390 #endif
00391
00392
00393
00394
00395
00396 void
00397 PRUNE_BOUND::REGION_remove_from_bound(AUX_ID aux_id, BOOL outset)
00398 {
00399 RID *rid = _cfg->Rid();
00400 Is_True(rid != NULL, ("PRUNE_BOUND::REGION_remove_from_bound, NULL RID"));
00401
00402
00403 if (aux_id == _opt_stab->Return_vsym()) {
00404 Is_Trace(Trace(),(TFile,"Return_vsym(), aux_id %d\n",aux_id));
00405 return;
00406 }
00407
00408 POINTS_TO *pt = _opt_stab->Points_to(aux_id);
00409 ST *st = pt->Base();
00410
00411 Is_True(st != NULL, ("PRUNE_BOUND::REGION_remove_from_bound, NULL st"));
00412
00413 #if 0
00414
00415
00416 if (st && ST_class(st) == CLASS_PREG) {
00417 BOOL ret = REGION_remove_preg(rid, pt->Ofst(), outset);
00418 Is_Trace(Trace() && ret,(TFile,"===== REGION_remove_from_bound (RGN %d), "
00419 "removing PREG %d, aux_id %d, %s\n", RID_id(rid),
00420 (PREG_NUM) pt->Ofst(), aux_id,
00421 outset ? "out-set" : "in-set"));
00422 }
00423 #endif
00424
00425
00426
00427
00428
00429
00430
00431 }
00432
00433
00434
00435
00436
00437
00438 void
00439 PRUNE_BOUND::Prune_boundary_sets(void)
00440 {
00441
00442 Collect_mod_use_sets(_cfg->Entry_bb());
00443
00444 if (Trace()) {
00445 fprintf(TFile,"PRUNE_BOUND::Prune_boundary_sets, modset: ");
00446 BS_Print(_modset,TFile);
00447 fprintf(TFile,"\nPRUNE_BOUND::Prune_boundary_sets, useset: ");
00448 BS_Print(_useset,TFile);
00449 fprintf(TFile,"\n");
00450 RID_set_print(TFile, _cfg->Rid());
00451 }
00452
00453 AUX_ID idx;
00454 AUX_STAB_ITER aux_stab_iter(_opt_stab);
00455 FOR_ALL_NODE(idx, aux_stab_iter, Init()) {
00456 if (_opt_stab->Aux_stab_entry(idx)->Is_real_var()) {
00457 if (!FBS_MemberP(_modset, idx))
00458 REGION_remove_from_bound(idx, TRUE);
00459 if (!FBS_MemberP(_useset, idx))
00460 REGION_remove_from_bound(idx, FALSE);
00461 }
00462 }
00463 }