Polaris: JumpFunction.cc Source File

JumpFunction.cc

Go to the documentation of this file.
00001 ///
00002 ///
00003 /// \file JumpFunction.cc
00004 ///
00005 #include "../Collection/KeyIterator.h"
00006 #include "../Collection/Iterator.h"
00007 #include "../Collection/Mutator.h"
00008 #include "../Collection/RefSet.h"
00009 #include "../Collection/RefList.h"
00010 #include "../Collection/Map.h"
00011 #include "../Collection/RefMap.h"
00012 #include "../Symbol/Symbol.h"
00013 #include "../Expression/Expression.h"
00014 
00015 #include "JumpFunction.h"
00016 #include "AliasSets.h"
00017 #include "IPCPConstants.h"
00018 
00019 
00020 /// simplify_var_mods
00021 ///   Simplify the given mapping of variable modifications.
00022 
00023 static void
00024 _simplify_var_mods(Map<Symbol, Expression> &var_mods)
00025 {
00026     RefSet<Symbol> *mod_vars = modified_vars(var_mods);
00027     Iterator<Symbol> mod_var_iter = *mod_vars;
00028     
00029     for ( ; mod_var_iter.valid(); ++mod_var_iter) {
00030     Symbol &var = mod_var_iter.current();
00031     Expression *simplified_mod = var_mods.grab(var);
00032     Boolean mod_is_ref = (simplified_mod->base_variable_ref() != 0);
00033     simplified_mod = simplify(simplified_mod);
00034 
00035     if (simplified_mod->op() == ID_OP
00036         && &simplified_mod->symbol() == &var)
00037 
00038         delete simplified_mod;
00039     else {
00040         if (simplified_mod->base_variable_ref() && ! mod_is_ref)
00041         simplified_mod = paren(simplified_mod);
00042 
00043         var_mods.ins(var, simplified_mod);
00044     }
00045     }
00046     
00047     delete mod_vars;
00048 }
00049 
00050 
00051 ///  Constructors
00052 
00053 ReturnJumpFunction::ReturnJumpFunction(const RefList<Symbol> &param_list,
00054                        const RefSet<Symbol> &used_global_vars,
00055                        Map<Symbol, Expression> *old_const_mods,
00056                        Map<Symbol, Expression> *new_consts)
00057 {
00058     _param_list = param_list;
00059     _used_global_vars = used_global_vars;
00060     _simplify_var_mods(*new_consts);
00061     _simplify_var_mods(*old_const_mods);
00062     _old_const_mods = old_const_mods;
00063     _new_consts = new_consts;
00064 }
00065 
00066 ReturnJumpFunction::ReturnJumpFunction(const ReturnJumpFunction &other)
00067 {
00068     _param_list = other._param_list;
00069     _used_global_vars = other._used_global_vars;
00070     _old_const_mods = new Map<Symbol,Expression>(*other._old_const_mods);
00071     _new_consts = new Map<Symbol,Expression>(*other._new_consts);
00072 }
00073 
00074 
00075 ///  Destructor
00076 
00077 ReturnJumpFunction::~ReturnJumpFunction()
00078 {
00079     delete _old_const_mods;
00080     delete _new_consts;
00081 }
00082 
00083 
00084 ///  _are_vars_in_expr
00085 ///    Return true if the given expression uses any of the variables in the
00086 ///    given set.
00087 
00088 static Boolean
00089 _are_vars_in_expr(const Expression &e, const RefSet<Symbol> &vars)
00090 {
00091     if (e.op() == ID_OP)
00092         return vars.member(e.symbol());
00093     else {
00094         Iterator<Expression> iter = e.arg_list();
00095 
00096         for ( ; iter.valid(); ++iter)
00097             if (_are_vars_in_expr(iter.current(), vars))
00098                 return True;
00099     }
00100 
00101     return False;
00102 }
00103 
00104 
00105 ///  subst_vars_in_expr
00106 ///    Substitute all variables in the given expression and in the
00107 ///    substitution mapping with their mapped values.
00108 
00109 static Expression *
00110 _subst_vars_in_expr1(Expression *expr, RefSet<Symbol> &subst_vars,
00111              const Map<Symbol, Expression> &subst_map)
00112 {
00113     p_assert(expr, "_subst_vars_in_expr was given a NULL expression.");
00114 
00115     if (expr->op() == ID_OP) {
00116     Symbol &var = expr->symbol();
00117     const Expression *subst_expr = subst_map.find_ref(var);
00118 
00119     if (subst_expr) {
00120         delete expr;
00121 
00122         if (! subst_vars.member(var)) {
00123         subst_vars.ins(var);
00124         expr = _subst_vars_in_expr1(subst_expr->clone(), subst_vars,
00125                         subst_map);
00126         subst_vars.del(var);
00127         }
00128         else
00129         expr = omega();
00130     }
00131     }
00132     else {
00133     Mutator<Expression> arg_iter = expr->arg_list();
00134 
00135     for ( ; arg_iter.valid(); ++arg_iter) {
00136         Assign<Expression> eas(arg_iter.assign());
00137         eas = _subst_vars_in_expr1(arg_iter.pull(),
00138                        subst_vars, subst_map);
00139         
00140         if (arg_iter.current().op() == OMEGA_OP) {
00141         Expression *om = arg_iter.grab();
00142         delete expr;
00143         return om;
00144         }
00145     }
00146     }
00147 
00148     return expr;
00149 }
00150 
00151 Expression *
00152 subst_vars_in_expr(Expression *expr,
00153            const Map<Symbol, Expression> &subst_map)
00154 {
00155     RefSet<Symbol> subst_vars;
00156     return _subst_vars_in_expr1(expr, subst_vars, subst_map);
00157 }
00158 
00159 
00160 /// subst_vars_in_map
00161 ///   Substitute the given variables in the expressions of the given map.
00162 
00163 void
00164 subst_vars_in_map(Map<Symbol, Expression> &var_mods,
00165           const Map<Symbol, Expression> &subst_map)
00166 {
00167     if (subst_map.entries() > 0) {
00168     RefSet<Symbol> *mod_vars = modified_vars(var_mods);
00169     Iterator<Symbol> mod_var_iter = *mod_vars;
00170     
00171     for ( ; mod_var_iter.valid(); ++mod_var_iter) {
00172         Symbol &var = mod_var_iter.current();
00173         var_mods.ins(var, subst_vars_in_expr(var_mods.grab(var), subst_map));
00174     }
00175     
00176     delete mod_vars;
00177     }
00178 }
00179 
00180 
00181 ///  modified_aliases
00182 ///    Return the set of aliased variables whose alias is modified.
00183 
00184 RefSet<Symbol> *
00185 ReturnJumpFunction::_modified_aliases(AliasSets &alias_sets) const
00186 {
00187     RefSet<Symbol> *modified_aliases = new RefSet<Symbol>;
00188     KeyIterator<Symbol, Expression> var_mod_iter = *_old_const_mods;
00189 
00190     for ( ; var_mod_iter.valid(); ++var_mod_iter) {
00191     RefSet<Symbol> *aliased_vars
00192         = alias_sets.aliases(var_mod_iter.current_key(),
00193                  _used_global_vars);
00194 
00195     Iterator<Symbol> alias_iter = *aliased_vars;
00196 
00197     for ( ; alias_iter.valid(); ++alias_iter)
00198         modified_aliases->ins(alias_iter.current());
00199 
00200     delete aliased_vars;
00201     }
00202     
00203     return modified_aliases;
00204 }
00205 
00206 
00207 ///  modified_vars
00208 
00209 RefSet<Symbol> *
00210 modified_vars(const Map<Symbol, Expression> &var_mods)
00211 {
00212     RefSet<Symbol> *modified_vars = new RefSet<Symbol>;
00213     KeyIterator<Symbol, Expression> var_mod_iter = var_mods;
00214 
00215     for ( ; var_mod_iter.valid(); ++var_mod_iter)
00216     modified_vars->ins(var_mod_iter.current_key());
00217 
00218     return modified_vars;
00219 }
00220 
00221 
00222 /// eliminate_modified_aliases
00223 ///   Make all variables that are aliased to a modified variables or
00224 ///   whose constant map contains a modified alias variable to be non-constant.
00225 
00226 void
00227 ReturnJumpFunction::_eliminate_modified_aliases(Map<Symbol, Expression> &var_mods,
00228                         AliasSets &alias_sets) const
00229 {
00230     RefSet<Symbol> *modified_aliases = _modified_aliases(alias_sets);
00231 
00232     if (modified_aliases->entries()) {
00233     /// ...  Make all aliased variables whose aliases are modified to be
00234     /// ...  non-constant in the modification map.
00235     
00236     Iterator<Symbol> alias_iter = *modified_aliases;
00237     
00238     for ( ; alias_iter.valid(); ++alias_iter)
00239         var_mods.ins(alias_iter.current(), omega());
00240     
00241     /// ...  Make all variables whose constant expressions contain aliased
00242     /// ...  variables whose aliases are modified to be non-constant in the
00243     /// ...  given modification map.
00244     
00245     RefSet<Symbol> *mod_vars = modified_vars(var_mods);
00246     Iterator<Symbol> mod_var_iter = *mod_vars;
00247     
00248     for ( ; mod_var_iter.valid(); ++mod_var_iter) {
00249         const Symbol &var = mod_var_iter.current();
00250         
00251         if (_are_vars_in_expr(var_mods[var], *modified_aliases))
00252         
00253         var_mods.ins(var, omega());
00254     }
00255     
00256     delete mod_vars;
00257     }
00258 
00259     delete modified_aliases;
00260 }
00261 
00262 
00263 /// rename_formals
00264 ///   Rename formal parameters to their aliased actual names.
00265 
00266 void
00267 ReturnJumpFunction::_rename_formals(Map<Symbol, Expression> &var_mods,
00268                     const List<Expression> &param_values) const
00269 {
00270     p_assert(_param_list.entries() == param_values.entries(),
00271          "ReturnJumpFunction::new_values():  The number of formals does not equal the number of actuals.");
00272     Iterator<Symbol> formal_iter = _param_list;
00273     Iterator<Expression> actual_iter = param_values;
00274 
00275     for ( ; formal_iter.valid(); ++formal_iter, ++actual_iter) {
00276     Symbol &formal = formal_iter.current();
00277     Expression &actual_expr = actual_iter.current();
00278 
00279     if (var_mods.member(formal)) {
00280         const Symbol *actual = actual_expr.base_variable_ref();
00281 
00282         if (actual) {
00283         if (actual_expr.op() == ID_OP
00284             && formal.type() == actual->type())
00285 
00286             var_mods.ins(*actual, var_mods.grab(formal));
00287         else {
00288             var_mods.del(formal);
00289             var_mods.ins(*actual, omega());
00290         }
00291         }
00292         else
00293         var_mods.del(formal);
00294     }
00295     }
00296 }
00297 
00298 
00299 /// param_map
00300 ///   Build a mapping from formal parameters to actual expressions.
00301 
00302 Map<Symbol, Expression> *
00303 ReturnJumpFunction::_param_map(const List<Expression> &param_values) const
00304 {
00305     p_assert(_param_list.entries() == param_values.entries(),
00306          "ReturnJumpFunction::_param_map():  The number of formals does not equal the number of actuals.");
00307     Map<Symbol, Expression> *param_map = new Map<Symbol, Expression>;
00308     Iterator<Symbol> formal_iter = _param_list;
00309     Iterator<Expression> actual_iter = param_values;
00310 
00311     for ( ; formal_iter.valid(); ++formal_iter, ++actual_iter) {
00312     const Symbol &formal = formal_iter.current();
00313     Expression &actual_expr = actual_iter.current();
00314 
00315     if (formal.type() == actual_expr.type())
00316         param_map->ins(formal, actual_expr.clone());
00317     else
00318         param_map->ins(formal, omega());
00319     }
00320 
00321     return param_map;
00322 }
00323 
00324 
00325 ///  const_mods
00326 
00327 Map<Symbol, Expression> *
00328 ReturnJumpFunction::const_mods(const List<Expression> &param_values,
00329                    AliasSets &alias_sets) const
00330 {
00331     Map<Symbol, Expression> *new_const_mods
00332     = new Map<Symbol, Expression>(*_old_const_mods);
00333     _eliminate_modified_aliases(*new_const_mods, alias_sets);
00334     _rename_formals(*new_const_mods, param_values);
00335 
00336     Map<Symbol, Expression> *param_map = _param_map(param_values);
00337     subst_vars_in_map(*new_const_mods, *param_map);
00338     delete param_map;
00339 
00340     return new_const_mods;
00341 }
00342 
00343 Map<Symbol, Expression> *
00344 ReturnJumpFunction::const_mods(const List<Expression> &param_values) const
00345 {
00346     AliasSets alias_sets;
00347     alias_sets.alias(_param_list, param_values);
00348     Map<Symbol, Expression> *new_const_mods = const_mods(param_values,
00349                              alias_sets);
00350     _simplify_var_mods(*new_const_mods);
00351     return new_const_mods;
00352 }
00353 
00354 
00355 ///  filter_out_mod_params
00356 ///   Replace all modified parameters with omega, with the exception to
00357 ///   parameters whose actual is a scalar or array reference.
00358 ///   This exception is allowed because aliasing of formal to actual
00359 ///   would guarantee that the substitution of actual for formal would
00360 ///   still be correct.
00361 
00362 static void
00363 _filter_out_mod_params(Map<Symbol,Expression> &param_map,
00364                const Map<Symbol,Expression> &var_mods)
00365 {
00366     RefSet<Symbol> *mod_vars = modified_vars(param_map);
00367     Iterator<Symbol> mod_var_iter = *mod_vars;
00368     
00369     for ( ; mod_var_iter.valid(); ++mod_var_iter) {
00370     const Symbol &var = mod_var_iter.current();
00371 
00372     if (var_mods.member(var) && ! param_map[var].base_variable_ref())
00373         param_map.ins(var, omega());
00374     }
00375 
00376     delete mod_vars;
00377 }    
00378     
00379 
00380 ///  delete_non_consts
00381 ///   Delete all non-constant variables from the given mapping.
00382 
00383 static void
00384 _delete_non_consts(Map<Symbol, Expression> &var_mods)
00385 {
00386     RefSet<Symbol> *mod_vars = modified_vars(var_mods);
00387     Iterator<Symbol> mod_var_iter = *mod_vars;
00388     
00389     for ( ; mod_var_iter.valid(); ++mod_var_iter) {
00390     Symbol &var = mod_var_iter.current();
00391 
00392     if (var_mods[var].op() == OMEGA_OP)
00393         var_mods.del(var);
00394     }
00395 
00396     delete mod_vars;
00397 }    
00398 
00399 
00400 ///  new_consts
00401 
00402 Map<Symbol, Expression> *
00403 ReturnJumpFunction::new_consts(const List<Expression> &param_values,
00404                    AliasSets &alias_sets) const
00405 {
00406     Map<Symbol, Expression> *new_consts = new Map<Symbol, Expression>(*_new_consts);
00407     _eliminate_modified_aliases(*new_consts, alias_sets);
00408     _rename_formals(*new_consts, param_values);
00409 
00410     Map<Symbol, Expression> *param_map = _param_map(param_values);
00411     _filter_out_mod_params(*param_map, *new_consts);
00412     subst_vars_in_map(*new_consts, *param_map);
00413     delete param_map;
00414     _delete_non_consts(*new_consts);
00415 
00416     return new_consts;
00417 }
00418 
00419 Map<Symbol, Expression> *
00420 ReturnJumpFunction::new_consts(const List<Expression> &param_values) const
00421 {
00422     AliasSets alias_sets;
00423     alias_sets.alias(_param_list, param_values);
00424     Map<Symbol, Expression> *consts = new_consts(param_values, alias_sets);
00425     _simplify_var_mods(*consts);
00426 
00427     return consts;
00428 }
00429 
00430 ///  listable_clone
00431 
00432 Listable *
00433 ReturnJumpFunction::listable_clone() const
00434 {
00435     return new ReturnJumpFunction(*this);
00436 }
00437 
00438 
00439 ///  print
00440 
00441 void
00442 _print(ostream &o, const Map<Symbol, Expression> &var_mods)
00443 {
00444     KeyIterator<Symbol,Expression> mod_iter = var_mods;
00445 
00446     if (mod_iter.valid()) {
00447     o << mod_iter.current_key().name_ref() << "="
00448         << mod_iter.current_data();
00449     ++mod_iter;
00450     
00451     for ( ; mod_iter.valid(); ++mod_iter)
00452         o << ", " << mod_iter.current_key().name_ref() << "="
00453         << mod_iter.current_data();
00454     }
00455 }
00456 
00457 void
00458 ReturnJumpFunction::print(ostream &o) const
00459 {
00460     o << "[";
00461     o << "param_list=(";
00462 
00463     Iterator<Symbol> param_iter = _param_list;
00464 
00465     if (param_iter.valid()) {
00466     o << param_iter.current().name_ref();
00467     ++param_iter;
00468     
00469     for ( ; param_iter.valid(); ++param_iter)
00470         o << ", " << param_iter.current().name_ref();
00471     }
00472 
00473     o << ")";
00474     o << ", old_const_mods={";
00475     _print(o, *_old_const_mods);
00476     o << "}";
00477     o << ", new_consts={";
00478     _print(o, *_new_consts);
00479     o << "}";
00480     o << "]";
00481 }
00482 
00483 
00484 ///  structures_OK
00485 
00486 int
00487 ReturnJumpFunction::structures_OK() const
00488 {
00489     return (_param_list.structures_OK()
00490         && _old_const_mods && _old_const_mods->structures_OK()
00491         && _new_consts && _new_consts->structures_OK());
00492 }
00493 
00494 
00495 ///  Constructors
00496 
00497 JumpFunction::JumpFunction(const RefList<Symbol> &param_list,
00498                const RefSet<Symbol> &used_global_vars,
00499                Map<Symbol, Expression> *old_const_mods,
00500                            Map<Symbol, Expression> *new_consts)
00501 : ReturnJumpFunction(param_list, used_global_vars, old_const_mods, new_consts)
00502 {
00503     /// ...  Nothing to do
00504 }
00505 
00506 JumpFunction::JumpFunction(const JumpFunction &other)
00507 : ReturnJumpFunction(other)
00508  {
00509     /// ...  Nothing to do
00510 }
00511 
00512 
00513 ///  Destructor
00514 
00515 JumpFunction::~JumpFunction()
00516 {
00517     /// ...  Nothing to do
00518 }
00519 
00520 
00521 ///  const_param_values
00522 ///   Generate a constant formal list from the given map of globals to
00523 ///   constant expressions.
00524 
00525 List<Expression> *
00526 JumpFunction::_const_param_values(const Map<Symbol,Expression> &const_map) const
00527 {
00528     List<Expression> *actuals = new List<Expression>;
00529     Iterator<Symbol> formal_iter = _param_list;
00530 
00531     for ( ; formal_iter.valid(); ++formal_iter) {
00532     const Symbol &formal = formal_iter.current();
00533     const Expression *actual_expr = const_map.find_ref(formal);
00534 
00535     if (actual_expr && actual_expr->type() == formal.type())
00536         actuals->ins_last(actual_expr->clone());
00537     else
00538         actuals->ins_last(omega());
00539     }
00540 
00541     return actuals;
00542 }
00543 
00544 
00545 ///  add_map_to_map
00546 ///   Add all the values in the second map to the first map
00547 
00548 static void
00549 _add_map_to_map(Map<Symbol,Expression> &dest_map,
00550         Map<Symbol,Expression> *source_map)
00551 {
00552     RefSet<Symbol> *mod_vars = modified_vars(*source_map);
00553     Iterator<Symbol> mod_var_iter = *mod_vars;
00554 
00555     for ( ; mod_var_iter.valid(); ++mod_var_iter) {
00556     Symbol &var = mod_var_iter.current();
00557     dest_map.ins(var, source_map->grab(var));
00558     }
00559 
00560     delete mod_vars;
00561     delete source_map;
00562 }
00563 
00564 
00565 ///  update_old_consts
00566 ///   Update the given set of constants to take the side-effects of the
00567 ///   routine into account.
00568 
00569 static void
00570 _update_old_consts(Map<Symbol,Expression> &consts,
00571            Map<Symbol,Expression> *var_mods)
00572 {
00573     /// ...  Build a set of all modified constants.
00574 
00575     Map<Symbol,Expression> modified_consts;
00576     KeyIterator<Symbol,Expression> var_mod_iter = *var_mods;
00577 
00578     for ( ; var_mod_iter.valid(); ++var_mod_iter) {
00579     const Symbol &var = var_mod_iter.current_key();
00580     const Expression *const_expr = consts.find_ref(var);
00581 
00582     if (const_expr)
00583         modified_consts.ins(var, const_expr->clone());
00584     else
00585         modified_consts.ins(var, omega());
00586     }
00587 
00588     /// ...  Add the updated consts to the constant set.
00589 
00590     _add_map_to_map(consts, var_mods);
00591 
00592     /// ...  Eliminate all modified variables from the set of constants.
00593 
00594     subst_vars_in_map(consts, modified_consts);
00595 
00596     /// ...  Filter out the OMs from the constant set.
00597 
00598     _delete_non_consts(consts);
00599 }
00600 
00601 
00602 ///  constants
00603 
00604 IPCPConstants *
00605 JumpFunction::constants(IPCPConstants &consts,
00606             const List<Expression> &param_values) const
00607 {
00608     AliasSets *alias_sets = new AliasSets(consts.alias_sets());
00609     alias_sets->alias(_param_list, param_values);
00610     List<Expression> *const_param_values
00611     = _const_param_values(consts.constants());
00612     Map<Symbol, Expression> *new_const_mods
00613     = const_mods(*const_param_values, *alias_sets);
00614     Map<Symbol, Expression> *updated_consts
00615     = new Map<Symbol,Expression>(consts.constants());
00616     _update_old_consts(*updated_consts, new_const_mods);
00617     Map<Symbol, Expression> *generated_consts
00618     = new_consts(*const_param_values, *alias_sets);
00619     delete const_param_values;
00620     _add_map_to_map(*updated_consts, generated_consts);
00621     _simplify_var_mods(*updated_consts);
00622 
00623     return new IPCPConstants(updated_consts, alias_sets);
00624 }
00625 
00626 
00627 ///  listable_clone
00628 
00629 Listable *
00630 JumpFunction::listable_clone() const
00631 {
00632     return new JumpFunction(*this);
00633 }
00634 
00635 
 © 1995-2005 University of Illinois, Urbana-Champaign. All rights reserved.  Fri Mar 25 23:05:57 2005