00001
00002
00003
00004
00005 #include "../Collection/Iterator.h"
00006 #include "../Statement/Statement.h"
00007 #include "../Directive/Assertion.h"
00008 #include "../utilities/equivalence_util.h"
00009
00010 #include "DeadCodeElimWS.h"
00011
00012
00013
00014
00015
00016
00017 static void
00018 _refs_to_set(IntSet &set, const RefSet<Expression> &refs,
00019 const Map<Symbol,IntElem> &candidates,
00020 Boolean only_id_exprs)
00021 {
00022 for (Iterator<Expression> iter = refs; iter.valid(); ++iter) {
00023 const Symbol *symbol = iter.current().base_variable_ref();
00024
00025 if (symbol && (! only_id_exprs || iter.current().op() == ID_OP)) {
00026 const IntElem *elem = candidates.find_ref(*symbol);
00027
00028 if (elem)
00029 set.ins(elem->value());
00030
00031 if (! only_id_exprs) {
00032
00033
00034 RefSet<Symbol> *aliases = equiv_aliases(*symbol);
00035
00036 if (aliases) {
00037 Iterator<Symbol> alias_iter = *aliases;
00038
00039 for ( ; alias_iter.valid(); ++alias_iter) {
00040 const IntElem *alias_elem
00041 = candidates.find_ref(alias_iter.current());
00042
00043 if (alias_elem)
00044 set.ins(alias_elem->value());
00045 }
00046
00047 delete aliases;
00048 }
00049 }
00050 }
00051 }
00052 }
00053
00054
00055
00056
00057
00058
00059 static void
00060 _assert_refs_to_set(IntSet &set, Iterator<Expression> iter,
00061 const Map<Symbol,IntElem> &candidates)
00062 {
00063 for (; iter.valid(); ++iter) {
00064 Expression & expr = iter.current();
00065 switch (expr.op()) {
00066 case ID_OP: {
00067 const Symbol &symbol = expr.symbol();
00068 const IntElem *elem = candidates.find_ref(symbol);
00069 if (elem)
00070 set.ins(elem->value());
00071 break;
00072 }
00073 default:
00074 _assert_refs_to_set(set, expr.arg_list(),
00075 candidates);
00076 }
00077 }
00078 }
00079
00080
00081
00082
00083
00084 DeadCodeElimWS::DeadCodeElimWS(unsigned long pass_tag, const Statement &stmt,
00085 const Map<Symbol,IntElem> &candidates)
00086 : WorkSpace(pass_tag),
00087 use_set(candidates.entries()), kill_set(candidates.entries()),
00088 in_live_vars(candidates.entries()), out_live_vars(candidates.entries())
00089 {
00090 _refs_to_set(use_set, stmt.in_refs(), candidates, False);
00091
00092 if (stmt.stmt_class() != READ_STMT) {
00093 _refs_to_set(kill_set, stmt.out_refs(), candidates, True);
00094 kill_set -= use_set;
00095 }
00096
00097 _is_eliminatable = False;
00098 _lhs_tag = -1;
00099 _private_kill_set = 0;
00100
00101 if (stmt.stmt_class() == ASSIGNMENT_STMT) {
00102 const Symbol *lhs_var = stmt.lhs().base_variable_ref();
00103 p_assert(lhs_var,
00104 "LHS of assignment statement is not an IDExpr or ArrayRefExpr");
00105
00106 const IntElem *tag_elem = candidates.find_ref(*lhs_var);
00107
00108 if (tag_elem) {
00109 _lhs_tag = candidates[*lhs_var].value();
00110
00111 if (stmt.rhs().is_side_effect_free())
00112 _is_eliminatable = True;
00113 }
00114 }
00115
00116 for (Iterator<Assertion> dirs = stmt.assertions(); dirs.valid(); ++dirs) {
00117 const Assertion & ass = dirs.current();
00118 switch (ass.type()) {
00119
00120
00121 case AS_PRIVATE:
00122 if (stmt.stmt_class()==BLOCK_ENTRY_STMT)
00123 _assert_refs_to_set(kill_set, ass.arg_list_guarded(), candidates);
00124 break;
00125 case AS_INDUCTION: {
00126
00127 Iterator<Expression> ass_iter1(ass.arg_list_guarded());
00128
00129 Iterator<Expression> ass_iter2(ass_iter1.current().arg_list());
00130
00131
00132
00133 ++ass_iter2;
00134 _assert_refs_to_set(use_set, ass_iter2, candidates);
00135 break;
00136 }
00137 default:
00138 continue;
00139 }
00140 }
00141 _num_visits = 0;
00142 _visited = False;
00143 _toporder = -1;
00144 }
00145
00146 DeadCodeElimWS::DeadCodeElimWS(const DeadCodeElimWS &other)
00147 : WorkSpace(other), use_set(other.use_set), kill_set(other.kill_set),
00148 in_live_vars(other.in_live_vars), out_live_vars(other.out_live_vars)
00149 {
00150 _is_eliminatable = other._is_eliminatable;
00151 _lhs_tag = other._lhs_tag;
00152
00153 if (other._private_kill_set)
00154 _private_kill_set = new IntSet(*other._private_kill_set);
00155 else
00156 _private_kill_set = 0;
00157
00158 _num_visits = other._num_visits;
00159 _visited = other._visited;
00160 _toporder = other._toporder;
00161 }
00162
00163 DeadCodeElimWS::~DeadCodeElimWS()
00164 {
00165 private_kill_set(0);
00166 }
00167
00168
00169
00170
00171 Boolean
00172 DeadCodeElimWS::update_out_live_vars()
00173 {
00174 Boolean changed = False;
00175
00176 if (! is_dead_code()) {
00177 IntSet new_out_live_vars(in_live_vars);
00178 new_out_live_vars -= kill_set;
00179 new_out_live_vars |= use_set;
00180
00181 if (new_out_live_vars != out_live_vars) {
00182 out_live_vars = new_out_live_vars;
00183 changed = True;
00184 }
00185 }
00186 else if (out_live_vars != in_live_vars) {
00187 out_live_vars = in_live_vars;
00188 changed = True;
00189 }
00190
00191 return changed;
00192 }
00193
00194
00195
00196
00197
00198 static void
00199 _pretty_print_set(ostream &o, const IntSet &set,
00200 const Array<Symbol *> &tag_to_candidate)
00201 {
00202 int sym_tag = set.first();
00203
00204 if (sym_tag != -1) {
00205 o << tag_to_candidate[sym_tag]->name_ref();
00206
00207 while ((sym_tag = set.next(sym_tag)) != -1)
00208 o << ", " << tag_to_candidate[sym_tag]->name_ref();
00209 }
00210 }
00211
00212
00213
00214
00215
00216 void
00217 DeadCodeElimWS::pretty_print(ostream &o,
00218 const Array<Symbol *> &tag_to_candidate) const
00219 {
00220 o << " is_eliminatable = " << _is_eliminatable;
00221 o << ", lhs_tag = " << _lhs_tag << endl;
00222 o << " num_visits = " << _num_visits;
00223 o << ", toporder = " << _toporder << endl;
00224
00225 o << " use = {";
00226 _pretty_print_set(o, use_set, tag_to_candidate);
00227 o << "}\n";
00228
00229 o << " kill = {";
00230 _pretty_print_set(o, kill_set, tag_to_candidate);
00231 o << "}\n";
00232
00233 if (_private_kill_set) {
00234 o << " priv_kill = {";
00235 _pretty_print_set(o, *_private_kill_set, tag_to_candidate);
00236 o << "}\n";
00237 }
00238
00239 o << " in_live_vars = {";
00240 _pretty_print_set(o, in_live_vars, tag_to_candidate);
00241 o << "}\n";
00242
00243 o << " out_live_vars = {";
00244 _pretty_print_set(o, out_live_vars, tag_to_candidate);
00245 o << "}\n";
00246 }
00247
00248
00249
00250
00251
00252 void
00253 DeadCodeElimWS::print(ostream &o) const
00254 {
00255 o << "DeadCodeElimWS:{";
00256 o << "is_elim=" << _is_eliminatable << ", ";
00257 o << "lhs_tag=" << _lhs_tag << ", ";
00258 o << "num_visits=" << _num_visits << ", ";
00259 o << "toporder=" << _toporder << ", ";
00260 o << "use=" << use_set << ", ";
00261 o << "kill=" << kill_set << ", ";
00262 o << "priv_kill=";
00263
00264 if (_private_kill_set)
00265 o << *_private_kill_set;
00266 else
00267 o << "NULL";
00268
00269 o << ", ";
00270 o << "in_live_vars=" << in_live_vars << ", ";
00271 o << "out_live_vars=" << out_live_vars;
00272 o << "}";
00273 }
00274
00275
00276
00277
00278
00279 Listable *
00280 DeadCodeElimWS::listable_clone() const
00281 {
00282 return new DeadCodeElimWS(*this);
00283 }
00284
00285
00286
00287
00288
00289 int
00290 DeadCodeElimWS::structures_OK() const
00291 {
00292 return (use_set.structures_OK()
00293 && kill_set.structures_OK()
00294 && in_live_vars.structures_OK()
00295 && out_live_vars.structures_OK());
00296 }