Polaris: PropConstWS.cc Source File

PropConstWS.cc

Go to the documentation of this file.
00001 ///
00002 ///
00003 /// \file PropConstWS.cc
00004 ///
00005 #include "../Collection/Iterator.h"
00006 #include "../Statement/Statement.h"
00007 #include "../utilities/equivalence_util.h"
00008 #include "../utilities/expression_util.h"
00009 
00010 #include "PropConstWS.h"
00011 #include "IPCPProcData.h"
00012 
00013 /// Template instantiations:
00014 
00015 template class TypedCollection<PropConstValue>;
00016 template class List<PropConstValue>;
00017 template ostream & operator << (ostream &, const List<PropConstValue> &);
00018 template class Assign<PropConstValue>;
00019 template class Iterator<PropConstValue>;
00020 template class Mutator<PropConstValue>;
00021 
00022 
00023 /// refs_to_set
00024 ///   Convert a collection of Expression references (e.g. in_refs or out_refs)
00025 ///   into a set of symbol tags.
00026 
00027 static void
00028 _refs_to_set(IntSet &set, const RefSet<Expression> &refs,
00029          const Map<Symbol,IntElem> &candidates)
00030 {
00031     for (Iterator<Expression> iter = refs; iter.valid(); ++iter) {
00032     const Symbol *symbol = iter.current().base_variable_ref();
00033 
00034     if (symbol) {
00035         const IntElem *elem = candidates.find_ref(*symbol);
00036 
00037         if (elem)
00038         set.ins(elem->value());
00039 
00040         /// ...  Also place any aliased variables in the set.
00041 
00042         RefSet<Symbol> *aliases = equiv_aliases(*symbol);
00043 
00044         if (aliases) {
00045         Iterator<Symbol> alias_iter = *aliases;
00046 
00047         for ( ; alias_iter.valid(); ++alias_iter) {
00048             const IntElem *alias_elem
00049             = candidates.find_ref(alias_iter.current());
00050 
00051             if (alias_elem)
00052             set.ins(alias_elem->value());
00053         }
00054 
00055         delete aliases;
00056         }
00057     }
00058     }
00059 }
00060 
00061 
00062 /// refs_are_candidates
00063 ///   Return true if all Expression references (e.g. in_refs or out_refs)
00064 ///   are either parameters or contained in the candidates Dictionary.
00065 
00066 static Boolean
00067 _refs_are_candidates(const RefSet<Expression> &refs,
00068              const Map<Symbol,IntElem> &candidates)
00069 {
00070     for (Iterator<Expression> iter = refs; iter.valid(); ++iter) {
00071     const Symbol *symbol = iter.current().base_variable_ref();
00072 
00073     if (symbol && 
00074         (symbol->sym_class() != SYMBOLIC_CONSTANT_CLASS
00075          && ! candidates.member(*symbol)))
00076         return False;
00077     }
00078 
00079     return True;
00080 }
00081 
00082 
00083 /// ok_to_substitute
00084 ///   Return true if it is ok to substitute the given statement.  A statement
00085 ///   is substitutable if it is an assignment statement which only uses
00086 ///   variables in the candidates set, and whose right hand side is free of
00087 ///   side effects.
00088 
00089 static Boolean
00090 _ok_to_substitute(const Statement &stmt,
00091           const Map<Symbol,IntElem> &def_candidates,
00092           const Map<Symbol,IntElem> &use_candidates)
00093 {
00094     if (stmt.stmt_class() == ASSIGNMENT_STMT
00095     && stmt.lhs().op() == ID_OP
00096     && def_candidates.member(stmt.lhs().symbol())
00097     && stmt.rhs().is_side_effect_free()
00098     && (int) _refs_are_candidates(stmt.in_refs(), use_candidates)
00099     && (int) _refs_are_candidates(stmt.out_refs(), use_candidates)
00100     && (int) _refs_are_candidates(stmt.act_refs(), use_candidates)
00101     && ! (stmt.lhs().type().data_type() == INTEGER_TYPE
00102           && stmt.rhs().type().data_type() != INTEGER_TYPE))
00103 
00104     return True;
00105 
00106     return False;
00107 }
00108 
00109 
00110 /// init_const_map
00111 ///   Initialize the constant mapping.
00112 
00113 void
00114 PropConstWS::_init_const_map(const Statement &stmt)
00115 {
00116     int sym_tag;
00117 
00118     for (sym_tag = mod_set.first();
00119      sym_tag != -1;
00120      sym_tag = mod_set.next(sym_tag)) {
00121     if (sym_tag != _lhs_tag) {
00122         out_const_map[sym_tag].non_const(stmt);
00123         out_const_map.int_non_const(sym_tag);
00124     }
00125     }
00126 }
00127 
00128 void
00129 PropConstWS::_init_const_map(const Statement &call_site,
00130                  const IPCPProcData &call_proc_data,
00131                  const IPCPProcData &proc_data,
00132                  Boolean use_old_const_mods)
00133 {
00134     Map<Symbol, Expression> *var_modifications;
00135 
00136     if (use_old_const_mods)
00137     var_modifications = proc_data.local_old_const_mods(call_site,
00138                                call_proc_data.return_jump_function());
00139     else
00140     var_modifications = proc_data.local_new_consts(call_site,
00141                                call_proc_data.return_jump_function());
00142 
00143     /// ...  Update the constant map to take the variable modifications into account.
00144 
00145     add_consts(*var_modifications);
00146 
00147     /// ...  Update the constant map to handle a function return.
00148 
00149     if (call_site.stmt_class() == ASSIGNMENT_STMT) {
00150     const Symbol &lhs_var = *call_site.lhs().base_variable_ref();
00151     const Expression *lhs_expr = var_modifications->find_ref(*call_proc_data.return_var());
00152     p_assert(lhs_expr || ! use_old_const_mods,
00153          "Internal Error: Function return value is marked as unmodified.");
00154 
00155     if (lhs_expr)
00156         _add_const(lhs_var, *lhs_expr);
00157     }
00158 
00159     delete var_modifications;
00160 }
00161         
00162 
00163 /// Constructors
00164 ///   Build a new PropConstWS object.
00165 
00166 PropConstWS::PropConstWS(unsigned long pass_tag, const Statement &stmt,
00167              const Map<Symbol,IntElem> &def_candidates,
00168              const Map<Symbol,IntElem> &use_candidates,
00169              const Array<Symbol *> &tag_to_candidate)
00170 : WorkSpace(pass_tag),
00171   mod_set(use_candidates.entries()), poisoned_vars(use_candidates.entries()),
00172   in_const_map(use_candidates.entries(), tag_to_candidate),
00173   out_const_map(use_candidates.entries(), tag_to_candidate)
00174 {
00175     _stmt = &stmt;
00176     _refs_to_set(mod_set, stmt.out_refs(), use_candidates);
00177     _is_substitutable = _ok_to_substitute(stmt, def_candidates,
00178                       use_candidates);
00179     _def_candidates = &def_candidates;
00180     _use_candidates = &use_candidates;
00181 
00182     if (_is_substitutable) {
00183     _add_const(*stmt.lhs().base_variable_ref(), stmt.rhs());
00184     _lhs_tag = def_candidates[*stmt.lhs().base_variable_ref()].value();
00185     }
00186     else {
00187     _lhs_tag = -1;
00188     }
00189 
00190     _init_const_map(stmt);
00191     pred = stmt.pred();
00192     succ = stmt.succ();
00193     const_cond = True;
00194     unknown_call = (stmt.stmt_class() == CALL_STMT
00195             || contains_func_call(stmt));
00196     _num_visits = 0;
00197     _visited = False;
00198     _toporder = -1;
00199 }
00200 
00201 PropConstWS::PropConstWS(unsigned long pass_tag, const Statement &stmt,
00202              const Statement &call_site,
00203              const IPCPProcData &call_proc_data,
00204              const IPCPProcData &proc_data,
00205              Boolean use_old_const_mods,
00206              const Map<Symbol,IntElem> &def_candidates,
00207              const Map<Symbol,IntElem> &use_candidates,
00208              const Array<Symbol *> &tag_to_candidate)
00209 : WorkSpace(pass_tag),
00210   mod_set(use_candidates.entries()), poisoned_vars(use_candidates.entries()),
00211   in_const_map(use_candidates.entries(), tag_to_candidate),
00212   out_const_map(use_candidates.entries(), tag_to_candidate)
00213 {
00214     _stmt = &stmt;
00215     _is_substitutable = False;
00216     _lhs_tag = -1;
00217     _def_candidates = &def_candidates;
00218     _use_candidates = &use_candidates;
00219     _init_const_map(call_site, call_proc_data, proc_data, use_old_const_mods);
00220     pred = stmt.pred();
00221     succ = stmt.succ();
00222     const_cond = True;
00223     unknown_call = (stmt.stmt_class() != CALL_STMT
00224             && stmt.stmt_class() != ASSIGNMENT_STMT
00225             && contains_func_call(stmt));
00226     _num_visits = 0;
00227     _visited = False;
00228     _toporder = -1;
00229 }
00230 
00231 PropConstWS::PropConstWS(const PropConstWS &other)
00232 : WorkSpace(other), mod_set(other.mod_set), poisoned_vars(other.poisoned_vars),
00233   in_const_map(other.in_const_map), out_const_map(other.out_const_map)
00234 {
00235     _stmt = other._stmt;
00236     _const_values = other._const_values;
00237     _is_substitutable = other._is_substitutable;
00238     _lhs_tag = other._lhs_tag;
00239     pred = other.pred;
00240     succ = other.succ;
00241     const_cond = other.const_cond;
00242     unknown_call = other.unknown_call;
00243     _num_visits = other._num_visits;
00244     _visited = other._visited;
00245     _toporder = other._toporder;
00246 }
00247 
00248 PropConstWS::~PropConstWS()
00249 {
00250     /// ...  Nothing to do
00251 }
00252 
00253 void
00254 PropConstWS::toporder(int val)
00255 {
00256     _toporder = val;
00257 
00258     Iterator<PropConstValue> iter = _const_values;
00259 
00260     for ( ; iter.valid(); ++iter)
00261     iter.current().stmt_toporder(val);
00262 }
00263 
00264 Boolean
00265 PropConstWS::update_out_const_map()
00266 {
00267     Boolean changed = False;
00268 
00269     for (int sym_tag = 0; sym_tag < in_const_map.entries(); ++sym_tag)
00270     if (! mod_set[sym_tag]) {
00271         if (out_const_map[sym_tag] != in_const_map[sym_tag]) {
00272         out_const_map[sym_tag] = in_const_map[sym_tag];
00273         changed = True;
00274         }
00275 
00276         if (out_const_map.int_state(sym_tag) != in_const_map.int_state(sym_tag)
00277         || (out_const_map.int_state(sym_tag) == CONST
00278              && (out_const_map.int_const_val(sym_tag)
00279              != in_const_map.int_const_val(sym_tag)))) {
00280 
00281         switch (in_const_map.int_state(sym_tag)) {
00282         case CONST:
00283             out_const_map.int_const(sym_tag,
00284                         in_const_map.int_const_val(sym_tag));
00285             break;
00286 
00287         case NON_CONST:
00288         case MAY_BE_CONST:
00289             out_const_map.int_non_const(sym_tag);
00290             break;
00291 
00292         default:
00293             p_abort("Internal error: PropConstWS::update_out_const_map().");
00294             break;
00295         }
00296 
00297         changed = True;
00298         }       
00299     }
00300 
00301     if (_update_int_consts())
00302     changed = True;
00303 
00304     return changed;
00305 }
00306 
00307 
00308 /// add_const
00309 
00310 void
00311 PropConstWS::_add_const(const Symbol &const_var,
00312             const Expression &const_expr)
00313 {
00314     const IntElem *elem = _use_candidates->find_ref(const_var);
00315 
00316     if (elem) {
00317     int sym_tag = elem->value();
00318     mod_set.ins(sym_tag);
00319     
00320     if (const_expr.op() == OMEGA_OP
00321         || ! _def_candidates->member(const_var)) {
00322 
00323         out_const_map[sym_tag].non_const(stmt());
00324         out_const_map.int_non_const(sym_tag);
00325     }
00326     else {
00327         PropConstValue *const_val = new PropConstValue(const_expr, stmt(),
00328                                -1,
00329                                *_use_candidates);
00330         _const_values.ins_last(const_val);
00331         out_const_map[sym_tag].constant(*const_val);
00332 
00333         if (const_val->expr().op() == INTEGER_CONSTANT_OP)
00334         out_const_map.int_const(sym_tag, const_val->expr().value());
00335         else if (const_val->expr().op() == LOGICAL_CONSTANT_OP)
00336         if (strcmp(const_val->expr().data_ref(), ".TRUE.") == 0)
00337             out_const_map.int_const(sym_tag, 1);
00338         else if (strcmp(const_val->expr().data_ref(), ".FALSE.") == 0)
00339             out_const_map.int_const(sym_tag, 0);
00340         else
00341             out_const_map.int_non_const(sym_tag);
00342         else
00343         out_const_map.int_non_const(sym_tag);
00344     }
00345     }
00346 }
00347 
00348 
00349 /// add_consts
00350 
00351 void
00352 PropConstWS::add_consts(const Map<Symbol, Expression> &constants)
00353 {
00354     KeyIterator<Symbol, Expression> const_iter = constants;
00355 
00356     for ( ; const_iter.valid(); ++const_iter)
00357     _add_const(const_iter.current_key(), const_iter.current_data());
00358 }
00359 
00360 
00361 /// subst_ints_in_expr
00362 ///   Substitute all variables in the given expression with their integer
00363 ///   values.  If this could not be done, return NULL.
00364 
00365 static Expression *
00366 _subst_ints_in_expr(Expression *expr,
00367             const PropConstMap &entering_consts,
00368             const Map<Symbol,IntElem> &candidates)
00369 {
00370     if (! expr)
00371     return expr;
00372     else if (expr->op() == ID_OP
00373          && expr->symbol().sym_class() == VARIABLE_CLASS) {
00374     const Symbol &var = expr->symbol();
00375     delete expr;
00376     const IntElem *elem = candidates.find_ref(var);
00377 
00378     if (elem) {
00379         int sym_tag = elem->value();
00380 
00381         if (entering_consts.int_state(sym_tag) == CONST)
00382         if (var.type().data_type() == LOGICAL_TYPE)
00383             if (entering_consts.int_const_val(sym_tag) == 0)
00384             return constant(".FALSE.");
00385             else
00386             return constant(".TRUE.");
00387         else
00388             return constant(entering_consts.int_const_val(sym_tag));
00389     }
00390 
00391     return 0;
00392     }
00393     else {
00394     Mutator<Expression> iter = expr->arg_list();
00395 
00396     for ( ; iter.valid(); ++iter) {
00397         Assign<Expression> eas(iter.assign());
00398         Expression *new_arg = _subst_ints_in_expr(iter.pull(),
00399                               entering_consts,
00400                               candidates);
00401 
00402         if (new_arg)
00403         eas = new_arg;
00404         else {
00405         delete expr;
00406         return  0;
00407         }
00408     }
00409     }
00410 
00411     return expr;
00412 }
00413 
00414 
00415 /// int_constval;
00416 
00417 Boolean
00418 int_const_val(const Expression &expr, const PropConstMap &entering_consts,
00419           const Map<Symbol, IntElem> &candidates,
00420           int &int_const)
00421 {
00422     int_const = -9999;
00423     Boolean success = False;
00424     Expression *int_expr = _subst_ints_in_expr(expr.clone(), entering_consts,
00425                            candidates);
00426 
00427     if (int_expr) {
00428     int_expr = simplify(int_expr);
00429 
00430     if (int_expr->op() == INTEGER_CONSTANT_OP) {
00431         int_const = int_expr->value();
00432         success = True;
00433     }
00434     else if (int_expr->op() == LOGICAL_CONSTANT_OP) {
00435         success = True;
00436 
00437         if (strcmp(int_expr->data_ref(), ".TRUE.") == 0)
00438         int_const = 1;
00439         else if (strcmp(int_expr->data_ref(), ".FALSE.") == 0)
00440         int_const = 0;
00441         else
00442         success = False;
00443     }
00444 
00445     delete int_expr;
00446     }
00447 
00448     return success;
00449 }
00450 
00451 
00452 /// update_int_consts
00453 
00454 Boolean
00455 PropConstWS::_update_int_consts()
00456 {
00457     Boolean changed = False;
00458 
00459     for (int sym_tag = mod_set.first();
00460      sym_tag != -1;
00461      sym_tag = mod_set.next(sym_tag)) {
00462     PropConstElem &elem = out_const_map[sym_tag];
00463 
00464     if (elem.state() == CONST
00465         && _const_values.member((PropConstValue &) elem.const_val())) {
00466 
00467         int constant;
00468 
00469         if (int_const_val(elem.expr(), in_const_map, *_use_candidates,
00470                   constant)) {
00471         if (out_const_map.int_state(sym_tag) != CONST
00472             || out_const_map.int_const_val(sym_tag) != constant)
00473 
00474             changed = True;
00475 
00476         out_const_map.int_const(sym_tag, constant);
00477         }
00478         else {
00479         if (out_const_map.int_state(sym_tag) != NON_CONST)
00480             changed = True;
00481 
00482         out_const_map.int_non_const(sym_tag);
00483         }
00484 
00485     }
00486     }
00487 
00488     return changed;
00489 }
00490 
00491 
00492 /// pretty_print_set
00493 ///   Print out a IntSet using symbol names rather than their integer tags.
00494 
00495 static void
00496 _pretty_print_set(ostream &o, const IntSet &set,
00497           const Array<Symbol *> &tag_to_candidate)
00498 {
00499     int sym_tag = set.first();
00500 
00501     if (sym_tag != -1) {
00502     o << tag_to_candidate[sym_tag]->name_ref();
00503 
00504     while ((sym_tag = set.next(sym_tag)) != -1)
00505         o << ", " << tag_to_candidate[sym_tag]->name_ref();
00506     }
00507 }
00508 
00509 
00510 /// pretty_print
00511 ///   Print out all of my fields in a nice, readable format
00512 
00513 void
00514 PropConstWS::pretty_print(ostream &o) const
00515 {
00516     o << "  stmt = " << _stmt->tag();
00517     o << ",  is_substitutable = " << _is_substitutable;
00518     o << ",  lhs_tag = " << _lhs_tag << endl;
00519     o << "  num_visits = " << _num_visits;
00520     o << ",  toporder = " << _toporder;
00521     o << ",  const_cond = " << const_cond << endl;
00522 
00523     o << "  pred = {";
00524     print_stmt_tags(o, (RefSet<Statement> &) pred);
00525     o << "},   succ = {";
00526     print_stmt_tags(o, (RefSet<Statement> &) succ);
00527     o << "}\n";
00528 
00529     o << "  mod = {";
00530     _pretty_print_set(o, mod_set, in_const_map.tag_to_candidate());
00531     o << "}\n";
00532 
00533     o << "  in_const_map = ";
00534     in_const_map.pretty_print(o);
00535     o << endl;
00536 
00537     o << "  out_const_map = ";
00538     out_const_map.pretty_print(o);
00539     o << endl;
00540 
00541     o << "  const_values = {" << _const_values << "}\n";
00542 }
00543 
00544 
00545 /// print
00546 ///   Print out all of my fields in a rather terse and unreadable format
00547 
00548 void
00549 PropConstWS::print(ostream &o) const
00550 {
00551     o << "PropConstWS:{";
00552     o << "mod=" << mod_set << ", ";
00553     o << "is_subst=" << _is_substitutable << ", ";
00554     o << "lhs_tag=" << _lhs_tag << ", ";
00555     o << "num_visits=" << _num_visits << ", ";
00556     o << "const_cond=" << const_cond << ", ";
00557     o << "unknown_call=" << unknown_call << ", ";
00558     o << "toporder=" << _toporder << ", ";
00559     o << "pred = ";
00560     print_stmt_tags(o, (RefSet<Statement> &) pred);
00561     o << ", ";
00562     o << "succ = ";
00563     print_stmt_tags(o, (RefSet<Statement> &) succ);
00564     o << ", ";
00565     o << "in_const_map={" << in_const_map << "}" << ", ";
00566     o << "out_const_map={" << out_const_map << "}" << ", ";
00567     o << "const_values={" << _const_values << "}";
00568     o << "}";
00569 }
00570 
00571 
00572 /// listable_clone
00573 ///   Return a copy of myself.
00574 
00575 Listable *
00576 PropConstWS::listable_clone() const
00577 {
00578     return new PropConstWS(*this);
00579 }
00580 
00581 
00582 /// structures_OK
00583 ///   Return true if all of my structures are OK.
00584 
00585 int
00586 PropConstWS::structures_OK() const
00587 {
00588     return (mod_set.structures_OK()
00589         && poisoned_vars.structures_OK()
00590         && in_const_map.structures_OK()
00591         && out_const_map.structures_OK());
00592 }
00593 
 © 1995-2005 University of Illinois, Urbana-Champaign. All rights reserved.  Fri Mar 25 23:06:02 2005