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 #ifdef USE_PCH
00065 #include "opt_pch.h"
00066 #endif // USE_PCH
00067 #pragma hdrstop
00068
00069
00070 #include "defs.h"
00071 #include "errors.h"
00072 #include "erglob.h"
00073 #include "glob.h"
00074 #include "tracing.h"
00075 #include "pf_cg.h"
00076
00077 #include "cxx_base.h"
00078 #include "erbe.h"
00079
00080 #include "opt_base.h"
00081 #include "opt_bb.h"
00082 #include "opt_config.h"
00083 #include "config_opt.h"
00084 #include "opt_sys.h"
00085 #include "bb_node_set.h"
00086 #include "idx_32_set.h"
00087 #include "opt_cfg.h"
00088 #include "opt_ssa.h"
00089 #include "opt_sym.h"
00090 #include "opt_mu_chi.h"
00091 #include "opt_htable.h"
00092 #include "opt_main.h"
00093 #include "opt_alias_rule.h"
00094 #include "opt_exc.h"
00095 #include "opt_util.h"
00096 #include "opt_project.h"
00097 #include "opt_dce.h"
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107 class DCE {
00108 private:
00109 OPT_PHASE _opt_phase;
00110 BOOL _is_varargs_func;
00111 BOOL _enable_dce_global;
00112 BOOL _enable_dce_alias;
00113 BOOL _do_unreachable;
00114 BOOL _enable_agg_dce;
00115 BOOL _enable_identity_removal;
00116 BOOL _enable_preg_renumbering;
00117 CFG *_cfg;
00118 OPT_STAB *_opt_stab;
00119 CODEMAP *_htable;
00120 const ALIAS_RULE *_alias_rule;
00121 BOOL _tracing;
00122 BB_NODE_SET *_may_need_label;
00123
00124
00125 BB_NODE_SET *_keep_unreached;
00126
00127
00128
00129 BB_NODE_SET *_may_need_goto;
00130
00131
00132
00133 BB_NODE_SET *_region_start_bbs;
00134
00135
00136 BS *_dce_visited;
00137 BS *_retvsym_visited;
00138
00139 AUX_ID _return_vsym;
00140 AUX_ID _return_vsym_max;
00141
00142
00143
00144
00145
00146 COND_EVAL *_cond_eval;
00147
00148
00149
00150
00151
00152 CODEREP **_cond_coderep;
00153 IDX_32_SET *_return_vsym_full_set;
00154
00155 IDX_32_SET *_return_vsym_reqd_set;
00156
00157
00158 STACK<MU_NODE*> *_mu_stack;
00159 STACK<POINTS_TO*> *_points_to_stack;
00160
00161
00162 MOD_PHI_BB_CONTAINER *_mod_phis;
00163 #if defined(TARG_SL)
00164 vector<STMTREP *> *_injured_aux_intrnop;
00165 #endif
00166
00167
00168 enum {
00169 DCE_UNKNOWN,
00170 DCE_UNREACHABLE,
00171 DCE_DEAD_STORE
00172 } _dce_phase;
00173
00174
00175 OPT_STAB *Opt_stab(void) const
00176 { return _opt_stab; }
00177 CODEMAP *Htable(void) const
00178 { return _htable; }
00179 AUX_ID Return_vsym(void) const
00180 { return _return_vsym; }
00181 AUX_ID Return_vsym_max(void) const
00182 { return _return_vsym_max; }
00183 IDX_32_SET *Return_vsym_full_set(void) const
00184 { return _return_vsym_full_set; }
00185 IDX_32_SET *Return_vsym_reqd_set(void) const
00186 { return _return_vsym_reqd_set; }
00187
00188 COND_EVAL Cond_eval( const BB_NODE *bb ) const
00189 { return _cond_eval[bb->Id()]; }
00190 void Set_cond_eval( const BB_NODE *bb, COND_EVAL eval ) const
00191 { _cond_eval[bb->Id()] = eval; }
00192 CODEREP *Cond_coderep( const BB_NODE *bb ) const
00193 { return _cond_coderep[bb->Id()]; }
00194 void Set_cond_coderep( const BB_NODE *bb, CODEREP *cond ) const
00195 { _cond_coderep[bb->Id()] = cond; }
00196
00197
00198 DCE(void);
00199 DCE(const DCE&);
00200 DCE& operator = (const DCE&);
00201
00202 BOOL Is_dce_visited(const CODEREP *cr) const
00203 { Is_True(cr->Coderep_id()>0,("DCE:Is_dce_visited, illegal CR id"));
00204 return BS_MemberP(_dce_visited, cr->Coderep_id());
00205 }
00206 BOOL Is_retvsym_visited(const CODEREP *cr) const
00207 { Is_True(cr->Coderep_id()>0,("DCE:is_retvsym_visited, illegal CR id"));
00208 return BS_MemberP(_retvsym_visited, cr->Coderep_id());
00209 }
00210 void Set_dce_visited(const CODEREP *cr)
00211 { Is_True(cr->Coderep_id()>0,("DCE:Set_dce_visited, illegal CR id"));
00212 _dce_visited = BS_Union1D(_dce_visited, cr->Coderep_id(),
00213 _cfg->Loc_pool());
00214 }
00215 void Set_retvsym_visited(const CODEREP *cr)
00216 { Is_True(cr->Coderep_id()>0,("DCE:Set_retvsym_visited, illegal CR id"));
00217 _retvsym_visited = BS_Union1D(_retvsym_visited, cr->Coderep_id(),
00218 _cfg->Loc_pool());
00219 }
00220
00221
00222
00223
00224
00225 BB_NODE_SET *May_need_label( void ) const
00226 { return _may_need_label; }
00227 void Reset_reaching_conditions(BB_NODE_SET *) const;
00228 void Compute_reaching_conditions(BB_NODE *bb, BB_NODE_SET *) const;
00229 BOOL Check_redundant_cond_br_new( BB_NODE *, CODEREP *, BB_NODE_SET *) const;
00230 BOOL Check_conditional_branches_dom( BB_NODE *,BB_NODE_SET * ) const;
00231 BOOL Check_conditional_branches_pred( CFG *cfg ) const;
00232 BB_NODE *Branch_target_block( const STMTREP *br_stmt ) const;
00233 void Add_goto_stmt(BB_NODE *, BB_NODE *, SRCPOS, BOOL) const;
00234 BOOL Check_constant_cond_br( BB_NODE *bb ) const;
00235 void Replace_condition_with_constant(BB_NODE *bb, INT64 val) const;
00236 void Check_unreachable_blocks( void ) const;
00237 void Replace_condbr_with_uncondbr(
00238 BB_NODE *bb, STMTREP *cond_br_stmt, BB_NODE *goto_bb ) const;
00239 BOOL Update_predecessor_lists( BB_NODE *bb ) const;
00240 void Check_for_label( BB_NODE *bb ) const;
00241 BOOL Hasexception( BB_NODE *bb ) const;
00242 void Check_for_unreachable_exceptions( BB_NODE *bb ) const;
00243 void Remove_path( BB_NODE *pred, BB_NODE *succ ) const;
00244 void Remove_unreached_statements( BB_NODE *bb ) const;
00245
00246
00247
00248
00249
00250 BB_NODE_SET *Keep_unreached( void ) const
00251 { return _keep_unreached; }
00252 void Keep_unreached_bb( BB_NODE *bb ) const;
00253 BB_NODE_SET *May_need_goto( void ) const
00254 { return _may_need_goto; }
00255 BB_NODE_SET *Region_start_bbs( void ) const
00256 { return _region_start_bbs; }
00257
00258 STACK<POINTS_TO *> *Points_to_stack( void ) const
00259 { return _points_to_stack; }
00260 STACK<MU_NODE *> *Mu_stack( void ) const
00261 { return _mu_stack; }
00262
00263
00264
00265
00266 BOOL Allow_dce_prop( void ) const
00267 { return FALSE; }
00268 CODEREP *Find_current_version( const STMTREP *, const CODEREP *) const;
00269
00270 BOOL Aliased( const POINTS_TO *pt1, const POINTS_TO *pt2 ) const;
00271 BOOL Loop_pragma(WN_PRAGMA_ID pragma) const;
00272 BOOL Required_call( const STMTREP *stmt, OPERATOR oper ) const;
00273 BOOL Required_asm( const STMTREP *stmt ) const;
00274 BOOL Required_store( const STMTREP *stmt, OPERATOR oper ) const;
00275 BOOL Required_istore( const STMTREP *stmt, OPERATOR oper ) const;
00276 BOOL Required_pragma( const STMTREP *stmt ) const;
00277 BOOL Required_stmt( const STMTREP *stmt ) const;
00278 BOOL Required_phi ( const PHI_NODE *phi) const;
00279 BOOL Required_bb ( const BB_NODE *bb ) const;
00280 CODEREP *Dce_prop(CODEREP *cr) const;
00281 void Mark_coderep_live( CODEREP *cr ) const;
00282 void Mark_phinode_live( PHI_NODE *phi, BOOL visit_opnds ) const;
00283 void Mark_chinode_live( CHI_NODE *chi, STMTREP *def_stmt ) const;
00284 void Mark_zero_version_chinode_live( STMTREP *stmt ) const;
00285 void Mark_cr_munode_live( CODEREP *cr ) const;
00286 void Mark_sr_munode_live( STMTREP *sr ) const;
00287 void Mark_block_live( BB_NODE *bb ) const;
00288 BOOL Need_condbr_target_label(STMTREP *stmt, BB_NODE *target) const;
00289 void Mark_branch_related_live( STMTREP *stmt ) const;
00290 void Mark_region_exits_live( STMTREP *stmt ) const;
00291 void Mark_return_vsym_chi_live( CHI_NODE *chi )const;
00292 void Mark_return_vsym_mu_ref_live( CODEREP *cr ) const;
00293 void Mark_return_vsym_phi_live( PHI_NODE *phi ) const;
00294 CODEREP *Prop_return_vsym_new_result( CODEREP * ) const;
00295 void Propagate_return_vsym_cr( CODEREP * ) const;
00296 void Propagate_return_vsym_bb( BB_NODE * ) const;
00297 void Mark_infinite_loops_live( void ) const;
00298 void Mark_statement_live( STMTREP *stmt ) const;
00299 void Mark_statements_dead( void ) const;
00300 BOOL BB_branch_live( BB_NODE *bb ) const;
00301 void Get_full_rcfg_dom_frontier( BB_NODE *bb ) const;
00302 void Add_path_to_ipdom( BB_NODE *bb ) const;
00303 void Replace_control_dep_succs( BB_NODE *bb ) const;
00304 void Check_required_blocks( void ) const;
00305 void Check_required_doend( BB_NODE *bb ) const;
00306 void Check_required_goto( BB_NODE *bb ) const;
00307 void Check_required_io( BB_NODE *bb ) const;
00308 void Check_required_logif( BB_NODE *bb ) const;
00309 void Check_required_region( BB_NODE *bb ) const;
00310 void Update_region_information( void ) const;
00311 void Check_required_repeatend( BB_NODE *bb ) const;
00312 void Check_required_vargoto( BB_NODE *bb ) const;
00313 void Check_required_agoto( BB_NODE *bb ) const;
00314 void Check_required_whileend( BB_NODE *bb ) const;
00315 void Find_required_statements( void ) const;
00316 void Find_assumed_goto_blocks( BB_NODE_SET *assumed_goto ) const;
00317 void Insert_required_gotos( void ) const;
00318 void Update_branch_to_bb_labels( BB_NODE *bb ) const;
00319 #ifdef KEY
00320 void Update_branch_to_bbs_labels( BB_LIST *bbs ) const;
00321 #endif
00322 BOOL Remove_dead_statements( void ) ;
00323 BOOL Enable_dce_global( void ) const { return _enable_dce_global; }
00324 BOOL Enable_dce_alias( void ) const { return _enable_dce_alias; }
00325 BOOL Enable_aggressive_dce ( void ) const
00326 { return _enable_agg_dce; }
00327 BOOL Enable_identity_removal(void) const { return _enable_identity_removal; }
00328 BOOL Enable_preg_renumbering(void) const { return _enable_preg_renumbering; }
00329
00330
00331
00332
00333
00334 BOOL Is_branch( OPERATOR opr ) const
00335 {
00336 switch ( opr ) {
00337 case OPR_AGOTO:
00338 case OPR_COMPGOTO:
00339 case OPR_GOTO:
00340 case OPR_FALSEBR:
00341 case OPR_REGION_EXIT:
00342 case OPR_RETURN:
00343 case OPR_RETURN_VAL:
00344 case OPR_TRUEBR:
00345 #ifdef KEY
00346 case OPR_GOTO_OUTER_BLOCK:
00347 #endif
00348 return TRUE;
00349 default:
00350 return FALSE;
00351 }
00352 }
00353 public:
00354
00355 DCE(CFG *cfg, OPT_STAB *optstab, ALIAS_RULE *alias_rule,
00356 CODEMAP *htable, BOOL tracing, OPT_PHASE opt_phase,
00357 BOOL do_unreachable, BOOL do_dce_global, BOOL do_dce_alias,
00358 BOOL do_agg_dce, BOOL do_identity_removal, BOOL do_preg_renumbering)
00359 : _cfg(cfg), _opt_stab(optstab), _alias_rule(alias_rule),
00360 _htable(htable), _tracing(tracing), _opt_phase(opt_phase),
00361 _dce_phase(DCE_UNKNOWN), _do_unreachable(do_unreachable),
00362 _enable_dce_global(do_dce_global && WOPT_Enable_DCE_Global),
00363 _enable_dce_alias(do_dce_alias && WOPT_Enable_DCE_Alias),
00364 _enable_agg_dce(do_agg_dce && WOPT_Enable_Aggressive_dce),
00365 _enable_identity_removal(do_identity_removal),
00366 _enable_preg_renumbering(do_preg_renumbering)
00367 {
00368 _may_need_label = CXX_NEW(
00369 BB_NODE_SET(cfg->Total_bb_count(), cfg, cfg->Loc_pool(),
00370 BBNS_EMPTY), cfg->Loc_pool());
00371 _keep_unreached = CXX_NEW(
00372 BB_NODE_SET(cfg->Total_bb_count(), cfg, cfg->Loc_pool(),
00373 BBNS_EMPTY), cfg->Loc_pool());
00374 _may_need_goto = CXX_NEW(
00375 BB_NODE_SET(cfg->Total_bb_count(), cfg, cfg->Loc_pool(),
00376 BBNS_EMPTY), cfg->Loc_pool());
00377 if ( cfg->Has_regions() ) {
00378 _region_start_bbs = CXX_NEW(
00379 BB_NODE_SET(cfg->Total_bb_count(), cfg, cfg->Loc_pool(),
00380 BBNS_EMPTY), cfg->Loc_pool());
00381 }
00382 else {
00383 _region_start_bbs = NULL;
00384 }
00385
00386 _is_varargs_func = Opt_stab()->Is_varargs_func();
00387 _return_vsym = Opt_stab()->Return_vsym();
00388 _return_vsym_max = 0;
00389 _return_vsym_full_set = NULL;
00390 _return_vsym_reqd_set = NULL;
00391
00392 if ( Enable_dce_alias() ) {
00393 _points_to_stack = CXX_NEW(
00394 STACK<POINTS_TO *>(cfg->Loc_pool()), cfg->Loc_pool());
00395 _mu_stack = CXX_NEW(
00396 STACK<MU_NODE *>(cfg->Loc_pool()), cfg->Loc_pool());
00397 }
00398 else {
00399 _points_to_stack = NULL;
00400 _mu_stack = NULL;
00401 }
00402
00403
00404 if ( WOPT_Enable_DCE_Branch ) {
00405 _cond_eval = TYPE_OPT_POOL_ALLOC_N( COND_EVAL,
00406 cfg->Loc_pool(), cfg->Total_bb_count(), DCE_DUMP_FLAG );
00407 BZERO( _cond_eval, sizeof(COND_EVAL)*cfg->Total_bb_count());
00408
00409 _cond_coderep = TYPE_OPT_POOL_ALLOC_N( CODEREP*,
00410 cfg->Loc_pool(), cfg->Total_bb_count(), DCE_DUMP_FLAG );
00411 BZERO(_cond_coderep,sizeof(CODEREP*)*cfg->Total_bb_count());
00412 }
00413 else {
00414 _cond_eval = NULL;
00415 _cond_coderep = NULL;
00416 }
00417 if (Htable()->Phi_hash_valid())
00418 _mod_phis = CXX_NEW(MOD_PHI_BB_CONTAINER(cfg->Loc_pool()),
00419 cfg->Loc_pool());
00420 else
00421 _mod_phis = NULL;
00422
00423 _dce_visited = BS_Create_Empty(Htable()->Coderep_id_cnt() + 1,
00424 cfg->Loc_pool()),
00425 _retvsym_visited = BS_Create_Empty(Htable()->Coderep_id_cnt() + 1,
00426 cfg->Loc_pool());
00427 #if defined(TARG_SL)
00428 _injured_aux_intrnop = CXX_NEW(vector<STMTREP *>, cfg->Loc_pool());
00429 #endif
00430 }
00431
00432 ~DCE(void)
00433 {
00434 MOD_PHI_BB *tmp;
00435 MOD_PHI_BB_ITER mod_iter(_mod_phis);
00436 FOR_ALL_NODE(tmp, mod_iter, Init()) {
00437 PHI_LIST_ITER phi_iter;
00438 PHI_NODE *pnode;
00439
00440 FOR_ALL_NODE(pnode, phi_iter, Init(tmp->Old_lst())) {
00441 Htable()->Remove_var_phi_hash(pnode);
00442 }
00443 FOR_ALL_NODE(pnode, phi_iter, Init(tmp->New_lst())) {
00444 Htable()->Enter_var_phi_hash(pnode);
00445 }
00446 }
00447 if ( _mod_phis != NULL )
00448 CXX_DELETE(_mod_phis, _cfg->Loc_pool());
00449 }
00450
00451 BOOL Enable_dce_unreachable( void ) const { return _do_unreachable; }
00452 void Set_phase_unreachable( void )
00453 { _dce_phase = DCE_UNREACHABLE; }
00454 void Set_phase_dead_store( void )
00455 { _dce_phase = DCE_DEAD_STORE; }
00456 BOOL Tracing(void) const { return _tracing; }
00457 BOOL Unreachable_code_elim(void) const;
00458 BOOL Dead_store_elim(void) ;
00459 void Init_return_vsym( void );
00460 #if defined(TARG_SL)
00461 void Append_Injured_AuxIntrnOp (STMTREP *stmt) const {
00462 _injured_aux_intrnop->insert(_injured_aux_intrnop->begin(), (STMTREP *)stmt);
00463 };
00464 void Repair_Injured_AuxIntrnOP() const;
00465 #endif
00466
00467 };
00468
00469 #if defined(TARG_SL)
00470 void
00471 DCE::Repair_Injured_AuxIntrnOP() const {
00472
00473 for (INT32 i = 0; i < _injured_aux_intrnop->size(); i++) {
00474 STMTREP *stmt = (*_injured_aux_intrnop)[i];
00475 if (stmt->Live_stmt())
00476 continue;
00477 CODEREP *rhs = stmt->Rhs();
00478 if (CR_Intrinsic_Op_Slave(rhs)) {
00479 CODEREP *parm2cr = rhs->Opnd(0);
00480 Is_True(parm2cr->Kind() == CK_IVAR, ("Repair_Injured_AuxIntrnOP::kid of intrinsic op must be parameter"));
00481 CODEREP *op2cr = parm2cr->Ilod_base();
00482 if (op2cr) {
00483 switch (op2cr->Kind()) {
00484 case CK_VAR:
00485 {
00486 if(op2cr->Defstmt()->Live_stmt())
00487 Mark_statement_live(stmt);
00488 }
00489 break;
00490 case CK_OP:
00491 {
00492 Mark_statement_live(stmt);
00493 };
00494 break;
00495 case CK_CONST:
00496 break;
00497 default:
00498 Is_True (0, ("Repair_Injured_AuxIntrnOP::slave intrinsic op(c3_ptr): first parameter is unsupported kind coderep"));
00499 }
00500 } else {
00501 Is_True (0, ("Repair_Injured_AuxIntrnOP::slave intrinsic op(c3_ptr): first parameter is null"));
00502 }
00503 } else {
00504 Is_True(0, ("Repair_Injured_AuxIntrnOP::rhs is not injure AuxIntrn"));
00505 }
00506 }
00507 return;
00508 }
00509 #endif
00510
00511
00512
00513
00514
00515 void
00516 DCE::Keep_unreached_bb( BB_NODE *bb ) const
00517 {
00518 if ( ! bb->Reached() )
00519 Keep_unreached()->Union1D( bb );
00520 }
00521
00522
00523
00524
00525
00526 BB_NODE *
00527 DCE::Branch_target_block( const STMTREP *br_stmt ) const
00528 {
00529 INT32 label_num = br_stmt->Label_number();
00530 return _cfg->Get_bb_from_label(label_num);
00531 }
00532
00533
00534
00535
00536
00537
00538 void
00539 DCE::Add_goto_stmt( BB_NODE *bb, BB_NODE *goto_bb, SRCPOS ln,
00540 BOOL rgn_exit ) const
00541 {
00542 const STMTREP *bb_branch = bb->Branch_stmtrep();
00543 if ( bb_branch != NULL ) {
00544 const OPERATOR opr = bb_branch->Opr();
00545
00546
00547 Warn_todo( "DCE::Add_goto_stmt: OPC_IO should be call" );
00548 if ( ! (OPERATOR_is_call(opr)||opr==OPR_IO) || _cfg->Calls_break() ) {
00549 FmtAssert( FALSE,
00550 ("DCE::Add_goto_stmt BB:%d already has branch %s",
00551 bb->Id(), OPERATOR_name(opr)) );
00552 }
00553 }
00554
00555
00556 if ( bb->Next() != goto_bb ) {
00557
00558
00559
00560 if ( goto_bb->Labnam() == 0 ) {
00561 _cfg->Append_label_map( _cfg->Alloc_label(), goto_bb );
00562 }
00563
00564 STMTREP *new_stmt;
00565 if (rgn_exit)
00566 new_stmt = CXX_NEW( STMTREP(OPC_REGION_EXIT), _cfg->Mem_pool() );
00567 else
00568 new_stmt = CXX_NEW( STMTREP(OPC_GOTO), _cfg->Mem_pool() );
00569 new_stmt->Init_Goto( NULL, goto_bb->Labnam(), ln );
00570 bb->Append_stmtrep( new_stmt );
00571
00572 if ( _dce_phase == DCE_UNREACHABLE ) {
00573
00574
00575 May_need_label()->Union1D( goto_bb );
00576 }
00577 else if ( _dce_phase == DCE_DEAD_STORE ) {
00578
00579
00580 Check_for_label( goto_bb );
00581 }
00582 else {
00583 Is_True( FALSE,
00584 ("DCE::Add_goto_stmt: unknown DCE phase") );
00585 }
00586
00587 if ( Tracing() ) {
00588 fprintf ( TFile, "<DCE> Add statement to BB:%d:\n", bb->Id() );
00589 new_stmt->Print( TFile );
00590 }
00591 }
00592 }
00593
00594
00595
00596
00597
00598
00599 void
00600 DCE::Replace_condbr_with_uncondbr( BB_NODE *bb, STMTREP *cond_br_stmt,
00601 BB_NODE *goto_bb ) const
00602 {
00603 if ( Tracing() ) {
00604 fprintf( TFile, "DCE::Replace_condbr_with_uncondbr: Updating bb:%d;\n",
00605 bb->Id() );
00606 fprintf( TFile, " new sole successor is bb:%d.\n",
00607 goto_bb->Id() );
00608 fflush( TFile );
00609 }
00610
00611
00612 bb->Remove_stmtrep(cond_br_stmt);
00613
00614
00615 _cfg->Change_block_kind( bb, BB_GOTO );
00616
00617
00618 BB_LIST *succlist, *nextsucc = NULL;
00619 for ( succlist = bb->Succ(); succlist != NULL; succlist = nextsucc ) {
00620
00621 nextsucc = succlist->Next();
00622
00623
00624 BB_NODE *succ = succlist->Node();
00625 if ( succ != goto_bb ) {
00626
00627 Remove_path( bb, succ );
00628
00629
00630 if ( _cfg->Feedback() )
00631 _cfg->Feedback()->Delete_edge( bb->Id(), succ->Id() );
00632 }
00633 }
00634
00635
00636 Add_goto_stmt( bb, goto_bb, cond_br_stmt->Linenum(), FALSE );
00637
00638 if ( Tracing() ) {
00639 fprintf( TFile, "DCE::Replace_condbr_with_uncondbr: Done with bb:%d\n",
00640 bb->Id() );
00641 fflush( TFile );
00642 }
00643 }
00644
00645
00646
00647
00648
00649
00650
00651 BOOL
00652 DCE::Check_constant_cond_br( BB_NODE *bb ) const
00653 {
00654 STMTREP *cond_br_stmt = NULL;
00655 OPERATOR cond_br_oper;
00656
00657 switch ( bb->Kind() ) {
00658 case BB_UNKNOWN:
00659 ErrMsg( EC_Unimplemented,
00660 "Check_constant_cond_br: Unknown bb Kind()" );
00661 return ( FALSE );
00662
00663 case BB_DOSTART:
00664 case BB_DOSTEP:
00665 case BB_DOHEAD:
00666 case BB_DOTAIL:
00667 case BB_ENTRY:
00668 case BB_EXIT:
00669 case BB_REGIONEXIT:
00670 case BB_GOTO:
00671 case BB_IO:
00672 case BB_REGIONSTART:
00673 case BB_REPEATBODY:
00674 case BB_SUMMARY:
00675 return ( FALSE );
00676
00677 case BB_WHILEEND:
00678 #ifdef KEY // bug 7905: to enable while (1) to be preserved by ipl's preopt
00679 if (_opt_phase == PREOPT_IPA0_PHASE)
00680 return ( FALSE );
00681
00682 #endif
00683 case BB_LOGIF:
00684 case BB_VARGOTO:
00685 case BB_DOEND:
00686 case BB_REPEATEND:
00687 cond_br_stmt = bb->Branch_stmtrep();
00688 break;
00689
00690 default:
00691 ErrMsg( EC_Unimplemented,
00692 "Check_constant_cond_br: invalid bb Kind()" );
00693 return ( FALSE );
00694 }
00695
00696 Is_True( cond_br_stmt != NULL,
00697 ("Check_constant_cond_br: null condition branch statement BB:%d",
00698 (INT)bb->Id()) );
00699
00700
00701 cond_br_oper = cond_br_stmt->Opr();
00702
00703
00704
00705 BB_NODE *goto_bb = NULL;
00706 switch ( cond_br_oper ) {
00707 case OPR_COMPGOTO:
00708 {
00709 CODEREP *cg_cond = cond_br_stmt->Rhs();
00710 if ( cg_cond->Kind() != CK_CONST ) {
00711 return ( FALSE );
00712 }
00713 else {
00714 Is_True( bb->Switchinfo() != NULL,
00715 ("DCE::Check_constant_cond_br: no switch info") );
00716
00717 if ( cg_cond->Const_val() >= 0 &&
00718 cg_cond->Const_val() < bb->Switchentries() )
00719 {
00720
00721 goto_bb = bb->Switchcase( cg_cond->Const_val() );
00722 }
00723 else {
00724
00725 if ( (goto_bb = bb->Switchdefault()) == NULL ) {
00726
00727
00728
00729 return ( FALSE );
00730 }
00731 }
00732 }
00733 break;
00734 }
00735
00736 case OPR_FALSEBR:
00737 case OPR_TRUEBR:
00738 {
00739 CODEREP *cb_cond = cond_br_stmt->Rhs();
00740 if ( cb_cond->Kind() != CK_CONST ) {
00741 return ( FALSE );
00742 }
00743 else {
00744
00745
00746 if ( (cb_cond->Const_val() && cond_br_oper == OPR_TRUEBR) ||
00747 (!cb_cond->Const_val() && cond_br_oper == OPR_FALSEBR) )
00748 {
00749
00750
00751
00752 goto_bb = Branch_target_block( cond_br_stmt );
00753 }
00754 else {
00755
00756
00757 goto_bb = bb->Next();
00758 }
00759 }
00760 break;
00761 }
00762
00763 case OPR_AGOTO:
00764 DevWarn( "DCE::Check_constant_cond_br: AGOTO not handled yet" );
00765
00766
00767 return ( FALSE );
00768
00769 default:
00770 ErrMsg( EC_Unimplemented,
00771 "Check_constant_cond_br: invalid conditional branch operator" );
00772 return ( FALSE );
00773 }
00774
00775 if ( goto_bb == NULL ) {
00776 ErrMsg( EC_Unimplemented,
00777 "DCE::Check_constant_cond_br: No goto block" );
00778 return ( FALSE );
00779 }
00780
00781
00782
00783
00784
00785 Replace_condbr_with_uncondbr( bb, cond_br_stmt, goto_bb );
00786 if ( Tracing() ) {
00787 fprintf( TFile, "DCE::Remove_br in bb:%d (%p)\n",bb->Id(),bb);
00788 }
00789
00790 return ( TRUE );
00791 }
00792
00793
00794
00795
00796
00797
00798 void
00799 DCE::Replace_condition_with_constant( BB_NODE *bb, INT64 val ) const
00800 {
00801 STMTREP *condbr = bb->Branch_stmtrep();
00802 CODEREP *oldrhs = condbr->Rhs();
00803
00804
00805 oldrhs->DecUsecnt();
00806
00807
00808 CODEREP *newrhs = Htable()->Add_const( oldrhs->Dtyp(), val );
00809
00810
00811 condbr->Set_rhs(newrhs);
00812
00813 if ( Tracing() ) {
00814 fprintf( TFile, "Replaced bb:%d condition with %lld\n",
00815 bb->Id(), val );
00816 }
00817 }
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827 BOOL
00828 DCE::Check_redundant_cond_br_new( BB_NODE *origbb, CODEREP *origcond,
00829 BB_NODE_SET *path ) const
00830 {
00831 BOOL found_redundant = FALSE;
00832
00833 BB_NODE *cdbb;
00834 BB_NODE_SET_ITER rcfg_iter;
00835 FOR_ALL_ELEM( cdbb, rcfg_iter, Init(path) ) {
00836 if ( Cond_eval( cdbb ) == EVAL_TRUE ||
00837 Cond_eval( cdbb ) == EVAL_FALSE )
00838 {
00839 COND_EVAL eval = Eval_redundant_cond_br( origcond,
00840 Cond_coderep(cdbb), Cond_eval(cdbb));
00841
00842
00843 if ( eval == EVAL_TRUE || eval == EVAL_FALSE || eval == EVAL_DEAD ) {
00844 Replace_condition_with_constant( origbb, (eval == EVAL_TRUE) ? 1 : 0);
00845 found_redundant = TRUE;
00846 break;
00847 }
00848 }
00849 else if ( Cond_eval( cdbb ) == EVAL_UNKNOWN ) {
00850
00851
00852 }
00853 else {
00854 fprintf( TFile, "origbb:%d path: ", origbb->Id() );
00855 path->Print(TFile);
00856 fprintf( TFile, "\n" );
00857 FmtAssert( FALSE,
00858 ("DCE::Check_redundant_cond_br_new: uninit bb:%d",cdbb->Id()) );
00859 found_redundant = TRUE;
00860 break;
00861 }
00862
00863 }
00864
00865 return found_redundant;
00866 }
00867
00868
00869
00870
00871 void
00872 DCE::Reset_reaching_conditions( BB_NODE_SET *path ) const
00873 {
00874 BB_NODE *bb;
00875 BB_NODE_SET_ITER cfg_iter;
00876 FOR_ALL_ELEM ( bb, cfg_iter, Init( path ) ) {
00877 if ( Cond_coderep( bb ) != NULL)
00878 Set_cond_eval( bb, EVAL_UNINIT );
00879 else
00880 Set_cond_eval( bb, EVAL_UNKNOWN );
00881 }
00882 }
00883
00884
00885 static BOOL
00886 dominates_all_but_one_preds( BB_NODE *dom, BB_NODE *bb, BB_NODE *cdbb )
00887 {
00888 BB_LIST_ITER pred_iter;
00889 BB_NODE *pred;
00890 FOR_ALL_ELEM( pred, pred_iter, Init( bb->Pred() ) ) {
00891 if ( ! dom->Dominates(pred) && pred != cdbb )
00892 return FALSE;
00893 }
00894 return TRUE;
00895 }
00896
00897
00898
00899
00900
00901
00902 void
00903 DCE::Compute_reaching_conditions( BB_NODE *bb, BB_NODE_SET *path ) const
00904 {
00905
00906 BB_NODE *cdbb;
00907 BB_NODE_SET_ITER rcfg_iter;
00908 BB_LIST_ITER bb_iter;
00909
00910 FOR_ALL_ELEM( cdbb, rcfg_iter, Init(path) ) {
00911
00912 if (Cond_eval( cdbb ) != EVAL_UNKNOWN ) {
00913
00914 Set_cond_eval( cdbb, EVAL_UNKNOWN );
00915
00916 Is_True(cdbb->Dominates(bb),
00917 ("DCE::Compute_reaching_conditions: cdbb does not dominate bb"));
00918
00919 Is_True(Cond_coderep( cdbb ) != NULL,
00920 ("DCE::Compute_reaching_conditions: NULL Cond_coderep"));
00921
00922 STMTREP *br = cdbb->Branch_stmtrep();
00923 Is_True(br != NULL, ("DCE::Compute_reaching_conditions: NULL branch"));
00924
00925 BB_NODE *true_bb = NULL, *false_bb = NULL;
00926 if ( br->Opr() == OPR_TRUEBR ) {
00927 true_bb = Branch_target_block( br );
00928 false_bb = cdbb->Next();
00929 } else if ( br->Opr() == OPR_FALSEBR ) {
00930 false_bb = Branch_target_block( br );
00931 true_bb = cdbb->Next();
00932 } else {
00933 Is_True(0, ("DCE::Compute_reaching_conditions: unexpected branch"));
00934 }
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946 if ( true_bb == false_bb ) {
00947 true_bb = NULL;
00948 false_bb = NULL;
00949 }
00950
00951 if ( true_bb && true_bb->Dominates(bb) &&
00952 dominates_all_but_one_preds( true_bb, true_bb, cdbb ) )
00953 Set_cond_eval( cdbb, EVAL_TRUE );
00954
00955 if ( false_bb && false_bb->Dominates(bb) &&
00956 dominates_all_but_one_preds( false_bb, false_bb, cdbb ) ) {
00957 Is_True( Cond_eval(cdbb) == EVAL_UNKNOWN,
00958 ("DCE::Compute_reaching_conditions: bb most recently dominated by both true and false branches"));
00959 Set_cond_eval( cdbb, EVAL_FALSE );
00960 }
00961 }
00962 }
00963 }
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980 BOOL
00981 DCE::Check_conditional_branches_dom( BB_NODE *bb, BB_NODE_SET *path ) const
00982 {
00983 BOOL changed_cflow = FALSE;
00984
00985 if ( WOPT_Enable_DCE_Branch ) {
00986 STMTREP *br = bb->Branch_stmtrep();
00987 if ( br != NULL && ( br->Opr() == OPR_TRUEBR || br->Opr() == OPR_FALSEBR ) )
00988 Set_cond_coderep( bb, br->Rhs() );
00989 else
00990 Set_cond_coderep( bb, NULL );
00991 }
00992
00993
00994 path->Union1D( bb );
00995
00996
00997 BB_NODE *dom_bb;
00998 BB_LIST_ITER dom_bb_iter;
00999 FOR_ALL_ELEM(dom_bb, dom_bb_iter, Init(bb->Dom_bbs())) {
01000
01001 if ( Check_conditional_branches_dom(dom_bb, path) ) {
01002 changed_cflow = TRUE;
01003 }
01004 }
01005
01006
01007 path->Difference1D( bb );
01008
01009 if ( WOPT_Enable_DCE_Branch ) {
01010
01011 CODEREP *condition = Cond_coderep( bb );
01012 Set_cond_eval( bb, EVAL_UNINIT );
01013 Set_cond_coderep( bb, NULL );
01014
01015
01016 if ( condition != NULL && condition->Kind() != CK_CONST ) {
01017 Reset_reaching_conditions( path );
01018 Compute_reaching_conditions( bb, path );
01019 Check_redundant_cond_br_new( bb, condition, path );
01020 }
01021 }
01022
01023
01024 if ( Check_constant_cond_br( bb ) ) {
01025 changed_cflow = TRUE;
01026 }
01027
01028 return changed_cflow;
01029 }
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039 BOOL
01040 DCE::Check_conditional_branches_pred( CFG *cfg ) const
01041 {
01042 if (! WOPT_Enable_DCE_Branch || WOPT_Enable_DCE_Branch_Pred_Limit < 1)
01043 return FALSE;
01044
01045
01046 BB_NODE *bb;
01047 POBB_ITER cfg_iter(cfg);
01048 FOR_ALL_ELEM(bb, cfg_iter, Init()) {
01049 STMTREP *br = bb->Branch_stmtrep();
01050 if ( br != NULL && ( br->Opr() == OPR_TRUEBR || br->Opr() == OPR_FALSEBR ) )
01051 Set_cond_coderep( bb, br->Rhs() );
01052 else
01053 Set_cond_coderep( bb, NULL );
01054 }
01055
01056 BOOL changed_cflow = FALSE;
01057
01058 if (Tracing()) fprintf(TFile,"DCE::Check_conditional_branches_pred\n");
01059
01060
01061
01062 FOR_ALL_ELEM(bb, cfg_iter, Init()) {
01063 CODEREP *condition = Cond_coderep( bb );
01064 if (condition == NULL || condition->Kind() == CK_CONST ) continue;
01065
01066
01067 COND_EVAL eval = EVAL_UNINIT;
01068
01069
01070
01071
01072
01073
01074
01075 vector<BB_NODE *> back_blocks(1, bb);
01076 back_blocks.reserve(WOPT_Enable_DCE_Branch_Pred_Limit);
01077
01078 if (Tracing()) fprintf(TFile,"back_blocks: ");
01079
01080 for (vector<BB_NODE *>::const_iterator current_iter = back_blocks.begin();
01081 current_iter != back_blocks.end(); ++current_iter) {
01082 BB_NODE *current_bb = *current_iter;
01083
01084 if (Tracing()) fprintf(TFile," %d", current_bb->Id());
01085
01086 BB_KIND kind = current_bb->Kind();
01087 if (kind == BB_ENTRY || kind == BB_REGIONSTART) {
01088 eval = EVAL_UNKNOWN;
01089 break;
01090 }
01091
01092
01093 BB_LIST_ITER pred_iter;
01094 BB_NODE *pred_bb;
01095 FOR_ALL_ELEM( pred_bb, pred_iter, Init( current_bb->Pred() ) ) {
01096
01097
01098 if ( find( back_blocks.begin(), back_blocks.end(), pred_bb )
01099 != back_blocks.end() )
01100 continue;
01101
01102
01103
01104 if ( Cond_coderep(pred_bb) != NULL ) {
01105
01106
01107 STMTREP *br = pred_bb->Branch_stmtrep();
01108 Is_True(br != NULL,
01109 ("DCE::Check_conditional_branches_pred: NULL branch"));
01110 BB_NODE *true_bb = NULL, *false_bb = NULL;
01111 if ( br->Opr() == OPR_TRUEBR ) {
01112 true_bb = Branch_target_block( br );
01113 false_bb = pred_bb->Next();
01114 } else if ( br->Opr() == OPR_FALSEBR ) {
01115 false_bb = Branch_target_block( br );
01116 true_bb = pred_bb->Next();
01117 } else
01118 Is_True(0, ("DCE::Check_conditional_branches_pred: unexpected branch"));
01119
01120
01121
01122
01123
01124 COND_EVAL eval_redundant = EVAL_UNINIT;
01125 if ( false_bb != current_bb )
01126 eval_redundant
01127 = Eval_redundant_cond_br( Cond_coderep(bb),
01128 Cond_coderep(pred_bb), EVAL_TRUE );
01129 else if ( true_bb != current_bb )
01130 eval_redundant
01131 = Eval_redundant_cond_br( Cond_coderep(bb),
01132 Cond_coderep(pred_bb), EVAL_FALSE );
01133
01134 if (eval_redundant == EVAL_DEAD) continue;
01135 else if (eval_redundant == EVAL_TRUE)
01136 if (eval == EVAL_FALSE) {
01137 eval = EVAL_UNKNOWN;
01138 break;
01139 } else {
01140 eval = EVAL_TRUE;
01141 continue;
01142 }
01143 else if (eval_redundant == EVAL_FALSE)
01144 if (eval == EVAL_TRUE) {
01145 eval = EVAL_UNKNOWN;
01146 break;
01147 } else {
01148 eval = EVAL_FALSE;
01149 continue;
01150 }
01151 }
01152
01153
01154
01155 if (back_blocks.size() < WOPT_Enable_DCE_Branch_Pred_Limit)
01156 back_blocks.push_back(pred_bb);
01157 else {
01158 eval = EVAL_UNKNOWN;
01159 break;
01160 }
01161 }
01162 if (eval == EVAL_UNKNOWN) break;
01163 }
01164
01165 if (Tracing())
01166 switch ( eval ) {
01167 case EVAL_UNINIT : fprintf(TFile, " UNINIT\n"); break;
01168 case EVAL_TRUE : fprintf(TFile, " TRUE\n"); break;
01169 case EVAL_FALSE : fprintf(TFile, " FALSE\n"); break;
01170 case EVAL_UNKNOWN: fprintf(TFile, " UNKNOWN\n"); break;
01171 case EVAL_DEAD : fprintf(TFile, " DEAD\n"); break;
01172 default : fprintf(TFile, "\n"); break;
01173 }
01174
01175 if (eval != EVAL_UNKNOWN) {
01176
01177 Replace_condition_with_constant( bb, (eval == EVAL_TRUE) ? 1 : 0 );
01178 Check_constant_cond_br(bb);
01179 Set_cond_coderep( bb, NULL );
01180 changed_cflow = TRUE;
01181 }
01182 }
01183
01184
01185 FOR_ALL_ELEM(bb, cfg_iter, Init())
01186 Set_cond_coderep( bb, NULL );
01187
01188 return changed_cflow;
01189 }
01190
01191
01192
01193
01194
01195
01196
01197
01198 COND_EVAL
01199 Eval_redundant_cond_br( CODEREP *origcond, CODEREP *evalcond, COND_EVAL eval )
01200 {
01201
01202
01203 if ( origcond == evalcond ) {
01204 return eval;
01205 }
01206
01207
01208 if (evalcond->Kind() == CK_CONST) {
01209 if (eval == EVAL_TRUE && !evalcond->Const_val()) return EVAL_DEAD;
01210 if (eval == EVAL_FALSE && evalcond->Const_val()) return EVAL_DEAD;
01211 if (origcond->Kind() == CK_CONST)
01212 return ( origcond->Const_val() ? EVAL_TRUE : EVAL_FALSE );
01213 return EVAL_UNKNOWN;
01214 }
01215 if (origcond->Kind() == CK_CONST)
01216 return ( origcond->Const_val() ? EVAL_TRUE : EVAL_FALSE );
01217
01218
01219 if ( origcond->Kind() == CK_OP && OPERATOR_is_compare(origcond->Opr()) &&
01220 evalcond->Kind() == CK_OP && OPERATOR_is_compare(evalcond->Opr()) )
01221 {
01222 CODEREP *origkid0 = origcond->Opnd(0);
01223 CODEREP *origkid1 = origcond->Opnd(1);
01224 CODEREP *evalkid0 = evalcond->Opnd(0);
01225 CODEREP *evalkid1 = evalcond->Opnd(1);
01226
01227
01228 if ( origkid0 == evalkid0 && origkid1 == evalkid1 ) {
01229 const OPERATOR origcomp = origcond->Opr();
01230 const OPERATOR evalcomp = evalcond->Opr();
01231
01232
01233
01234 if ( MTYPE_is_float(OPCODE_desc(origcond->Op())) ) {
01235 if ( origcomp != OPR_EQ && origcomp != OPR_NE ) {
01236 return EVAL_UNKNOWN;
01237 }
01238 }
01239 #ifdef KEY // bug 11685
01240 if (origcond->Dsctyp() != evalcond->Dsctyp())
01241 return EVAL_UNKNOWN;
01242 #endif
01243
01244
01245
01246
01247
01248 OPERATOR comparison;
01249 if ( eval == EVAL_FALSE ) {
01250 switch ( evalcomp ) {
01251 case OPR_LT: comparison = OPR_GE; break;
01252 case OPR_LE: comparison = OPR_GT; break;
01253 case OPR_EQ: comparison = OPR_NE; break;
01254 case OPR_NE: comparison = OPR_EQ; break;
01255 case OPR_GE: comparison = OPR_LT; break;
01256 case OPR_GT: comparison = OPR_LE; break;
01257 }
01258 }
01259 else {
01260 comparison = evalcomp;
01261 }
01262
01263 switch ( comparison ) {
01264 case OPR_LT:
01265
01266 switch ( origcomp ) {
01267 case OPR_LT: return EVAL_TRUE;
01268 case OPR_LE: return EVAL_TRUE;
01269 case OPR_EQ: return EVAL_FALSE;
01270 case OPR_NE: return EVAL_TRUE;
01271 case OPR_GE: return EVAL_FALSE;
01272 case OPR_GT: return EVAL_FALSE;
01273 }
01274 break;
01275
01276 case OPR_LE:
01277
01278 switch ( origcomp ) {
01279 case OPR_LT: return EVAL_UNKNOWN;
01280 case OPR_LE: return EVAL_TRUE;
01281 case OPR_EQ: return EVAL_UNKNOWN;
01282 case OPR_NE: return EVAL_UNKNOWN;
01283 case OPR_GE: return EVAL_UNKNOWN;
01284 case OPR_GT: return EVAL_FALSE;
01285 }
01286 break;
01287
01288 case OPR_EQ:
01289
01290 switch ( origcomp ) {
01291 case OPR_LT: return EVAL_FALSE;
01292 case OPR_LE: return EVAL_TRUE;
01293 case OPR_EQ: return EVAL_TRUE;
01294 case OPR_NE: return EVAL_FALSE;
01295 case OPR_GE: return EVAL_TRUE;
01296 case OPR_GT: return EVAL_FALSE;
01297 }
01298 break;
01299
01300 case OPR_NE:
01301
01302 switch ( origcomp ) {
01303 case OPR_LT: return EVAL_UNKNOWN;
01304 case OPR_LE: return EVAL_UNKNOWN;
01305 case OPR_EQ: return EVAL_FALSE;
01306 case OPR_NE: return EVAL_TRUE;
01307 case OPR_GE: return EVAL_UNKNOWN;
01308 case OPR_GT: return EVAL_UNKNOWN;
01309 }
01310 break;
01311
01312 case OPR_GE:
01313
01314 switch ( origcomp ) {
01315 case OPR_LT: return EVAL_FALSE;
01316 case OPR_LE: return EVAL_UNKNOWN;
01317 case OPR_EQ: return EVAL_UNKNOWN;
01318 case OPR_NE: return EVAL_UNKNOWN;
01319 case OPR_GE: return EVAL_TRUE;
01320 case OPR_GT: return EVAL_UNKNOWN;
01321 }
01322 break;
01323
01324 case OPR_GT:
01325
01326 switch ( origcomp ) {
01327 case OPR_LT: return EVAL_FALSE;
01328 case OPR_LE: return EVAL_FALSE;
01329 case OPR_EQ: return EVAL_FALSE;
01330 case OPR_NE: return EVAL_TRUE;
01331 case OPR_GE: return EVAL_TRUE;
01332 case OPR_GT: return EVAL_TRUE;
01333 }
01334 break;
01335
01336 }
01337 }
01338 }
01339
01340 return EVAL_UNKNOWN;
01341 }
01342
01343
01344
01345
01346
01347
01348 void
01349 DCE::Remove_path( BB_NODE *pred, BB_NODE *succ ) const
01350 {
01351 _cfg->Remove_path( pred, succ );
01352 }
01353
01354
01355
01356
01357
01358
01359
01360 BOOL
01361 DCE::Update_predecessor_lists( BB_NODE *bb ) const
01362 {
01363 BB_NODE *pred;
01364 BB_LIST *predlist, *nextpred = NULL;
01365 BOOL changed_cflow = FALSE;
01366
01367 if ( Tracing() ) {
01368 fprintf( TFile, "DCE::Update_predecessor_lists: Updating bb:%d\n",
01369 bb->Id() );
01370 fflush( TFile );
01371 }
01372
01373 for ( predlist = bb->Pred(); predlist != NULL; predlist = nextpred ) {
01374
01375 nextpred = predlist->Next();
01376
01377 pred = predlist->Node();
01378 if ( ! pred->Reached() || ! bb->Reached() ) {
01379 Remove_path( pred, bb );
01380 changed_cflow = TRUE;
01381
01382
01383 if ( _cfg->Feedback() && _cfg->Removable_bb(bb) )
01384 _cfg->Feedback()->Delete_edge( pred->Id(), bb->Id() );
01385 }
01386 }
01387
01388 if ( Tracing() ) {
01389 fprintf( TFile, "DCE::Update_predecessor_lists: Done with bb:%d\n",
01390 bb->Id() );
01391 fprintf( TFile, "DCE::Update_predecessor_lists: changed_cflow == %d\n",
01392 (INT) changed_cflow );
01393 fflush( TFile );
01394 }
01395 return ( changed_cflow );
01396 }
01397
01398
01399
01400
01401
01402 void
01403 DCE::Check_for_label( BB_NODE *bb ) const
01404 {
01405 Is_True(bb != NULL, ("DCE::Check_for_label, NULL bb"));
01406 STMTREP *label_stmt = bb->Label_stmtrep();
01407 if ( label_stmt == NULL ) {
01408
01409
01410 if (bb->Labnam() == 0) {
01411 bb->Set_labnam( _cfg->Alloc_label());
01412 #ifdef KEY // bug 3152
01413 _cfg->Append_label_map( bb->Labnam(), bb );
01414 #endif
01415 }
01416
01417
01418 bb->Add_label_stmtrep( _cfg->Mem_pool() );
01419 label_stmt = bb->Label_stmtrep();
01420
01421 if ( Tracing() )
01422 fprintf( TFile, "DCE::Check_for_label: Add label to BB:%d\n", bb->Id() );
01423 }
01424
01425 Mark_statement_live( label_stmt );
01426 }
01427
01428
01429
01430
01431 BOOL
01432 DCE::Hasexception( BB_NODE *bb ) const
01433 {
01434 return bb->Haspragma();
01435 }
01436
01437
01438
01439
01440
01441
01442
01443
01444
01445
01446
01447
01448
01449
01450
01451
01452
01453 void
01454 DCE::Check_for_unreachable_exceptions( BB_NODE *bb ) const
01455 {
01456 Is_True( Hasexception(bb),
01457 ("Check_for_unreachable_exceptions: called on block with no exc") );
01458
01459 if (!bb->Reached()) {
01460 BB_NODE *bb1 = bb;
01461
01462
01463
01464 while (!bb1->Reached())
01465 bb1 = bb1->Prev();
01466
01467 if (bb1 != NULL) {
01468 STMTREP * stmt, *next_stmt = NULL;
01469
01470 for (stmt = bb->First_stmtrep(); stmt; stmt = next_stmt) {
01471 next_stmt = stmt->Next();
01472 if (stmt->Opr() == OPR_EXC_SCOPE_BEGIN ||
01473 stmt->Opr() == OPR_EXC_SCOPE_END) {
01474 if (Tracing()) {
01475 fprintf(TFile, "Moving OPR_EXC_SCOPE_%s from bb:%d to bb:%d\n",
01476 stmt->Opr() == OPR_EXC_SCOPE_BEGIN ? "BEGIN" : "END",
01477 bb->Id(), bb1->Id());
01478 }
01479
01480
01481 bb->Remove_stmtrep(stmt);
01482
01483
01484 STMTREP * br_stmt = bb1->Branch_stmtrep();
01485 if (br_stmt == NULL) {
01486 bb1->Append_stmtrep(stmt);
01487 }
01488 else {
01489 bb1->Insert_stmtrep_before(stmt, br_stmt);
01490 }
01491 }
01492 }
01493 }
01494 }
01495 }
01496
01497
01498
01499
01500
01501
01502 void
01503 DCE::Remove_unreached_statements( BB_NODE *bb ) const
01504 {
01505
01506 STMTREP *stmt;
01507
01508 if (bb->Kind() == BB_REGIONSTART)
01509 Remove_region_entry(bb);
01510 else {
01511
01512 while ( (stmt = bb->Last_stmtrep()) != NULL ) {
01513 if (stmt->Opr() == OPR_REGION_EXIT)
01514 Remove_region_exit(bb, FALSE);
01515 bb->Remove_stmtrep(stmt);
01516 }
01517 }
01518
01519 while ( bb->Phi_list() != NULL && !bb->Phi_list()->Is_Empty() ) {
01520 PHI_NODE *phi = bb->Phi_list()->Remove_Headnode();
01521 phi->Reset_live();
01522 }
01523 }
01524
01525
01526
01527
01528
01529
01530
01531
01532
01533 BOOL Remove_region_exit(BB_NODE *bb, BOOL is_whirl)
01534 {
01535 Is_True(bb != NULL && bb->Kind() == BB_REGIONEXIT,
01536 ("DCE::Remove_region_exit, REGION_EXIT not inside "
01537 "BB_REGION_EXIT, BB%d",bb->Id()));
01538
01539 BB_REGION *bb_region = bb->Regioninfo();
01540 if (bb_region == NULL)
01541 return TRUE;
01542
01543 RID *rid = bb_region->Rid();
01544
01545 if (rid == NULL) {
01546 bb_region->Set_region_end(NULL);
01547 bb->Set_regioninfo(NULL);
01548 return TRUE;
01549 }
01550
01551
01552
01553
01554 if (RID_TYPE_mp(rid)) {
01555 bb_region->Set_region_end(NULL);
01556 return TRUE;
01557 }
01558 if (RID_TYPE_eh(rid))
01559 return FALSE;
01560
01561
01562 IDTYPE label_no;
01563 if (is_whirl) {
01564 Is_True(WN_operator(bb->Laststmt()) == OPR_REGION_EXIT,
01565 ("DCE::Remove_region_exit, last statement is not region exit"));
01566 label_no = WN_label_number(bb->Laststmt());
01567 } else {
01568 Is_True(bb->Last_stmtrep()->Opr() == OPR_REGION_EXIT,
01569 ("DCE::Remove_region_exit, last statement is not region exit"));
01570 label_no = bb->Last_stmtrep()->Label_number();
01571 }
01572
01573
01574
01575 REGION_delete_exit(rid, label_no, bb_region->Region_exit_list(), FALSE);
01576 Is_True(bb_region->Region_num_exits() == RID_num_exits(rid) + 1,
01577 ("Remove_region_exits, miscalculated number of exits"));
01578 bb_region->Set_region_num_exits(rid);
01579 return FALSE;
01580 }
01581
01582
01583
01584
01585
01586
01587 void Remove_region_entry(BB_NODE *bb)
01588 {
01589 Is_True(bb != NULL && bb->Kind() == BB_REGIONSTART,
01590 ("DCE::Remove_region_entry, something wrong with region entry, BB%d",
01591 bb->Id()));
01592 BB_REGION *bb_region = bb->Regioninfo();
01593 if (bb_region == NULL)
01594 return;
01595 Is_True(bb_region->Region_start() == bb,
01596 ("DCE::Remove_region_entry, could not find region entry"));
01597
01598
01599 RID *rid = bb_region->Rid();
01600 Is_True(rid != NULL, ("Remove_region_entry, NULL RID"));
01601 RID_Delete2(rid);
01602
01603
01604 #ifndef KEY // bug 5714
01605 bb_region->Set_region_start(NULL);
01606 bb_region->Set_rid(NULL);
01607 #endif
01608 bb->Set_regioninfo(NULL);
01609 }
01610
01611
01612
01613
01614
01615
01616 void
01617 DCE::Check_unreachable_blocks( void ) const
01618 {
01619 CFG_ITER cfg_iter(_cfg);
01620 BB_NODE *bb;
01621
01622 FOR_ALL_NODE( bb, cfg_iter, Init() ) {
01623 if ( bb->Reached() ) {
01624 switch ( bb->Kind() ) {
01625 case BB_DOEND:
01626 case BB_DOHEAD:
01627 case BB_DOSTART:
01628 case BB_DOSTEP:
01629 case BB_DOTAIL:
01630 case BB_ENTRY:
01631 case BB_EXIT:
01632 case BB_REGIONEXIT:
01633 case BB_GOTO:
01634 case BB_IO:
01635 case BB_REPEATBODY:
01636 case BB_REPEATEND:
01637 case BB_SUMMARY:
01638 case BB_VARGOTO:
01639 break;
01640
01641 case BB_WHILEEND:
01642
01643 if ( ! bb->Loopstep()->Reached() ||
01644 ! bb->Loopmerge()->Reached() )
01645 {
01646 _cfg->Change_block_kind( bb, BB_LOGIF );
01647 }
01648 break;
01649
01650 case BB_REGIONSTART:
01651 {
01652
01653
01654 BB_REGION *region = bb->Regioninfo();
01655 Is_True(region != NULL,
01656 ("DCE::Check_unreachable_blocks, NULL bb_region"));
01657 BB_NODE *last_region_bb = region->Region_end();
01658 if ( last_region_bb && ! last_region_bb->Reached() ) {
01659
01660
01661 while ( ! last_region_bb->Reached() ) {
01662 last_region_bb = last_region_bb->Prev();
01663
01664
01665 if ( last_region_bb == bb ) {
01666 last_region_bb = NULL;
01667 break;
01668 }
01669 }
01670
01671 if ( last_region_bb == NULL ) {
01672
01673 bb->Set_regioninfo( NULL );
01674 bb->Set_kind( BB_GOTO );
01675 } else
01676 region->Set_region_end( last_region_bb );
01677 }
01678 }
01679 break;
01680
01681 case BB_LOGIF:
01682 if ( bb->Ifinfo() != NULL ) {
01683 Is_True( bb->If_then()->Reached(),
01684 ("IF (bb:%d) reached, but THEN (bb:%d) is not",
01685 bb->Id(), bb->If_then()->Id()) );
01686 Is_True( bb->If_else()->Reached(),
01687 ("IF (bb:%d) reached, but ELSE (bb:%d) is not",
01688 bb->Id(), bb->If_else()->Id()) );
01689
01690
01691
01692
01693 if ( ! bb->If_merge()->Reached() ) {
01694
01695
01696 if ( !_cfg->Lower_fully() )
01697 Check_for_label( bb->If_then() );
01698 bb->Set_ifinfo( NULL );
01699 }
01700 }
01701 break;
01702
01703 case BB_UNKNOWN:
01704 default:
01705 ErrMsg( EC_Unimplemented,
01706 "Check_unreachable_blocks: invalid bb Kind()" );
01707 break;
01708 }
01709
01710 }
01711
01712
01713
01714
01715 }
01716 }
01717
01718
01719
01720
01721
01722
01723
01724 BOOL
01725 DCE::Unreachable_code_elim( void ) const
01726 {
01727
01728 CFG_ITER cfg_iter(_cfg);
01729 BB_NODE *bb;
01730 FOR_ALL_NODE( bb, cfg_iter, Init() ) {
01731 bb->Reset_reached();
01732 }
01733
01734
01735
01736 BB_NODE_SET cb_path( _cfg->Total_bb_count(), _cfg,
01737 _cfg->Loc_pool(), BBNS_EMPTY );
01738 BOOL changed_cflow;
01739 {
01740 changed_cflow = Check_conditional_branches_dom( _cfg->Entry_bb(), &cb_path );
01741 changed_cflow |= Check_conditional_branches_pred( _cfg );
01742 }
01743
01744
01745 _cfg->Find_not_reached();
01746
01747
01748
01749 Check_unreachable_blocks();
01750
01751 BB_NODE *nextbb = NULL;
01752 for ( bb = _cfg->First_bb(); bb != NULL; bb = nextbb ) {
01753
01754 nextbb = bb->Next();
01755
01756
01757
01758
01759 Warn_todo( "DCE::Unreachable_code_elim: update preds necessary?");
01760 changed_cflow |= Update_predecessor_lists( bb );
01761
01762
01763
01764 if ( bb->Reached() ) {
01765 if ( May_need_label()->MemberP( bb ) ) {
01766 Check_for_label( bb );
01767 }
01768 }
01769 else {
01770
01771 if ( Tracing() ) {
01772 fprintf( TFile, "DCE: Removing stmts in BB%d (0x%p)\n",
01773 bb->Id(), bb );
01774 }
01775
01776
01777 Remove_unreached_statements( bb );
01778
01779
01780
01781 #if !defined(TARG_SL)
01782 if ( OPT_Cyg_Instrument > 0 && bb->Labnam() != 0 &&
01783 LABEL_addr_saved( bb->Labnam() ) ) {
01784 #else
01785 if ( 0 && bb->Labnam() != 0 &&
01786 LABEL_addr_saved( bb->Labnam() ) ) {
01787 #endif
01788 Keep_unreached_bb( bb );
01789
01790 Check_for_label( bb );
01791 }
01792
01793
01794
01795 if ( bb->Kind() != BB_EXIT && bb->Kind() != BB_REGIONEXIT )
01796 _cfg->Change_block_kind( bb, BB_GOTO );
01797
01798 if ( !Keep_unreached()->MemberP(bb) && _cfg->Removable_bb(bb) ) {
01799
01800
01801
01802 BB_LIST *succ_ref;
01803 BB_LIST *nextsucc = NULL;
01804 for ( succ_ref = bb->Succ();
01805 succ_ref != NULL;
01806 succ_ref = nextsucc ) {
01807 nextsucc = succ_ref->Next();
01808 changed_cflow |= Update_predecessor_lists( succ_ref->Node() );
01809 }
01810
01811 _cfg->Remove_bb(bb);
01812 #ifdef Is_True_On
01813 if (bb->Kind() == BB_DOSTART &&
01814 (bb->Loop()->Flags() & LOOP_ORIGINAL_DO))
01815 DevWarn("DO-loop is demoted to WHILE-loop in preopt.");
01816 #endif
01817 if ( Tracing() ) {
01818 fprintf( TFile, "DCE: Removed BB%d\n",bb->Id());
01819 fflush( TFile );
01820 }
01821 }
01822 }
01823 }
01824
01825
01826
01827 if ( changed_cflow )
01828 _cfg->Invalidate_loops();
01829
01830 return ( changed_cflow );
01831 }
01832
01833
01834
01835
01836
01837
01838
01839
01840
01841
01842
01843
01844
01845
01846
01847
01848
01849
01850
01851
01852
01853 CODEREP *
01854 DCE::Find_current_version( const STMTREP *ref_stmt, const CODEREP *cr ) const
01855 {
01856 Is_True( cr->Kind() == CK_VAR,
01857 ("DCE::Find_current_version: non-VAR coderep") );
01858 Is_True( ref_stmt != NULL,
01859 ("DCE::Find_current_version: null ref_stmt") );
01860
01861 const AUX_ID aux_id = cr->Aux_id();
01862 BB_NODE *ref_bb = ref_stmt->Bb();
01863
01864 for ( BB_NODE *bb = ref_bb; bb != NULL; bb = bb->Idom() ) {
01865
01866
01867
01868 const STMTREP *stmt;
01869 if ( bb != ref_bb )
01870 stmt = bb->Last_stmtrep();
01871 else
01872 stmt = ref_stmt->Prev();
01873
01874 for ( ; stmt != NULL; stmt = stmt->Prev() ) {
01875
01876
01877 if (stmt->Has_chi()) {
01878 CHI_LIST_ITER chi_iter;
01879 CHI_NODE *cnode;
01880 FOR_ALL_NODE(cnode,chi_iter,Init(stmt->Chi_list())) {
01881 if (! cnode->Dse_dead()) {
01882 if ( cnode->Aux_id() == aux_id )
01883 return cnode->RESULT();
01884 }
01885 }
01886 }
01887
01888
01889 CODEREP *lhs = stmt->Lhs();
01890 if ( lhs && lhs->Kind() == CK_VAR && lhs->Aux_id() == aux_id ) {
01891 return lhs;
01892 }
01893
01894 }
01895
01896
01897
01898
01899 PHI_LIST_ITER phi_iter;
01900 PHI_NODE *pnode;
01901 FOR_ALL_ELEM(pnode,phi_iter,Init(bb->Phi_list())) {
01902 if ( pnode->Aux_id() == aux_id )
01903 return pnode->RESULT();
01904 }
01905 }
01906
01907 return NULL;
01908 }
01909
01910
01911 #if 0
01912
01913
01914
01915
01916
01917
01918
01919 BOOL
01920 DCE::Is_identity_assignment( const STMTREP *stmt ) const
01921 {
01922 if ( ! Allow_dce_prop() )
01923 return FALSE;
01924
01925 Is_True ( stmt->Opr() == OPR_STID,
01926 ("DCE::Is_identity_assignment: non-STID operator") );
01927
01928 const CODEREP *lhs = stmt->Lhs();
01929
01930
01931 if (lhs->Is_var_volatile())
01932 return ( FALSE );
01933
01934
01935
01936 if (stmt->Rhs()->Kind() == CK_VAR &&
01937 stmt->Rhs()->Aux_id() == stmt->Lhs()->Aux_id() &&
01938 !stmt->Rhs()->Is_var_volatile() &&
01939 Find_current_version(stmt, stmt->Rhs()) == stmt->Rhs() )
01940 {
01941 return ( TRUE );
01942 }
01943
01944 return ( FALSE );
01945 }
01946 #endif
01947
01948
01949
01950
01951
01952
01953 BOOL
01954 DCE::Required_store( const STMTREP *stmt, OPERATOR oper ) const
01955 {
01956 Is_True ( OPERATOR_is_scalar_store (oper),
01957 ("DCE::Required_store: expecting STID/STBITS operator") );
01958
01959 const CODEREP *lhs = stmt->Lhs();
01960
01961
01962 if (lhs->Is_var_volatile())
01963 return ( TRUE );
01964
01965 #if defined(TARG_SL)
01966 if (CR_Intrinsic_Op_Slave(stmt->Rhs())) {
01967 Append_Injured_AuxIntrnOp((STMTREP *)stmt);
01968 }
01969 #endif
01970
01971
01972
01973 if ( Enable_identity_removal() &&
01974 stmt->Is_identity_assignment_removable( ) ) {
01975 return ( FALSE );
01976 }
01977
01978
01979 if (lhs->Is_flag_set(CF_INCOMPLETE_USES))
01980 return TRUE;
01981
01982
01983 ST *s = Opt_stab()->St(lhs->Aux_id());
01984 if ( ST_class(s) == CLASS_PREG && Preg_Is_Dedicated(lhs->Offset()) )
01985 return ( TRUE );
01986
01987
01988
01989 if (_is_varargs_func && ST_sclass(s) == SCLASS_FORMAL) {
01990 const CODEREP *rhs = stmt->Rhs();
01991
01992 if (rhs->Kind() == CK_VAR &&
01993 ST_class(Opt_stab()->St(rhs->Aux_id())) == CLASS_PREG &&
01994 Preg_Is_Dedicated(rhs->Offset())) {
01995 Warn_todo("better processing of varargs in DCE.");
01996 return TRUE;
01997 }
01998 }
01999
02000 #ifdef KEY // deleting fetch of MTYPE_M return value can cause lowerer to omit
02001
02002 if (Opt_stab()->Phase() == PREOPT_IPA0_PHASE && lhs->Dsctyp() == MTYPE_M &&
02003 stmt->Rhs()->Kind() == CK_VAR &&
02004 ST_class(Opt_stab()->St(stmt->Rhs()->Aux_id())) == CLASS_PREG &&
02005 Preg_Is_Dedicated(stmt->Rhs()->Offset()))
02006 return TRUE;
02007 #endif
02008
02009
02010 return ( FALSE );
02011 }
02012
02013 BOOL
02014 DCE::Required_istore( const STMTREP *stmt, OPERATOR oper ) const
02015 {
02016 Is_True ( ! OPERATOR_is_scalar_store (oper),
02017 ("DCE::Required_istore: STID/STBITS operator") );
02018
02019 if (stmt->Lhs()->Is_ivar_volatile())
02020 return ( TRUE );
02021
02022
02023 #if 0
02024
02025 if (stmt->Lhs()->Points_to(Opt_stab())->Unique_pt()) {
02026 Warn_todo("Handle unique pts.");
02027 return TRUE;
02028 }
02029 #endif
02030
02031
02032
02033
02034
02035
02036
02037
02038
02039
02040 if (stmt->Lhs()->Points_to(Opt_stab())->Restricted())
02041 return TRUE;
02042
02043 #ifdef KEY // deleting fetch of MTYPE_M return value can cause lowerer to omit
02044
02045 if (Opt_stab()->Phase() == PREOPT_IPA0_PHASE && stmt->Lhs()->Dsctyp() == MTYPE_M &&
02046 stmt->Rhs()->Kind() == CK_VAR &&
02047 ST_class(Opt_stab()->St(stmt->Rhs()->Aux_id())) == CLASS_PREG &&
02048 Preg_Is_Dedicated(stmt->Rhs()->Offset()))
02049 return TRUE;
02050 #endif
02051
02052 return ( FALSE );
02053 }
02054
02055
02056
02057
02058
02059 BOOL
02060 DCE::Required_call( const STMTREP *stmt, OPERATOR oper ) const
02061 {
02062 Warn_todo( "DCE::Required_call" );
02063 return ( TRUE );
02064 }
02065
02066
02067
02068
02069
02070 BOOL
02071 DCE::Required_asm( const STMTREP *stmt ) const
02072 {
02073 if (stmt->Asm_stmt_flags() & WN_ASM_VOLATILE)
02074 return TRUE;
02075 else
02076 return FALSE;
02077 }
02078
02079
02080
02081
02082
02083 BOOL
02084 DCE::Required_phi( const PHI_NODE *phi ) const
02085 {
02086 if (phi->Dse_dead())
02087 return FALSE;
02088 if (phi->RESULT() != NULL &&
02089 (phi->RESULT()->Is_flag_set(CF_IS_ZERO_VERSION) ||
02090 phi->RESULT()->Is_flag_set(CF_INCOMPLETE_USES)))
02091 return ( TRUE );
02092 return FALSE;
02093 }
02094
02095 inline BOOL
02096 DCE::Loop_pragma(WN_PRAGMA_ID pragma) const
02097 {
02098 switch (pragma) {
02099
02100
02101 case WN_PRAGMA_AGGRESSIVE_INNER_LOOP_FISSION:
02102 case WN_PRAGMA_BLOCKABLE:
02103 case WN_PRAGMA_BLOCKING_SIZE:
02104 case WN_PRAGMA_CRI_CNCALL:
02105 case WN_PRAGMA_FISSION:
02106 case WN_PRAGMA_FISSIONABLE:
02107 case WN_PRAGMA_FUSE:
02108 case WN_PRAGMA_FUSEABLE:
02109 case WN_PRAGMA_INTERCHANGE:
02110 case WN_PRAGMA_IVDEP:
02111 case WN_PRAGMA_KAP_ASSERT_CONCURRENT_CALL:
02112 case WN_PRAGMA_KAP_ASSERT_DO:
02113 case WN_PRAGMA_KAP_ASSERT_DOPREFER:
02114 case WN_PRAGMA_NEXT_SCALAR:
02115 case WN_PRAGMA_NORECURRENCE:
02116 case WN_PRAGMA_NO_BLOCKING:
02117 case WN_PRAGMA_NO_FISSION:
02118 case WN_PRAGMA_NO_FUSION:
02119 case WN_PRAGMA_NO_INTERCHANGE:
02120 case WN_PRAGMA_UNROLL:
02121 return TRUE;
02122 }
02123 return FALSE;
02124 }
02125
02126
02127
02128
02129
02130
02131 inline BOOL
02132 DCE::Required_pragma( const STMTREP *stmt ) const
02133 {
02134 WN_PRAGMA_ID pragma = (WN_PRAGMA_ID)WN_pragma(stmt->Orig_wn());
02135 #ifdef KEY
02136 if (pragma == WN_PRAGMA_UNROLL) return TRUE;
02137 #endif
02138 if (Loop_pragma(pragma)) return FALSE;
02139
02140 switch ( pragma ) {
02141 case WN_PRAGMA_INLINE_BODY_START:
02142 case WN_PRAGMA_INLINE_BODY_END:
02143 return FALSE;
02144 }
02145
02146 return TRUE;
02147 }
02148
02149
02150
02151
02152
02153 BOOL
02154 DCE::Required_stmt( const STMTREP *stmt ) const
02155 {
02156 const OPERATOR opr = stmt->Opr();
02157
02158
02159 if ( stmt->Volatile_stmt() )
02160 return TRUE;
02161
02162 if (OPERATOR_is_scalar_store (opr) &&
02163 Enable_identity_removal() &&
02164 stmt->Is_identity_assignment_removable())
02165 return FALSE;
02166
02167
02168 if ( WOPT_Enable_Zero_Version && stmt->Has_zver())
02169 return TRUE;
02170
02171 #ifdef KEY // bugs 5401 and 5267
02172 if (OPERATOR_is_scalar_store(opr) &&
02173 Opt_stab()->Aux_stab_entry(stmt->Lhs()->Aux_id())->Mp_no_dse())
02174 return TRUE;
02175 #endif
02176
02177 CHI_LIST_ITER chi_iter;
02178 CHI_NODE *cnode;
02179 FOR_ALL_NODE(cnode, chi_iter, Init(stmt->Chi_list())) {
02180
02181 if (!cnode->Dse_dead() &&
02182 cnode->RESULT() != NULL &&
02183 cnode->RESULT()->Is_flag_set(CF_INCOMPLETE_USES))
02184 return TRUE;
02185
02186
02187 if (Opt_stab()->Aux_stab_entry(cnode->Aux_id())->Is_volatile())
02188 return TRUE;
02189 }
02190
02191
02192 switch ( opr ) {
02193 case OPR_AGOTO:
02194 case OPR_TRUEBR:
02195 case OPR_FALSEBR:
02196 case OPR_GOTO:
02197 return ( !Enable_aggressive_dce() );
02198
02199 case OPR_COMPGOTO:
02200 #ifdef KEY
02201 if ((PU_has_mp(Get_Current_PU()) || PU_mp_lower_generated(Get_Current_PU()))
02202 && Early_MP_Processing)
02203 return TRUE;
02204 #endif
02205 return ( !Enable_aggressive_dce() );
02206
02207 case OPR_LABEL:
02208 return ( !Enable_aggressive_dce() ||
02209 LABEL_addr_saved( stmt->Label_number() ) );
02210
02211 case OPR_PRAGMA:
02212 case OPR_XPRAGMA:
02213 return ( Required_pragma(stmt) );
02214
02215 case OPR_ASSERT:
02216 case OPR_BACKWARD_BARRIER:
02217 case OPR_FORWARD_BARRIER:
02218 case OPR_DEALLOCA:
02219 case OPR_EXC_SCOPE_BEGIN:
02220 case OPR_EXC_SCOPE_END:
02221 case OPR_IO:
02222 case OPR_PREFETCH:
02223 case OPR_PREFETCHX:
02224 case OPR_REGION:
02225 case OPR_RETURN:
02226 case OPR_RETURN_VAL:
02227 case OPR_REGION_EXIT:
02228 case OPR_OPT_CHI:
02229 #ifdef KEY
02230 case OPR_GOTO_OUTER_BLOCK:
02231 #endif
02232 return TRUE;
02233
02234 case OPR_CALL:
02235 case OPR_ICALL:
02236 case OPR_INTRINSIC_CALL:
02237 return ( Required_call( stmt, opr ) );
02238
02239 case OPR_STID:
02240 case OPR_STBITS:
02241 return ( Required_store( stmt, opr ) );
02242
02243 case OPR_MSTORE:
02244 case OPR_ISTORE:
02245 case OPR_ISTBITS:
02246 case OPR_ISTOREX:
02247 return ( Required_istore( stmt, opr ) );
02248
02249 case OPR_ALTENTRY:
02250 case OPR_FUNC_ENTRY:
02251 FmtAssert(FALSE, ("DCE::Required_stmt: Unexpected OPR\n"));
02252 break;
02253
02254 case OPR_ASM_STMT:
02255 return ( Required_asm( stmt ));
02256
02257 default:
02258 break;
02259 }
02260
02261 return FALSE;
02262 }
02263
02264
02265
02266
02267
02268 BOOL
02269 DCE::Required_bb( const BB_NODE *bb ) const
02270 {
02271 if ( bb->Kind() == BB_REGIONSTART ) {
02272
02273 BB_REGION *bb_region = bb->Regioninfo();
02274 Is_True(bb_region != NULL, ("DCE::Required_bb, NULL bb_region"));
02275 Is_True(bb_region->Rid() != NULL, ("DCE::Required_bb, NULL RID"));
02276 if ( RID_TYPE_guard(bb_region->Rid()) )
02277 return TRUE;
02278 }
02279 return FALSE;
02280 }
02281
02282
02283
02284
02285 CODEREP *
02286 DCE::Dce_prop(CODEREP *opnd) const
02287 {
02288 if (!Allow_dce_prop()) return NULL;
02289
02290 CODEREP *newopnd = opnd;
02291
02292
02293
02294
02295 while ( newopnd != NULL ) {
02296
02297 if (newopnd->Is_flag_set(CF_DEF_BY_PHI)) break;
02298 if (newopnd->Defstmt() == NULL) break;
02299
02300
02301 CODEREP *lhs = newopnd->Defstmt()->Lhs();
02302 if (lhs == NULL) break;
02303 if (lhs->Kind() != CK_VAR) break;
02304
02305 CODEREP *rhs = newopnd->Defstmt()->Rhs();
02306 if (rhs->Kind() != CK_VAR) break;
02307 if (rhs->Aux_id() != lhs->Aux_id()) break;
02308
02309
02310 if (rhs->Is_var_volatile()) break;
02311
02312
02313 if ( Find_current_version(newopnd->Defstmt(), rhs) != rhs ) break;
02314
02315
02316
02317
02318
02319 if ( ! newopnd->Is_flag_set(CF_DEF_BY_CHI) )
02320 newopnd = rhs;
02321 else
02322 newopnd = newopnd->Defchi()->OPND();
02323
02324 if ( Tracing() ) {
02325 fprintf( TFile, "DCE::Dce_prop: revising mu/chi CODEREP from\n" );
02326 opnd->Print( 0, TFile );
02327 fprintf( TFile, " to\n" );
02328 newopnd->Print( 0, TFile );
02329 }
02330 }
02331
02332 return (newopnd == opnd) ? NULL : newopnd;
02333 }
02334
02335
02336
02337
02338
02339
02340
02341 void
02342 DCE::Mark_phinode_live( PHI_NODE *phi, BOOL visit_opnds ) const
02343 {
02344 if ( phi->Live() )
02345 return;
02346
02347 phi->Set_live();
02348
02349
02350 if ( ! phi->Bb()->Reached() ) {
02351 Mark_block_live( phi->Bb() );
02352 }
02353
02354
02355 if ( visit_opnds ) {
02356 BOOL ignore_pregs = Opt_stab()->Is_virtual(phi->RESULT()->Aux_id());
02357 for ( INT pkid = 0; pkid < phi->Size(); pkid++ ) {
02358 CODEREP *cr;
02359 if ((cr = Dce_prop(phi->OPND(pkid))) != NULL) {
02360 phi->Set_opnd(pkid,cr);
02361 cr->Set_flag(CF_DONT_PROP);
02362 }
02363 else cr = phi->OPND(pkid);
02364
02365 STMTREP *proj_defstmt = Proj_defstmt(cr, Opt_stab());
02366 if (proj_defstmt != NULL) {
02367
02368
02369
02370 proj_defstmt->Inc_proj_op_uses(2);
02371 }
02372
02373
02374 cr->Reset_safe_to_renumber_preg();
02375 Mark_coderep_live(cr);
02376 }
02377 }
02378 }
02379
02380
02381
02382
02383
02384 BOOL
02385 DCE::Aliased( const POINTS_TO *pt1, const POINTS_TO *pt2 ) const
02386 {
02387 if ( pt1 == NULL || pt2 == NULL )
02388
02389 return TRUE;
02390
02391 return ( _alias_rule->Aliased_Memop( pt1, pt2 ) );
02392 }
02393
02394
02395
02396
02397
02398
02399
02400 void
02401 DCE::Mark_chinode_live( CHI_NODE *chi, STMTREP *def_stmt ) const
02402 {
02403 if (chi->Live() || chi->Dse_dead()) return;
02404
02405
02406 if ( Enable_dce_global() &&
02407 chi->OPND()->Aux_id() == Return_vsym() )
02408 return;
02409
02410 #if 0
02411
02412
02413
02414
02415 if ( Enable_dce_alias() && def_stmt != NULL &&
02416 Points_to_stack()->Elements() > 0 )
02417 {
02418 if ( ! Aliased( def_stmt->Points_to(Opt_stab()),
02419 Points_to_stack()->Top() ) )
02420 {
02421 MU_NODE *tos_mu = Mu_stack()->Top();
02422 CODEREP *old_opnd = tos_mu->OPND();
02423
02424
02425
02426 Warn_todo( "DCE::Mark_chinode_live: update pvl list?" );
02427 tos_mu->Set_OPND( chi->OPND() );
02428
02429 if ( Tracing() ) {
02430 fprintf( TFile, "DCE::Mark_chinode_live: revising chi from\n" );
02431 old_opnd->Print( 0, TFile );
02432 fprintf( TFile, " to\n" );
02433 chi->OPND()->Print( 0, TFile );
02434 }
02435
02436
02437 return;
02438 }
02439 }
02440
02441
02442 CODEREP *opnd = chi->OPND();
02443 CODEREP *res = chi->RESULT();
02444
02445
02446
02447
02448 if ( Allow_dce_prop() && opnd->Is_flag_set(CF_DEF_BY_CHI) ) {
02449 Is_True(res->Kind() == CK_VAR && opnd->Kind() == CK_VAR, ("chi must contain CK_VAR."));
02450 if (res->Defstmt()->Same_lhs(opnd->Defstmt())) {
02451
02452 chi->Set_OPND( opnd->Defchi()->OPND());
02453
02454 Mark_chinode_live( chi, def_stmt );
02455 return;
02456 }
02457 }
02458 #endif
02459
02460 CODEREP *cr = Dce_prop(chi->OPND());
02461 if (cr != NULL) {
02462 AUX_STAB_ENTRY *aux_entry = Opt_stab()->Aux_stab_entry(cr->Aux_id());
02463 Is_True(!aux_entry->Is_non_dedicated_preg(),
02464 ("DCE: mu/chi of non-dedicated PREG not allowed"));
02465
02466
02467 if (aux_entry->Is_non_dedicated_preg()) {
02468 cr->Reset_safe_to_renumber_preg();
02469 }
02470 chi->Set_OPND(cr);
02471 Mark_chinode_live(chi, def_stmt);
02472 } else {
02473 AUX_STAB_ENTRY *aux_entry =
02474 Opt_stab()->Aux_stab_entry(chi->OPND()->Aux_id());
02475 Is_True((!aux_entry->Is_non_dedicated_preg()) ||
02476 (def_stmt->Opr() == OPR_OPT_CHI) ||
02477 ((def_stmt->Opr() == OPR_REGION) &&
02478 (def_stmt->Black_box())),
02479 ("DCE: mu/chi of non-dedicated PREG not allowed"));
02480
02481
02482
02483 if (aux_entry->Is_non_dedicated_preg()) {
02484 chi->OPND()->Reset_safe_to_renumber_preg();
02485 }
02486 chi->Set_live(TRUE);
02487 Mark_coderep_live( chi->OPND() );
02488 }
02489 }
02490
02491
02492
02493
02494
02495
02496
02497 void
02498 DCE::Mark_zero_version_chinode_live( STMTREP *stmt ) const
02499 {
02500 Is_True( stmt->Has_zver(),
02501 ("DCE::Mark_zero_version_chinode_live: stmt does not have zver") );
02502
02503 BOOL made_chi_live = FALSE;
02504 CHI_LIST_ITER chi_iter;
02505 CHI_NODE *chi;
02506 CHI_LIST *chi_list = stmt->Chi_list();
02507 FOR_ALL_NODE( chi, chi_iter, Init(chi_list)) {
02508 if ( ! chi->Dse_dead() ) {
02509 CODEREP *res = chi->RESULT();
02510 if ( res->Is_flag_set(CF_IS_ZERO_VERSION) ) {
02511 Mark_chinode_live(chi, stmt);
02512 made_chi_live = TRUE;
02513 }
02514 }
02515 }
02516
02517 if ( made_chi_live ) {
02518 if ( ! stmt->Live_stmt()) {
02519 Mark_statement_live( stmt );
02520 }
02521 }
02522 else {
02523 FmtAssert( FALSE,
02524 ("DCE::Mark_zero_version_chinode_live: no zero-version chi") );
02525 }
02526 }
02527
02528
02529
02530
02531
02532
02533
02534 void
02535 DCE::Mark_cr_munode_live( CODEREP *cr ) const
02536 {
02537 MU_NODE *mu;
02538
02539 if ( Enable_dce_alias() && cr->Ivar_mu_node() != NULL ) {
02540 Points_to_stack()->Push( cr->Points_to(Opt_stab()) );
02541 }
02542
02543 mu = cr->Ivar_mu_node();
02544
02545 if (mu) {
02546
02547
02548 if ( Enable_dce_global() &&
02549 mu->OPND()->Aux_id() == Return_vsym() ) {
02550 Mark_return_vsym_mu_ref_live( mu->OPND() );
02551 } else {
02552
02553 if ( Enable_dce_alias() ) {
02554 Mu_stack()->Push( mu );
02555 }
02556
02557 if (mu->OPND()->Defstmt() == NULL) {
02558
02559 if (mu->OPND()->Is_flag_set(CF_DEF_BY_PHI)) {
02560 if ( !(mu->OPND()->Defphi()->Live()) )
02561 Mark_coderep_live( mu->OPND() );
02562 }
02563 }
02564 else if (mu->OPND()->Is_flag_set(CF_DEF_BY_CHI)) {
02565 Mark_coderep_live(mu->OPND());
02566 }
02567 else {
02568 if (!(mu->OPND()->Defstmt()->Live_stmt())) {
02569 CODEREP *cr;
02570 if ((cr = Dce_prop(mu->OPND())) != NULL) {
02571 mu->Set_OPND(cr);
02572 Mark_coderep_live(cr);
02573 } else
02574 Mark_coderep_live( mu->OPND() );
02575 }
02576 }
02577
02578 if ( Enable_dce_alias() ) {
02579 Mu_stack()->Pop();
02580 }
02581 }
02582 }
02583
02584 if ( Enable_dce_alias() && cr->Ivar_mu_node() != NULL ) {
02585 Points_to_stack()->Pop();
02586 }
02587
02588 }
02589
02590
02591
02592
02593
02594
02595
02596 void
02597 DCE::Mark_sr_munode_live( STMTREP *sr ) const
02598 {
02599 MU_NODE *mu;
02600
02601 if ( Enable_dce_alias() && sr->Mu_list() != NULL ) {
02602 Points_to_stack()->Push( sr->Points_to(Opt_stab()) );
02603 }
02604
02605 mu = (sr->Mu_list() ? sr->Mu_list()->Head() : NULL);
02606 while (mu != NULL) {
02607
02608 if ( Enable_dce_global() &&
02609 mu->OPND()->Aux_id() == Return_vsym() )
02610 {
02611 Mark_return_vsym_mu_ref_live( mu->OPND() );
02612 mu = mu->Next();
02613 continue;
02614 }
02615
02616 if ( Enable_dce_alias() ) {
02617 Mu_stack()->Push( mu );
02618 }
02619
02620 CODEREP *cr;
02621 if ((cr = Dce_prop(mu->OPND())) != NULL) {
02622 mu->Set_OPND(cr);
02623 Mark_coderep_live(cr);
02624 } else
02625 Mark_coderep_live( mu->OPND() );
02626
02627 if ( Enable_dce_alias() ) {
02628 Mu_stack()->Pop();
02629 }
02630 mu = mu->Next();
02631 }
02632
02633 if ( Enable_dce_alias() && sr->Mu_list() != NULL ) {
02634 Points_to_stack()->Pop();
02635 }
02636 }
02637
02638
02639
02640
02641
02642
02643
02644 void
02645 DCE::Mark_coderep_live( CODEREP *cr ) const
02646 {
02647
02648 if ( ! inCODEKIND(cr->Kind(), CK_LDA|CK_CONST|CK_RCONST) ) {
02649
02650
02651 if ( cr->Is_flag_set(CF_DEF_BY_PHI) ) {
02652 if ( ! cr->Defphi()->Live() ) {
02653 Mark_phinode_live( cr->Defphi(), TRUE );
02654 }
02655 }
02656 else {
02657 switch ( cr->Kind() ) {
02658 case CK_VAR:
02659
02660
02661 if ( Enable_dce_global() &&
02662 cr->Aux_id() == Return_vsym() )
02663 {
02664 Is_True( FALSE,
02665 ("Should not see Return_vsym() here") );
02666 return;
02667 }
02668
02669
02670
02671
02672
02673 if (cr->Is_flag_set(CF_DEF_BY_CHI)) {
02674 Mark_chinode_live( cr->Defchi(), cr->Defstmt() );
02675 }
02676
02677
02678
02679
02680
02681 if ( cr->Defstmt() != NULL && !cr->Defstmt()->Live_stmt() ) {
02682
02683
02684
02685
02686
02687 BOOL make_live = TRUE;
02688 if ( cr->Is_flag_set(CF_DEF_BY_CHI) &&
02689 WOPT_Enable_Zero_Version )
02690 {
02691 const STMTREP *defstmt = cr->Defstmt();
02692 const OPERATOR defoper = defstmt->Opr();
02693 if (OPERATOR_is_scalar_store (defoper) &&
02694 Enable_identity_removal() &&
02695 defstmt->Is_identity_assignment_removable() )
02696 make_live = FALSE;
02697 }
02698
02699 if ( make_live )
02700 Mark_statement_live( cr->Defstmt() );
02701 }
02702 break;
02703
02704 case CK_IVAR:
02705
02706 if ( cr->Istr_base() != NULL )
02707 Mark_coderep_live( cr->Istr_base() );
02708 else
02709 Mark_coderep_live( cr->Ilod_base() );
02710
02711
02712 if ( cr->Opr() == OPR_MLOAD ) {
02713 Mark_coderep_live( cr->Mload_size() );
02714 }
02715 else if ( cr->Opr() == OPR_ILOADX ) {
02716 Mark_coderep_live( cr->Index() );
02717 }
02718
02719 if ( cr->Opr() == OPR_PARM ) {
02720
02721 }
02722 else {
02723
02724 PF_POINTER *pf = cr->Ivar_occ()->Pf_pointer();
02725 if (pf != NULL) {
02726 if (PF_PTR_wn_pref_1L(pf) != NULL)
02727 Mark_statement_live((STMTREP *) PF_PTR_wn_pref_1L(pf));
02728 if (PF_PTR_wn_pref_2L(pf) != NULL)
02729 Mark_statement_live((STMTREP *) PF_PTR_wn_pref_2L(pf));
02730 }
02731 }
02732
02733
02734
02735
02736 if (cr->Ivar_defstmt() != NULL && !cr->Ivar_defstmt()->Live_stmt()) {
02737 Mark_statement_live( cr->Ivar_defstmt() );
02738 }
02739 Mark_cr_munode_live( cr );
02740 break;
02741
02742 case CK_OP:
02743 {
02744 if ( Is_dce_visited(cr) )
02745 return;
02746 ((DCE *) this)->Set_dce_visited( cr );
02747
02748 if (Projection_operation(cr->Opr())) {
02749 CODEREP *opnd = cr->Opnd(0);
02750
02751 if (opnd->Kind() == CK_VAR) {
02752
02753
02754
02755
02756
02757
02758 STMTREP *opnd_def = Proj_defstmt(opnd, Opt_stab());
02759 if (opnd_def != NULL) {
02760 Is_True(Projectable_operation(opnd_def->Rhs()),
02761 ("Definition of projected var must be projectable"));
02762 opnd_def->Inc_proj_op_uses();
02763 }
02764 else {
02765
02766
02767
02768
02769
02770
02771
02772 }
02773 }
02774 else {
02775
02776
02777
02778
02779
02780 }
02781 }
02782
02783 for ( INT32 ikid = 0; ikid < cr->Kid_count(); ikid++ ) {
02784 Mark_coderep_live( cr->Opnd(ikid) );
02785 }
02786 }
02787 break;
02788
02789 default:
02790 FmtAssert( FALSE, ("DCE::Mark_coderep_live: invalid kind 0x%x", cr->Kind()) );
02791 break;
02792 }
02793
02794 }
02795 }
02796 }
02797
02798
02799
02800
02801
02802
02803
02804
02805 BOOL
02806 DCE::Need_condbr_target_label( STMTREP *stmt, BB_NODE *target ) const
02807 {
02808 Is_True( stmt->Opr() == OPR_TRUEBR || stmt->Opr() == OPR_FALSEBR,
02809 ("DCE::Need_condbr_target_label: invalid branch") );
02810
02811 Is_True( ! _cfg->Lower_fully(),
02812 ("DCE::Need_condbr_target_label: lowered fully") );
02813
02814 BB_NODE *stmt_bb = stmt->Bb();
02815 switch ( stmt_bb->Kind() ) {
02816 case BB_LOGIF:
02817 if ( stmt_bb->Ifinfo() != NULL ) {
02818
02819
02820 return FALSE;
02821 }
02822 break;
02823
02824 case BB_REPEATEND:
02825 if ( stmt_bb->Loop() != NULL ) {
02826
02827
02828 if ( stmt_bb->Loopbody() == target &&
02829 target->Kind() == BB_REPEATBODY )
02830 {
02831 return FALSE;
02832 }
02833 }
02834 break;
02835 }
02836
02837 return TRUE;
02838 }
02839
02840
02841
02842
02843
02844
02845 void
02846 DCE::Mark_branch_related_live( STMTREP *stmt ) const
02847 {
02848 BB_NODE *br_bb = Branch_target_block( stmt );
02849 BOOL check_target_label = TRUE;
02850
02851 if ( ! _cfg->Lower_fully() ) {
02852
02853
02854 if ( ! Need_condbr_target_label( stmt, br_bb ) ) {
02855 check_target_label = FALSE;
02856 }
02857 }
02858
02859 if ( check_target_label ) {
02860 Check_for_label( br_bb );
02861 }
02862
02863
02864 BB_NODE *fall_thru = stmt->Bb()->Next();
02865 if ( ! fall_thru->Reached() )
02866 Mark_block_live( fall_thru );
02867
02868 switch ( stmt->Bb()->Kind() ) {
02869 case BB_DOEND:
02870 case BB_REPEATEND:
02871 case BB_WHILEEND:
02872 {
02873
02874 BB_LOOP *loop = stmt->Bb()->Loop();
02875 if ( loop != NULL ) {
02876 if ( _cfg->Lower_fully() ) {
02877
02878
02879
02880
02881 BB_NODE *dohead = loop->Start();
02882 if ( dohead && dohead->Kind() == BB_DOHEAD ) {
02883 STMTREP_ITER stmt_iter(dohead->Stmtlist());
02884 STMTREP *dohead_stmt;
02885 FOR_ALL_NODE( dohead_stmt, stmt_iter, Init() ) {
02886 if ( !dohead_stmt->Live_stmt() &&
02887 dohead_stmt->Opr() == OPR_EVAL )
02888 {
02889 Mark_statement_live( dohead_stmt );
02890 }
02891 }
02892 }
02893 }
02894 }
02895 }
02896 break;
02897 }
02898 }
02899
02900
02901
02902
02903
02904
02905 void
02906 DCE::Mark_region_exits_live( STMTREP *stmt ) const
02907 {
02908 RID *rid = REGION_get_rid(stmt->Black_box_wn());
02909 WN *wn_exit_list = WN_region_exits(RID_rwn(rid));
02910 for (WN *wtmp=WN_first(wn_exit_list); wtmp; wtmp=WN_next(wtmp)) {
02911 INT32 label_num = WN_label_number(wtmp);
02912 BB_NODE *bb = _cfg->Get_bb_from_label(label_num);
02913 Is_True(bb != NULL, ("DCE::Mark_region_exits_live, need BB for label"));
02914 Mark_block_live(bb);
02915 if (Tracing())
02916 fprintf(TFile,"Mark_region_exits_live, marking label %d for RGN%d\n",
02917 label_num, RID_id(rid));
02918 }
02919 }
02920
02921
02922
02923
02924
02925
02926
02927
02928
02929
02930
02931 void
02932 DCE::Mark_return_vsym_chi_live( CHI_NODE *chi ) const
02933 {
02934 if ( chi->Live() )
02935 return;
02936
02937 CODEREP *res = chi->RESULT();
02938 STMTREP *stmt= res->Defstmt();
02939 const OPERATOR opr = stmt->Opr();
02940
02941
02942 BOOL make_live = TRUE;
02943
02944 if ( ! stmt->Live_stmt() ) {
02945
02946 if (OPERATOR_is_scalar_store (opr)) {
02947 AUX_ID aux_id = stmt->Lhs()->Aux_id();
02948
02949
02950 if ( Return_vsym_reqd_set()->MemberP( aux_id ) ) {
02951
02952 Return_vsym_reqd_set()->Difference1D( aux_id );
02953 }
02954 else if ( Return_vsym_full_set()->MemberP( aux_id ) ) {
02955
02956
02957 make_live = FALSE;
02958
02959 if ( Tracing() ) {
02960 fprintf(TFile, "Mark_return_vsym_chi_live: skip stid def:");
02961 stmt->Lhs()->Print(0,TFile);
02962 }
02963 }
02964 }
02965 }
02966
02967 if ( make_live ) {
02968
02969
02970
02971 chi->Set_live(TRUE);
02972
02973 if ( ! stmt->Live_stmt() ) {
02974 Mark_statement_live(stmt);
02975 }
02976 }
02977
02978
02979
02980 stmt->Set_dce_retvsym();
02981
02982
02983 CODEREP *chiopnd = chi->OPND();
02984 if ( chiopnd->Is_flag_set(CF_DEF_BY_PHI) ) {
02985 Mark_return_vsym_phi_live( chiopnd->Defphi() );
02986 }
02987 else if ( chiopnd->Is_flag_set(CF_DEF_BY_CHI) ) {
02988 Mark_return_vsym_chi_live( chiopnd->Defchi() );
02989 }
02990 else {
02991
02992 Is_True( chiopnd->Is_var_nodef(),
02993 ("DCE::Mark_return_vsym_chi_live: vsym has real def?") );
02994 }
02995
02996 }
02997
02998
02999
03000
03001
03002
03003 void
03004 DCE::Mark_return_vsym_mu_ref_live( CODEREP *cr ) const
03005 {
03006 Is_True( cr->Aux_id() == Return_vsym(),
03007 ("DCE::Mark_return_vsym_mu_ref_live: not return vsym") );
03008
03009
03010 Return_vsym_reqd_set()->CopyD( Return_vsym_full_set() );
03011
03012 if ( cr->Is_flag_set(CF_DEF_BY_PHI) ) {
03013 Mark_return_vsym_phi_live( cr->Defphi() );
03014 }
03015 else if ( cr->Is_flag_set(CF_DEF_BY_CHI) ) {
03016 Mark_return_vsym_chi_live( cr->Defchi() );
03017 }
03018 else {
03019
03020 Is_True( cr->Is_var_nodef(),
03021 ("DCE::Mark_return_vsym_mu_ref_live: vsym has real def?") );
03022 }
03023
03024 }
03025
03026
03027
03028
03029
03030 void
03031 DCE::Mark_return_vsym_phi_live( PHI_NODE *phi ) const
03032 {
03033
03034 if ( phi->Live() )
03035 return;
03036
03037
03038
03039 Mark_phinode_live( phi, FALSE );
03040
03041
03042
03043 IDX_32_SET *saved_reqd = Return_vsym_reqd_set()->Copy(_cfg->Loc_pool());
03044 BOOL need_copy = FALSE;
03045
03046 for ( INT pkid = 0; pkid < phi->Size(); pkid++ ) {
03047
03048 if ( need_copy )
03049 Return_vsym_reqd_set()->CopyD( saved_reqd );
03050
03051 CODEREP *cr = phi->OPND(pkid);
03052 if ( cr->Is_flag_set(CF_DEF_BY_PHI) ) {
03053 Mark_return_vsym_phi_live( cr->Defphi() );
03054 }
03055 else if ( cr->Is_flag_set(CF_DEF_BY_CHI) ) {
03056 Mark_return_vsym_chi_live( cr->Defchi() );
03057 }
03058 else {
03059
03060 Is_True( cr->Is_var_nodef(),
03061 ("DCE::Mark_return_vsym_phi_live: vsym has real def?") );
03062 }
03063
03064
03065 need_copy = TRUE;
03066 }
03067 }
03068
03069
03070
03071
03072
03073 void
03074 DCE::Init_return_vsym( void )
03075 {
03076 AUX_ID max_id = 0;
03077
03078 if ( Enable_dce_global() ) {
03079 IDX_32_SET *vsym_set = CXX_NEW( IDX_32_SET(Opt_stab()->Lastidx()+1,
03080 _cfg->Loc_pool(),OPTS_FALSE), _cfg->Loc_pool());
03081 _return_vsym_reqd_set = CXX_NEW( IDX_32_SET(Opt_stab()->Lastidx()+1,
03082 _cfg->Loc_pool(),OPTS_FALSE), _cfg->Loc_pool());
03083
03084 AUX_ID_LIST_ITER id_list_iter;
03085 AUX_ID_NODE *id_node;
03086 FOR_ALL_ELEM( id_node, id_list_iter,
03087 Init(Opt_stab()->Aux_id_list(Return_vsym())) )
03088 {
03089 AUX_ID id = id_node->Aux_id();
03090
03091 vsym_set->Union1D( id );
03092 if ( id > max_id )
03093 max_id = id;
03094 }
03095
03096 _return_vsym_full_set = vsym_set;
03097 }
03098
03099 _return_vsym_max = max_id+1;
03100 }
03101
03102
03103
03104
03105
03106 CODEREP *
03107 DCE::Prop_return_vsym_new_result( CODEREP *cr ) const
03108 {
03109 if ( cr->Is_flag_set(CF_DEF_BY_PHI) ) {
03110
03111 return cr->Defphi()->RESULT();
03112 }
03113 else if ( cr->Is_flag_set(CF_DEF_BY_CHI) ) {
03114
03115 if ( cr->Defstmt()->Live_stmt() ) {
03116 return cr->Defchi()->RESULT();
03117 }
03118 else {
03119
03120
03121
03122 # ifdef KEY
03123 if (!cr->Defchi()->Live())
03124 return Prop_return_vsym_new_result(cr->Defchi()->OPND());
03125 else
03126 return cr->Defchi()->OPND();
03127 # else
03128 return cr->Defchi()->OPND();
03129 # endif
03130 }
03131 }
03132 else {
03133
03134 Is_True( cr->Is_var_nodef(),
03135 ("DCE::Prop_return_vsym_new_result: vsym has real def?") );
03136 return cr;
03137 }
03138 }
03139
03140
03141
03142
03143
03144
03145
03146
03147
03148
03149 void
03150 DCE::Propagate_return_vsym_cr( CODEREP *cr ) const
03151 {
03152 switch ( cr->Kind() ) {
03153 case CK_LDA:
03154 case CK_CONST:
03155 case CK_RCONST:
03156 case CK_VAR:
03157
03158 break;
03159
03160 case CK_IVAR:
03161 {
03162 if ( cr->Istr_base() != NULL )
03163 Propagate_return_vsym_cr( cr->Istr_base() );
03164 else
03165 Propagate_return_vsym_cr( cr->Ilod_base() );
03166
03167 if ( cr->Opr() == OPR_MLOAD )
03168 Propagate_return_vsym_cr( cr->Mload_size() );
03169 else if ( cr->Opr() == OPR_ILOADX )
03170 Propagate_return_vsym_cr( cr->Index() );
03171
03172 MU_NODE *mu = cr->Ivar_mu_node();
03173 if ( mu && mu->OPND()->Aux_id() == Return_vsym() ) {
03174 mu->Set_OPND( Prop_return_vsym_new_result(mu->OPND()) );
03175 }
03176 }
03177 break;
03178
03179 case CK_OP:
03180 {
03181
03182 if ( Is_retvsym_visited( cr ) )
03183 break;
03184 ((DCE *) this)->Set_retvsym_visited( cr );
03185
03186
03187 for ( INT32 ikid = 0; ikid < cr->Kid_count(); ikid++ ) {
03188 Propagate_return_vsym_cr( cr->Opnd(ikid) );
03189 }
03190 }
03191 break;
03192
03193 case CK_DELETED:
03194 default:
03195 FmtAssert( FALSE,
03196 ("DCE::Propagate_return_vsym_cr: bad coderep") );
03197 break;
03198 }
03199 }
03200
03201
03202
03203
03204
03205
03206
03207
03208
03209
03210
03211
03212
03213
03214
03215 void
03216 DCE::Propagate_return_vsym_bb( BB_NODE *bb ) const
03217 {
03218
03219 PHI_LIST_ITER phi_iter;
03220 PHI_NODE *phi;
03221 FOR_ALL_ELEM ( phi, phi_iter, Init(bb->Phi_list()) ) {
03222 if ( ! phi->Dse_dead() ) {
03223 CODEREP *res = phi->RESULT();
03224 if ( res->Aux_id() == Return_vsym() ) {
03225 for ( INT pkid = 0; pkid < phi->Size(); pkid++ ) {
03226 phi->Set_opnd(pkid, Prop_return_vsym_new_result(phi->OPND(pkid)));
03227 }
03228 }
03229 }
03230 }
03231
03232
03233 STMTREP_ITER stmt_iter(bb->Stmtlist());
03234 STMTREP *stmt;
03235 FOR_ALL_NODE(stmt, stmt_iter, Init()) {
03236
03237
03238 if ( stmt->Live_stmt() ) {
03239
03240 if ( stmt->Has_mu() ) {
03241 MU_LIST_ITER mu_iter;
03242 MU_NODE *mu;
03243 FOR_ALL_NODE( mu, mu_iter, Init(stmt->Mu_list()) ) {
03244 if ( mu->OPND()->Aux_id() == Return_vsym() ) {
03245 mu->Set_OPND( Prop_return_vsym_new_result(mu->OPND()) );
03246 }
03247 }
03248 }
03249
03250
03251 if ( stmt->Lhs() != NULL ) {
03252 Propagate_return_vsym_cr( stmt->Lhs() );
03253 }
03254
03255
03256 if ( stmt->Rhs() != NULL ) {
03257 Propagate_return_vsym_cr( stmt->Rhs() );
03258 }
03259 }
03260
03261
03262
03263 if ( stmt->Has_chi() ) {
03264 CHI_LIST_ITER chi_iter;
03265 CHI_NODE *chi;
03266 FOR_ALL_NODE( chi, chi_iter, Init(stmt->Chi_list())) {
03267 if ( ! chi->Dse_dead() && chi->Aux_id() == Return_vsym() ) {
03268
03269 chi->Set_OPND( Prop_return_vsym_new_result( chi->OPND() ));
03270
03271
03272
03273
03274
03275
03276
03277 if ( ! chi->Live() && stmt->Live_stmt() &&
03278 stmt->Dce_retvsym() )
03279 {
03280 chi->Set_live(TRUE);
03281 }
03282 }
03283 }
03284 }
03285
03286 }
03287
03288
03289 BB_NODE *dom_bb;
03290 BB_LIST_ITER dom_bb_iter;
03291 FOR_ALL_ELEM(dom_bb, dom_bb_iter, Init(bb->Dom_bbs())) {
03292 Propagate_return_vsym_bb(dom_bb);
03293 }
03294 }
03295
03296
03297
03298
03299
03300
03301
03302 void
03303 DCE::Mark_statement_live( STMTREP *stmt ) const
03304 {
03305
03306
03307 if ( stmt->Live_stmt() )
03308 return;
03309
03310
03311
03312
03313
03314
03315 OPERATOR opr = stmt->Opr();
03316
03317 if (OPERATOR_is_scalar_store (opr) &&
03318 Enable_identity_removal() &&
03319 stmt->Is_identity_assignment_removable()) {
03320
03321 CODEREP *rhs = stmt->Rhs();
03322 if ( rhs != NULL ) {
03323 if (stmt->Opr() == OPR_PREFETCH)
03324 Mark_coderep_live(rhs->Ilod_base());
03325 else
03326 Mark_coderep_live( rhs );
03327 }
03328 return;
03329 }
03330
03331
03332 stmt->Set_live_stmt();
03333
03334 switch (opr) {
03335
03336 case OPR_STID:
03337 case OPR_STBITS:
03338 break;
03339
03340 case OPR_ISTORE:
03341 case OPR_ISTBITS:
03342 {
03343 Mark_coderep_live(stmt->Lhs()->Istr_base());
03344
03345
03346 PF_POINTER *pf = stmt->Lhs()->Ivar_occ()->Pf_pointer();
03347 if (pf != NULL) {
03348 if (PF_PTR_wn_pref_1L(pf) != NULL)
03349 Mark_statement_live((STMTREP *) PF_PTR_wn_pref_1L(pf));
03350 if (PF_PTR_wn_pref_2L(pf) != NULL)
03351 Mark_statement_live((STMTREP *) PF_PTR_wn_pref_2L(pf));
03352 }
03353 }
03354 break;
03355
03356 case OPR_MSTORE:
03357 Mark_coderep_live(stmt->Lhs()->Istr_base());
03358 Mark_coderep_live(stmt->Lhs()->Mstore_size());
03359 break;
03360
03361 case OPR_REGION:
03362 Mark_region_exits_live(stmt);
03363 break;
03364
03365 case OPR_GOTO:
03366 case OPR_REGION_EXIT:
03367 { BB_NODE *goto_bb = Branch_target_block( stmt );
03368 if (goto_bb)
03369 Check_for_label( goto_bb );
03370 }
03371 break;
03372
03373 case OPR_TRUEBR:
03374 case OPR_FALSEBR:
03375 Mark_branch_related_live( stmt );
03376 break;
03377
03378 case OPR_FORWARD_BARRIER:
03379 case OPR_BACKWARD_BARRIER:
03380
03381
03382
03383
03384
03385
03386
03387
03388
03389
03390
03391
03392
03393 break;
03394
03395 default:
03396
03397 CODEREP *lhs = stmt->Lhs();
03398 if ( lhs != NULL ) {
03399 Mark_coderep_live( lhs );
03400 }
03401 }
03402
03403
03404 CODEREP *rhs = stmt->Rhs();
03405 if ( rhs != NULL ) {
03406 if (stmt->Opr() == OPR_PREFETCH)
03407 Mark_coderep_live(rhs->Ilod_base());
03408 else
03409 Mark_coderep_live( rhs );
03410 }
03411
03412
03413
03414 if ( WOPT_Enable_Zero_Version && stmt->Has_zver() ) {
03415
03416
03417 Mark_zero_version_chinode_live( stmt );
03418 }
03419
03420
03421 CHI_LIST_ITER chi_iter;
03422 CHI_NODE *cnode;
03423 FOR_ALL_NODE(cnode, chi_iter, Init(stmt->Chi_list())) {
03424 if (!cnode->Dse_dead() &&
03425 cnode->RESULT() != NULL &&
03426 cnode->RESULT()->Is_flag_set(CF_INCOMPLETE_USES))
03427 Mark_chinode_live(cnode, stmt);
03428 }
03429
03430
03431 if ( stmt->Has_mu() ) {
03432 Mark_sr_munode_live( stmt );
03433 }
03434
03435
03436 if ( ! stmt->Bb()->Reached() ) {
03437 Mark_block_live( stmt->Bb() );
03438 }
03439 }
03440
03441
03442
03443
03444
03445
03446 void
03447 DCE::Mark_infinite_loops_live( void ) const
03448 {
03449 if (Tracing())
03450 fprintf( TFile, "DCE::Mark_infinite_loops_live\n");
03451
03452
03453 if ( _cfg->Exit_bb() == _cfg->Fake_exit_bb() ) {
03454 BB_LIST_ITER pred_iter;
03455 BB_NODE *pred;
03456 FOR_ALL_ELEM( pred, pred_iter, Init(_cfg->Fake_exit_bb()->Pred()) ) {
03457
03458 if (! pred->Willexit() && pred->Kind() == BB_GOTO) {
03459 STMTREP *goto_stmt = pred->Branch_stmtrep();
03460 if ( goto_stmt != NULL )
03461 Mark_statement_live( goto_stmt );
03462 }
03463
03464
03465
03466
03467
03468
03469
03470
03471
03472
03473
03474
03475
03476 }
03477 }
03478 }
03479
03480
03481
03482
03483
03484
03485 void
03486 DCE::Mark_block_live( BB_NODE *bb ) const
03487 {
03488 if ( bb->Reached() ) {
03489 return;
03490 }
03491
03492
03493
03494
03495
03496 bb->Set_reached();
03497
03498
03499 BB_NODE *cdbb;
03500 BB_NODE_SET_ITER rcfg_iter;
03501 FOR_ALL_ELEM( cdbb, rcfg_iter, Init( bb->Rcfg_dom_frontier() ) ) {
03502
03503 STMTREP *brstmt = cdbb->Branch_stmtrep();
03504 if ( brstmt != NULL && ! brstmt->Live_stmt() ) {
03505 Mark_statement_live( brstmt );
03506 }
03507 }
03508
03509
03510 STMTREP *labelstmt = bb->Label_stmtrep();
03511 if ( labelstmt != NULL && ! labelstmt->Live_stmt() ) {
03512 Mark_statement_live( labelstmt );
03513 }
03514
03515
03516 if ( bb->Haspragma() ) {
03517 STMTREP_ITER stmt_iter(bb->Stmtlist());
03518 STMTREP *stmt;
03519 FOR_ALL_NODE(stmt, stmt_iter, Init()) {
03520 if ( stmt->Opr() == OPR_PRAGMA || stmt->Opr() == OPR_XPRAGMA ) {
03521 Mark_statement_live( stmt );
03522 }
03523 }
03524 }
03525
03526
03527
03528
03529
03530
03531
03532
03533 if ( bb->Kind() == BB_DOEND && (bb->Loop()->Flags() & LOOP_PREOPT) ) {
03534 BB_NODE *loop_start = bb->Loopstart();
03535 if (loop_start != NULL && !loop_start->Reached())
03536 Mark_block_live( loop_start );
03537 }
03538
03539
03540
03541 if ( bb->Kind() == BB_DOSTART && (bb->Loop()->Flags() & LOOP_PREOPT) ) {
03542 BB_NODE *prev_bb = bb->Prev();
03543 STMTREP_ITER stmt_iter(prev_bb->Stmtlist());
03544 STMTREP *stmt;
03545 FOR_ALL_NODE(stmt, stmt_iter, Init()) {
03546 if ( stmt->Opr() == OPR_PRAGMA &&
03547 Loop_pragma( (WN_PRAGMA_ID)WN_pragma(stmt->Orig_wn()) ) ) {
03548 Mark_block_live( prev_bb );
03549 break;
03550 }
03551 }
03552 }
03553 }
03554
03555
03556
03557
03558
03559 void
03560 DCE::Mark_statements_dead( void ) const
03561 {
03562 #if 0
03563
03564
03565 Htable()->Reset_DCE_visited_flags();
03566 #endif
03567
03568 CFG_ITER cfg_iter(_cfg);
03569 BB_NODE *bb;
03570
03571
03572 FOR_ALL_NODE( bb, cfg_iter, Init() ) {
03573
03574
03575 STMTREP_ITER stmt_iter(bb->Stmtlist());
03576 STMTREP *stmt;
03577 FOR_ALL_NODE(stmt, stmt_iter, Init()) {
03578 stmt->Reset_live_stmt();
03579 if (Stores_proj_op_to_temp(stmt, Opt_stab())) {
03580 stmt->Set_proj_op_uses(0);
03581 }
03582
03583
03584 if (Enable_preg_renumbering() &&
03585 OPERATOR_is_scalar_store (stmt->Opr ())) {
03586 CODEREP *lhs = stmt->Lhs();
03587 AUX_STAB_ENTRY *aux_entry =
03588 Opt_stab()->Aux_stab_entry(lhs->Aux_id());
03589 if (aux_entry->Is_non_dedicated_preg()) {
03590 lhs->Set_safe_to_renumber_preg();
03591 aux_entry->Reset_emitter_flags();
03592 }
03593 }
03594 if (stmt->Has_chi()) {
03595 bool update_mu = OPERATOR_is_scalar_istore (stmt->Opr()) &&
03596 stmt->Lhs()->Ivar_mu_node();
03597 CHI_LIST_ITER chi_iter;
03598 CHI_NODE *cnode;
03599 FOR_ALL_NODE(cnode,chi_iter,Init(stmt->Chi_list())) {
03600 if (cnode->Live()) {
03601 cnode->Set_live(FALSE);
03602 cnode->Set_dse_dead(FALSE);
03603 }
03604 else {
03605 cnode->Set_dse_dead(TRUE);
03606
03607
03608 if (update_mu &&
03609 stmt->Lhs()->Ivar_mu_node() &&
03610 stmt->Lhs()->Ivar_mu_node()->Aux_id() == cnode->Aux_id())
03611 stmt->Lhs()->Set_ivar_mu_node(NULL);
03612 }
03613 }
03614 }
03615 }
03616
03617
03618 PHI_LIST_ITER phi_iter;
03619 PHI_NODE *phi;
03620 FOR_ALL_ELEM ( phi, phi_iter, Init(bb->Phi_list()) ) {
03621 if (phi->Live()) {
03622 phi->Reset_live();
03623 phi->Reset_dse_dead();
03624 }
03625 else {
03626 phi->Set_dse_dead();
03627 }
03628 }
03629
03630
03631 bb->Reset_reached();
03632 }
03633 }
03634
03635
03636
03637
03638
03639 BOOL
03640 DCE::BB_branch_live( BB_NODE *bb ) const
03641 {
03642 STMTREP *br = bb->Branch_stmtrep();
03643 if ( br && br->Live_stmt() ) {
03644
03645
03646 const OPERATOR opr = br->Opr();
03647 if ( Is_branch(opr) ) {
03648 return TRUE;
03649 }
03650
03651
03652 if ( opr == OPR_IO && bb->Kind() == BB_IO ) {
03653 return TRUE;
03654 }
03655 }
03656
03657 return FALSE;
03658 }
03659
03660
03661
03662
03663
03664
03665
03666 void
03667 DCE::Get_full_rcfg_dom_frontier( BB_NODE *bb ) const
03668 {
03669 BB_NODE_SET saved_set( _cfg->Total_bb_count(), _cfg,
03670 _cfg->Loc_pool(), BBNS_EMPTY );
03671 BOOL changed;
03672
03673 do {
03674 changed = FALSE;
03675 saved_set.CopyD( bb->Rcfg_dom_frontier() );
03676
03677
03678
03679
03680 BB_NODE *rcfgbb;
03681 BB_NODE_SET_ITER rcfg_iter;
03682 FOR_ALL_ELEM( rcfgbb, rcfg_iter, Init( &saved_set ) ) {
03683 bb->Rcfg_dom_frontier()->UnionD( rcfgbb->Rcfg_dom_frontier() );
03684 }
03685
03686
03687 if ( ! saved_set.EqualP( bb->Rcfg_dom_frontier() ) )
03688 changed = TRUE;
03689 } while ( changed );
03690 }
03691
03692
03693
03694
03695
03696
03697
03698
03699
03700
03701 void
03702 DCE::Add_path_to_ipdom( BB_NODE *bb ) const
03703 {
03704 BB_NODE *ipdom = bb->Ipdom();
03705
03706 if ( ipdom == _cfg->Fake_exit_bb() ) {
03707 if ( bb->Willexit() ) {
03708 FmtAssert( FALSE,
03709 ("DCE::Add_path_to_ipdom: post-dom block is fake exit block") );
03710 }
03711 else {
03712
03713
03714 return;
03715 }
03716 }
03717
03718
03719 if ( ipdom->Pred()->Contains(bb) )
03720 return;
03721
03722
03723
03724
03725
03726
03727
03728
03729
03730
03731
03732 BB_LIST_ITER pred_iter;
03733 BB_NODE *ipdom_pred;
03734 BB_NODE *rep_bb = NULL;
03735 INT rep_pos= -1;
03736 FOR_ALL_ELEM( ipdom_pred, pred_iter, Init(ipdom->Pred()) ) {
03737 Get_full_rcfg_dom_frontier( ipdom_pred );
03738 if ( ipdom_pred->Rcfg_dom_frontier()->MemberP( bb ) ) {
03739
03740 rep_bb = ipdom_pred;
03741 rep_pos= ipdom->Pred()->Pos(ipdom_pred);
03742 break;
03743 }
03744 }
03745
03746 FmtAssert( rep_bb != NULL,
03747 ("DCE::Add_path_to_ipdom: no representative bb for BB:%d",
03748 bb->Id()) );
03749
03750 if ( Tracing() ) {
03751 fprintf( TFile, "DCE::Add_path_to_ipdom: add bb%d -> ipdom bb%d\n",
03752 bb->Id(), ipdom->Id() );
03753 }
03754
03755 bb->Append_succ( ipdom, _cfg->Mem_pool() );
03756 ipdom->Append_pred( bb, _cfg->Mem_pool() );
03757 PHI_LIST *new_philist =
03758 ipdom->Phi_list()->Dup_phi_node(_cfg->Mem_pool(), ipdom, rep_pos);
03759 _mod_phis->Add_entry(ipdom, ipdom->Phi_list(), new_philist, _cfg->Mem_pool());
03760 ipdom->Set_phi_list(new_philist);
03761 }
03762
03763
03764
03765
03766
03767
03768
03769 void
03770 DCE::Replace_control_dep_succs( BB_NODE *bb ) const
03771 {
03772 BOOL all_cd = TRUE;
03773
03774 #ifdef KEY
03775 if (bb->Succ() == NULL)
03776 return;
03777 #endif
03778
03779 BB_LIST *succlist, *nextsucc = NULL;
03780 for ( succlist = bb->Succ(); succlist != NULL; succlist = nextsucc ) {
03781
03782 nextsucc = succlist->Next();
03783
03784
03785 BB_NODE *succ = succlist->Node();
03786 if ( succ->Rcfg_dom_frontier()->MemberP( bb ) ) {
03787 Remove_path( bb, succ );
03788 }
03789 else {
03790 all_cd = FALSE;
03791 }
03792 }
03793
03794 if ( all_cd ) {
03795
03796 Add_path_to_ipdom( bb );
03797 }
03798
03799
03800 if ( _cfg->Feedback() )
03801 _cfg->Feedback()->Merge_outgoing_edges( bb->Id(), bb->Ipdom()->Id() );
03802 }
03803
03804
03805
03806
03807
03808 void
03809 DCE::Check_required_repeatend( BB_NODE *bb ) const
03810 {
03811 if ( BB_branch_live( bb ) ) {
03812
03813
03814 if ( _cfg->Lower_fully() ) {
03815 Keep_unreached_bb(bb->Loopstart());
03816 Keep_unreached_bb(bb->Loopbody());
03817 Keep_unreached_bb(bb->Loopmerge());
03818
03819
03820 Check_for_label( bb->Loopbody() );
03821 }
03822 else {
03823 Keep_unreached_bb(bb->Loopbody());
03824 Keep_unreached_bb(bb->Loopmerge());
03825 }
03826 }
03827 else {
03828
03829
03830 if ( _cfg->Lower_fully() ) {
03831 bb->Loopstart()->Set_kind( BB_GOTO );
03832
03833 }
03834 else {
03835 Remove_path( bb, bb->Loopbody() );
03836 bb->Loopbody()->Set_kind( BB_GOTO );
03837 }
03838
03839 Replace_control_dep_succs( bb );
03840 bb->Set_loop( NULL );
03841 bb->Set_kind( BB_GOTO );
03842 }
03843 }
03844
03845
03846
03847
03848
03849 void
03850 DCE::Check_required_whileend( BB_NODE *bb ) const
03851 {
03852 if ( BB_branch_live( bb ) ) {
03853
03854
03855 if ( _cfg->Lower_fully() ) {
03856 Keep_unreached_bb(bb->Loopstart());
03857 Keep_unreached_bb(bb->Loopbody());
03858 Keep_unreached_bb(bb->Loopmerge());
03859
03860
03861 Check_for_label( bb->Loopbody() );
03862 }
03863 else {
03864 Keep_unreached_bb(bb->Loopbody());
03865 Keep_unreached_bb(bb->Loopstep());
03866 Keep_unreached_bb(bb->Loopmerge());
03867 }
03868 }
03869 else {
03870
03871
03872
03873 BB_LOOP *loopinfo = bb->Loop();
03874 if ( loopinfo != NULL ) {
03875 if ( _cfg->Lower_fully() ) {
03876 if ( loopinfo->Start() != NULL &&
03877 loopinfo->Start()->Kind() == BB_DOHEAD )
03878 {
03879
03880 loopinfo->Start()->Set_kind( BB_GOTO );
03881 }
03882 if ( loopinfo->Merge() != NULL &&
03883 loopinfo->Merge()->Kind() == BB_DOTAIL )
03884 {
03885
03886 loopinfo->Merge()->Set_kind( BB_GOTO );
03887 }
03888 }
03889
03890
03891 }
03892
03893 Replace_control_dep_succs( bb );
03894 bb->Set_loop( NULL );
03895 bb->Set_kind( BB_GOTO );
03896 }
03897 }
03898
03899
03900
03901
03902
03903 void
03904 DCE::Check_required_doend( BB_NODE *bb ) const
03905 {
03906 if ( BB_branch_live( bb ) ) {
03907 if ( bb->Loop() != NULL ) {
03908
03909 BOOL valid_loop = TRUE;
03910 if ( _cfg->Lower_fully() ) {
03911
03912
03913
03914
03915
03916 Check_for_label( Branch_target_block( bb->Branch_stmtrep() ) );
03917 }
03918 else {
03919
03920 if ( !bb->Loopstart()->Reached() ||
03921 bb->Loopstart()->Kind() != BB_DOSTART )
03922 valid_loop = FALSE;
03923 else if ( !bb->Loopstep()->Reached() ||
03924 bb->Loopstep()->Kind() != BB_DOSTEP )
03925 valid_loop = FALSE;
03926
03927 if ( ! valid_loop ) {
03928
03929 bb->Loopstart()->Set_kind( BB_GOTO );
03930 bb->Loopstep()->Set_kind( BB_GOTO );
03931 bb->Loopend()->Set_kind( BB_WHILEEND );
03932
03933 Check_required_whileend( bb );
03934
03935 return;
03936 }
03937 }
03938
03939 if ( valid_loop ) {
03940
03941 Keep_unreached_bb(bb->Loopstart());
03942 Keep_unreached_bb(bb->Loopbody());
03943 Keep_unreached_bb(bb->Loopstep());
03944 Keep_unreached_bb(bb->Loopmerge());
03945 Keep_unreached_bb(bb->Loopend());
03946
03947 Is_True( bb->Loop()->Trip_count_stmt() == NULL ||
03948 bb->Loop()->Trip_count_stmt()->Live_stmt(),
03949 ("DCE::Check_required_doend: Trip_count not live") );
03950 }
03951 }
03952 else {
03953 FmtAssert( FALSE,
03954 ("DCE::Check_required_doend: no loop info for end bb:%d",
03955 bb->Id()) );
03956 }
03957 }
03958 else {
03959
03960 Replace_control_dep_succs( bb );
03961
03962
03963
03964 bb->Loopstart()->Set_kind( BB_GOTO );
03965 if ( bb->Loopstep()->Kind() == BB_DOSTEP )
03966 bb->Loopstep()->Set_kind( BB_GOTO );
03967
03968 if ( bb->Looptail()->Kind() == BB_DOTAIL )
03969 bb->Looptail()->Set_kind( BB_GOTO );
03970
03971
03972 bb->Loopend()->Set_kind( BB_GOTO );
03973
03974 bb->Set_loop( NULL );
03975 }
03976 }
03977
03978
03979
03980
03981
03982 void
03983 DCE::Check_required_goto( BB_NODE *bb ) const
03984 {
03985
03986 if ( bb->Reached() ) {
03987 STMTREP *br_stmt = bb->Branch_stmtrep();
03988
03989 if (br_stmt->Opr() == OPR_REGION) {
03990 Mark_statement_live( br_stmt );
03991 BB_LIST_ITER bb_succ_iter;
03992 BB_NODE *succ;
03993 FOR_ALL_ELEM(succ, bb_succ_iter, Init(bb->Succ())) {
03994 Mark_block_live(succ);
03995 }
03996 } else {
03997
03998 if ( br_stmt->Live_stmt() )
03999 return;
04000
04001
04002 BB_NODE *goto_bb = Branch_target_block( br_stmt );
04003 if ( goto_bb->Reached() ) {
04004 Mark_statement_live( br_stmt );
04005 }
04006 }
04007 }
04008 }
04009
04010
04011
04012
04013
04014 void
04015 DCE::Check_required_io( BB_NODE *bb ) const
04016 {
04017 STMTREP *br_stmt = bb->Branch_stmtrep();
04018
04019 FmtAssert( br_stmt->Live_stmt(),
04020 ("DCE::Check_required_io: non-live IO statment bb:%d", bb->Id()) );
04021
04022
04023
04024 BB_LIST_ITER succ_iter;
04025 BB_NODE *succ;
04026 FOR_ALL_ELEM( succ, succ_iter, Init(bb->Succ()) ) {
04027 Keep_unreached_bb( succ );
04028 }
04029
04030
04031 INT32 num_entries = bb->IO_entries();
04032 for (INT32 num_entry = 0; num_entry < num_entries; num_entry++ ) {
04033 Check_for_label( bb->IO_bb( num_entry ) );
04034 }
04035 }
04036
04037
04038
04039
04040
04041 void
04042 DCE::Check_required_logif( BB_NODE *bb ) const
04043 {
04044 if ( BB_branch_live( bb ) ) {
04045 if ( bb->Ifinfo() != NULL ) {
04046
04047
04048 Keep_unreached_bb(bb->If_then());
04049 Keep_unreached_bb(bb->If_else());
04050 Keep_unreached_bb(bb->If_merge());
04051 }
04052 else {
04053
04054
04055 BB_NODE *goto_bb = Branch_target_block( bb->Branch_stmtrep() );
04056 Keep_unreached_bb( goto_bb );
04057 Keep_unreached_bb( bb->Next() );
04058
04059
04060 Check_for_label( goto_bb );
04061 }
04062 }
04063 else {
04064
04065 if ( bb->Ifinfo() != NULL ) {
04066 bb->If_merge()->Reset_ifmerge();
04067 bb->Set_ifinfo( NULL );
04068 }
04069
04070
04071 Replace_control_dep_succs( bb );
04072 bb->Set_kind( BB_GOTO );
04073 }
04074 }
04075
04076
04077
04078
04079
04080 void
04081 DCE::Check_required_region( BB_NODE *bb ) const
04082 {
04083
04084
04085 Region_start_bbs()->Union1D( bb );
04086 }
04087
04088
04089
04090
04091
04092 void
04093 DCE::Update_region_information( void ) const
04094 {
04095 if ( ! _cfg->Has_regions() )
04096 return;
04097
04098 BB_NODE *regbb;
04099 BB_NODE_SET_ITER reg_iter;
04100 FOR_ALL_ELEM( regbb, reg_iter, Init( Region_start_bbs() ) ) {
04101
04102 if ( regbb->Kind() == BB_REGIONSTART ) {
04103 BB_REGION *bb_region = regbb->Regioninfo();
04104 Is_True(bb_region != NULL,
04105 ("DCE::Update_region_information, NULL bb_region"));
04106 BB_NODE *region_end = bb_region->Region_end();
04107
04108 if (RID_TYPE_guard(bb_region->Rid())) {
04109 Is_Trace(Tracing(),(TFile,"DCE::Update_region_information, keeping "
04110 "EH GUARD region\n"));
04111 BB_NODE *btmp = region_end;
04112 while (btmp != regbb) {
04113 if ( ! btmp->Reached() )
04114 Keep_unreached_bb(btmp);
04115 btmp = btmp->Prev();
04116 }
04117 if ( ! regbb->Reached() )
04118 Keep_unreached_bb(regbb);
04119 }
04120
04121 BOOL remove_region = FALSE;
04122 if (region_end) {
04123
04124 while ( ! (region_end->Reached() ||
04125 Keep_unreached()->MemberP(region_end)) )
04126 {
04127 if ( region_end != regbb )
04128 region_end = region_end->Prev();
04129 else {
04130
04131
04132
04133 region_end = NULL;
04134 remove_region = TRUE;
04135 break;
04136 }
04137 }
04138 }
04139
04140 if (remove_region) {
04141
04142 Remove_region_entry(regbb);
04143 regbb->Set_kind( BB_GOTO );
04144 if ( Tracing() ) {
04145 fprintf( TFile,
04146 "Update_region_information: removed region bb%d->bb%d\n",
04147 regbb->Id(), bb_region->Region_end()->Id() );
04148 }
04149 } else {
04150
04151
04152
04153
04154 if ( ! regbb->Reached() ) {
04155 Keep_unreached_bb( regbb );
04156 }
04157
04158
04159
04160 BB_LIST_ITER pred_iter;
04161 BB_NODE *pred;
04162 INT pred_cnt = 0;
04163 FOR_ALL_ELEM( pred, pred_iter, Init( regbb->Pred() ) ) {
04164 Keep_unreached_bb( pred );
04165 pred_cnt++;
04166 Is_True(pred_cnt == 1, ("DCE::Update_region_information: start "
04167 "(bb:%d) has more than 1 pred",regbb->Id()));
04168 }
04169
04170
04171 region_end = bb_region->Region_end();
04172 if ( region_end && ! region_end->Reached() ) {
04173 Keep_unreached_bb( region_end );
04174 }
04175
04176
04177
04178
04179 if ( region_end &&
04180 region_end->Succ() != NULL &&
04181 region_end->Succ()->Len() > 0 )
04182 {
04183 for (BB_LIST *succlist=region_end->Succ(); succlist!=NULL;
04184 succlist=succlist->Next()) {
04185 if (!succlist->Node()->Reached())
04186 Keep_unreached_bb(succlist->Node());
04187 }
04188 }
04189
04190 }
04191
04192
04193
04194
04195
04196
04197 if (regbb->Kind() == BB_REGIONSTART && regbb->Succ() != NULL && regbb->Succ()->Len() == 1) {
04198 #ifndef KEY
04199 Is_True(regbb->Succ() != NULL && regbb->Succ()->Len() == 1,
04200 ("DCE::Update_region_information, multiple successors "
04201 "for region start"));
04202 #endif
04203 BB_NODE *succ = regbb->Succ()->Node();
04204 if (!succ->Reached())
04205 Keep_unreached_bb(succ);
04206 }
04207
04208 }
04209 }
04210 }
04211
04212
04213
04214
04215
04216 void
04217 DCE::Check_required_vargoto( BB_NODE *bb ) const
04218 {
04219 if ( BB_branch_live( bb ) ) {
04220
04221 INT32 num_entries = bb->Switchentries();
04222 for (INT32 num_entry = 0; num_entry < num_entries; num_entry++ ) {
04223 Keep_unreached_bb( bb->Switchcase( num_entry ) );
04224 Check_for_label( bb->Switchcase( num_entry ) );
04225 }
04226
04227 if ( bb->Switchdefault() ) {
04228 Keep_unreached_bb( bb->Switchdefault() );
04229 Check_for_label( bb->Switchdefault() );
04230 }
04231 }
04232 else {
04233
04234 bb->Set_switchinfo( NULL );
04235
04236
04237 Replace_control_dep_succs( bb );
04238 bb->Set_kind( BB_GOTO );
04239 }
04240 }
04241
04242
04243 void
04244 DCE::Check_required_agoto( BB_NODE *bb ) const
04245 {
04246 if ( BB_branch_live( bb ) ) {
04247
04248 INT32 num_entries = _cfg->Agoto_succ_entries();
04249 for (INT32 num_entry = 0; num_entry < num_entries; ++num_entry ) {
04250 Keep_unreached_bb( _cfg->Agoto_succ_bb( num_entry ) );
04251 Check_for_label( _cfg->Agoto_succ_bb( num_entry ) );
04252 }
04253 }
04254 else {
04255
04256
04257 Replace_control_dep_succs( bb );
04258 bb->Set_kind( BB_GOTO );
04259 _cfg->Remove_agoto_pred( bb );
04260 }
04261 }
04262
04263
04264
04265
04266
04267
04268
04269
04270
04271
04272 void
04273 DCE::Check_required_blocks( void ) const
04274 {
04275 if ( Tracing() )
04276 fprintf( TFile, "DCE::Check_required_blocks\n" );
04277
04278
04279
04280
04281 CFG_ITER cfg_iter(_cfg);
04282 BB_NODE *bb;
04283 FOR_ALL_NODE( bb, cfg_iter, Init() ) {
04284 switch ( bb->Kind() ) {
04285
04286 case BB_DOEND:
04287 Check_required_doend( bb );
04288 break;
04289
04290 case BB_DOHEAD:
04291
04292 break;
04293
04294 case BB_DOSTART:
04295
04296 break;
04297
04298 case BB_DOSTEP:
04299
04300 break;
04301
04302 case BB_DOTAIL:
04303
04304 break;
04305
04306 case BB_ENTRY:
04307 if ( ! bb->Reached() ) {
04308 if ( bb == _cfg->Fake_entry_bb() )
04309 Keep_unreached_bb( bb );
04310 else
04311 bb->Set_reached();
04312 }
04313
04314
04315
04316
04317 if ( bb != _cfg->Fake_entry_bb() ) {
04318 Keep_unreached_bb(bb->Next());
04319 }
04320 break;
04321
04322 case BB_EXIT:
04323 if ( ! bb->Reached() ) {
04324
04325
04326 if ( bb != _cfg->Fake_exit_bb() )
04327 bb->Set_reached();
04328 else
04329 Keep_unreached_bb( bb );
04330 }
04331 break;
04332
04333 case BB_GOTO:
04334
04335 if ( bb->Branch_stmtrep() != NULL ) {
04336 Check_required_goto( bb );
04337 }
04338 break;
04339
04340 case BB_IO:
04341 Check_required_io( bb );
04342 break;
04343
04344 case BB_LOGIF:
04345 Check_required_logif( bb );
04346 break;
04347
04348 case BB_REGIONEXIT:
04349 break;
04350
04351 case BB_REGIONSTART:
04352 Check_required_region( bb );
04353 break;
04354
04355 case BB_REPEATBODY:
04356
04357 break;
04358
04359 case BB_REPEATEND:
04360 Check_required_repeatend( bb );
04361 break;
04362
04363 case BB_SUMMARY:
04364 break;
04365
04366 case BB_VARGOTO:
04367 if ( bb->Switchinfo() ) {
04368 Check_required_vargoto( bb );
04369 } else {
04370 Check_required_agoto( bb );
04371 }
04372 break;
04373
04374 case BB_WHILEEND:
04375 Check_required_whileend( bb );
04376 break;
04377
04378 case BB_UNKNOWN:
04379 default:
04380 ErrMsg( EC_Unimplemented,
04381 "DCE::Check_required_blocks: invalid bb Kind()" );
04382 break;
04383 }
04384 }
04385
04386
04387
04388 Update_region_information();
04389 }
04390
04391
04392
04393
04394
04395
04396
04397 void
04398 DCE::Find_required_statements( void ) const
04399 {
04400 CFG_ITER cfg_iter(_cfg);
04401 BB_NODE *bb;
04402
04403 if ( Tracing() )
04404 fprintf( TFile, "DCE::Find_required_statements\n" );
04405
04406
04407
04408 Keep_unreached()->ClearD();
04409
04410
04411
04412 FOR_ALL_NODE( bb, cfg_iter, Init() ) {
04413
04414
04415 if ( Required_bb( bb ) )
04416 Mark_block_live( bb );
04417
04418
04419
04420 STMTREP_ITER stmt_iter(bb->Stmtlist());
04421 STMTREP *stmt;
04422
04423
04424 PHI_LIST_ITER phi_iter;
04425 PHI_NODE *phi;
04426 FOR_ALL_ELEM ( phi, phi_iter, Init(bb->Phi_list()) ) {
04427 if ( ! phi->Live() && Required_phi( phi ) ) {
04428 Mark_phinode_live( phi, TRUE );
04429 }
04430 }
04431
04432 FOR_ALL_NODE(stmt, stmt_iter, Init()) {
04433 if ( ! stmt->Live_stmt() && Required_stmt( stmt ) ) {
04434
04435
04436 Mark_statement_live( stmt );
04437 }
04438 }
04439
04440 }
04441 #ifdef TARG_SL
04442 Repair_Injured_AuxIntrnOP();
04443 #endif
04444
04445
04446 Mark_infinite_loops_live();
04447
04448 if ( Tracing() ) {
04449 fprintf( TFile, "DCE::Keep_unreached stmts: " );
04450 Keep_unreached()->Print( TFile ) ;
04451 fprintf( TFile, "\n" );
04452 }
04453
04454
04455
04456
04457 Keep_unreached()->ClearD();
04458 Check_required_blocks();
04459
04460 if ( Tracing() ) {
04461 fprintf( TFile, "DCE::Keep_unreached blocks: " );
04462 Keep_unreached()->Print( TFile ) ;
04463 fprintf( TFile, "\n" );
04464 }
04465
04466
04467 if ( Enable_dce_global() ) {
04468 Propagate_return_vsym_bb( _cfg->Entry_bb() );
04469 }
04470 }
04471
04472
04473
04474
04475
04476 #ifdef KEY
04477 void
04478 DCE::Update_branch_to_bbs_labels( BB_LIST *bbs ) const
04479 {
04480 BB_NODE *bb, *last_bb;
04481 BB_LIST_ITER bb_iter;
04482 BOOL label_needed = FALSE;
04483
04484 FOR_ALL_ELEM( bb, bb_iter, Init(bbs) )
04485 last_bb = bb;
04486
04487 FOR_ALL_ELEM( bb, bb_iter, Init(bbs) ){
04488 if ( bb->Labnam() != 0 )
04489 label_needed = TRUE;
04490 }
04491 if (label_needed == FALSE)
04492 return;
04493
04494
04495
04496 BB_LIST_ITER succ_iter;
04497 BB_NODE *succ, *the_succ = NULL;
04498 FOR_ALL_ELEM( succ, succ_iter, Init( last_bb->Succ() ) )
04499 if (succ != last_bb) {
04500 Is_True(the_succ == NULL,
04501 ("DCE::Update_branch_to_bb_labels: Multiple successors\n"));
04502 the_succ = succ;
04503 }
04504
04505 LABEL_IDX label;
04506 if (the_succ == NULL)
04507 label = 0;
04508 else {
04509 label = the_succ->Labnam();
04510 if ( label == 0 ) {
04511 label = _cfg->Alloc_label();
04512 the_succ->Set_labnam( label );
04513 _cfg->Append_label_map(label, the_succ);
04514 if (the_succ->Label_stmtrep() == NULL)
04515 the_succ->Add_label_stmtrep( _cfg->Mem_pool() );
04516 }
04517 }
04518
04519
04520 BB_LIST_ITER pred_iter;
04521 BB_NODE *pred;
04522 FOR_ALL_ELEM( bb, bb_iter, Init(bbs) ){
04523 FOR_ALL_ELEM( pred, pred_iter, Init( bb->Pred() ) ) {
04524 if (bbs->Contains(pred))
04525 continue;
04526 STMTREP *branch_stmt = pred->Branch_stmtrep();
04527 if (branch_stmt != NULL) {
04528 OPERATOR opr = branch_stmt->Opr();
04529 if ((opr == OPR_GOTO ||
04530 opr == OPR_TRUEBR ||
04531 opr == OPR_FALSEBR) &&
04532 (branch_stmt->Label_number() == bb->Labnam())){
04533 if (Tracing())
04534 fprintf( TFile, " changing label %u to %u in BB%u\n",
04535 bb->Labnam(), label, pred->Id() );
04536 branch_stmt->Set_label_number(label);
04537 }
04538 }
04539 }
04540 }
04541 }
04542 #endif
04543
04544 void
04545 DCE::Update_branch_to_bb_labels( BB_NODE *bb ) const
04546 {
04547 if ( bb->Labnam() == 0 ) return;
04548 if (Tracing())
04549 fprintf( TFile, "DCE::Update_branch_to_bb_labels for BB%u\n",
04550 bb->Id());
04551
04552
04553 BB_LIST_ITER succ_iter;
04554 BB_NODE *succ, *the_succ = NULL;
04555 FOR_ALL_ELEM( succ, succ_iter, Init( bb->Succ() ) )
04556 if (succ != bb) {
04557 Is_True(the_succ == NULL,
04558 ("DCE::Update_branch_to_bb_labels: Multiple successors\n"));
04559 the_succ = succ;
04560 }
04561
04562
04563
04564
04565
04566
04567
04568
04569
04570
04571
04572 LABEL_IDX label;
04573
04574 if (the_succ == NULL)
04575 label = 0;
04576 else {
04577 label = the_succ->Labnam();
04578
04579 if ( label == 0 ) {
04580 label = _cfg->Alloc_label();
04581 the_succ->Set_labnam( label );
04582 _cfg->Append_label_map(label, the_succ);
04583 if (the_succ->Label_stmtrep() == NULL)
04584 the_succ->Add_label_stmtrep( _cfg->Mem_pool() );
04585 }
04586 }
04587
04588
04589 BB_LIST_ITER pred_iter;
04590 BB_NODE *pred;
04591 FOR_ALL_ELEM( pred, pred_iter, Init( bb->Pred() ) ) {
04592 STMTREP *branch_stmt = pred->Branch_stmtrep();
04593 if (branch_stmt != NULL) {
04594 OPERATOR opr = branch_stmt->Opr();
04595 if ((opr == OPR_GOTO ||
04596 opr == OPR_TRUEBR ||
04597 opr == OPR_FALSEBR) &&
04598 branch_stmt->Label_number() == bb->Labnam()) {
04599 if (Tracing())
04600 fprintf( TFile, " changing label %u to %u in BB%u\n",
04601 bb->Labnam(), label, pred->Id() );
04602 branch_stmt->Set_label_number(label);
04603 }
04604 }
04605 }
04606 }
04607
04608
04609
04610
04611
04612
04613 BOOL
04614 DCE::Remove_dead_statements( void )
04615 {
04616 BB_NODE *bb;
04617 BOOL changed_cflow = FALSE;
04618 BB_LIST *removable_bbs = NULL;
04619 BB_LIST *removable_bb_chain = NULL;
04620
04621
04622
04623 BB_NODE *nextbb = NULL;
04624 for ( bb = _cfg->First_bb(); bb != NULL; bb = nextbb ) {
04625
04626 nextbb = bb->Next();
04627
04628 if ( bb->Reached() || Keep_unreached()->MemberP(bb) ) {
04629
04630 STMTREP *stmt, *nextstmt = NULL;
04631
04632
04633 if ( Tracing() ) {
04634 for (stmt = bb->First_stmtrep(); stmt != NULL; stmt = nextstmt){
04635 nextstmt = stmt->Next();
04636 if ( ! stmt->Live_stmt() ) {
04637 fprintf( TFile, "Remove dead statement from live BB:%d\n",
04638 bb->Id() );
04639 stmt->Print( TFile );
04640 }
04641 }
04642 }
04643
04644
04645 for ( stmt = bb->First_stmtrep(), nextstmt = NULL;
04646 stmt != NULL;
04647 stmt = nextstmt )
04648 {
04649 nextstmt = stmt->Next();
04650 if ( ! stmt->Live_stmt() ) {
04651 bb->Remove_stmtrep(stmt);
04652 }
04653 else {
04654
04655
04656
04657 }
04658 }
04659
04660
04661
04662 if ( ! bb->Reached() && _cfg->Removable_bb(bb) ) {
04663 bb->Set_reached();
04664 }
04665 }
04666 else {
04667
04668
04669 if ( Tracing() ) {
04670 fprintf( TFile, "DCE_A: BB%d unreached (0x%p)\n", bb->Id(), bb );
04671 }
04672
04673 if ( Enable_aggressive_dce() ) {
04674
04675 Is_True( _cfg->Removable_bb(bb),
04676 ("DCE::Remove_dead_statements: BB%d not removable",
04677 bb->Id()) );
04678 #ifdef KEY
04679 if (WOPT_Enable_Aggressive_dce_for_bbs)
04680 removable_bbs = removable_bbs->Append(bb, _cfg->Loc_pool());
04681 else{
04682 Update_branch_to_bb_labels( bb );
04683 _cfg->Delete_bb( bb, _mod_phis );
04684 }
04685 #endif
04686 changed_cflow = TRUE;
04687
04688 if ( Tracing() ) {
04689 fprintf( TFile, "DCE_A: Removed BB%d (%p)\n", bb->Id(), bb );
04690 }
04691 }
04692 else {
04693 bb->Set_reached();
04694 }
04695 #ifdef KEY
04696 if ( !removable_bbs->Contains(bb) || !WOPT_Enable_Aggressive_dce_for_bbs )
04697 #endif
04698 Remove_unreached_statements( bb );
04699 }
04700 }
04701
04702 #ifdef KEY
04703 if ( !Enable_aggressive_dce() || !WOPT_Enable_Aggressive_dce_for_bbs)
04704 return ( changed_cflow );
04705
04706 BB_LIST_ITER bb_iter;
04707 BB_NODE *cur_bb;
04708 BOOL last_bb_unique_succ = TRUE;
04709
04710 for ( ; removable_bbs->Len() ; ){
04711 bb = removable_bbs->Node();
04712
04713 if (removable_bb_chain != NULL){
04714 CXX_DELETE(removable_bb_chain, _cfg->Loc_pool());
04715 removable_bb_chain = NULL;
04716 }
04717
04718 while (bb->Pred()->Len() == 1 && bb->Pred()->Node() != bb && removable_bbs->Contains( bb->Pred()->Node() ))
04719 bb = bb->Pred()->Node();
04720 while (bb){
04721 removable_bb_chain = removable_bb_chain->Append(bb, _cfg->Loc_pool());
04722 removable_bbs = removable_bbs->Remove(bb, _cfg->Loc_pool());
04723 if (bb->Succ()->Len() == 1 && bb->Succ()->Node() != bb && removable_bbs->Contains( bb->Succ()->Node() )){
04724 bb = bb->Succ()->Node();
04725 if (bb->Succ()->Len() == 1 &&
04726 bb->Succ()->Node()->Pred()->Len() == 1 &&
04727 bb->Succ()->Node()->Phi_list()->Is_Empty() &&
04728 bb->Phi_list() != NULL)
04729 bb = NULL;
04730 }
04731 else{
04732 if (bb->Succ()->Len() != 1)
04733 last_bb_unique_succ = FALSE;
04734 bb = NULL;
04735 }
04736 }
04737
04738 if ( removable_bb_chain && removable_bb_chain->Len() > 1 && last_bb_unique_succ){
04739
04740 Update_branch_to_bbs_labels( removable_bb_chain );
04741 _cfg->Delete_bbs( removable_bb_chain, _mod_phis );
04742 FOR_ALL_ELEM( bb, bb_iter, Init(removable_bb_chain) ){
04743 Remove_unreached_statements( bb );
04744 }
04745 }
04746 else if ( removable_bb_chain ){
04747
04748 FOR_ALL_ELEM( bb, bb_iter, Init(removable_bb_chain) ){
04749 Update_branch_to_bb_labels( bb );
04750 _cfg->Delete_bb( bb, _mod_phis );
04751 Remove_unreached_statements( bb );
04752 }
04753 }
04754 }
04755 #endif
04756 return ( changed_cflow );
04757 }
04758
04759
04760
04761
04762
04763
04764
04765
04766 void
04767 DCE::Find_assumed_goto_blocks( BB_NODE_SET *assumed_goto ) const
04768 {
04769 Is_True( ! _cfg->Lower_fully(),
04770 ("DCE::Find_assumed_goto_blocks: do not call if lowered fully") );
04771
04772 CFG_ITER cfg_iter(_cfg);
04773 BB_NODE *bb;
04774 FOR_ALL_NODE( bb, cfg_iter, Init() ) {
04775 if ( ! bb->Reached() )
04776 continue;
04777
04778 switch ( bb->Kind() ) {
04779
04780 case BB_DOEND:
04781
04782 assumed_goto->Union1D( bb->Loopstep() );
04783 break;
04784
04785 case BB_DOSTART:
04786
04787 break;
04788
04789 case BB_DOSTEP:
04790
04791 break;
04792
04793 case BB_ENTRY:
04794
04795 break;
04796
04797 case BB_EXIT:
04798 case BB_REGIONEXIT:
04799
04800 break;
04801
04802 case BB_GOTO:
04803
04804 break;
04805
04806 case BB_IO:
04807
04808 break;
04809
04810 case BB_LOGIF:
04811 if ( bb->Ifinfo() != NULL ) {
04812
04813
04814 BB_NODE *last_then = bb->If_else()->Prev();
04815 if ( last_then->Succ()->Contains( bb->If_merge() ) ) {
04816 assumed_goto->Union1D( last_then );
04817 }
04818 }
04819 break;
04820
04821 case BB_REGIONSTART:
04822 break;
04823
04824 case BB_REPEATBODY:
04825
04826 break;
04827
04828 case BB_REPEATEND:
04829
04830 break;
04831
04832 case BB_SUMMARY:
04833
04834 break;
04835
04836 case BB_VARGOTO:
04837
04838 break;
04839
04840 case BB_WHILEEND:
04841
04842 assumed_goto->Union1D( bb->Loopstep() );
04843 break;
04844
04845 case BB_UNKNOWN:
04846 default:
04847 ErrMsg( EC_Unimplemented,
04848 "DCE::Find_assumed_goto_blocks: invalid bb Kind()" );
04849 break;
04850 }
04851 }
04852
04853 if ( Tracing() ) {
04854 fprintf( TFile, "DCE::Find_assumed_goto_blocks: " );
04855 assumed_goto->Print( TFile ) ;
04856 fprintf( TFile, "\n" );
04857 }
04858 }
04859
04860
04861
04862
04863
04864
04865 void
04866 DCE::Insert_required_gotos( void ) const
04867 {
04868
04869 BB_NODE_SET assumed_goto( _cfg->Total_bb_count(), _cfg,
04870 _cfg->Loc_pool(), BBNS_EMPTY );
04871
04872
04873 if ( ! _cfg->Lower_fully() ) {
04874 Find_assumed_goto_blocks( &assumed_goto );
04875 }
04876
04877
04878 CFG_ITER cfg_iter(_cfg);
04879 BB_NODE *bb;
04880 FOR_ALL_NODE( bb, cfg_iter, Init() ) {
04881 if ( ! bb->Reached() )
04882 continue;
04883
04884
04885 if ( assumed_goto.MemberP( bb ) )
04886 continue;
04887
04888
04889
04890 STMTREP *br_stmt = bb->Branch_stmtrep();
04891 if ( br_stmt != NULL ) {
04892 const OPERATOR br_op = br_stmt->Opr();
04893 if ( Is_branch(br_op) )
04894 continue;
04895
04896 if ( br_op == OPR_IO && bb->Kind() == BB_IO )
04897 continue;
04898 }
04899
04900
04901
04902
04903
04904
04905
04906
04907
04908
04909 if (bb->Last_stmtrep() && bb->Last_stmtrep()->Opr() == OPR_REGION )
04910 continue;
04911
04912 #ifdef KEY // needed due to fix for bug 8690
04913 if (bb->MP_region() && _opt_phase != MAINOPT_PHASE &&
04914 bb->Kind() == BB_REGIONSTART) {
04915
04916 BOOL single_pragma_found = FALSE;
04917 STMTREP_ITER stmt_iter(bb->Stmtlist());
04918 STMTREP *stmt;
04919 FOR_ALL_NODE( stmt, stmt_iter, Init() ) {
04920 if (stmt->Opr() == OPR_PRAGMA &&
04921 WN_pragma(stmt->Orig_wn()) == WN_PRAGMA_SINGLE_PROCESS_BEGIN) {
04922 single_pragma_found = TRUE;
04923 break;
04924 }
04925 }
04926 if (single_pragma_found)
04927 continue;
04928 }
04929 #endif
04930
04931
04932
04933
04934 INT succ_cnt = 0;
04935 BB_LIST_ITER bb_succ_iter;
04936 BB_NODE *succ;
04937 FOR_ALL_ELEM( succ, bb_succ_iter, Init(bb->Succ()) ) {
04938 FmtAssert( succ_cnt == 0,
04939 ("DCE::Insert_required_gotos: more than one succ BB%d",
04940 bb->Id()) );
04941 succ_cnt++;
04942 if ( succ != bb->Next() ) {
04943 Add_goto_stmt( bb, succ, bb->Linenum(), bb->Kind() == BB_REGIONEXIT );
04944 br_stmt = bb->Branch_stmtrep();
04945 if ( br_stmt != NULL )
04946 Mark_statement_live( br_stmt );
04947 }
04948 }
04949 }
04950 }
04951
04952
04953
04954
04955
04956 BOOL
04957 DCE::Dead_store_elim(void)
04958 {
04959 BOOL changed_cflow = FALSE;
04960
04961
04962 Mark_statements_dead();
04963
04964
04965 Find_required_statements();
04966
04967
04968 changed_cflow = Remove_dead_statements();
04969
04970 Insert_required_gotos();
04971
04972
04973
04974 if ( changed_cflow )
04975 _cfg->Invalidate_loops();
04976
04977 return ( changed_cflow );
04978 }
04979
04980
04981
04982
04983
04984
04985
04986
04987
04988
04989 void
04990 COMP_UNIT::Do_dead_code_elim(BOOL do_unreachable,
04991 BOOL do_dce_global,
04992 BOOL do_dce_alias,
04993 BOOL do_agg_dce,
04994 BOOL do_identity_removal,
04995 BOOL do_preg_renumbering,
04996 BOOL *paths_removed)
04997 {
04998
04999 OPT_POOL_Push( Cfg()->Loc_pool(), DCE_DUMP_FLAG);
05000
05001 BOOL unreachable = FALSE;
05002 if (paths_removed) *paths_removed = unreachable;
05003 {
05004 DCE dce(Cfg(), Opt_stab(), Arule(), Htable(),
05005 Get_Trace( TP_GLOBOPT, DCE_DUMP_FLAG ), Phase(),
05006 do_unreachable, do_dce_global, do_dce_alias, do_agg_dce,
05007 do_identity_removal, do_preg_renumbering);
05008 if ( dce.Enable_dce_unreachable() ) {
05009 if ( dce.Tracing() ) {
05010 fprintf( TFile, "%sUnreachable_code_elim\n%s", SBar, SBar );
05011 }
05012
05013 dce.Set_phase_unreachable();
05014 unreachable = dce.Unreachable_code_elim();
05015
05016 if ( unreachable ) {
05017 Cfg()->Invalidate_and_update_aux_info();
05018 }
05019 }
05020
05021 if ( dce.Tracing() ) {
05022 fprintf( TFile, "%sDead_store_elim\n%s", SBar, SBar );
05023 }
05024
05025 dce.Set_phase_dead_store();
05026 dce.Init_return_vsym();
05027 unreachable = dce.Dead_store_elim();
05028
05029 if ( unreachable ) {
05030 Cfg()->Invalidate_and_update_aux_info();
05031 }
05032
05033
05034 if ( Cfg()->Fake_entry_bb() != NULL )
05035 Cfg()->Fake_entry_bb()->Reset_reached();
05036 if ( Cfg()->Fake_exit_bb() != NULL )
05037 Cfg()->Fake_exit_bb()->Reset_reached();
05038
05039 if ( dce.Tracing() ) {
05040 fprintf( TFile, "%sAfter COMP_UNIT::Do_dead_code_elim\n%s",
05041 DBar, DBar );
05042 Cfg()->Print( TFile );
05043 }
05044 if (paths_removed)
05045 *paths_removed = unreachable;
05046 }
05047
05048
05049 OPT_POOL_Pop( Cfg()->Loc_pool(), DCE_DUMP_FLAG);
05050 }
05051
05052 #ifdef KEY
05053 #include "../../include/gnu/demangle.h"
05054 extern "C" char *cplus_demangle (const char *, int);
05055
05056 void
05057 COMP_UNIT::Find_uninit_locals_for_entry(BB_NODE *bb)
05058 {
05059 if (bb->Kind() != BB_ENTRY)
05060 return;
05061 STMTREP *stmt = bb->First_stmtrep();
05062 Is_True(bb->First_stmtrep()->Op() == OPC_OPT_CHI,
05063 ("Find_uninit_locals_for_entry: cannot find entry chi"));
05064 CHI_NODE *cnode;
05065 CHI_LIST_ITER chi_iter;
05066 AUX_STAB_ENTRY *sym;
05067 FOR_ALL_NODE(cnode, chi_iter, Init(bb->First_stmtrep()->Chi_list())) {
05068 if (! cnode->Live())
05069 continue;
05070 if (cnode->RESULT()->Is_flag_set(CF_IS_ZERO_VERSION))
05071 continue;
05072 sym = Opt_stab()->Aux_stab_entry(cnode->Aux_id());
05073 if (sym->St() == NULL)
05074 continue;
05075 if (ST_sclass(sym->St()) != SCLASS_AUTO)
05076 continue;
05077 if (! sym->Is_real_var())
05078 continue;
05079 if (ST_is_temp_var(sym->St()))
05080 continue;
05081 if (sym->Is_volatile())
05082 continue;
05083 if (sym->Mp_shared())
05084 continue;
05085 if (sym->Has_nested_ref())
05086 continue;
05087 if (! sym->Points_to()->Local())
05088 continue;
05089 if (! sym->Points_to()->No_alias())
05090 continue;
05091 if (sym->Points_to()->F_param())
05092 continue;
05093
05094 char *output_pu_name = Cur_PU_Name;
05095 char *output_var_name = &Str_Table[sym->St()->u1.name_idx];
05096 char *p = NULL;
05097 char *v = NULL;
05098 if ((PU_src_lang(Get_Current_PU()) & PU_CXX_LANG)) {
05099
05100 if (output_pu_name[0] == '_' && output_pu_name[1] == 'Z') {
05101 p = cplus_demangle(output_pu_name, DMGL_PARAMS|DMGL_ANSI|DMGL_TYPES);
05102 if (p)
05103 output_pu_name = p;
05104 }
05105 if (output_var_name[0] == '_' && output_var_name[1] == 'Z') {
05106 v = cplus_demangle(output_var_name, DMGL_PARAMS|DMGL_ANSI|DMGL_TYPES);
05107 if (v)
05108 output_var_name = v;
05109 }
05110 }
05111
05112 ErrMsg(EC_Uninitialized, output_var_name, Cur_PU_Name);
05113 if (p != NULL && p != Cur_PU_Name)
05114 free(p);
05115 if (v != NULL && v != &Str_Table[sym->St()->u1.name_idx])
05116 free(v);
05117 }
05118 }
05119
05120
05121
05122
05123
05124
05125
05126
05127
05128
05129 void
05130 COMP_UNIT::Find_uninitialized_locals(void)
05131 {
05132 if (Cfg()->Fake_entry_bb() == NULL)
05133 Find_uninit_locals_for_entry(Cfg()->Entry_bb());
05134 else {
05135 BB_NODE *entry_bb;
05136 BB_LIST_ITER bb_iter;
05137 FOR_ALL_ELEM (entry_bb, bb_iter, Init(Cfg()->Fake_entry_bb()->Succ())) {
05138 Find_uninit_locals_for_entry(entry_bb);
05139 }
05140 }
05141 }
05142 #endif