00001
00002
00003
00004
00005
00006 #include "../Collection/Map.h"
00007 #include "../Collection/Iterator.h"
00008 #include "../Collection/Mutator.h"
00009 #include "../ProgramUnit.h"
00010 #include "../Statement/Statement.h"
00011 #include "../Directive/Assertion.h"
00012 #include "../utilities/switches_util.h"
00013 #include "../utilities/expression_util.h"
00014 #include "../utilities/equivalence_util.h"
00015 #include "../Data.h"
00016 #include "../IntElem.h"
00017 #include "../IntSet.h"
00018 #include "../Array.h"
00019 #include "../Boolean.h"
00020 #include "../Timer.h"
00021 #include "../p-assert.h"
00022 #include "../macros.h"
00023
00024 #include "DeadCodeElimWS.h"
00025 #include "deadcode.h"
00026
00027 #include "../Range/range.h"
00028 #include "../Range/AIRangeDict.h"
00029 #include "../Range/ControlRangeDict.h"
00030 #include "../Range/RangeAccessor.h"
00031 #include "../Range/RangeExpr.h"
00032 #include "../Range/range.h"
00033 #include "../Range/range_util.h"
00034
00035 #include <set>
00036
00037 static unsigned int _pass_tag;
00038
00039 static int _debug_level = 0;
00040
00041
00042
00043
00044
00045
00046
00047 static void
00048 _collect_candidates(const ProgramUnit &pgm,
00049 Map<Symbol,IntElem> &candidates,
00050 Array<Symbol *> &tag_to_candidate,
00051 DCE_ARRAY_BOOL deadcode_arrays)
00052 {
00053 DictionaryIter<Symbol> sym_iter = pgm.symtab().iterator();
00054 int tag = 0;
00055 tag_to_candidate.resize(pgm.symtab().entries());
00056
00057 for ( ; sym_iter.valid(); ++sym_iter) {
00058 Symbol &symbol = sym_iter.current();
00059
00060 switch(symbol.sym_class()) {
00061 case VARIABLE_CLASS:
00062 if (! symbol.is_array() || deadcode_arrays == DEADCODE_ARRAYS) {
00063 tag_to_candidate[tag] = &symbol;
00064 candidates.ins(symbol, new IntElem(tag++));
00065 }
00066 break;
00067 default:
00068 continue;
00069 }
00070 }
00071
00072 tag_to_candidate.resize(tag);
00073
00074 p_assert(tag == candidates.entries(),
00075 "Error in Map<Symbol,IntElem>::entries().");
00076 }
00077
00078
00079
00080
00081
00082
00083
00084 static void
00085 _init_workspaces(ProgramUnit &pgm,
00086 const Map<Symbol,IntElem> &candidates)
00087 {
00088 Iterator<Statement> iter = pgm.stmts().iterator();
00089
00090 for ( ; iter.valid(); ++iter) {
00091 DeadCodeElimWS *my_ws = new DeadCodeElimWS(_pass_tag, iter.current(),
00092 candidates);
00093
00094 iter.current().work_stack().push(my_ws);
00095 }
00096 }
00097
00098
00099
00100
00101
00102 static DeadCodeElimWS &
00103 _get_workspace(const Statement &stmt)
00104 {
00105 WorkSpace *ws = stmt.work_stack().top_ref(_pass_tag);
00106
00107 p_assert(ws, "Statement doesn't have a DeadCodeElimWS.");
00108
00109 return * (DeadCodeElimWS *) ws;
00110 }
00111
00112
00113
00114
00115
00116 static void
00117 _dump_workspaces(ostream &o, const ProgramUnit &pgm,
00118 const Array<Symbol *> &tag_to_candidate)
00119 {
00120 Iterator<Statement> iter = pgm.stmts().iterator();
00121
00122 for ( ; iter.valid(); ++iter) {
00123 iter.current().structures_OK();
00124 o << iter.current().tag() << ": ";
00125 iter.current().print_debug(o, 0);
00126 o << endl;
00127 _get_workspace(iter.current()).pretty_print(o, tag_to_candidate);
00128 }
00129 }
00130
00131
00132
00133
00134
00135 static void
00136 _init_non_local_vars(IntSet &non_local_vars, IntSet &live_end_vars,
00137 const ProgramUnit &pgm,
00138 const Map<Symbol,IntElem> &candidates,
00139 const Array<Symbol *> &tag_to_candidate)
00140 {
00141
00142
00143
00144 RefSet<Symbol> data_vars;
00145 Iterator<Data> data_iter = pgm.data();
00146
00147 for ( ; data_iter.valid(); ++data_iter) {
00148 Iterator<Expression> data_var_iter
00149 = data_iter.current().variable_list().arg_list();
00150
00151 for ( ; data_var_iter.valid(); ++data_var_iter) {
00152 Symbol *var = data_var_iter.current().base_variable_ref();
00153
00154 if (var)
00155 data_vars.ins(*var);
00156 }
00157 }
00158
00159 for (int sym_tag = 0; sym_tag < tag_to_candidate.entries(); ++sym_tag) {
00160 Symbol &var = *tag_to_candidate[sym_tag];
00161 switch (var.sym_class()) {
00162 case VARIABLE_CLASS:
00163 if (var.common_ref()) {
00164 non_local_vars.ins(sym_tag);
00165 live_end_vars.ins(sym_tag);
00166
00167
00168
00169
00170 RefSet<Symbol> *aliases = equiv_aliases(var);
00171
00172 if (aliases) {
00173 Iterator<Symbol> alias_iter = *aliases;
00174
00175 for ( ; alias_iter.valid(); ++alias_iter) {
00176 const IntElem *alias_elem
00177 = candidates.find_ref(alias_iter.current());
00178
00179 if (alias_elem) {
00180 non_local_vars.ins(alias_elem->value());
00181 live_end_vars.ins(alias_elem->value());
00182 }
00183 }
00184
00185 delete aliases;
00186 }
00187 }
00188 else if (var.formal() == IS_FORMAL
00189 || var.saved() == IS_SAVED
00190 || data_vars.member(var)) {
00191
00192 live_end_vars.ins(sym_tag);
00193
00194
00195
00196
00197 RefSet<Symbol> *aliases = equiv_aliases(var);
00198
00199 if (aliases) {
00200 Iterator<Symbol> alias_iter = *aliases;
00201
00202 for ( ; alias_iter.valid(); ++alias_iter) {
00203 const IntElem *alias_elem
00204 = candidates.find_ref(alias_iter.current());
00205
00206 if (alias_elem)
00207 live_end_vars.ins(alias_elem->value());
00208 }
00209
00210 delete aliases;
00211 }
00212 }
00213 break;
00214 default:
00215 continue;
00216 }
00217 }
00218 }
00219
00220
00221
00222
00223
00224
00225 static void
00226 _make_nonlocals_used_at_calls(StmtList &stmts, const IntSet &non_local_vars)
00227 {
00228 Iterator<Statement> iter = stmts.iterator();
00229
00230 for ( ; iter.valid(); ++iter) {
00231 Statement &stmt = iter.current();
00232
00233 if (stmt.stmt_class() == CALL_STMT || contains_func_call(stmt)) {
00234 DeadCodeElimWS &ws = _get_workspace(stmt);
00235 ws.use_set |= non_local_vars;
00236 ws.kill_set -= non_local_vars;
00237 }
00238 }
00239 }
00240
00241
00242
00243
00244
00245
00246 static void
00247 _compute_private_kill_sets(StmtList &stmts,
00248 const Map<Symbol,IntElem> &candidates)
00249 {
00250 Iterator<Statement> stmt_iter = stmts.stmts_of_type(DO_STMT);
00251
00252 for ( ; stmt_iter.valid(); ++stmt_iter) {
00253 Statement &stmt = stmt_iter.current();
00254 RefSet<Symbol> private_vars;
00255 Iterator<Assertion> asrt_iter = stmt.assertions();
00256
00257 for ( ; asrt_iter.valid(); ++asrt_iter) {
00258 if (asrt_iter.current().type() == AS_PRIVATE) {
00259 Iterator<Expression> item_iter = asrt_iter.current().arg_list_guarded();
00260
00261 for ( ; item_iter.valid(); ++item_iter) {
00262 Symbol *var = item_iter.current().base_variable_ref();
00263
00264 if (var && var->is_array())
00265 private_vars.ins(*var);
00266 }
00267 }
00268 }
00269
00270 for (asrt_iter.reset(); asrt_iter.valid(); ++asrt_iter) {
00271 if (asrt_iter.current().type() == AS_FIRSTVALUE) {
00272 Iterator<Expression> item_iter = asrt_iter.current().arg_list_guarded();
00273
00274 for ( ; item_iter.valid(); ++item_iter) {
00275 Symbol *var = item_iter.current().base_variable_ref();
00276
00277 if (var && var->is_array() && private_vars.member(*var))
00278 private_vars.del(*var);
00279 }
00280 }
00281 }
00282
00283 if (private_vars.entries() > 0) {
00284 IntSet *my_private_kill_set = new IntSet(candidates.entries());
00285 Iterator<Symbol> priv_iter = private_vars;
00286
00287 for ( ; priv_iter.valid(); ++priv_iter) {
00288 const IntElem *elem = candidates.find_ref(priv_iter.current());
00289
00290 if (elem)
00291 my_private_kill_set->ins(elem->value());
00292 }
00293
00294 _get_workspace(stmt).private_kill_set(my_private_kill_set);
00295 }
00296 }
00297 }
00298
00299
00300
00301
00302
00303
00304
00305 static void
00306 _calc_toporder1(Statement &stmt, int &toporder)
00307 {
00308 DeadCodeElimWS &my_ws = _get_workspace(stmt);
00309
00310 if (! my_ws.visited()) {
00311 my_ws.visited(1);
00312
00313 Iterator<Statement> pred_iter = stmt.pred();
00314
00315 for ( ; pred_iter.valid(); ++pred_iter)
00316 _calc_toporder1(pred_iter.current(), toporder);
00317
00318 my_ws.toporder(toporder--);
00319 }
00320 }
00321
00322 static void
00323 _calc_toporder(ProgramUnit &pgm, Array<Statement *> &toporder_to_stmt)
00324 {
00325
00326
00327 int toporder = pgm.stmts().entries() - 1;
00328
00329 if (toporder >= 0) {
00330 Iterator<Statement> exit_iter = pgm.stmts().stmts_of_type(FLOW_EXIT_STMT);
00331
00332 for ( ; exit_iter.valid(); ++exit_iter)
00333 _calc_toporder1(exit_iter.current(), toporder);
00334
00335 p_assert(toporder >= -1,
00336 "_calc_toporder visited a stmt more than once.");
00337 }
00338
00339
00340
00341 toporder_to_stmt.resize(pgm.stmts().entries());
00342
00343 for (int i = 0; i <= toporder; ++i)
00344 toporder_to_stmt[i] = 0;
00345
00346 Iterator<Statement> iter = pgm.stmts().iterator();
00347
00348 for ( ; iter.valid(); ++iter) {
00349 int stmt_toporder = _get_workspace(iter.current()).toporder();
00350
00351 if (stmt_toporder >= 0)
00352 toporder_to_stmt[stmt_toporder] = &iter.current();
00353 }
00354 }
00355
00356
00357
00358
00359
00360 static void
00361 _put_pred_on_work_list(IntSet &work_list, Statement &stmt)
00362 {
00363 Iterator<Statement> pred_iter = stmt.pred();
00364
00365 for ( ; pred_iter.valid(); ++pred_iter)
00366 work_list.ins(_get_workspace(pred_iter.current()).toporder());
00367 }
00368
00369
00370
00371
00372
00373
00374 static void
00375 _iterate_to_fixed_point(ProgramUnit &pgm,
00376 const Array<Statement *> &toporder_to_stmt,
00377 const Map<Symbol,IntElem> & ,
00378 const Array<Symbol *> &tag_to_candidate,
00379 const IntSet &flow_exit_vars)
00380 {
00381
00382
00383 IntSet work_list(toporder_to_stmt.entries());
00384
00385
00386
00387
00388 Iterator<Statement> exit_iter = pgm.stmts().stmts_of_type(FLOW_EXIT_STMT);
00389
00390 for ( ; exit_iter.valid(); ++exit_iter)
00391 work_list.ins(_get_workspace(exit_iter.current()).toporder());
00392
00393
00394
00395 while (work_list.entries() > 0) {
00396
00397
00398 for (int stmt_num = work_list.first();
00399 stmt_num != -1;
00400 stmt_num = work_list.next(stmt_num)) {
00401
00402 Statement &curr = *toporder_to_stmt[stmt_num];
00403 work_list.del(stmt_num);
00404 DeadCodeElimWS &curr_ws = _get_workspace(curr);
00405 curr_ws.incr_num_visits();
00406 Boolean changed = False;
00407
00408
00409
00410 IntSet new_live_vars(tag_to_candidate.entries());
00411
00412 if (curr.stmt_class() == FLOW_EXIT_STMT) {
00413 if (pgm.pu_class() != PROGRAM_PU_TYPE)
00414 new_live_vars = flow_exit_vars;
00415 }
00416 else if (curr_ws.private_kill_set()) {
00417 p_assert(curr.stmt_class() == DO_STMT,
00418 "Only DO statements can have a non-NULL private_kill_set field.");
00419 const DeadCodeElimWS &body_ws
00420 = _get_workspace(*curr.next_ref());
00421
00422 if (body_ws.num_visits() > 0) {
00423 new_live_vars = body_ws.out_live_vars;
00424 new_live_vars -= *curr_ws.private_kill_set();
00425 }
00426
00427 const DeadCodeElimWS &exit_ws
00428 = _get_workspace(*curr.follow_ref()->next_ref());
00429
00430 if (exit_ws.num_visits() > 0)
00431 new_live_vars |= exit_ws.out_live_vars;
00432 }
00433 else {
00434 Iterator<Statement> succ_iter = curr.succ();
00435
00436 for ( ; succ_iter.valid(); ++succ_iter) {
00437 const DeadCodeElimWS &succ_ws
00438 = _get_workspace(succ_iter.current());
00439
00440 if (succ_ws.num_visits() > 0)
00441 new_live_vars |= succ_ws.out_live_vars;
00442 }
00443 }
00444
00445 if (curr_ws.num_visits() == 1
00446 || new_live_vars != curr_ws.in_live_vars) {
00447
00448
00449
00450
00451
00452 if (_debug_level >= 20) {
00453 cout << "! Statement ";
00454 curr.print_debug(cout, 0);
00455 cout << " was visited and updated.\n";
00456 }
00457
00458 curr_ws.in_live_vars = new_live_vars;
00459 changed = curr_ws.update_out_live_vars();
00460
00461 if (changed || curr_ws.num_visits() == 1) {
00462
00463
00464
00465
00466
00467 _put_pred_on_work_list(work_list, curr);
00468 }
00469
00470 if (_debug_level >= 30)
00471 curr_ws.pretty_print(cout, tag_to_candidate);
00472 }
00473 }
00474 }
00475 }
00476
00477
00478
00479
00480
00481 static void
00482 _remove_assertion(const Symbol &var, Statement &stmt, AssertionType atyp)
00483 {
00484 for (Iterator<Assertion> dirs = stmt.assertions(); dirs.valid(); ++dirs) {
00485 Assertion & ass = dirs.current();
00486
00487 if (ass.type() == atyp) {
00488 Mutator<Expression> items = ass.arg_list_guarded();
00489
00490 for ( ; items.valid(); ++items)
00491 if (items.current().base_variable_ref() == &var)
00492 items.del();
00493
00494 if (ass.arg_list_guarded().entries() == 0)
00495 stmt.assertions().del(ass);
00496 }
00497 }
00498 }
00499
00500
00501
00502
00503
00504
00505 static Boolean
00506 _are_vars_in_expr(const Expression &e, const RefSet<Symbol> &vars)
00507 {
00508 if (e.op() == ID_OP)
00509 return vars.member(e.symbol());
00510 else {
00511 Iterator<Expression> iter = e.arg_list();
00512
00513 for ( ; iter.valid(); ++iter)
00514 if (_are_vars_in_expr(iter.current(), vars))
00515 return True;
00516 }
00517
00518 return False;
00519 }
00520
00521
00522
00523
00524
00525 static void
00526 _delete_dead_code(ProgramUnit &pgm, const Array<Symbol *> tag_to_candidate,
00527 const IntSet &non_local_vars)
00528 {
00529 Iterator<Statement> stmt_iter = pgm.stmts().iterator();
00530 IntSet pgm_live_vars = non_local_vars;
00531
00532 for ( ; stmt_iter.valid(); ++stmt_iter) {
00533 Statement &stmt = stmt_iter.current();
00534 const DeadCodeElimWS &ws = _get_workspace(stmt);
00535 pgm_live_vars |= ws.in_live_vars;
00536
00537 if (! ws.is_dead_code() && stmt.stmt_class() != BLOCK_ENTRY_STMT)
00538 pgm_live_vars |= ws.kill_set;
00539
00540
00541
00542 if (stmt.stmt_class() == DO_STMT) {
00543
00544
00545
00546 const DeadCodeElimWS &follow_ws = _get_workspace(*stmt.follow_ref()->next_ref());
00547 for (int sym_tag = 0; sym_tag < tag_to_candidate.entries(); ++sym_tag)
00548 if (! follow_ws.out_live_vars[sym_tag]) {
00549 _remove_assertion(*tag_to_candidate[sym_tag], stmt,
00550 AS_LASTVALUE);
00551 _remove_assertion(*tag_to_candidate[sym_tag], stmt,
00552 AS_DYNLASTVALUE);
00553 }
00554 }
00555
00556
00557
00558 if (ws.is_dead_code()) {
00559 if (_debug_level >= 5) {
00560 cout << "! Deleted stmt: ";
00561 stmt.print_debug(cout, 0);
00562 cout << endl;
00563 }
00564 pgm.stmts().del(stmt);
00565 }
00566 }
00567
00568
00569
00570 RefSet<Symbol> dead_vars;
00571
00572 for (int sym_tag = 0; sym_tag < tag_to_candidate.entries(); ++sym_tag)
00573 if (! pgm_live_vars[sym_tag])
00574 dead_vars.ins(*tag_to_candidate[sym_tag]);
00575
00576
00577
00578 for (stmt_iter.reset() ; stmt_iter.valid(); ++stmt_iter) {
00579 Statement &stmt = stmt_iter.current();
00580
00581 Iterator<Assertion> dirs = stmt.assertions();
00582
00583 for ( ; dirs.valid(); ++dirs) {
00584 Assertion & ass = dirs.current();
00585
00586 if (ass.arg_list_valid() &&
00587 (ass.arg_list_guarded().entries() != 0)) {
00588 Mutator<Expression> items = ass.arg_list_guarded();
00589
00590 for ( ; items.valid(); ++items)
00591 if (_are_vars_in_expr(items.current(), dead_vars))
00592 items.del();
00593
00594 if (ass.arg_list_guarded().entries() == 0)
00595 stmt.assertions().del(ass);
00596 }
00597 }
00598 }
00599
00600
00601
00602 if (_debug_level >= 5) {
00603 cout << "! Dead symbols: {";
00604 Iterator<Symbol> dead_iter = dead_vars;
00605
00606 for ( ; dead_iter.valid(); ++dead_iter)
00607 cout << dead_iter.current().name_ref() << ", ";
00608
00609 cout << "}\n";
00610 }
00611
00612 pgm.clean();
00613 }
00614
00615
00616 void dfs_stmts(Statement& stmt, set<Statement*>& visited){
00617 if (visited.find(&stmt)!=visited.end()){
00618
00619 return;
00620 } else {
00621
00622 visited.insert(&stmt);
00623 for(Iterator<Statement> stit=stmt.succ(); stit.valid(); ++stit){
00624 dfs_stmts(stit.current(), visited);
00625 }
00626 }
00627 }
00628
00629
00630 void eliminate_unreachable_statements(ProgramUnit& pgm){
00631 set<Statement*> visited;
00632 Iterator<Statement> stit=pgm.stmts().stmts_of_type(ENTRY_STMT);
00633 for(; stit.valid(); ++stit){
00634 dfs_stmts(stit.current(), visited);
00635 }
00636 RefSet<Statement> todel;
00637 for(Statement* ps=pgm.stmts().first_ref(); ps!=0; ps=ps->next_ref()){
00638 if (visited.find(ps)==visited.end()){
00639
00640 if (ps->stmt_class()!=FLOW_ENTRY_STMT){
00641
00642 todel.ins(*ps);
00643 }
00644 }
00645 }
00646 pgm.stmts().del(todel);
00647 pgm.stmts().build_all_refs();
00648 }
00649
00650
00651
00652
00653
00654
00655 void
00656 eliminate_dead_code(ProgramUnit &pgm,
00657 DCE_ARRAY_BOOL deadcode_arrays GIV(DONT_DEADCODE_ARRAYS),
00658 int debug GIV(0))
00659 {
00660
00661 Map<Symbol,IntElem> candidates;
00662
00663
00664 Array<Symbol *> tag_to_candidate;
00665
00666
00667 Array<Statement *> toporder_to_stmt;
00668
00669 _debug_level = debug;
00670 Timer tot_timer;
00671 Timer timer;
00672
00673
00674
00675 _collect_candidates(pgm, candidates, tag_to_candidate, deadcode_arrays);
00676 _pass_tag = create_pass_tag();
00677 _init_workspaces(pgm, candidates);
00678
00679 IntSet non_local_vars(candidates.entries());
00680 IntSet live_end_vars(candidates.entries());
00681 _init_non_local_vars(non_local_vars, live_end_vars,
00682 pgm, candidates, tag_to_candidate);
00683 if (non_local_vars.first() != -1)
00684 _make_nonlocals_used_at_calls(pgm.stmts(), non_local_vars);
00685
00686 if (deadcode_arrays == DEADCODE_ARRAYS)
00687 _compute_private_kill_sets(pgm.stmts(), candidates);
00688
00689 _calc_toporder(pgm, toporder_to_stmt);
00690
00691 if (_debug_level > 0) {
00692 cout << "! Initialization: " << timer << endl;
00693 timer.reset();
00694 }
00695
00696
00697
00698
00699 _iterate_to_fixed_point(pgm, toporder_to_stmt, candidates,
00700 tag_to_candidate, live_end_vars);
00701
00702 if (_debug_level > 0) {
00703 cout << "! Iterating to fixed point: " << timer << endl;
00704 timer.reset();
00705 }
00706
00707
00708
00709 _delete_dead_code(pgm, tag_to_candidate, live_end_vars);
00710
00711 if (_debug_level > 0)
00712 cout << "! Deleting dead code: " << timer << endl;
00713
00714 if (_debug_level >= 10)
00715 _dump_workspaces(cout, pgm, tag_to_candidate);
00716
00717
00718
00719 pgm.clean_workspace(_pass_tag);
00720
00721 if (_debug_level > 0) {
00722 cout << "! Total time: " << tot_timer << endl;
00723 cout << "! Number of statements: " << pgm.stmts().entries() << endl;
00724 cout << "! Number of candidate variables: " << candidates.entries() << endl;
00725 }
00726
00727
00728 eliminate_unreachable_statements(pgm);
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758 }