00001
00002
00003
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
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
00024
00025
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
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
00063
00064
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
00084
00085
00086
00087
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
00111
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
00144
00145 add_consts(*var_modifications);
00146
00147
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
00164
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
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
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
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
00362
00363
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
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
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
00493
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
00511
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
00546
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
00573
00574
00575 Listable *
00576 PropConstWS::listable_clone() const
00577 {
00578 return new PropConstWS(*this);
00579 }
00580
00581
00582
00583
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