Polaris: SSAFullRangeData.cc Source File

SSAFullRangeData.cc

Go to the documentation of this file.
00001 ///
00002 ///
00003 /// \file SSAFullRangeData.cc
00004 ///
00005 #include "utilities/expression_util.h"
00006 
00007 #include "range_util.h"
00008 #include "RangeExpr.h"
00009 #include "SSAFullRangeData.h"
00010 #include "SSAFullRangeDict.h"
00011 
00012 /// Template instantiations
00013 
00014 template class TypedBaseMap<Symbol,SSARangeOrData>;
00015 template class ProtoMap<Symbol,SSARangeOrData>;
00016 template class Map<Symbol,SSARangeOrData>;
00017 template ostream & operator << (ostream &,
00018                                 const Map<Symbol,SSARangeOrData> &);
00019 template class KeyIterator<Symbol,SSARangeOrData>;
00020 
00021 template class TypedCollection<SSAFullRangeData>;
00022 template class RefList<SSAFullRangeData>;
00023 template ostream & operator << (ostream &, const RefList<SSAFullRangeData> &);
00024 template class RefSet<SSAFullRangeData>;
00025 template ostream & operator << (ostream &, const RefSet<SSAFullRangeData> &);
00026 template class Assign<SSAFullRangeData>;
00027 template class Iterator<SSAFullRangeData>;
00028 
00029 template class TypedBaseMap<Symbol,SSAFullRangeData>;
00030 template class ProtoMap<Symbol,SSAFullRangeData>;
00031 template class Map<Symbol,SSAFullRangeData>;
00032 template ostream & operator << (ostream &,
00033                                 const Map<Symbol,SSAFullRangeData> &);
00034 template class KeyIterator<Symbol,SSAFullRangeData>;
00035 
00036 
00037 ///  SSARangeOrData::print
00038 ///    Print out a SSARangeOrData object
00039 ///
00040 
00041 void
00042 SSARangeOrData::print(ostream &o) const
00043 {
00044     o << "[";
00045 
00046     if (_is_range) {
00047     o << "range=";
00048 
00049     if (_range_ref)
00050         o << *_range_ref;
00051     else
00052         o << NULL;
00053     }
00054     else
00055     o << "data=" << _data_ref->stmt().tag();
00056 
00057     o << "]";
00058 }
00059 
00060 
00061 /// is_ssa_function
00062 ///   Return true if the expression is one of the pseudo-functions inserted
00063 ///   by SSA.
00064 
00065 static int
00066 _is_ssa_function( const Expression & ex )
00067 {
00068     switch (ex.op()) {
00069     case ALPHA_OP:
00070     case ETA_OP:
00071     case GAMMA_OP:
00072     case GMU_OP:
00073     case MU_OP:
00074     case PHI_OP:
00075         return 1;
00076     }
00077 
00078     return 0;
00079 }
00080 
00081 
00082 /// Constructors
00083 
00084 SSAFullRangeData::SSAFullRangeData(const Statement &stmt, int timestamp,
00085                    SSAFullRangeDict &range_dict,
00086                    int debug GIV(0))
00087 : _accessor(range_dict, stmt)
00088 {
00089     p_assert(stmt.stmt_class() == ASSIGNMENT_STMT,
00090          "The statement given to the SSAFullRangeData constructor was not an assignment statement.");
00091     _stmt_ref = &stmt;
00092     _timestamp = timestamp;
00093     _control_ranges_ref = &range_dict._control_ranges;
00094     is_phi_stmt = _is_ssa_function(stmt.rhs());
00095 
00096     if (is_phi_stmt)
00097     _range = new RangeExpr(constant(1), constant(0));
00098     else
00099     _range = simplify(stmt.rhs().clone());
00100 
00101     is_poisoned = false;
00102     needs_iteration = false;
00103     needs_widening = false;
00104     are_all_args_defined = false;
00105     union_arg_ranges = false;
00106     toporder = -1;
00107     num_updates = 0;
00108     computed = false;
00109     df_order = -1;
00110     low_link = -1;
00111     _debug_level = debug;
00112 }
00113 
00114 SSAFullRangeData::SSAFullRangeData(const SSAFullRangeData &other)
00115 : _accessor(other._accessor)
00116 {
00117     _stmt_ref = other._stmt_ref;
00118     _timestamp = other._timestamp;
00119     _control_ranges_ref = other._control_ranges_ref;
00120 
00121     if (other._range)
00122     _range = other._range->clone();
00123     else
00124     _range = 0;
00125 
00126     is_phi_stmt = other.is_phi_stmt;
00127     is_poisoned = other.is_poisoned;
00128     needs_iteration = other.needs_iteration;
00129     needs_widening = other.needs_widening;
00130     arg_ranges_or_data = other.arg_ranges_or_data;
00131     arg_preds = other.arg_preds;
00132     are_all_args_defined = other.are_all_args_defined;
00133     toporder = other.toporder;
00134     num_updates = other.num_updates;
00135     computed = other.computed;
00136     df_order = other.df_order;
00137     low_link = other.low_link;
00138     _debug_level = other._debug_level;
00139 }
00140 
00141 
00142 /// Destructor
00143 
00144 SSAFullRangeData::~SSAFullRangeData()
00145 {
00146     if (_range)
00147     delete _range;
00148 }
00149 
00150 
00151 /// modify_expr
00152 ///   Modify the given expression with the new expression value,
00153 ///   deleting the old expression if necessary.
00154 
00155 static inline void
00156 _modify_expr(Expression *& expr, Expression *new_expr)
00157 {
00158     if (expr)
00159     delete expr;
00160 
00161     expr = new_expr;
00162 }
00163 
00164 
00165 /// _arg_full_range
00166 ///   Return the range for the given argument.  This range incorporates
00167 ///   the control flow constraints for that variable as well as its current
00168 ///   data flow range.  This method also guarantees that the variable for
00169 ///   this object does not occur in the returned range
00170 
00171 Expression *
00172 SSAFullRangeData::_arg_full_range(const Symbol &arg)
00173 {
00174     Expression *arg_full_range = 0;
00175     SSARangeOrData *range_or_data = arg_ranges_or_data.find_ref(arg);
00176 
00177     if (range_or_data) {
00178     const Expression *arg_range;
00179 
00180     if (range_or_data->is_range())
00181         arg_range = range_or_data->range_ref();
00182     else
00183         arg_range = range_or_data->data().range_ref();
00184 
00185     if (arg_range)
00186         arg_full_range = arg_range->clone();
00187     }
00188         
00189     /// ...  Intersect the argument's range with constraints for its
00190     /// ...  entering flow edge.
00191     
00192     const Statement *control_stmt = arg_preds.find_ref(arg);
00193     
00194     if (! control_stmt)
00195     control_stmt = &stmt();
00196 
00197     RangeAccessor control_accessor(*_control_ranges_ref, *control_stmt);
00198     const Expression * arg_control_range = control_accessor.get_range_ref(arg);
00199 
00200     if (arg_control_range && arg_control_range->op() != OMEGA_OP)
00201     _modify_expr(arg_full_range,
00202              intersect_ranges(arg_full_range, _accessor,
00203                       arg_control_range, _accessor));
00204     
00205     /// ...  Eliminate any references to my lhs variable from the argument.
00206 
00207     const Symbol &var = stmt().lhs().symbol();
00208 
00209     if (arg_full_range && is_var_in_expr(*arg_full_range, var)) {
00210     
00211     Expression *subst_range;
00212     
00213     if (range_ref())
00214         subst_range = range_ref()->clone();
00215     else
00216         subst_range = 0;
00217 
00218     const Expression *my_control_range = control_accessor.get_range_ref(var);
00219     if (my_control_range && my_control_range->op() != OMEGA_OP)
00220         _modify_expr(subst_range,
00221              intersect_ranges(subst_range, _accessor,
00222                       my_control_range, _accessor));
00223     
00224     arg_full_range = _accessor.subst_var_and_simplify(arg_full_range, var,
00225                               subst_range);
00226 
00227     if (subst_range)
00228         delete subst_range;
00229     }
00230 
00231     return arg_full_range;
00232 }
00233 
00234 
00235 /// union_args
00236 ///   Union the ranges of my arguments togethor and return the result.
00237 ///   The flag union_arg_ranges determines whether the arguments, or
00238 ///   the range of the arguments should be used.
00239 
00240 Expression *
00241 SSAFullRangeData::_union_args(bool &new_all_args_are_defined)
00242 {
00243     Expression *new_range = new RangeExpr(constant(1), constant(0));
00244     new_all_args_are_defined = true;
00245     Iterator<Symbol> iter = args;
00246     
00247     for ( ; iter.valid(); ++iter) {
00248         Symbol &arg = iter.current();
00249         SSARangeOrData &range_or_data = arg_ranges_or_data[arg];
00250     const Expression *arg_range = 0;
00251     
00252     if (range_or_data.is_range())
00253         arg_range = range_or_data.range_ref();
00254     else
00255         arg_range = range_or_data.data().range_ref();
00256     
00257     if (arg_range && is_empty_range(*arg_range))
00258         new_all_args_are_defined = false;
00259     else {
00260         Expression *arg_full_range;
00261 
00262         if (! union_arg_ranges
00263         && ( ! range_or_data.is_data()
00264             || range_or_data.data().toporder <= toporder))
00265 
00266         arg_full_range = id(arg);
00267         else
00268         arg_full_range = _arg_full_range(arg);
00269         
00270         /// ...  Union the argument's range to the lhs's range.
00271         
00272         if (_debug_level >= 30) {
00273         cout << "! unioning ";
00274         
00275         if (new_range)
00276             cout << *new_range;
00277         else
00278             cout << "NULL";
00279         
00280         cout << " with ";
00281         
00282         if (arg_full_range)
00283             cout << *arg_full_range;
00284         else
00285             cout << "NULL";
00286         
00287         cout << endl;
00288         }
00289         
00290         if (arg_full_range && is_empty_range(*arg_full_range))
00291         new_all_args_are_defined = false;
00292         else
00293         _modify_expr(new_range, union_ranges(new_range, _accessor,
00294                              arg_full_range,
00295                              _accessor));
00296         
00297         if (arg_full_range)
00298         delete arg_full_range;
00299     }
00300     }
00301     
00302     return new_range;
00303 }
00304     
00305 
00306 /// update
00307 
00308 bool
00309 SSAFullRangeData::update(bool in_widening_phase GIV(true))
00310 {
00311     bool changed = false;
00312 
00313     /// ...  Update my is_poisoned and needs_iteration fields.
00314 
00315     KeyIterator<Symbol, SSARangeOrData> iter = arg_ranges_or_data;
00316 
00317     for ( ; iter.valid(); ++iter)
00318     if (iter.current_data().is_data()) {
00319         const SSAFullRangeData &arg_data = iter.current_data().data();
00320 
00321         if (! is_poisoned
00322         && (arg_data.timestamp() != timestamp()
00323             || arg_data.is_poisoned)) {
00324         is_poisoned = true;
00325         changed = true;
00326         }
00327     }
00328 
00329     /// ...  Update my range_ref field.
00330 
00331     if (is_phi_stmt) {
00332     bool new_all_args_are_defined;
00333     Expression *new_range = _union_args(new_all_args_are_defined);
00334 
00335     if (! new_range && ! union_arg_ranges) {
00336         union_arg_ranges = true;
00337         new_range = _union_args(new_all_args_are_defined);
00338     }
00339     
00340     if (in_widening_phase) {
00341         if (needs_widening && are_all_args_defined)
00342         _modify_expr(new_range, widen_range(new_range, _range, _accessor));
00343     }
00344     else
00345         _modify_expr(new_range, narrow_range(new_range, _range, _accessor));
00346     
00347     are_all_args_defined = new_all_args_are_defined;
00348     
00349     if ((! _range && new_range) 
00350         || (_range && ! new_range)
00351         || (_range && _range->compare(*new_range) != 0)) {
00352         
00353         _modify_expr(_range, new_range);
00354         new_range = 0;
00355         changed = true;
00356     }
00357 
00358     if (new_range)
00359         delete new_range;
00360     }
00361 
00362     ++num_updates;
00363 
00364     if (_debug_level >= 20) {
00365     cout << stmt().tag() << ": ";
00366     int zero = 0;
00367     stmt().write(cout, zero);
00368     cout << "        " << *this << endl;
00369     }
00370 
00371     /// ...  Ordinary assignment stmts always change when their arguments
00372     /// ...  change.
00373 
00374     if (! is_phi_stmt)
00375     changed = true;
00376 
00377     return changed;
00378 }
00379 
00380 
00381 /// succs
00382 
00383 RefSet<SSAFullRangeData> *
00384 SSAFullRangeData::succs() const
00385 {
00386     RefSet<SSAFullRangeData> *my_succs = new RefSet<SSAFullRangeData>;
00387     KeyIterator<Symbol, SSARangeOrData> iter = arg_ranges_or_data;
00388 
00389     for ( ; iter.valid(); ++iter)
00390     if (iter.current_data().is_data()
00391         && ! iter.current_data().data().computed
00392         && iter.current_data().data().timestamp() == timestamp())
00393 
00394         my_succs->ins(iter.current_data().data());
00395 
00396     return my_succs;
00397 }
00398 
00399 
00400 /// listable_clone
00401 
00402 Listable *
00403 SSAFullRangeData::listable_clone() const
00404 {
00405     return new SSAFullRangeData(*this);
00406 }
00407 
00408 
00409 /// print
00410 
00411 void
00412 SSAFullRangeData::print(ostream &o) const
00413 {
00414     o << "[";
00415     o << "stmt=" << _stmt_ref->tag();
00416     o << ", ts=" << _timestamp;
00417     o << ", range=";
00418 
00419     if (_range)
00420     o << *_range;
00421     else
00422     o << "NULL";
00423 
00424     o << ", psnd=" << is_poisoned;
00425     o << ", iter=" << needs_iteration;
00426     o << ", wide=" << needs_widening;
00427     o << ", adef=" << are_all_args_defined;
00428 
00429     o << ", tord=" << toporder;
00430     o << ", nupd=" << num_updates;
00431     o << ", unar=" << union_arg_ranges;
00432     o << ", comp=" << computed;
00433     o << ", dfor=" << df_order;
00434     o << ", lwlk=" << low_link;
00435     o << ", args={";
00436 
00437     Iterator<Symbol> arg_iter = args;
00438 
00439     if (arg_iter.valid()) {
00440     o << arg_iter.current().name_ref() << ":"
00441         << arg_ranges_or_data[arg_iter.current()];
00442     ++arg_iter;
00443 
00444     for ( ; arg_iter.valid(); ++arg_iter)
00445         o << ", " << arg_iter.current().name_ref() << ":"
00446         << arg_ranges_or_data[arg_iter.current()];
00447     }
00448 
00449     o << "}";
00450     o << ", pred={";
00451 
00452     KeyIterator<Symbol,Statement> pred_iter = arg_preds;
00453 
00454     if (pred_iter.valid()) {
00455     o << pred_iter.current_key().name_ref() << ":"
00456         << pred_iter.current_data().tag();
00457     ++pred_iter;
00458 
00459     for ( ; pred_iter.valid(); ++pred_iter)
00460         o << ", " << pred_iter.current_key().name_ref()
00461         << ":" << pred_iter.current_data().tag();
00462     }
00463 
00464     o << "}";
00465     o << ", users={";
00466 
00467     Iterator<SSAFullRangeData> user_iter = users;
00468 
00469     if (user_iter.valid()) {
00470     o << user_iter.current().stmt().tag();
00471     ++user_iter;
00472 
00473     for ( ; user_iter.valid(); ++user_iter)
00474         o << ", " << user_iter.current().stmt().tag();
00475     }
00476 
00477     o << "}";
00478     o << "]";
00479 }
00480 
00481 
00482 /// structures_OK
00483 
00484 int
00485 SSAFullRangeData::structures_OK() const
00486 {
00487     return (_stmt_ref->structures_OK()
00488         && arg_ranges_or_data.structures_OK());
00489 }
00490 
 © 1995-2005 University of Illinois, Urbana-Champaign. All rights reserved.  Fri Mar 25 23:06:08 2005