Polaris: deadcode.cc Source File

deadcode.cc

Go to the documentation of this file.
00001 ///
00002 ///
00003 /// \file deadcode.cc
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;  /// ...  Pass tag associated with this pass
00038 
00039 static int _debug_level = 0;
00040 
00041 
00042 /// collect_candidates -
00043 ///   Determine all the variables that are candidates for forward substitution
00044 ///   and initialize the _candidates and _tag_to_candidates data structures
00045 ///   to contain these variables.
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 /// init_workspaces
00080 ///   Initialize the workspaces for each statement in the program.
00081 ///   Note: A lot of the initialization for eliminate_dead_code are hidden
00082 ///   in the constructor for DeadCodeElimWS.
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 /// get_workspace
00100 ///   Get the workspace for the given statement.
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 /// dump_workspaces
00114 ///   Dump out the data inside all of the workspaces of the program
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 /// _init_non_local_vars
00133 ///   Initialize the sets of non-local and live-end variables.
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     /// ...  Determine all variables that are contained in DATA statements.
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         /// ...  Mark any variables aliased to the non-local variable
00168         /// ...  as also non-local and live-end
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         /// ...  Mark any variables aliased to the live-end variable
00195         /// ...  as also live-end
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 /// _make_nonlocals_used_at_calls
00222 ///   Make all non-local variables be marked as potentially used for all
00223 ///   call statements and all statements containing function calls.
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 /// _compute_private_kill_sets
00243 ///   Compute the set of array variables to kill for do loop bodies because
00244 ///   they are private to the loop's body.
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 /// _calc_toporder
00301 ///   Calculate toporder for the flow graph.  Essentially, this algorithm
00302 ///   performs a topological sort on the flow graph, ignoring back
00303 ///   edges.
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     /// ...  Calculate the topological order for each statement
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     /// ...  Initialize toporder_to_stmt
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 /// put_pred_on_work_list
00358 ///   Put all of my predecessors on the work list.
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 /// iterate_to_fixed_point
00371 ///   Propagate the constants contained in the statement's const_maps until
00372 ///   a fixed point is reached.
00373 
00374 static void
00375 _iterate_to_fixed_point(ProgramUnit &pgm, 
00376             const Array<Statement *> &toporder_to_stmt,
00377             const Map<Symbol,IntElem> & /* candidates */,
00378             const Array<Symbol *> &tag_to_candidate,
00379             const IntSet &flow_exit_vars)
00380 {
00381     /// ...  List of statements that need to be updated.
00382 
00383     IntSet work_list(toporder_to_stmt.entries());
00384 
00385     /// ...  Mark all variables for entry statements as non-const and put all
00386     /// ...  entries on the work list.
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     /// ...  Iterate until there are no more elements on the work list
00394 
00395     while (work_list.entries() > 0) {
00396     /// ...  Visit each statement in the work list, in topological order
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         /// ...  Generate the new live variable set for the end of the statement.
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         /// ...  New entering live variable set differs from the old
00449         /// ...  one.  So update the entering and exiting live variable
00450         /// ...  sets for the statement.
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             /// ...  Exiting live var set has changed, so place
00463             /// ...  the statement's predecessors on the work list so
00464             /// ...  that they can update their live variable sets
00465             /// ...  with my live var set.
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 ///  remove_assertion
00479 ///    Remove all assertions of the given type with the given variable.
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 ///  _are_vars_in_expr
00502 ///    Return true if the given expression uses any of the variables in the
00503 ///    given set.
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 /// delete_dead_code
00523 ///   Delete all dead code from a program unit.
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     /// ...  Delete all dead LAST VALUE assertions.
00541 
00542     if (stmt.stmt_class() == DO_STMT) {
00543             /// ...  Look at the workspace of the statement after the DO loop's
00544             /// ...  ENDDO statement.
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     /// ...  Delete the statement if it is dead code.
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     /// ...  Compute the set of variables that are dead for the entire program
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     /// ...  Delete all assertions containing any of the dead variables.
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     /// ...  Delete all dead variables from the symbol table.
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     /// ...  Already visited.
00619     return;
00620   } else {
00621     /// ...  First occurence
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 /// silvius: eliminate all statements that cannot be reached from any entry.
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       /// ...  Make sure we are not removing the flow entry.
00640       if (ps->stmt_class()!=FLOW_ENTRY_STMT){
00641         /// ...  Unreachable.
00642         todel.ins(*ps);
00643       }
00644     }
00645   }
00646   pgm.stmts().del(todel);
00647   pgm.stmts().build_all_refs();
00648 }
00649 
00650 
00651 
00652 /// eliminate_dead_code
00653 ///   Delete all dead code from a program unit.
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     /// ...  Set of all variables that are candidates for dead code elimination.
00661     Map<Symbol,IntElem> candidates;
00662 
00663     /// ...  An array that maps integers to variable candidates.
00664     Array<Symbol *> tag_to_candidate;
00665 
00666     /// ...  An array that maps integers to statements.
00667     Array<Statement *> toporder_to_stmt;
00668 
00669     _debug_level = debug;
00670     Timer tot_timer;
00671     Timer timer;
00672 
00673     /// ...  Initialize
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     /// ...  Iteratively propagate the constants throughout the program until a
00697     /// ...  fixed point is reached.
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     /// ...  Delete all dead code from the program unit.
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     /// ...  Clean up
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     /// ...  silvius:
00728     eliminate_unreachable_statements(pgm);
00729 
00730     /// ...  This test is a kluge.  This causes the code below to run
00731     /// ...  before privatization and not after.  When this is done 
00732     /// ...  permanently, we'll figure out a better way.
00733 
00734     /// ...  The stuff below eliminates IF statements whose conditions are 
00735     /// ...  found (through range propagation) to be constant, either .TRUE.
00736     /// ...  or .FALSE. .  The IF itself and the appropriate side of the IF are 
00737     /// ...  removed.
00738     
00739 ///     if (deadcode_arrays == DONT_DEADCODE_ARRAYS) {
00740 ///     AIRangeDict *ranges = new AIRangeDict ( pgm );
00741 ///     
00742 ///     Iterator<Statement> if_iter = pgm.stmts().stmts_of_type (IF_STMT);
00743 /// 
00744 ///     for (; if_iter.valid(); ++if_iter) {
00745 ///         Statement & ifstmt = if_iter.current();
00746 ///         RangeAccessor if_ranges ( *ranges, ifstmt );
00747 /// 
00748 ///         Expression *ifcondition = ifstmt.expr().clone();
00749 ///         if_ranges.eliminate_vars (ifcondition, NULL);
00750 /// 
00751 ///         if (ifcondition->op() == LOGICAL_CONSTANT_OP) {
00752 ///         if (ifcondition->str_data() == ".TRUE.") {
00753 ///         } else {
00754 ///         }
00755 ///         }
00756 ///     }
00757 ///    }
00758 }
 © 1995-2005 University of Illinois, Urbana-Champaign. All rights reserved.  Fri Mar 25 23:05:44 2005