Polaris: RangeComparator.cc Source File

RangeComparator.cc

Go to the documentation of this file.
00001 ///
00002 ///
00003 /// \file RangeComparator.cc
00004 ///
00005 #include <limits.h>
00006 
00007 #include "../Expression/Expression.h"
00008 #include "../Expression/InfinityExpr.h"
00009 #include "../Expression/NonBinaryExpr.h"
00010 #include "../Collection/Iterator.h"
00011 #include "../Collection/Mutator.h"
00012 #include "../Collection/KeyIterator.h"
00013 #include "../Collection/RefSet.h"
00014 #include "../Collection/Set.h"
00015 #include "../Collection/RefList.h"
00016 #include "../utilities/switches_util.h"
00017 #include "../utilities/expression_util.h"
00018 #include "../Symtab.h"
00019 #include "../Timer.h"
00020 
00021 #include "RangeComparator.h"
00022 #include "RangeExpr.h"
00023 #include "range_util.h"
00024 
00025 #include "../Constant/constant.h"
00026 
00027 
00028 #define MAX_SUBST 1     /// ...  Maximum number of times a variable should
00029                 /// ...  be substituted by the compare method.
00030 
00031 //static int _range_compare_accuracy = 1;
00032 
00033 /// Statistics collecting object.
00034 
00035 #define HIST_SIZE 64
00036 
00037 /// Template instantiations
00038 
00039 template class TypedBaseMap<Symbol,CompareData>;
00040 template class ProtoMap<Symbol,CompareData>;
00041 template class Map<Symbol,CompareData>;
00042 template ostream & operator << (ostream &,
00043                                 const Map<Symbol,CompareData> &);
00044 template class KeyIterator<Symbol,CompareData>;
00045 
00046 class RangeComparatorStats {
00047 public:
00048     RangeComparatorStats();
00049     RangeComparatorStats(const RangeComparatorStats &other);
00050     virtual ~RangeComparatorStats();
00051 
00052     void reset();
00053     /// ...  Reset all my statistics;
00054 
00055     void start_compare();
00056     /// ...  Start a comparison operator.
00057 
00058     void making_a_var_subst();
00059     /// ...  Curlrent comparison is making a variable substitution.
00060 
00061     void end_compare();
00062     /// ...  End a comparison operator.
00063 
00064     void print(ostream &o);
00065     /// ...  Print out all my statistics.
00066 private:
00067     int _compare_level;     /// ...  Current number of invocations of compare
00068                 /// ...  on the calling stack.
00069     int _num_compares;      /// ...  Number of compare() invocations.
00070     int _num_top_level_compares; /// ...  Number of top level compares().
00071     int _num_substs;        /// ...  Number of variable substitutions by current
00072                 /// ...  compare(), including recursive calls.
00073     Timer _compare_time;    /// ...  Time taken by current compare.
00074     int _num_subst_histogram[HIST_SIZE]; /// ...  Histogram of number of compares with
00075                      /// ...  the given number of substitutions.
00076     Timer _time_histogram[HIST_SIZE]; /// ...  Histogram of time taken by a 
00077                       /// ...  comparison that made the given number
00078                       /// ...  of substitutions
00079 };
00080 
00081 static RangeComparatorStats *_stats = 0;
00082 
00083 
00084 ///  flip_sign
00085 
00086 EXPR_SIGN
00087 flip_sign(EXPR_SIGN sign)
00088 {
00089     if (sign == POS_EXPR)
00090         return NEG_EXPR;
00091     else if (sign == NEG_EXPR)
00092         return POS_EXPR;
00093 
00094     return sign;
00095 }
00096 
00097 
00098 ///  CompareData methods
00099 
00100 CompareData::CompareData()
00101 {
00102     num_subst = 0;
00103     sign_cache = UNKNOWN_SIGN;
00104     /// ...  use_the_big_guns = (range_compare_accuracy() >= 1);
00105 }
00106 
00107 CompareData::CompareData(const CompareData &other)
00108 {
00109     num_subst = other.num_subst;
00110     sign_cache = other.sign_cache;
00111     /// ...  use_the_big_guns = other.use_the_big_guns;
00112 }
00113 
00114 CompareData::~CompareData()
00115 {
00116     /// ...  Nothing to do
00117 }
00118 
00119 Listable *
00120 CompareData::listable_clone() const
00121 {
00122     return new CompareData(*this);
00123 }
00124 
00125 int
00126 CompareData::structures_OK() const
00127 {
00128     return 1;
00129 }
00130 
00131 void
00132 CompareData::print(ostream &o) const
00133 {    o << "[";
00134     o << "ns=" << num_subst << ", ";
00135     o << "sc=";
00136 
00137     switch (sign_cache) {
00138     case POS_EXPR:      o << "+";   break;
00139     case NEG_EXPR:      o << "-";   break;
00140     case POS_NEG_EXPR:  o << "+-";  break;
00141     case UNKNOWN_SIGN:  o << "?";   break;
00142     case PENDING:       o << "P";   break;
00143     default: break;
00144     }
00145 
00146     /// ...  o << ", ";
00147     /// ...  o << "ubg=" << use_the_big_guns;
00148     o << "]";
00149 }
00150     
00151 
00152 ///  RangeComparatorStats methods
00153 
00154 RangeComparatorStats::RangeComparatorStats()
00155 {
00156     reset();
00157 }
00158 
00159 RangeComparatorStats::RangeComparatorStats(const RangeComparatorStats &other)
00160 {
00161     _compare_level = other._compare_level;
00162     _num_compares = other._num_compares;
00163     _num_top_level_compares = other._num_top_level_compares;
00164     _num_substs = other._num_substs;
00165     _compare_time  = other._compare_time;
00166 
00167     for (int i = 0; i < HIST_SIZE; ++i) {
00168     _num_subst_histogram[i] = other._num_subst_histogram[i];
00169     _time_histogram[i] = other._time_histogram[i];
00170     }
00171 }
00172 
00173 RangeComparatorStats::~RangeComparatorStats()
00174 {
00175     /// ...  Nothing to do.
00176 }
00177 
00178 void
00179 RangeComparatorStats::reset()
00180 {
00181     _compare_level = 0;
00182     _num_compares = 0;
00183     _num_top_level_compares = 0;
00184     _num_substs = 0;
00185     _compare_time.stop();
00186     _compare_time.reset();
00187 
00188     for (int i = 0; i < HIST_SIZE; ++i) {
00189     _num_subst_histogram[i] = 0;
00190     _time_histogram[i].stop();
00191     _time_histogram[i].reset();
00192     }
00193 }
00194 
00195 void
00196 RangeComparatorStats::start_compare()
00197 {
00198     ++_compare_level;
00199     ++_num_compares;
00200 
00201     if (_compare_level == 1) {
00202     ++_num_top_level_compares;
00203     _num_substs = 0;
00204     _compare_time.reset();
00205     _compare_time.restart();
00206     }
00207 }
00208 
00209 void
00210 RangeComparatorStats::making_a_var_subst()
00211 {
00212     if (_compare_level > 0)
00213     ++_num_substs;
00214 }
00215 
00216 void
00217 RangeComparatorStats::end_compare()
00218 {
00219     p_assert(_compare_level > 0,
00220          "There were more end_compare() invocations than start_compare() invocations.");
00221 
00222     if (_compare_level == 1) {
00223     _compare_time.stop();
00224 
00225     if (_num_substs >= HIST_SIZE)
00226         _num_substs = HIST_SIZE - 1;
00227 
00228     ++_num_subst_histogram[_num_substs];
00229     _time_histogram[_num_substs] += _compare_time;
00230     }
00231 
00232     --_compare_level;
00233 }
00234 
00235 static void _print_avg_time(ostream &o, const Timer &timer, int count)
00236 {
00237     if (count > 0) {
00238     double user, system, wallclock;
00239     timer.timings(user, system, wallclock);
00240     user /= count;
00241     system /= count;
00242     wallclock /= count;
00243     o <<user<<"\t"
00244       <<system<<"\t"
00245       <<wallclock;
00246 ///     o << form("%.4fu %.4fs %.4fw", user, system, wallclock);
00247     }
00248     else
00249     o <<0<<"\t"
00250       <<0<<"\t"
00251       <<0;
00252 ///     o << form("%.4fu %.4fs %.4fw", 0.0, 0.0, 0.0);
00253 
00254 }
00255 
00256     
00257 void 
00258 RangeComparatorStats::print(ostream &o)
00259 {
00260     o << "Number of compare() invocations = " << _num_compares << endl;
00261     o << "Number of top-level compare() invocations = "
00262     << _num_top_level_compares << endl;
00263 
00264     o << endl;
00265     o << " Num. Substs    Num. TL Compares     Total time         Time per subst.\n";
00266     o << "------------------------------------------------------------------------\n";
00267 
00268     int tot_substs = 0;
00269     Timer tot_time;
00270     tot_time.stop();
00271     tot_time.reset();
00272 
00273     for (int i = 0; i < HIST_SIZE; ++i)
00274     if (_num_subst_histogram[i] > 0) {
00275       o <<i<<"\t"<< _num_subst_histogram[i];
00276 ///         o << form(" %7d        %10d      ",
00277 ///               i, _num_subst_histogram[i]);
00278         o << _time_histogram[i];
00279         o << "   ";
00280         _print_avg_time(o, _time_histogram[i],
00281                 i * _num_subst_histogram[i]);
00282         o << endl;
00283         tot_substs += i * _num_subst_histogram[i];
00284         tot_time += _time_histogram[i];
00285     }
00286 
00287     o << "Total number of substitutions performed = " << tot_substs << endl;
00288     o << "Total time taken = " << tot_time << endl;
00289     o << "Total time per substitution = ";
00290     _print_avg_time(o, tot_time, tot_substs);
00291     o << endl;
00292 }
00293 
00294 
00295 /// collect_range_stats
00296 ///   Tell the range comparator to collect statistics.
00297 
00298 void
00299 collect_range_stats()
00300 {
00301     _stats = new RangeComparatorStats();
00302 }
00303 
00304 
00305 /// stop_range_stats
00306 ///   Tell the range comparator to stop collecting statistics.
00307 
00308 void
00309 stop_range_stats()
00310 {
00311     if (_stats) {
00312     delete _stats;
00313     _stats = 0;
00314     }
00315 }
00316 
00317 
00318 /// print_range_stats
00319 ///   Print out the statistics collected so far.
00320 
00321 void
00322 print_range_stats(ostream &o)
00323 {
00324     if (_stats)
00325     _stats->print(o);
00326 }
00327 
00328 
00329 /// _compare_data
00330 ///   Return the comparison data collected for the given variable.
00331 
00332 CompareData &
00333 RangeComparator::_compare_data(const Symbol &var)
00334 {
00335     CompareData *data = _compare_info.find_ref(var);
00336 
00337     if (! data) {
00338     data = new CompareData;
00339     _compare_info.ins(var, data);
00340     }
00341 
00342     return *data;
00343 }
00344 
00345 
00346 ///  RangeComparator
00347 
00348 RangeComparator::RangeComparator(const Symtab &symtab)
00349 {
00350     _symtab_ref = &symtab;
00351     debug_level(0);
00352     range_join_accuracy(switch_value("range_acc"));
00353     range_compare_accuracy(1);
00354     _cache_expr_signs = 0;
00355 }
00356 
00357 RangeComparator::RangeComparator(const RangeComparator &other)
00358 {
00359     *this = other;
00360 }
00361 
00362 
00363 ///  ~RangeComparator
00364 
00365 RangeComparator::~RangeComparator()
00366 {
00367     /// ...  nothing to do
00368 }
00369 
00370 
00371 /// skip_int_const_exprs
00372 ///   Set the given argument to the next expression of the list, skipping
00373 ///   over any integer constants.  The sum of the values of these skipped
00374 ///   integer constants is returned.  
00375 
00376 static int
00377 _skip_int_const_exprs(const Expression *& term)
00378 {
00379     int value = 0;
00380 
00381     while (term && is_integer_constant(*term)) {
00382     value += term->value();
00383     term = (const Expression *) term->next_ref();
00384     }
00385 
00386     return value;
00387 }
00388 
00389 
00390 /// int_diff
00391 ///    If expression e1 differs from expression e2 by an integer value,
00392 ///    return true and this integer difference.  Else, return false.
00393 ///
00394 ///    This function assumes that e1 and e2 have been simplified
00395 ///    (i.e., all integer constants have been folded, they are in
00396 ///    in sum-of-products form, etc.).  This function will also take
00397 ///    unsimplified expressions, but is more likely to fail
00398 ///    (i.e., return false.)  This function may reorder the arguments
00399 ///    of commutative subexpressions within these expressions.
00400 ///
00401 ///    This function was designed to be a much quicker alternative to
00402 ///    the performing "simplify(sub(e1.clone(), e2.clone()))", which
00403 ///    is often used for expression comparison.  When doing such
00404 ///    comparisons, it is suggested to try this function first.
00405 ///    If it fails, apply the code fragment above.
00406 
00407 static bool
00408 _int_diff(const Expression &e1, const Expression &e2, int &diff)
00409 {
00410     if (is_integer_constant(e1) && is_integer_constant(e2)) {
00411     /// ...  Both expressions are integers, so return true and their difference.
00412 
00413     diff = e1.value() - e2.value();
00414     return true;
00415     }
00416     else if (e1.op() != ADD_OP && e2.op() != ADD_OP) {
00417     /// ...  Neither expression are addition expressions, so return true
00418     /// ...  if and only if the expressions equal each other.
00419 
00420     diff = 0;
00421     return (e1.compare(e2) == 0);
00422     }
00423     else if (e1.op() != ADD_OP || e2.op() != ADD_OP) {
00424     /// ...  Exactly one expression is an addition expression.  So return
00425     /// ...  true with the difference C if and only if the expressions
00426     /// ...  are of the form A+C and A.
00427 
00428     const Expression *add_expr, *other_expr;
00429 
00430     if (e1.op() == ADD_OP) {
00431         add_expr = &e1;
00432         other_expr = &e2;
00433     }
00434     else {
00435         add_expr = &e2;
00436         other_expr = &e1;
00437     }
00438 
00439     const List<Expression> &add_args = add_expr->arg_list();
00440 
00441     if (add_args.entries() != 2)
00442         return false;
00443 
00444     const Expression *add_term;
00445 
00446     if (is_integer_constant(*add_args.first_ref())) {
00447         diff = add_args.first_ref()->value();
00448         add_term = add_args.last_ref();
00449     }
00450     else if (is_integer_constant(*add_args.last_ref())) {
00451         diff = add_args.last_ref()->value();
00452         add_term = add_args.first_ref();
00453     }
00454     else
00455         return false;
00456 
00457     if (add_expr == &e2)
00458         diff = -diff;
00459 
00460     return (add_term->compare(*other_expr) == 0);
00461     }
00462     else {
00463     /// ...  Both expressions are addition expressions.  So return
00464     /// ...  true with the difference C1-C2 if and only if the expressions
00465     /// ...  are of the form A1+A2+...+AN+C1 and A1+A2+...AN+C2.
00466 
00467     /// ...  e1.standardize();
00468     /// ...  e2.standardize();
00469 
00470     const Expression *e1_term = e1.arg_list().first_ref();
00471     const Expression *e2_term = e2.arg_list().first_ref();
00472 
00473     diff = 0;
00474     diff += _skip_int_const_exprs(e1_term);
00475     diff -= _skip_int_const_exprs(e2_term);
00476 
00477     while (e1_term && e2_term) {
00478         if (e1_term->compare(*e2_term) != 0)
00479         return false;
00480 
00481         e1_term = (Expression *) e1_term->next_ref();
00482         e2_term = (Expression *) e2_term->next_ref();
00483 
00484         diff += _skip_int_const_exprs(e1_term);
00485         diff -= _skip_int_const_exprs(e2_term);
00486     }
00487 
00488     return (! e1_term && ! e2_term);
00489     }
00490 }
00491 
00492 
00493 ///  compare
00494 
00495 static bool contains_infinity(const Expression& e){
00496   if (e.op()==INFINITY_OP){
00497     return true;
00498   } else {
00499     for(Iterator<Expression> eit=e.arg_list(); eit.valid(); ++eit){
00500       if (contains_infinity(eit.current())){
00501     return true;
00502       }
00503     }
00504   }
00505   return false;
00506 }
00507 
00508 Relation
00509 RangeComparator::compare(const Expression &e1, const Expression &e2)
00510 {
00511 
00512 /// silvius: there seems to be an error:
00513 /// compare(N, Inf) results in <=, but it should be <
00514   if (e1.op() == INFINITY_OP && !contains_infinity(e2)){
00515     if (e1.sign()==-1){
00516       /// ...  <
00517       return Relation(true, false, false);
00518     } else {
00519       /// ...  >
00520       return Relation(false, false, true);
00521     }
00522   }
00523   if (e2.op() == INFINITY_OP && !contains_infinity(e1)){
00524     if (e2.sign()==1){
00525       /// ...  <
00526       return Relation(true, false, false);
00527     } else {
00528       /// ...  >
00529       return Relation(false, false, true);
00530     }
00531   }
00532   if (e1==e2){
00533     return Relation(false, true, false);
00534   }
00535 
00536     /// ...  The method compare determines relationships between two expressions
00537     /// ...  by subtracting one expression from the other, and testing whether this
00538     /// ...  difference is less than, equal, or greater than zero.
00539 
00540     if (_debug_level >= 10)
00541     cout << "Comparing (" << e1 << ") to (" << e2 << ") {\n";
00542 
00543     if (_stats)
00544     _stats->start_compare();
00545 
00546     _begin_caching_expr_signs();
00547 
00548     Relation rel;
00549 
00550     if (is_empty_range(e1) || is_empty_range(e2))
00551     ; // Do nothing
00552     else if (e1.op() == INFINITY_OP) {
00553       /// ...  Set main part of relation
00554       rel = Relation(((InfinityExpr *) &e1)->sign() <= 0, true,
00555              ((InfinityExpr *) &e1)->sign() >= 0);
00556       /// ...  Now test for circularity if e2 is non-constant
00557       switch (e2.op()) {
00558       case INFINITY_OP:
00559       case INTEGER_CONSTANT_OP:
00560       case REAL_CONSTANT_OP:
00561       case LOGICAL_CONSTANT_OP:
00562     break;
00563       default: {
00564       Relation rel2 = _compare(e2.clone());
00565       rel.circular(rel2.is_circular());
00566     }
00567       }
00568     }
00569     else if (e2.op() == INFINITY_OP) {
00570       /// ...  Set main part of relation
00571       rel = Relation(((InfinityExpr *) &e2)->sign() >= 0, true,
00572              ((InfinityExpr *) &e2)->sign() <= 0);
00573       /// ...  Now test for circularity if e1 is non-constant
00574       switch (e1.op()) {
00575       case INFINITY_OP:
00576       case INTEGER_CONSTANT_OP:
00577       case REAL_CONSTANT_OP:
00578       case LOGICAL_CONSTANT_OP:
00579     break;
00580       default: {
00581       Relation rel1 = _compare(e1.clone());
00582       rel.circular(rel1.is_circular());
00583     }
00584       }
00585     }
00586     else {
00587     int diff = 0;
00588     
00589     if (_int_diff(e1, e2, diff))
00590         rel = Relation(diff < 0, diff == 0, diff > 0);
00591     else
00592         rel = _compare(_build_delta(e1, e2));
00593     }
00594 
00595     _end_caching_expr_signs();
00596     
00597     if (_stats)
00598     _stats->end_compare();
00599  
00600     if (_debug_level >= 10)
00601     cout << "}  result(compare): (" << e1 << ") " << rel << " (" << e2 << ")\n";
00602     
00603     return rel;
00604 }
00605 
00606 Relation
00607 RangeComparator::compare(const Expression &e1, int value)
00608 {
00609     if (_debug_level >= 10)
00610     cout << "Comparing (" << e1 << ") to (" << value << ") {\n";
00611 
00612     if (_stats)
00613     _stats->start_compare();
00614  
00615     _begin_caching_expr_signs();
00616 
00617     Relation rel;
00618 
00619     if (is_empty_range(e1))
00620     ;
00621     else if (e1.op() == INFINITY_OP)
00622     rel = Relation(((InfinityExpr *) &e1)->sign() <= 0, true,
00623                ((InfinityExpr *) &e1)->sign() >= 0);
00624     else {
00625     Expression *delta;
00626     
00627     if (value != 0) {
00628         Expression *value_expr = constant(value);
00629         delta = _build_delta(e1, *value_expr);
00630         delete value_expr;
00631     }
00632     else {
00633         delta = expr_expand_substituted(e1.clone());
00634         delta = simplify(delta);
00635     }
00636     
00637     rel = _compare(delta);
00638     }
00639 
00640     _end_caching_expr_signs();
00641     
00642     if (_stats)
00643     _stats->end_compare();
00644  
00645     if (_debug_level >= 10)
00646     cout << "}  result(compare): (" << e1 << ") " << rel << " (" << value << ")\n";
00647 
00648     return rel;
00649 }
00650 
00651 
00652 ///  _build_delta
00653 ///    Compute the symbolic difference between the two expressions.
00654 
00655 Expression *
00656 RangeComparator::_build_delta(const Expression &e1, const Expression &e2)
00657 {
00658     Expression *delta;
00659 
00660     if (is_integer_zero(e2))
00661     delta = e1.clone();
00662     else
00663     delta = sub(e1.clone(), e2.clone());
00664 
00665     if (e1.op() == RANGE_OP || e1.op() == OMEGA_OP
00666     || e2.op() == RANGE_OP || e2.op() == OMEGA_OP)
00667 
00668     delta = pull_ranges_out(delta, *this);
00669 
00670     delta = expr_expand_substituted(delta);
00671     delta = simplify(delta);
00672     delta = pull_min_max_out(delta, *this);
00673 
00674     if (is_min_or_max(*delta))
00675     delta = simplify(delta);
00676 
00677     return delta;
00678 }
00679 
00680 
00681 ///  _is_pos_max
00682 ///    Return true if the given expression is a positive MAX expression
00683 
00684 static bool
00685 _is_pos_max(const Expression &e)
00686 {
00687     if (is_max(e)) {
00688     Iterator<Expression> iter = e.parameters_guarded().arg_list();
00689 
00690     for ( ; iter.valid(); ++iter) {
00691         const Expression &arg = iter.current();
00692 
00693         if (arg.op() == INTEGER_CONSTANT_OP && arg.value() > 0)
00694         return true;
00695     }
00696     }
00697 
00698     return false;
00699 }
00700 
00701 
00702 ///  _is_neg_min
00703 ///    Return true if the given expression is a negative MIN expression
00704 
00705 static bool
00706 _is_neg_min(const Expression &e)
00707 {
00708     if (is_min(e)) {
00709     Iterator<Expression> iter = e.parameters_guarded().arg_list();
00710 
00711     for ( ; iter.valid(); ++iter) {
00712         const Expression &arg = iter.current();
00713 
00714         if (arg.op() == INTEGER_CONSTANT_OP && arg.value() < 0)
00715         return true;
00716     }
00717     }
00718 
00719     return false;
00720 }
00721 
00722 
00723 ///  _is_comparable
00724 ///    Return true if the given expression is comparable without further
00725 ///    transformations.  An expression is comparable if it is omega, an
00726 ///    integer, or a range bounded by omegas or integers.
00727 
00728 static bool
00729 _is_comparable(const Expression &e)
00730 {
00731     if (e.op() == INTEGER_CONSTANT_OP || e.op() == OMEGA_OP)
00732     return true;
00733     /// ...  <integer>**<expr>
00734     else if ((e.op() == EXP_OP) && (e.left_guarded().op() == INTEGER_CONSTANT_OP))
00735     return true;
00736     /// ...  for addition or multiplication, all terms must be comparable
00737     else if ((e.op() == MULT_OP) ||
00738          (e.op() == ADD_OP)) {
00739 
00740     bool comp = true;
00741     for (Iterator<Expression> iter = e.arg_list();
00742          iter.valid();
00743          ++iter) {
00744         Expression & subexp = iter.current();
00745 
00746         comp = comp && _is_comparable( subexp );
00747     }
00748     return comp;
00749     }
00750         
00751     else if (e.op() == RANGE_OP) {
00752     RangeExpr &range = * (RangeExpr *) &e;
00753 
00754     if (is_empty_range(e))
00755         return true;
00756     else if ((! range.has_lb()
00757          || range.lb().op() == INTEGER_CONSTANT_OP)
00758         && (! range.has_ub()
00759         || range.ub().op() == INTEGER_CONSTANT_OP))
00760         return true;
00761     else if (range.has_lb()
00762          && ((range.lb().op() == INTEGER_CONSTANT_OP
00763               && range.lb().value() > 0)
00764              || _is_pos_max(range.lb())))
00765         return true;
00766     else if (range.has_ub()
00767          && ((range.ub().op() == INTEGER_CONSTANT_OP
00768               && range.ub().value() < 0)
00769              || _is_neg_min(range.ub())))
00770         return true;
00771     }
00772 
00773     return false;
00774 }
00775 
00776 
00777 ///  _determine_relation
00778 ///    Determine the proper relationship from the given delta expression.
00779 ///    This method will return an unknown relationship if it is not comparable,
00780 ///    (i.e. _is_comparable(delta) returns false.)
00781 ///
00782 ///    An omega or totally unbounded delta expression is assumed to be from a
00783 ///    circular reference if a dummy range was just substituted, otherwise
00784 ///    an unknown value
00785 
00786 static Relation
00787 _determine_relation(const Expression &delta, bool dummy_range_just_substituted, 
00788             RangeComparator * comp)
00789 {
00790     Relation relation;
00791 
00792     if (delta.op() == INTEGER_CONSTANT_OP) {
00793     if (delta.value() < 0)
00794         relation.less_than(true);
00795     else if (delta.value() > 0)
00796         relation.greater_than(true);
00797     else
00798         relation.equal(true);
00799     }
00800     else if ((delta.op() == EXP_OP) &&
00801          (delta.left_guarded().op() == INTEGER_CONSTANT_OP)) {
00802     if (delta.left_guarded().value() >= 0)
00803         relation.greater_than(true);
00804     else if (delta.right_guarded().op() == INTEGER_CONSTANT_OP) {
00805         if ((abs(delta.right_guarded().value()) / 2 * 2) == 
00806         abs(delta.right_guarded().value())) {
00807         relation.greater_than(true);
00808         }
00809     }
00810     }
00811 
00812     else if (delta.op() == MULT_OP) {
00813     int c=1;
00814     for (Iterator<Expression> iter = delta.arg_list();
00815          iter.valid();
00816          ++iter) {
00817         Expression & subexp = iter.current();
00818 
00819         Relation r = _determine_relation(subexp, dummy_range_just_substituted, comp);
00820         if (r.is_less_than()) {
00821         c *= -1;
00822         } else if (r.is_equal()) {
00823         c = 0;
00824         } else if (r.is_greater_than()) {
00825         } else {  /// ...  unknown
00826         c *= 2;
00827         }
00828     }
00829     if (c == 0) {
00830         relation.equal(true);
00831     } else if (c == 1) {
00832         relation.greater_than(true);
00833     } else if (c == -1) {
00834         relation.less_than(true);
00835     }
00836     }
00837 
00838     else if (delta.op() == ADD_OP) {
00839     bool less = false;
00840     bool grtr = false;
00841     bool zero = false;
00842     bool unknown = false;
00843     int minus_one_count = 0;
00844     int pos_exp_count = 0;
00845     for (Iterator<Expression> iter = delta.arg_list();
00846          iter.valid();
00847          ++iter) {
00848         Expression & subexp = iter.current();
00849 
00850         Relation r = _determine_relation(subexp, dummy_range_just_substituted, comp);
00851 
00852         if (r.is_less_than()) {
00853         less = true;
00854         if (is_integer_constant(subexp, -1)) {
00855             minus_one_count++;
00856         }
00857         } else if (r.is_greater_than()) {
00858         grtr = true;
00859         if (subexp.op() == EXP_OP) {
00860             pos_exp_count++;
00861         }
00862         } else if (r.is_equal()) {
00863         zero = true;
00864         } else {
00865         unknown = true;
00866         }
00867     }
00868     if (less && !grtr && !zero && !unknown) {
00869         relation.less_than(true);
00870     } else if (grtr && !less && !zero && !unknown) {
00871         relation.greater_than(true);
00872     } else if (zero && !less && !grtr && !unknown) {
00873         relation.equal(true);
00874     } else {
00875         /// ...  if it's all (-1) and (x**y) terms, use fact that x**y is >=1
00876         if (minus_one_count+pos_exp_count == delta.arg_list().entries()) {
00877         if (pos_exp_count>minus_one_count) {
00878             relation.greater_than(true);
00879         } else if (pos_exp_count == minus_one_count) {
00880             relation.greater_than(true);
00881             relation.equal(true);
00882         }
00883         } else 
00884         /// ...  Check for difference of 2 exponentials
00885 
00886         if ((delta.arg_list().entries() == 2) &&
00887             less && grtr) {
00888 
00889             const Expression & left  = delta.arg_list()[0];
00890             const Expression & right = delta.arg_list()[1];
00891 
00892             if ((left.op() == MULT_OP) &&
00893             (left.arg_list()[0].op() == INTEGER_CONSTANT_OP) &&
00894             (left.arg_list()[0].value() == -1) &&
00895             (left.arg_list()[1].op() == EXP_OP) &&
00896             (left.arg_list()[1].arg_list()[0].op() == INTEGER_CONSTANT_OP) &&
00897             (right.op() == EXP_OP) &&
00898             (right.arg_list()[0].op() == INTEGER_CONSTANT_OP)) {
00899 
00900             /// ...  make sure the bases of the exponentials are equal
00901 
00902             if (left.arg_list()[1].arg_list()[0].value() ==
00903                 right.arg_list()[0].value()) {
00904 
00905                 Relation r = comp->compare(right.arg_list()[1],
00906                                left.arg_list()[1].arg_list()[1]);
00907             }
00908             } else 
00909             if ((right.op() == MULT_OP) &&
00910                 (right.arg_list()[0].op() == INTEGER_CONSTANT_OP) &&
00911                 (right.arg_list()[0].value() == -1) &&
00912                 (right.arg_list()[1].op() == EXP_OP) &&
00913                 (right.arg_list()[1].arg_list()[0].op() == INTEGER_CONSTANT_OP) &&
00914                 (left.op() == EXP_OP) &&
00915                 (left.arg_list()[0].op() == INTEGER_CONSTANT_OP)) {
00916 
00917                 /// ...  make sure the bases of the exponentials are equal
00918 
00919                 if (right.arg_list()[1].arg_list()[0].value() ==
00920                 left.arg_list()[0].value()) {
00921                 
00922                 Relation r = comp->compare(left.arg_list()[1],
00923                                right.arg_list()[1].arg_list()[1]);
00924                 relation = r;
00925                 }
00926             }
00927         }
00928     }
00929     }
00930 
00931     else if (is_unbounded_range(delta)) {
00932     relation.circular(dummy_range_just_substituted);
00933     }
00934     else if (delta.op() != RANGE_OP ||
00935          is_empty_range(delta))
00936     ; // Return an undefined range.
00937     else {
00938     const RangeExpr &range = * (const RangeExpr *) &delta;
00939     int lb_val = INT_MIN;
00940     int ub_val = INT_MAX;
00941 
00942     if (range.has_lb())
00943         if (range.lb().op() == INTEGER_CONSTANT_OP)
00944         lb_val = range.lb().value();
00945         else if (_is_pos_max(range.lb()))
00946         lb_val = 1;
00947 
00948     if (range.has_ub())
00949         if (range.ub().op() == INTEGER_CONSTANT_OP)
00950         ub_val = range.ub().value();
00951         else if (_is_neg_min(range.ub()))
00952         ub_val = -1;
00953 
00954     if (lb_val > ub_val)
00955         ;  /// ...  Unknown relationship
00956     else if (lb_val < 0) {
00957         relation.less_than(true);
00958         relation.equal(ub_val >= 0);
00959         relation.greater_than(ub_val > 0);
00960     }
00961     else if (lb_val == 0) {
00962         relation.equal(true);
00963         relation.greater_than(ub_val > 0);
00964     }
00965     else
00966         relation.greater_than(true);
00967     }
00968 
00969     return relation;
00970 }
00971 
00972 
00973 ///  vars_in_expr
00974 ///    Return the set of variables that occur in the given expression.
00975 
00976 static void
00977 _vars_in_expr(RefSet<Symbol> &vars, const Expression &expr)
00978 {
00979     if (expr.op() == ID_OP) {
00980     if (expr.symbol().sym_class() == VARIABLE_CLASS)
00981         vars.ins(expr.symbol());
00982     }
00983     else {
00984     Iterator<Expression> iter = expr.arg_list();
00985 
00986     for ( ; iter.valid(); ++iter)
00987         _vars_in_expr(vars, iter.current());
00988     }
00989 }
00990 
00991 
00992 ///  _find_visit_order
00993 ///    Use heuristics to decide the ordering of the given expressions.
00994 ///    These heuristics attempt to insert variables whose ranges are more
00995 ///    difficult to manipulate before variables whose ranges are more
00996 ///    simple to manipulate.
00997 static void
00998 _find_visit_order(RefList<Symbol> &ordered_vars, const RefSet<Symbol> &vars,
00999           RangeComparator &comparator)
01000 {
01001     RefSet<Symbol> unconstrained;
01002     RefSet<Symbol> equal_ranges;
01003     RefSet<Symbol> simple_ranges;
01004     RefSet<Symbol> ranges;
01005     RefSet<Symbol> equal_min_max_ranges;
01006     RefSet<Symbol> min_max_ranges;
01007 
01008     Iterator<Symbol> var_iter = vars;
01009 
01010     for ( ; var_iter.valid(); ++var_iter) {
01011     Symbol &var = var_iter.current();
01012     const Expression *range_expr = comparator.get_range_ref(var);
01013     
01014     if (! range_expr)
01015         unconstrained.ins(var);
01016     else if (range_expr->op() != RANGE_OP) {
01017         if (is_min_or_max(*range_expr))
01018         equal_min_max_ranges.ins(var);
01019         else
01020         equal_ranges.ins(var);
01021     }
01022     else {
01023         const RangeExpr &range = * (const RangeExpr *) range_expr;
01024 
01025         if ((! range.has_lb() || range.lb().op() == INTEGER_CONSTANT_OP
01026          || range.lb().op() == ID_OP)
01027         && (! range.has_ub() || range.ub().op() == INTEGER_CONSTANT_OP
01028             || range.ub().op() == ID_OP))
01029         simple_ranges.ins(var);
01030         else if ((range.has_lb() && is_min_or_max(range.lb()))
01031              || (range.has_lb() && is_min_or_max(range.lb())))
01032         min_max_ranges.ins(var);
01033         else
01034         ranges.ins(var);
01035     }
01036     }
01037 
01038     for (var_iter = unconstrained; var_iter.valid(); ++var_iter)
01039     ordered_vars.ins_first(var_iter.current());
01040 
01041     for (var_iter = equal_ranges; var_iter.valid(); ++var_iter)
01042     ordered_vars.ins_first(var_iter.current());
01043 
01044     for (var_iter = simple_ranges; var_iter.valid(); ++var_iter)
01045     ordered_vars.ins_first(var_iter.current());
01046 
01047     for (var_iter = ranges; var_iter.valid(); ++var_iter)
01048     ordered_vars.ins_first(var_iter.current());
01049 
01050     for (var_iter = equal_min_max_ranges; var_iter.valid(); ++var_iter)
01051     ordered_vars.ins_first(var_iter.current());
01052 
01053     for (var_iter = min_max_ranges; var_iter.valid(); ++var_iter)
01054     ordered_vars.ins_first(var_iter.current());
01055 }
01056 
01057 
01058 ///  _generate_subst_order1
01059 ///    Determine an ordering of variable substitution for the given expression
01060 ///    that will maximize the cancellation of common terms.  This ordering
01061 ///    is returned in the list subst_order.
01062 ///
01063 ///    Since this problem is at least NP-Complete, a heuristic is used to
01064 ///    calculate the ordering.  Essentially, this algorithm traverses the
01065 ///    depth first tree of the graph of variable dependences.  (Each node is
01066 ///    labeled with a variable name , and there is an edge A-->B if the
01067 ///    substitutable value of variable A contains variable B.)  In this tree,
01068 ///    the parent occurs earlier in the list than its children.  Thus, if
01069 ///    the graph is a DAG, the assigned order would be a topological order,
01070 ///    which can be shown as an optimal order.
01071 
01072 static void
01073 _generate_subst_order1(RefList<Symbol> &subst_order, const Expression &e,
01074                RangeComparator &comparator,
01075                RefSet<Symbol> &visited)
01076 {
01077     RefSet<Symbol> vars;
01078     _vars_in_expr(vars, e);
01079     RefList<Symbol> ordered_vars;
01080     _find_visit_order(ordered_vars, vars, comparator);
01081 
01082     Iterator<Symbol> var_iter = ordered_vars;
01083 
01084     for ( ;var_iter.valid(); ++var_iter) {
01085     Symbol &var = var_iter.current();
01086 
01087     if (! visited.member(var)) {
01088         visited.ins(var);
01089         const Expression *range = comparator.get_range_ref(var);
01090         
01091         if (range)
01092         _generate_subst_order1(subst_order, *range, comparator,
01093                        visited);
01094 
01095         subst_order.ins_first(var);
01096     }
01097     }
01098 }
01099 
01100 static void
01101 _generate_subst_order1(RefList<Symbol> &subst_order, const Expression &e,
01102                RangeComparator &comparator)
01103 {
01104     RefSet<Symbol> visited;
01105     _generate_subst_order1(subst_order, e, comparator, visited);
01106 }
01107 
01108 
01109 ///  build_range_use_set
01110 ///    For each variable, build a set all variables whose ranges contain
01111 ///    that variable.
01112 
01113 static void
01114 _build_range_use_set(Map<Symbol, RefSet<Symbol> > &range_use_set,
01115              const RefList<Symbol> &candidate_vars,
01116              RangeComparator &comparator)
01117 {
01118     Iterator<Symbol> cand_iter = candidate_vars;
01119 
01120     for ( ; cand_iter.valid(); ++cand_iter) {
01121     Symbol &cand_var = cand_iter.current();
01122     const Expression *range = comparator.get_range_ref(cand_var);
01123 
01124     if (range) {
01125         RefSet<Symbol> vars_used;
01126         _vars_in_expr(vars_used, *range);
01127         Iterator<Symbol> used_iter = vars_used;
01128         
01129         for ( ; used_iter.valid(); ++used_iter) {
01130         Symbol &used_var = used_iter.current();
01131         RefSet<Symbol> *use_set = range_use_set.find_ref(used_var);
01132         
01133         if (! use_set) {
01134             use_set = new RefSet<Symbol>;
01135             range_use_set.ins(used_var, use_set);
01136         }
01137         
01138         use_set->ins(cand_var);
01139         }
01140     }
01141     }
01142 }
01143 
01144 
01145 ///  _grab_scc_from_list
01146 ///    This function grabs all variables in rev_topological_order that are
01147 ///    in a strongly connected component (SCC) containing root_var, and returns
01148 ///    them in scc.  The variables rev_topological_order are assumed to be
01149 ///    ordered in reverse topological order (ignoring back edges) of the
01150 ///    variable dependency graph (see _generate_subst_order1).  The map
01151 ///    reversed_edges contains the edges of the variable dependency graph in
01152 ///    reverse order.  The order of the variables in scc is guarantteed to be
01153 ///    the same as their order in rev_topological_order.
01154 ///    The algorithm for identifying SCCs was adapted from
01155 ///    "Introduction of Algorithms" by Cormen, Leiserson, and Rivest.
01156 
01157 static void
01158 _find_scc_from_list(RefSet<Symbol> &scc,
01159             const RefList<Symbol> &rev_topological_order,
01160             const Symbol &root_var,
01161             const Map<Symbol, RefSet<Symbol> > &reversed_edges)
01162 {
01163     if (! scc.member(CASTAWAY(Symbol &) root_var)) {
01164     scc.ins(CASTAWAY(Symbol &) root_var);
01165     const RefSet<Symbol> *predecessors = reversed_edges.find_ref(root_var);
01166 
01167     if (predecessors) {
01168         Iterator<Symbol> pred_iter = *predecessors;
01169 
01170         for ( ; pred_iter.valid(); ++pred_iter)
01171         if (rev_topological_order.member(pred_iter.current()))
01172             _find_scc_from_list(scc, rev_topological_order,
01173                     pred_iter.current(), reversed_edges);
01174     }
01175     }
01176 }
01177         
01178 static void
01179 _grab_scc_from_list(RefList<Symbol> &scc,
01180             RefList<Symbol> &rev_topological_order,
01181             const Symbol &root_var,
01182             const Map<Symbol, RefSet<Symbol> > &reversed_edges)
01183 {
01184     RefSet<Symbol> scc_set;
01185     _find_scc_from_list(scc_set, rev_topological_order, root_var,
01186             reversed_edges);
01187 
01188     if (scc_set.entries() == 1)
01189     scc.ins_last(rev_topological_order.grab(scc_set.grab()));
01190     else {
01191     Mutator<Symbol> rto_iter = rev_topological_order;
01192 
01193     for ( ; rto_iter.valid(); ++rto_iter)
01194         if (scc_set.member(rto_iter.current()))
01195         scc.ins_last(rev_topological_order.grab(rto_iter.current()));
01196     }
01197 
01198     p_assert(scc.entries() > 0,
01199          "_grab_scc_from_list returned an empty SCC.");
01200 }
01201 
01202 
01203 ///  _generate_subst_order
01204 ///    Determine an ordering of variable substitution for the given expression
01205 ///    that will maximize the cancellation of common terms.  This ordering
01206 ///    is returned in the list subst_order.
01207 ///
01208 ///    This function is essentially an extension of _generate_subst_order1.
01209 ///    The order is identical to _generate_subst_order1 except that all
01210 ///    variables in strongly connected components (SCC) are visited twice.
01211 
01212 static void
01213 _generate_subst_order(RefList<Symbol> &subst_order, const Expression &e,
01214               RangeComparator &comparator)
01215 {
01216     RefList<Symbol> acyclic_subst_order;
01217     _generate_subst_order1(acyclic_subst_order, e, comparator);
01218     Map<Symbol, RefSet<Symbol> > range_use_set;
01219     _build_range_use_set(range_use_set, acyclic_subst_order, comparator);
01220 
01221     while (acyclic_subst_order.entries() > 0) {
01222     Symbol &var = acyclic_subst_order.grab(0);
01223     acyclic_subst_order.ins_first(var);
01224     RefList<Symbol> scc;
01225     _grab_scc_from_list(scc, acyclic_subst_order, var, range_use_set);
01226 
01227     if (scc.entries() == 1)
01228         subst_order.ins_last(scc.grab());
01229     else {
01230         /// ...  SCC has more than one variable, so add each variable in it
01231         /// ...  twice.
01232 
01233         Iterator<Symbol> scc_iter = scc;
01234 
01235         for ( ; scc_iter.valid(); ++scc_iter)
01236         subst_order.ins_last(scc_iter.current());
01237 
01238         for (scc_iter.reset(); scc_iter.valid(); ++scc_iter)
01239         subst_order.ins_last(scc_iter.current());
01240     }
01241     }
01242 }
01243 
01244 
01245 
01246 ///  _replace_vars_with_omega
01247 ///    Replace all variables in the expresion with omega expressions.
01248 
01249 static Expression *
01250 _replace_vars_with_omega(Expression * e)
01251 {
01252     if (! e)
01253     return e;
01254 
01255     if (e->op() == ID_OP
01256     && (e->symbol().sym_class() == VARIABLE_CLASS
01257         || e->symbol().sym_class() == SYMBOLIC_CONSTANT_CLASS)) {
01258     delete e;
01259     return omega();
01260     }
01261     else if (e->op() == ARRAY_REF_OP || e->op() == INTRINSIC_CALL_OP
01262          || e->op() == FUNCTION_CALL_OP) {
01263     Expression &params = *e->arg_list().last_ref();
01264     Assign<Expression> eas(e->arg_list().assign(params));
01265     eas = _replace_vars_with_omega(e->arg_list().pull(params));
01266     }
01267     else {
01268     Mutator<Expression> iter(e->arg_list());
01269 
01270     for ( ; iter.valid(); ++iter) {
01271         Assign<Expression> eas(iter.assign());
01272         eas = _replace_vars_with_omega(iter.pull());
01273     }
01274     }
01275 
01276     return e;
01277 }
01278 
01279 
01280 ///  _num_var_occurrences_in_expr
01281 ///    Return the number of times that the given variable occurs in the
01282 ///    given expression.
01283 
01284 static int
01285 _num_var_occurrences_in_expr(const Expression &expr, const Symbol &var)
01286 {
01287     int num_occurrences = 0;
01288 
01289     if (expr.op() == ID_OP) {
01290     if (&var == &expr.symbol())
01291         num_occurrences = 1;
01292     }
01293     else {
01294     Iterator<Expression> iter = expr.arg_list();
01295 
01296     for ( ; iter.valid(); ++iter)
01297         num_occurrences += _num_var_occurrences_in_expr(iter.current(), var);
01298     }
01299 
01300     return num_occurrences;
01301 }
01302 
01303 
01304 ///  _remove_truncates
01305 ///   Replace all subexpressions of the form B*(A/B) with A - MOD(A, B) in
01306 ///   the given expression.
01307 
01308 static Expression *
01309 _remove_truncates1(Expression *expr, const Symbol &var, bool &changed,
01310            Symtab &symtab)
01311 {
01312     /// ...  Remove any truncates from my arguments.
01313 
01314     changed = false;
01315     Mutator<Expression> arg_iter = expr->arg_list();
01316 
01317     for ( ; arg_iter.valid(); ++arg_iter) {
01318     bool arg_changed;
01319     Assign<Expression> eas(arg_iter.assign());
01320     eas = _remove_truncates1(arg_iter.pull(), var,
01321                  arg_changed, symtab);
01322     changed = changed || arg_changed;
01323     }
01324 
01325     /// ...  Remove any top-level truncates.
01326 
01327     if (expr->op() == MULT_OP) {
01328     /// ...  Collect all divisions in the multiplication.
01329 
01330     List<Expression> div_args;
01331     Mutator<Expression> arg_iter = expr->arg_list();
01332 
01333     for ( ; arg_iter.valid(); ++arg_iter)
01334         if (arg_iter.current().op() == DIV_OP
01335         && is_var_in_expr(arg_iter.current(), var))
01336 
01337         div_args.ins_last(arg_iter.grab());
01338 
01339     /// ...  Eliminate as many of these divisions as possible.
01340 
01341     if (expr->arg_list().entries() > 0) {
01342         bool merged_a_truncate = true;
01343         
01344         while (div_args.entries() > 0 && merged_a_truncate) {
01345         merged_a_truncate = false;
01346         Mutator<Expression> div_iter = div_args;
01347         
01348         for ( ; div_iter.valid(); ++div_iter) {
01349             Expression &curr_div = div_iter.current();
01350             Expression *mod = mod_expr(expr->clone(),
01351                            curr_div.right_guarded().clone(),
01352                            symtab);
01353             mod = simplify(mod);
01354             
01355             if (is_integer_zero(*mod)) {
01356             expr = div(expr, curr_div.right_guarded().clone());
01357             Expression *trunc_arg = curr_div.left_guarded().clone();
01358             
01359             if (curr_div.right_guarded().op() != INTEGER_CONSTANT_OP
01360                 || ! is_evenly_divisible(curr_div.left_guarded(),
01361                              curr_div.right_guarded().value()))
01362                 trunc_arg = sub(trunc_arg,
01363                         mod_expr(curr_div.grab_left(),
01364                              curr_div.grab_right(),
01365                              symtab));
01366 
01367             expr = mul(expr, trunc_arg);
01368             div_iter.del();
01369             merged_a_truncate = true;
01370             changed = true;
01371             }
01372 
01373             delete mod;
01374         }
01375         }
01376     }
01377 
01378     /// ...  Put the remaining divisions back into the multiplication expr.
01379 
01380     if (expr->op() != MULT_OP)
01381         expr = new NonBinaryExpr(MULT_OP, expr->type(), expr);
01382 
01383     while (div_args.entries() > 0)
01384         expr->arg_list().ins_last(div_args.grab(0));
01385     }
01386 
01387     return expr;
01388 }
01389 
01390 Expression *
01391 RangeComparator::_remove_truncates(Expression *expr, const Symbol &var)
01392 {
01393     if (expr) {
01394     bool changed;
01395     expr = _remove_truncates1(expr, var, changed, (Symtab &) symtab());
01396 
01397     if (changed) {
01398         expr = simplify(expr);
01399 
01400         if (debug_level() >= 20)
01401         cout << "  delta = (" << *expr << ")"
01402             << " after eliminating truncations for "
01403             << var.name_ref() << endl;
01404     }
01405     }
01406 
01407     return expr;
01408 }
01409 
01410 
01411 ///  _multiply_out_div
01412 ///    Multiply out the given division expression, if possible.  If successful,
01413 ///    the factor used to eliminate the division is multiplied to the given
01414 ///    factor argument and passed back.  More specifically, if the given
01415 ///    expression and factor is A/B and F respectively, where B >= 0,
01416 ///    the returned expression would be A - (A mod B) and the returned factor
01417 ///    would be F*B.  If B < 0, the returned results would be (A mod B) - A and
01418 ///    -F*B.
01419 
01420 static Expression *
01421 _multiply_out_div(Expression *expr, Expression *& factor,
01422           RangeComparator &comparator)
01423 {
01424     p_assert(expr->op() == DIV_OP,
01425          "_multiply_out_div() expects a division expression.");
01426 
01427     factor = 0;
01428     EXPR_SIGN denom_sign = comparator.signz(expr->right_guarded());
01429 
01430     if (denom_sign == POS_NEG_EXPR || denom_sign == ZERO_EXPR)
01431     return expr;
01432 
01433     Expression *new_expr = expr->grab_left();
01434     factor = expr->grab_right();
01435     delete expr;
01436 
01437     if (factor->op() != INTEGER_CONSTANT_OP
01438     || ! is_evenly_divisible(*new_expr, factor->value()))
01439 
01440     new_expr = sub(new_expr, mod_expr(new_expr->clone(), factor->clone(),
01441                       (Symtab &) comparator.symtab()));
01442 
01443     if (denom_sign == NEG_EXPR) {
01444     new_expr = unary_minus(new_expr);
01445     factor = unary_minus(factor);
01446     }
01447 
01448     return new_expr;
01449 }
01450 
01451 
01452 ///  _multiply_out_divs_for_var
01453 ///    If the given var occurs in at least twice in the given expression, and
01454 ///    at least one of the subexpressions it occurs in is a
01455 ///    divide, remove these division expressions by multiplying the entire
01456 ///    expression by the denominators of these subexpressions.
01457 ///    Only division expressions that occur at the top level, sum-of-products
01458 ///    expressions and whose denominator is evenly divisible are considered.
01459 ///    Integer division expressions are handled by transforming B*(A/B) into
01460 ///    A - (A mod B).
01461 ///
01462 ///    You may ask why such a function exists, especially with such a
01463 ///    strange decision procedure for application.  Essentially, the purpose
01464 ///    of this procedure is to collapse expressions like (A/B) - A, where
01465 ///    B > 0, down to A mod B, allowing one to prove that A/B < A if A > 0.
01466 ///    Another case that this procedure handles is B*(100/B) - 100.
01467 
01468 static Expression *
01469 _multiply_out_divs_for_var1(Expression *expr, const Symbol &var,
01470                 Expression *& factor,
01471                 bool multiply_out_divs,
01472                 RangeComparator &comparator)
01473 {
01474     factor = 0;
01475 
01476     if (! expr)
01477     return expr;
01478 
01479     switch (expr->op()) {
01480     case DIV_OP:
01481     {
01482         if (multiply_out_divs && is_var_in_expr(*expr, var))
01483         expr = _multiply_out_div(expr, factor, comparator);
01484     }
01485     break;
01486 
01487     case EXP_OP:
01488     {
01489         const Expression &power = expr->right_guarded();
01490         
01491         if (expr->left_guarded().op() == DIV_OP
01492         && power.op() == INTEGER_CONSTANT_OP
01493         && power.value() > 0) {
01494         
01495         expr->left(_multiply_out_divs_for_var1(expr->grab_left(), var,
01496                                factor,
01497                                multiply_out_divs,
01498                                comparator));
01499         }
01500         
01501         if (factor)
01502         factor = exponent(factor, power.clone());
01503     }
01504     break;
01505 
01506     case MULT_OP:
01507     {
01508         if (! multiply_out_divs)
01509         if (_num_var_occurrences_in_expr(*expr, var) >= 2)
01510             multiply_out_divs = true;
01511         else
01512             return expr;
01513 
01514         Mutator<Expression> term_iter = expr->arg_list();
01515         
01516         for ( ; term_iter.valid(); ++term_iter) {
01517         Expression *term_factor = 0;
01518         Assign<Expression> eas(term_iter.assign());
01519         eas = _multiply_out_divs_for_var1(term_iter.pull(), var,
01520                           term_factor,
01521                           multiply_out_divs,
01522                           comparator);
01523 
01524         if (term_factor)
01525             if (factor)
01526             factor = mul(factor, term_factor);
01527             else
01528             factor = term_factor;
01529         }
01530     }
01531     break;
01532 
01533     case ADD_OP:
01534     case RANGE_OP:
01535     case INTRINSIC_CALL_OP:
01536     {
01537         if (expr->op() == INTRINSIC_CALL_OP && ! is_min_or_max(*expr))
01538         return expr;
01539 
01540         if (! multiply_out_divs && expr->op() == ADD_OP)
01541         if (_num_var_occurrences_in_expr(*expr, var) >= 2)
01542             multiply_out_divs = true;
01543         else
01544             return expr;
01545         
01546         List<Expression> *args;
01547 
01548         if (expr->op() == INTRINSIC_CALL_OP)
01549         args = &expr->parameters_guarded().arg_list();
01550         else
01551         args = &expr->arg_list();
01552         
01553         RefList<Expression> visited_args;
01554         Mutator<Expression> arg_iter = *args;
01555 
01556         for ( ; arg_iter.valid(); ++arg_iter) {
01557         Assign<Expression> argas(arg_iter.assign());
01558         Expression *arg = arg_iter.pull();
01559         Expression *arg_factor = 0;
01560 
01561         arg = _multiply_out_divs_for_var1(arg, var, arg_factor,
01562                           multiply_out_divs,
01563                           comparator);
01564 
01565         /// ...  If a new factor was generated by this argument, multiply all
01566         /// ...  previously visited arguments with this new factor.
01567 
01568         if (factor)
01569             arg = mul(factor->clone(), arg);
01570 
01571         if (arg_factor) {
01572             Iterator<Expression> visited_iter = visited_args;
01573 
01574             for ( ; visited_iter.valid(); ++visited_iter) {
01575             Assign<Expression> eas(args->assign(visited_iter.current()));
01576             eas = mul(arg_factor->clone(),
01577                   args->pull(visited_iter.current()));
01578             }
01579             
01580             if (factor)
01581             factor = mul(factor, arg_factor);
01582             else
01583             factor = arg_factor;
01584         }
01585         
01586         argas = arg;
01587         visited_args.ins_last(*arg);
01588         }
01589     }
01590     break;
01591 
01592     default:
01593     /// ...  Do nothing;
01594     break;
01595     }
01596 
01597     return expr;
01598 }
01599 
01600 static Expression *
01601 _multiply_out_divs_for_var(Expression *expr, const Symbol &var,
01602                RangeComparator &comparator)
01603 {
01604     if (! expr)
01605     return expr;
01606 
01607     Expression *factor = 0;
01608     bool multiply_out_divs = false;
01609     expr = _multiply_out_divs_for_var1(expr, var, factor, multiply_out_divs,
01610                        comparator);
01611     
01612     if (factor) {
01613     /// ...  If factor is non-NULL, then at least one division expression was
01614     /// ...  eliminated from the expression.  So simplify it.
01615 
01616     delete factor;
01617     expr = simplify(expr);
01618 
01619     if (comparator.debug_level() >= 20)
01620         cout << "  delta = (" << *expr << ")"
01621         << " after multiplying out divisions for "
01622             << var.name_ref() << endl;
01623     }
01624 
01625     return expr;
01626 }    
01627 
01628 
01629 
01630 ///  _compare
01631 
01632 Relation
01633 RangeComparator::_compare(Expression *delta)
01634 {
01635     if (_debug_level >= 20)
01636     cout << "  delta = (" << *delta << ")\n";
01637 
01638     bool dummy_range_just_substituted = false;
01639 
01640     if (! _is_comparable(*delta)) {
01641     /// ...  Eliminate all constrained variables in the expression by
01642     /// ...  repeatedly substituting a variable with its range, moving the
01643     /// ...  ranges out so the expression containes no inner ranges
01644     /// ...  and simplifying.
01645 
01646     RefList<Symbol> subst_order;
01647     _generate_subst_order(subst_order, *delta, *this);
01648 
01649     while(! _is_comparable(*delta) && subst_order.entries() > 0) {
01650         dummy_range_just_substituted = false;
01651 
01652         Symbol &var = subst_order[0];
01653         subst_order.del(var);
01654 
01655         /// ...  Substitute variable's range into the expression, move the
01656         /// ...  ranges outwards so that there are no more inner ranges,
01657         /// ...  then simplify.
01658 
01659         if (is_var_in_expr(*delta, var)) {
01660         const Expression *range = get_range_ref(var);
01661         CompareData &compare_data = _compare_data(var);
01662         if (range) {
01663           if (is_unbounded_range(*range)) {
01664             dummy_range_just_substituted = true;
01665             range = 0;
01666           }
01667           else {
01668             if (compare_data.num_subst >= MAX_SUBST)
01669             range = 0;
01670           }
01671         }
01672             
01673         ++compare_data.num_subst;
01674 
01675         if (range && range->op() == RANGE_OP) {
01676             delta = _remove_truncates(delta, var);
01677             delta = _multiply_out_divs_for_var(delta, var, *this);
01678         }
01679 
01680         delta = subst_var_and_simplify(delta, var, range);
01681 
01682         --compare_data.num_subst;
01683 
01684         if (_debug_level >= 20) {
01685             cout << "  delta = (" << *delta << ")"
01686              << " after substituting " << var.name_ref()
01687              << " = (";
01688 
01689             if (range)
01690             cout << *range;
01691             else
01692             cout << "[-Inf:Inf]";
01693 
01694             cout << ")\n";
01695         }
01696         }
01697     }
01698 
01699     if (! _is_comparable(*delta)) {
01700         /// ...  Expression contains unconstrained variables.  So, replace
01701         /// ...  all variables with omega, bubble these omega expressions up
01702         /// ...  through the expression, and simplify.
01703 
01704         delta = _replace_vars_with_omega(delta);
01705         delta = pull_ranges_out(delta, *this);
01706         delta = simplify(delta);
01707 
01708         if (_debug_level >= 20)
01709         cout << "  delta = (" << *delta << ")"
01710             << " after eliminating vars\n";
01711     }
01712     }
01713     
01714     /// ...  Now, determine the relationships of the simplified expression.
01715     /// ...  If the expression is omega and a dummy range was just substituted,
01716     /// ...  indicate that a circular reference was found.  Otherwise, if the
01717     /// ...  the expression is omega or is still not comparable, the default
01718     /// ...  relationship is returned.  (By default, no relationship is known.)
01719 
01720     Relation rel = _determine_relation(*delta, dummy_range_just_substituted, this);
01721     delete delta;
01722 
01723     return rel;
01724 }
01725 
01726 
01727 ///  sign
01728 
01729 EXPR_SIGN
01730 RangeComparator::sign(const Expression &e)
01731 {
01732     EXPR_SIGN sign = signz(e);
01733 
01734     if (sign == ZERO_EXPR)
01735     return POS_EXPR;
01736 
01737     return sign;
01738 }
01739         
01740 EXPR_SIGN
01741 RangeComparator::signz(const Expression &e)
01742 {
01743     EXPR_SIGN my_sign = POS_NEG_EXPR;
01744 
01745     switch (e.op()) {
01746     case ARRAY_REF_OP:
01747     my_sign = POS_NEG_EXPR;
01748     break;
01749 
01750     case RANGE_OP:
01751     {
01752         RangeExpr &range = * (RangeExpr *) &e;
01753         EXPR_SIGN lb_sign = signz(range.lb());
01754         
01755         if (lb_sign == POS_EXPR)
01756         my_sign = POS_EXPR;
01757         else {
01758         EXPR_SIGN ub_sign = signz(range.ub());
01759 
01760         if (ub_sign == NEG_EXPR)
01761             my_sign = NEG_EXPR;
01762         else if (lb_sign == ZERO_EXPR && ub_sign == ZERO_EXPR)
01763             my_sign = ZERO_EXPR;
01764         else if (lb_sign == ZERO_EXPR)
01765             my_sign = POS_EXPR;
01766         else if (ub_sign == ZERO_EXPR)
01767             my_sign = NEG_EXPR;
01768         }
01769     }
01770     break;
01771 
01772     case ID_OP:
01773     {
01774         const Expression *range = get_range_ref(e.symbol());
01775 
01776         if (range) {
01777         CompareData &compare_data = _compare_data(e.symbol());
01778         
01779         if (compare_data.sign_cache == PENDING)
01780             my_sign = POS_NEG_EXPR;
01781         else if (compare_data.sign_cache != UNKNOWN_SIGN)
01782             my_sign = compare_data.sign_cache;
01783         else {
01784             compare_data.sign_cache = PENDING; 
01785             my_sign = signz(*range);
01786             compare_data.sign_cache = my_sign;
01787         }
01788         }
01789     }
01790     break;
01791 
01792     case INTEGER_CONSTANT_OP:
01793     if (e.value() > 0)
01794         my_sign = POS_EXPR;
01795     else if (e.value() == 0)
01796         my_sign = ZERO_EXPR;
01797     else
01798         my_sign = NEG_EXPR;
01799     break;
01800 
01801     case INFINITY_OP:
01802     my_sign = (((InfinityExpr *) &e)->sign() >= 0) ? POS_EXPR : NEG_EXPR;
01803     break;
01804 
01805     case MULT_OP:
01806     {
01807         my_sign = POS_EXPR;
01808         Iterator<Expression> arg_iter = e.arg_list();
01809         
01810         for ( ; arg_iter.valid() && my_sign != POS_NEG_EXPR; ++arg_iter) {
01811         Expression &arg = arg_iter.current();
01812         
01813         if (e.arg_list().next_ref(arg)
01814             && arg == *e.arg_list().next_ref(arg)) {
01815             /// ...  Skip pairs of terms of the form N*N, since they are
01816             /// ...  always positive.
01817 
01818             ++arg_iter;
01819         }
01820         else {
01821             EXPR_SIGN arg_sign = signz(arg);
01822             
01823             if (arg_sign == NEG_EXPR)
01824             my_sign = flip_sign(my_sign);
01825             else if (arg_sign == ZERO_EXPR)
01826             my_sign = ZERO_EXPR;
01827             else if (arg_sign == POS_NEG_EXPR)
01828             my_sign = POS_NEG_EXPR;
01829         }
01830         }
01831     }
01832     break;
01833 
01834     case DIV_OP:
01835     {
01836         my_sign = signz(e.left_guarded());
01837 
01838         if (my_sign == POS_EXPR || my_sign == NEG_EXPR) {
01839         EXPR_SIGN denom_sign = signz(e.right_guarded());
01840 
01841         if (denom_sign == POS_NEG_EXPR || denom_sign == ZERO_EXPR)
01842             my_sign = POS_NEG_EXPR;
01843         else if (denom_sign == NEG_EXPR)
01844             my_sign = flip_sign(my_sign);
01845         }
01846     }
01847     break;
01848 
01849     case EXP_OP:
01850     {
01851         if (e.right_guarded().op() == INTEGER_CONSTANT_OP) {
01852         if (e.right_guarded().value() == 0)
01853             my_sign = POS_EXPR;
01854         else {
01855             EXPR_SIGN base_sign = signz(e.left_guarded());
01856 
01857             if (base_sign == ZERO_EXPR || base_sign == POS_EXPR)
01858             my_sign = base_sign;
01859             else if (e.right_guarded().value() % 2 == 0)
01860             my_sign = POS_EXPR;
01861             else
01862             my_sign = base_sign;
01863         }
01864         }
01865     }
01866     break;
01867 
01868     default:
01869     {   
01870         if (is_max(e)) {
01871         my_sign = UNKNOWN_SIGN;
01872         Iterator<Expression> arg_iter = e.parameters_guarded().arg_list();
01873 
01874         for ( ; arg_iter.valid() && my_sign != POS_EXPR; ++arg_iter) {
01875             EXPR_SIGN arg_sign = signz(arg_iter.current());
01876 
01877             if (my_sign == UNKNOWN_SIGN || my_sign == NEG_EXPR)
01878             my_sign = arg_sign;
01879             else if (arg_sign == POS_EXPR)
01880             my_sign = POS_EXPR;
01881             else if (arg_sign == ZERO_EXPR) {
01882             if (my_sign == POS_NEG_EXPR)
01883                 my_sign = POS_EXPR;
01884             }
01885         }
01886 
01887         if (my_sign == UNKNOWN_SIGN)
01888             my_sign = POS_NEG_EXPR;
01889         }
01890         else if (is_min(e)) {
01891         my_sign = UNKNOWN_SIGN;
01892         Iterator<Expression> arg_iter = e.parameters_guarded().arg_list();
01893 
01894         for ( ; arg_iter.valid() && my_sign != NEG_EXPR; ++arg_iter) {
01895             EXPR_SIGN arg_sign = signz(arg_iter.current());
01896 
01897             if (my_sign == UNKNOWN_SIGN || my_sign == POS_EXPR)
01898             my_sign = arg_sign;
01899             else if (arg_sign == NEG_EXPR)
01900             my_sign = NEG_EXPR;
01901             else if (arg_sign == ZERO_EXPR) {
01902             if (my_sign == POS_NEG_EXPR)
01903                 my_sign = NEG_EXPR;
01904             }
01905         }
01906 
01907         if (my_sign == UNKNOWN_SIGN)
01908             my_sign = POS_NEG_EXPR;
01909         }
01910         else if (is_mod(e)) {
01911         my_sign = signz(e.parameters_guarded().arg_list()[0]);
01912         }
01913         else if (is_abs(e)) {
01914         my_sign = signz(e.parameters_guarded().arg_list()[0]);
01915 
01916         if (my_sign != ZERO_EXPR && my_sign != POS_EXPR)
01917             my_sign = POS_EXPR;
01918         }
01919         else {
01920         const Expression *cached_expr = _cached_sign_exprs.representative(CASTAWAY(Expression &) e);
01921 
01922         if (cached_expr)
01923             my_sign = (EXPR_SIGN) _cached_expr_signs[*cached_expr].value();
01924         else {
01925             Relation rel = compare(e, 0);
01926             
01927             if (rel.is_equal())
01928             my_sign = ZERO_EXPR;
01929             else if (rel.is_greater_equal())
01930             my_sign = POS_EXPR;
01931             else if (rel.is_less_equal())
01932             my_sign = NEG_EXPR;
01933 
01934             if (_cache_expr_signs > 0) {
01935             cached_expr = &_cached_sign_exprs.ins(e.clone());
01936             _cached_expr_signs.ins(*cached_expr, new IntElem((int) my_sign));
01937             }
01938         }
01939         }
01940     }
01941     break;
01942     }
01943 
01944     if (_debug_level >= 10) {
01945     cout << "Sign of (" << e << ") is ";
01946 
01947     switch (my_sign) {
01948     case POS_EXPR:   cout << "positive\n";   break;
01949     case NEG_EXPR:   cout << "negative\n";   break; 
01950     case ZERO_EXPR:  cout << "zero\n";       break;
01951     default:         cout << "unknown\n";    break;
01952         }
01953     }
01954 
01955     return my_sign;
01956 }
01957 
01958 
01959 /// forward_diff
01960 ///   Return the forward difference of the given expression for the given
01961 ///   value.  That is, if the expression can be represented as a function
01962 ///   f(i,j,k,...), where i,j,k,... are variables, then the forward
01963 ///   difference for j is f(i,j+1,k,...) - f(i,j,k,...).
01964    
01965 static Expression *
01966 _forward_diff(const Expression &e, const Symbol &var)
01967 {
01968     Expression *var_plus_1 = add(constant(1),
01969                  id(CASTAWAY(Symbol &) var));
01970     Expression *expr_step = substitute_var(e.clone(), var, *var_plus_1);
01971     delete var_plus_1;
01972     return simplify(sub(expr_step, e.clone()));
01973 }
01974 
01975 
01976 /// var_power_in_expr
01977 ///   Return the maximum power of the given variable in the given expression.
01978 
01979 static int
01980 _var_power_in_expr(const Expression &expr, const Symbol &var)
01981 {
01982     int var_power = 0;
01983 
01984     switch (expr.op()) {
01985     case ID_OP:
01986         if (&expr.symbol() == &var)
01987             var_power = 1;
01988 
01989         break;
01990 
01991     case MULT_OP:
01992         {
01993             Iterator<Expression> arg_iter = expr.arg_list();
01994             
01995             for ( ; arg_iter.valid(); ++arg_iter)
01996                 var_power += _var_power_in_expr(arg_iter.current(), var);
01997         }
01998         break;
01999 
02000     case EXP_OP:
02001         var_power = _var_power_in_expr(expr.left_guarded(), var);
02002         
02003         if (expr.right_guarded().op() == INTEGER_CONSTANT_OP)
02004             var_power = var_power * expr.right_guarded().value();
02005 
02006         break;
02007 
02008     default:
02009         {
02010             Iterator<Expression> arg_iter = expr.arg_list();
02011             
02012             for ( ; arg_iter.valid(); ++arg_iter) {
02013         int arg_power = _var_power_in_expr(arg_iter.current(), var);
02014                 var_power = max(var_power, arg_power);
02015         }
02016         }
02017         break;
02018     }
02019 
02020     return var_power;
02021 }
02022 
02023 
02024 /// monotonicity_for_var
02025 ///   Return whether the given expression is monotonically increasing or
02026 ///   decreasing for the given variable.
02027 
02028 enum _MONO_STATE {
02029     _NON_MONO,          /// ...  Expression is not monotonic
02030     _MONO_DEC,          /// ...  Expression is monotonically decreasing
02031     _MONO_INC,          /// ...  Expression is monotonically increasing
02032 };
02033 
02034 static _MONO_STATE
02035 _monotonicity_for_var(const Expression &expr, const Symbol &var,
02036               RangeComparator &comparator)
02037 {
02038     if (comparator.debug_level() >= 30)
02039     cout << "    testing monotonicity of " << expr << " for "
02040         << var.name_ref() << endl;
02041 
02042     _MONO_STATE mono = _NON_MONO;
02043     int var_power = _var_power_in_expr(expr, var);
02044     Expression *diff = _forward_diff(expr, var);
02045     int diff_power = _var_power_in_expr(*diff, var);
02046 
02047     if (abs(diff_power) < abs(var_power)) {
02048     switch (comparator.sign(*diff)) {
02049         case POS_EXPR:   mono = _MONO_INC;   break;
02050         case NEG_EXPR:   mono = _MONO_DEC;   break;
02051         default:         mono = _NON_MONO;   break;
02052         }
02053     }
02054 
02055     delete diff;
02056 
02057     return mono;
02058 }
02059 
02060 
02061 ///  substitute_mono_var
02062 ///    Substitute the given substitution expression for the given variable
02063 ///    in the given expression, where the given expression is either
02064 ///    monotonically increasing or monotonically decreasing.  This method
02065 ///    uses the given monotonicity information to substitute expressions
02066 ///    containing mins and maxes at their top level more accurately.
02067 
02068 static Expression *
02069 _substitute_mono_var1(Expression *expr, const Symbol &var,
02070               const Expression &mono_function, bool var_is_mono_inc,
02071               const Symtab &symtab)
02072 {
02073     Expression *new_expr = 0;
02074 
02075     if (! is_min_or_max(*expr)) {
02076     new_expr = substitute_var(mono_function.clone(), var, *expr);
02077     delete expr;
02078     }
02079     else {
02080     if (! var_is_mono_inc)
02081         swap_min_max(*expr, symtab);
02082 
02083     Mutator<Expression> arg_iter = expr->parameters_guarded().arg_list();
02084 
02085     for ( ; arg_iter.valid(); ++arg_iter) {
02086         Assign<Expression> eas(arg_iter.assign());
02087         eas = _substitute_mono_var1(arg_iter.pull(), var,
02088                     mono_function,
02089                     var_is_mono_inc, symtab);
02090     }
02091 
02092     new_expr = expr;
02093     }
02094 
02095     return new_expr;
02096 }
02097 
02098 static Expression *
02099 _substitute_mono_var(Expression *expr, const Symbol &var,
02100              const Expression &subst_expr, bool var_is_mono_inc,
02101              const Symtab &symtab)
02102 {
02103     Expression *new_expr = 0;
02104 
02105     if (! is_min_or_max(subst_expr))
02106     new_expr = substitute_var(expr, var, subst_expr);
02107     else {
02108     new_expr = _substitute_mono_var1(subst_expr.clone(), var, *expr,
02109                      var_is_mono_inc, symtab);
02110     delete expr;
02111     }
02112 
02113     return new_expr;
02114 }
02115 
02116 
02117 ///  solve_monotonic
02118 ///    If the given expression is monotonically increasing or monotonically
02119 ///    decreasing for the given variable, calculate the resulting range of
02120 ///    the expression by substituting the lower and upper bounds of the
02121 ///    variables range into the expression.  If this function fails, it
02122 ///    returns NULL.
02123 
02124 Expression *
02125 RangeComparator::_solve_monotonic(Expression *expr, const Symbol &var,
02126                  const RangeExpr &subst_range)
02127 {
02128     Expression *new_expr = 0;
02129     CompareData &compare_data = _compare_data(var);
02130     --compare_data.num_subst;
02131     _MONO_STATE mono = _monotonicity_for_var(*expr, var, *this);
02132     ++compare_data.num_subst;
02133 
02134 
02135     if (mono != _NON_MONO) {
02136     if (_debug_level >= 30)
02137         cout << "    solve_monotonic(expr=" << *expr << ", var="
02138         << var.name_ref() << ", subst_range=" << subst_range << ") = ";
02139 
02140     Expression *bound1 = 0;
02141     Expression *bound2 = 0;
02142 
02143     if (subst_range.has_lb())
02144         bound1 = _substitute_mono_var(expr->clone(), var, subst_range.lb(),
02145                       mono == _MONO_INC, symtab());
02146        
02147     if (subst_range.has_ub())
02148         bound2 = _substitute_mono_var(expr, var, subst_range.ub(),
02149                       mono == _MONO_INC, symtab());
02150     else
02151         delete expr;
02152 
02153     if (mono == _MONO_INC)
02154         new_expr = new RangeExpr(bound1, bound2);
02155     else
02156         new_expr = new RangeExpr(bound2, bound1);
02157 
02158     if (_debug_level >= 30)
02159         cout << *new_expr << endl;
02160     }
02161 
02162     return new_expr;
02163 }
02164 
02165 
02166 ///  subst_mods_with_var
02167 ///    Replace the left hand side of modulo operations that contain the given
02168 ///    variable with the given expression.  Return true if the expression
02169 ///    contained such a modulo operation
02170 
02171 static bool
02172 _subst_mods_with_var(Expression &expr, const Symbol &var,
02173              const Expression &subst_expr)
02174 {
02175     bool has_mods_with_var = false;
02176 
02177     if (expr.op() == INTRINSIC_CALL_OP
02178     && strcmp(expr.intrinsic().symbol().name_ref(), "MOD") == 0
02179     && is_var_in_expr(expr.parameters_guarded(), var)) {
02180 
02181     Assign<Expression> eas(expr.parameters_guarded().arg_list().assign(0));
02182     eas = substitute_var(expr.parameters_guarded().arg_list().pull(0),
02183                  var, subst_expr);
02184     has_mods_with_var = true;
02185     }
02186     else {
02187     Iterator<Expression> arg_iter = expr.arg_list();
02188 
02189     for ( ; arg_iter.valid(); ++arg_iter) {
02190         bool arg_has_mods_with_var
02191         = _subst_mods_with_var(arg_iter.current(), var, subst_expr);
02192         has_mods_with_var = has_mods_with_var || arg_has_mods_with_var;
02193     }
02194     }
02195 
02196     return has_mods_with_var;
02197 }
02198 
02199 
02200 ///  remove_mods_with_var
02201 ///    Transform all modulo operations that contain the given variable into
02202 ///    ranges.
02203 
02204 static Expression *
02205 _remove_mods_with_var(Expression *expr, const Symbol &var,
02206               const Expression &subst_expr,
02207               RangeComparator &comparator)
02208 {
02209     bool has_mods_with_var = _subst_mods_with_var(*expr, var, subst_expr);
02210 
02211     if (has_mods_with_var) {
02212     expr = pull_ranges_out(expr, comparator);
02213     expr = pull_min_max_out(expr, comparator);
02214     expr = simplify(expr);
02215     }
02216 
02217     return expr;
02218 }
02219 
02220 
02221 ///  _member_exp_ref
02222 ///    If the variable, or a power of it, is the given expression or is
02223 ///    a term of a multiplication expression, return the term.  Otherwise,
02224 ///    return NULL.
02225 
02226 static Expression *
02227 _member_exp_ref(Expression &expr, const Symbol &var)
02228 {
02229     if (expr.op() == ID_OP
02230     && &expr.symbol() == &var)
02231 
02232     return &expr;
02233     else if (expr.op() == EXP_OP
02234          && expr.left_guarded().op() == ID_OP
02235          && &expr.left_guarded().symbol() == &var
02236          && expr.right_guarded().op() == INTEGER_CONSTANT_OP
02237          && expr.right_guarded().value() > 0)
02238     return &expr;
02239     else if (expr.op() == MULT_OP) {
02240     Iterator<Expression> iter = expr.arg_list();
02241 
02242     for ( ; iter.valid(); ++iter)
02243         if (iter.current().op() != MULT_OP) {
02244         Expression *arg_member = _member_exp_ref(iter.current(), var);
02245 
02246         if (arg_member)
02247             return arg_member;
02248         }
02249     }
02250 
02251     return 0;
02252 }
02253 
02254 
02255 ///  _factor_out_var
02256 ///    Factor out the given variable from the top level ofgiven expression.
02257 ///    For example, the factored form of the expression "x*a + x*b + c"
02258 ///    for variable x is "x*(a + b) + c".
02259 
02260 static Expression *
02261 _factor_out_var_top(Expression *expr, const Symbol &var)
02262 {
02263     Expression *new_expr = expr;
02264 
02265     if (expr->op() == ADD_OP) {
02266     Set<Expression> args_with_var;
02267 
02268     Mutator<Expression> arg_iter = expr->arg_list();
02269 
02270     for ( ; arg_iter.valid(); ++arg_iter)
02271         if (_member_exp_ref(arg_iter.current(), var))
02272         args_with_var.ins(arg_iter.grab());
02273 
02274     if (args_with_var.entries() == 1)
02275         expr->arg_list().ins_last(args_with_var.grab());
02276     else if (args_with_var.entries() > 1) {
02277         Expression *factored_expr = new NonBinaryExpr(ADD_OP, expr->type());
02278 
02279         while (args_with_var.entries()) {
02280         Expression *arg = args_with_var.grab();
02281         Expression *factored_arg = 0;
02282         
02283         if (arg->op() == ID_OP) {
02284             delete arg;
02285             factored_arg = constant(1);
02286         }
02287         else if (arg->op() == MULT_OP) {
02288             Expression *term = _member_exp_ref(*arg, var);
02289             p_assert(term, "Internal error.");
02290 
02291             if (term->op() == ID_OP)
02292             arg->arg_list().del(*term);
02293             else {
02294             p_assert(term->op() == EXP_OP, "Internal error.");
02295             int power = term->right_guarded().value();
02296             -- power;
02297             term->right_guarded().value(power);
02298 
02299             if (power == 0)
02300                 arg->arg_list().del(*term);
02301             else if (power == 1)
02302                 arg->arg_list().modify(*term, term->grab_left());
02303             }
02304 
02305             if (arg->arg_list().entries() == 1) {
02306             factored_arg = arg->arg_list().grab(*arg->arg_list().first_ref());
02307             delete arg;
02308             }
02309             else
02310             factored_arg = arg;
02311         }
02312         else if (arg->op() == EXP_OP) {
02313             int power = arg->right_guarded().value();
02314             --power;
02315             arg->right_guarded().value(power);
02316 
02317             if (power == 0) {
02318             delete arg;
02319             factored_arg = constant(1);
02320             }
02321             else if (power == 1) {
02322             factored_arg = arg->grab_left();
02323             delete arg;
02324             }
02325             else
02326             factored_arg = arg;
02327         }
02328         else
02329             p_abort("_factor_out_var_top() attempted to factor a non-scalar variable.");
02330 
02331         factored_expr->arg_list().ins_last(factored_arg);
02332         }
02333 
02334         factored_expr = _factor_out_var_top(factored_expr, var);
02335         factored_expr = mul(id(CASTAWAY(Symbol &) var), factored_expr);
02336 
02337         if (expr->arg_list().entries() == 0) {
02338         delete expr;
02339         new_expr = factored_expr;
02340         }
02341         else
02342         expr->arg_list().ins_last(factored_expr);
02343     }
02344     }
02345 
02346     return new_expr;
02347 }
02348 
02349 
02350 ///  _factor_out_var
02351 ///    Factor out the given variable from the given expression.  For example,
02352 ///    the factored form of the expression "x*a + x*b + c" for variable x is
02353 ///    "x*(a + b) + c".
02354 
02355 static Expression *
02356 _factor_out_var(Expression *expr, const Symbol &var)
02357 {
02358     if (! expr)
02359     return expr;
02360 
02361     Mutator<Expression> arg_iter = expr->arg_list();
02362 
02363     for ( ; arg_iter.valid(); ++arg_iter) {
02364     Assign<Expression> eas(arg_iter.assign());
02365     eas = _factor_out_var(arg_iter.pull(), var);
02366     }
02367 
02368     return _factor_out_var_top(expr, var);
02369 }
02370 
02371 
02372 ///  solve_linear_expr
02373 ///    Solve the given expression for the given variable.  The expression
02374 ///    is assumed to be linear for the given variable.
02375 
02376 static Expression *
02377 _solve_linear_expr(Expression *e, const Symbol &var,
02378            RangeComparator &comparator)
02379 {
02380     /// ...  Pull the terms containing var out of the expression.
02381 
02382     Expression *var_term = 0;
02383 
02384     if (e->op() != ADD_OP) {
02385     var_term = e;
02386     e = constant(0);
02387     }
02388     else {
02389     var_term = new NonBinaryExpr(ADD_OP, e->type());
02390 
02391     Mutator<Expression> arg_iter = e->arg_list();
02392 
02393     for ( ; arg_iter.valid(); ++arg_iter)
02394         if (is_var_in_expr(arg_iter.current(), var))
02395         var_term->arg_list().ins_last(arg_iter.grab());
02396 
02397     if (e->arg_list().entries() == 0) {
02398         delete e;
02399         e = constant(0);
02400     }
02401     else if (e->arg_list().entries() == 1) {
02402         Expression *arg = e->arg_list().grab(
02403         *e->arg_list().first_ref());
02404         delete e;
02405         e = arg;
02406     }
02407 
02408     p_assert(var_term->arg_list().entries() > 0,
02409          "Internal error: Expression doesn't contain variable.");
02410 
02411     if (var_term->arg_list().entries() == 1) {
02412         Expression *arg = var_term->arg_list().grab(
02413         *var_term->arg_list().first_ref());
02414         delete var_term;
02415         var_term = arg;
02416     }
02417     }
02418 
02419     /// ...  Factor out the variable from var_term.
02420 
02421     if (var_term->op() == ADD_OP)
02422     var_term = _factor_out_var(var_term, var);
02423 
02424     e = unary_minus(e);
02425 
02426     if (var_term->op() == ID_OP) {
02427     delete var_term;
02428     }
02429     else if (var_term->op() == MULT_OP) {
02430     /// ...  Compute the divisor of the solution.
02431 
02432     Mutator <Expression> arg_iter = var_term->arg_list();
02433 
02434     for ( ; arg_iter.valid(); ++arg_iter)
02435         if (arg_iter.current().op() == ID_OP
02436         && &arg_iter.current().symbol() == &var) {
02437 
02438         arg_iter.del();
02439         break;
02440         }
02441 
02442     if (is_var_in_expr(*var_term, var)) {
02443         delete e;
02444         delete var_term;
02445         return 0;
02446     }
02447 
02448     if (var_term->arg_list().entries() == 1) {
02449         Expression *arg = var_term->arg_list().grab(
02450         *var_term->arg_list().first_ref());
02451         delete var_term;
02452         var_term = arg;
02453     }
02454 
02455     EXPR_SIGN term_sign = comparator.sign(*var_term);
02456 
02457     if (term_sign == POS_NEG_EXPR) {
02458         delete var_term;
02459         delete e;
02460         return 0;
02461     }
02462 
02463     EXPR_SIGN e_sign = comparator.sign(*e);
02464 
02465     if (e_sign == POS_NEG_EXPR) {
02466         delete var_term;
02467         delete e;
02468         return 0;
02469     }
02470     else if (e_sign == NEG_EXPR)
02471         term_sign = flip_sign(term_sign);       
02472 
02473     e = div(e, var_term);
02474 
02475     /// ...  We want e to be rounded upwards.  So if e
02476     /// ...  is positive, add one to it.
02477 
02478     if (term_sign == POS_EXPR)
02479         e = add(constant(1), e);
02480 
02481     e = simplify(e);
02482     }
02483 
02484     return e;
02485 }
02486     
02487 
02488 ///  find_quad_range
02489 ///    Try to find the exact range for the given expression, variable and
02490 ///    substitution range, where the expression is quadratic in terms of the
02491 ///    variable.  If it can find it, it returns this exact range.
02492 ///    Otherwise, it returns NULL
02493 
02494 Expression *
02495 RangeComparator::_find_quad_range(const Expression &e, const Symbol &var,
02496                   const RangeExpr &subst_range)
02497 {
02498     int var_power = _var_power_in_expr(e, var);
02499 
02500     if (var_power != 2)
02501     return NULL;
02502 
02503     /// ...  Take the forward difference of the expression.  The forward difference
02504     /// ...  is an approximation of the derivative of e.
02505 
02506     Expression *forward_diff = _forward_diff(e, var);
02507 
02508     int diff_var_power = _var_power_in_expr(*forward_diff, var);
02509 
02510     if (diff_var_power >= var_power) {
02511     delete forward_diff;
02512     return 0;
02513     }
02514 
02515     /// ...  Solve forward_diff = 0 for var.
02516 
02517     Expression *root = _solve_linear_expr(forward_diff->clone(), var, *this);
02518 
02519     if (! root) {
02520     delete forward_diff;
02521     return 0;
02522     }
02523 
02524     /// ...  Determine whether root falls within bounds of variable.  If not,
02525     /// ...  abort.
02526 
02527     if ((subst_range.has_lb()
02528      && ! compare(subst_range.lb(), *root).is_less_equal())
02529     || (subst_range.has_ub()
02530         && ! compare(*root, subst_range.ub()).is_less_equal())) {
02531 
02532     delete forward_diff;
02533     delete root;
02534     return 0;
02535     }
02536 
02537     /// ...  Determine whether the root is a minimum or maximum.
02538 
02539     Expression *forward_diff_diff = _forward_diff(*forward_diff, var);
02540     
02541     if (is_var_in_expr(*forward_diff_diff, var)) {
02542     delete forward_diff_diff;
02543     delete forward_diff;
02544     delete root;
02545     return 0;
02546     }
02547     
02548     bool root_is_min = (sign(*forward_diff_diff) == POS_EXPR);
02549     delete forward_diff_diff;
02550     delete forward_diff;
02551 
02552     /// ...  Generate the new range from this root.
02553 
02554     Expression *border_lb, *border_ub;
02555 
02556     if (root_is_min) {
02557     border_lb = _substitute_mono_var(e.clone(), var, subst_range.lb(),
02558                      false, symtab());
02559     border_ub = _substitute_mono_var(e.clone(), var, subst_range.ub(),
02560                      true, symtab());
02561     }
02562     else {
02563     border_lb = _substitute_mono_var(e.clone(), var, subst_range.lb(),
02564                      true, symtab());
02565     border_ub = _substitute_mono_var(e.clone(), var, subst_range.ub(),
02566                      false, symtab());
02567     }
02568 
02569     border_lb = simplify(border_lb);
02570     border_ub = simplify(border_ub);
02571     Relation border_rel = compare(*border_lb, *border_ub);
02572 
02573     if (border_rel.is_greater_equal()) {
02574     Expression *temp = border_lb;
02575     border_lb = border_ub;
02576     border_ub = temp;
02577     }
02578     else if (border_rel.is_unknown()) {
02579     delete border_lb;
02580     delete border_ub;
02581     border_lb = 0;
02582     border_ub = 0;
02583     }
02584 
02585     Expression *root_bound = simplify(substitute_var(e.clone(), var,
02586                              *root));
02587     delete root;
02588     Expression *result;
02589     
02590     if (root_is_min) {
02591     result = new RangeExpr(root_bound, border_ub);
02592     if (border_lb) delete border_lb;
02593     }
02594     else {
02595     result = new RangeExpr(border_lb, root_bound);
02596     if (border_ub) delete border_ub;
02597     }
02598 
02599     return result;
02600 }
02601 
02602 
02603 ///  num_args_with_var
02604 ///    Return the number of arguments that contain the given variable.
02605 
02606 static int
02607 _num_args_with_var(const Expression &expr, const Symbol &var)
02608 {
02609     int num_args_with_var = 0;
02610 
02611     Iterator<Expression> iter = expr.arg_list();
02612 
02613     for ( ; iter.valid(); ++iter)
02614     if (is_var_in_expr(iter.current(), var))
02615         ++num_args_with_var;
02616 
02617     return num_args_with_var;
02618 }
02619 
02620 
02621 ///  is_aritmetic_expr
02622 ///    Return true if the top level expression is some sort of arithmetic
02623 ///    operator.
02624 
02625 static bool
02626 _is_arithmetic_expr(const Expression &expr)
02627 {
02628     OP_TYPE op = expr.op();
02629 
02630     return (op == ADD_OP || op == SUB_OP || op == MULT_OP || op == DIV_OP
02631         || op == EXP_OP);
02632 }
02633 
02634 
02635 ///  eliminate_quads
02636 ///    Eliminate any quadratic equations from the function.
02637 
02638 Expression *
02639 RangeComparator::_eliminate_quads(Expression *expr, const Symbol &var,
02640                  const RangeExpr &subst_range)
02641 {
02642     if (! expr)
02643     return expr;
02644 
02645     int var_power = _var_power_in_expr(*expr, var);
02646 
02647     if (var_power < 2)
02648     return expr;
02649 
02650     int num_args_with_var = _num_args_with_var(*expr, var);
02651 
02652     if (var_power > 2 || num_args_with_var < 2
02653     || ! _is_arithmetic_expr(*expr)) {
02654 
02655     if (var_power > 2 && num_args_with_var >= 2
02656         && _is_arithmetic_expr(*expr))
02657 
02658         expr = _factor_out_var(expr, var);
02659 
02660     Mutator<Expression> arg_iter = expr->arg_list();
02661 
02662     for ( ; arg_iter.valid(); ++arg_iter) {
02663         Assign<Expression> eas(arg_iter.assign());
02664         eas = _eliminate_quads(arg_iter.pull(), var,
02665                    subst_range);
02666     }
02667     }
02668     else {
02669     if (_debug_level >= 30)
02670         cout << "    eliminate_quads(expr=" << *expr << ", var="
02671         << var.name_ref() << ", subst_range=" << subst_range << ") {\n";
02672 
02673     if (expr->op() == RANGE_OP) {
02674         RangeExpr &range = * (RangeExpr *) expr;
02675         Expression *new_lb = _find_quad_range(range.lb(), var, subst_range);
02676         if (new_lb)
02677         range.lb(new_lb);
02678 
02679         Expression *new_ub = _find_quad_range(range.ub(), var, subst_range);
02680         if (new_ub)
02681         range.ub(new_ub);
02682     }
02683     else {
02684         Expression *new_expr = _find_quad_range(*expr, var, subst_range);
02685         
02686         if (new_expr) {
02687         delete expr;
02688         expr = new_expr;
02689         }
02690     }
02691 
02692     if (_debug_level >= 30)
02693         cout << "    }  result(elim quads): " << *expr << endl;
02694     }
02695 
02696     return expr;
02697 }
02698     
02699 
02700 ///  solve_for_range
02701 ///    Try to determine the exact lower and upper bounds of the given
02702 ///    expression for the given range of values taken by the given variable.
02703 
02704 Expression *
02705 RangeComparator::_solve_for_range(Expression *expr, const Symbol &var,
02706                  const RangeExpr &subst_range)
02707 {
02708     if (! expr)
02709     return expr;
02710 
02711     if (! _is_arithmetic_expr(*expr)) {
02712     Mutator<Expression> arg_iter = expr->arg_list();
02713 
02714     for ( ; arg_iter.valid(); ++arg_iter) {
02715         Assign<Expression> eas(arg_iter.assign());
02716         eas = _solve_for_range(arg_iter.pull(), var,
02717                    subst_range);
02718     }
02719 
02720     /// ...  Assume that the expression forming the range-op
02721     /// ...  is monotonic (_solve_monotonic checks that).
02722     /// ...  That means that we just have to check the two
02723     /// ...  end-points of the range against the other expression.
02724 
02725     if (is_relational_op(expr->op()) &&
02726         (expr->arg_list()[0].op() == RANGE_OP)) {
02727 
02728         Expression *new_expr;
02729 
02730         switch (expr->op()) 
02731         {
02732         case LE_OP:
02733             new_expr = and(le(expr->arg_list()[0].arg_list()[0].clone(),
02734                       expr->arg_list()[1].clone()),
02735                    le(expr->arg_list()[0].arg_list()[1].clone(),
02736                       expr->arg_list()[1].clone()));
02737             delete expr;
02738 
02739             expr = new_expr;
02740             break;
02741         case LT_OP:
02742             new_expr = and(lt(expr->arg_list()[0].arg_list()[0].clone(),
02743                       expr->arg_list()[1].clone()),
02744                    lt(expr->arg_list()[0].arg_list()[1].clone(),
02745                       expr->arg_list()[1].clone()));
02746             delete expr;
02747 
02748             expr = new_expr;
02749             break;
02750         case GE_OP:
02751             new_expr = and(ge(expr->arg_list()[0].arg_list()[0].clone(),
02752                       expr->arg_list()[1].clone()),
02753                    ge(expr->arg_list()[0].arg_list()[1].clone(),
02754                       expr->arg_list()[1].clone()));
02755             delete expr;
02756 
02757             expr = new_expr;
02758             break;
02759         case GT_OP:
02760             new_expr = and(gt(expr->arg_list()[0].arg_list()[0].clone(),
02761                       expr->arg_list()[1].clone()),
02762                    gt(expr->arg_list()[0].arg_list()[1].clone(),
02763                       expr->arg_list()[1].clone()));
02764             delete expr;
02765 
02766             expr = new_expr;
02767             break;
02768         default:
02769             break;
02770         }
02771     }    
02772     }
02773     else if (_num_var_occurrences_in_expr(*expr, var) > 1) {
02774     Expression *new_expr = _solve_monotonic(expr, var, subst_range);
02775     
02776     if (new_expr)
02777         expr = new_expr;
02778     else if (range_compare_accuracy() >= 2)
02779         expr = _eliminate_quads(expr, var, subst_range);
02780     }
02781 
02782     return expr;
02783 }
02784     
02785 
02786 ///  subst_var_outside_array_refs
02787 ///    Like substitute_var() except that variables inside array references
02788 ///    cannot be substituted by a range.
02789 
02790 Expression *
02791 _subst_var_outside_array_refs(Expression *expr, const Symbol &var,
02792                   const Expression &subst_expr)
02793 {
02794     if (expr->op() == ID_OP) {
02795     if (&expr->symbol() == &var) {
02796         delete expr;
02797         return subst_expr.clone();
02798     }
02799     }
02800     else {
02801     Mutator<Expression> iter = expr->arg_list();
02802 
02803     if (expr->op() == ARRAY_REF_OP && subst_expr.op() == RANGE_OP) {
02804         Assign<Expression> eas(iter.assign());
02805         eas = _subst_var_outside_array_refs(iter.pull(), var,
02806                         subst_expr);
02807     }
02808     else {
02809         for ( ; iter.valid(); ++iter) {
02810         Assign<Expression> eas2(iter.assign());
02811         eas2 = _subst_var_outside_array_refs(iter.pull(), var,
02812                             subst_expr);
02813         }
02814     }
02815     }
02816 
02817     return expr;
02818 }
02819 
02820 
02821 ///  subst_var_and_simplify
02822 
02823 Expression *
02824 RangeComparator::subst_var_and_simplify(Expression *e, const Symbol &var,
02825                        const Expression *subst_expr)
02826 {
02827     if (subst_expr && is_empty_range(*subst_expr)) {
02828     if (e)
02829         delete e;
02830 
02831     e = new RangeExpr(constant(1), constant(0));
02832     }
02833     else if (e) {
02834     if (_debug_level >= 30) {
02835         cout << "    subst_var_and_simplify(e=" << *e << ", var="
02836         << var.name_ref() << ", subst_expr=";
02837 
02838         if (subst_expr)
02839         cout << *subst_expr << ");\n";
02840         else
02841         cout << "NULL);\n";
02842     }
02843 
02844     if (_stats)
02845         _stats->making_a_var_subst();
02846 
02847     if (subst_expr) {
02848         if (subst_expr->op() == RANGE_OP
02849         && _use_the_big_guns) {
02850 
02851         if (range_compare_accuracy() < 3)
02852             _use_the_big_guns = false;
02853 
02854         e = _remove_mods_with_var(e, var, *subst_expr, *this);
02855         e = _solve_for_range(e, var, * (RangeExpr *) subst_expr);
02856         _use_the_big_guns = true;
02857         }
02858 
02859         e = substitute_var(e, var, *subst_expr);
02860     }
02861     else {
02862         Expression *om = omega();
02863         e = substitute_var(e, var, *om);
02864         delete om;
02865     }
02866 
02867     if (_debug_level >= 30)
02868         cout << "      e = " << *e << " after substituting\n";
02869     
02870     if (! subst_expr
02871         || subst_expr->op() == RANGE_OP
02872         || subst_expr->op() == OMEGA_OP) {
02873         
02874         e = pull_ranges_out(e, *this);
02875 
02876         if (_debug_level >= 30)
02877         cout << "      e = " << *e << " after pulling out ranges\n";
02878     }
02879     
02880     e = pull_min_max_out(e, *this);
02881 
02882     if (_debug_level >= 30)
02883         cout << "      e = " << *e << " after pulling out min/max\n";
02884     
02885     e = expr_expand_substituted(e);
02886     e = simplify(e);
02887 
02888     if (_debug_level >= 30)
02889         cout << "      e = " << *e << " after simplifying\n";
02890     }
02891 
02892     return e;
02893 }
02894 
02895 
02896 ///  remove_truncates_with_var
02897 
02898 Expression *
02899 RangeComparator::remove_truncates_with_var(Expression *e,
02900                        const Symbol &var)
02901 {
02902     if (e) {
02903     e = _remove_truncates(e, var);
02904     const Expression *subst_range = get_range_ref(var);
02905 
02906     if (subst_range)
02907         e = _remove_mods_with_var(e, var, *subst_range, *this);
02908     else {
02909         Expression *om = omega();
02910         e = _remove_mods_with_var(e, var, *om, *this);
02911         delete om;
02912     }
02913     }
02914 
02915     return e;
02916 }
02917 
02918 
02919 ///  eliminate_vars
02920 
02921 Expression *
02922 RangeComparator::eliminate_vars(Expression *e,
02923                const RefSet<Symbol> *vars_to_eliminate)
02924 {
02925     if (vars_to_eliminate && vars_to_eliminate->entries() == 0)
02926     return e;
02927 
02928     e = expr_expand_substituted(e);
02929     e = simplify(e);
02930 
02931     if (_debug_level >= 1) {
02932     cout << "Eliminating vars {";
02933 
02934     if (vars_to_eliminate)
02935         for(Iterator<Symbol> iter = vars_to_eliminate; iter.valid(); ++iter)
02936         cout << iter.current().name_ref() << ", ";
02937     else
02938         cout << "<all vars>";
02939 
02940     cout << "} from (" << *e << ") {\n";
02941     }
02942 
02943     RefList<Symbol> subst_order;
02944     _generate_subst_order(subst_order, *e, *this);
02945 
02946     while(subst_order.entries() > 0) {
02947     Symbol &var = subst_order.grab(0);
02948 
02949     if ((! vars_to_eliminate || vars_to_eliminate->member(var))
02950         && is_var_in_expr(*e, var)) {
02951 
02952         const Expression *range = get_range_ref(var);
02953 
02954         if (range && range->op() == RANGE_OP)
02955         e = _remove_truncates(e, var);
02956 
02957         e = subst_var_and_simplify(e, var, range);
02958 
02959         if (_debug_level >= 20) {
02960         cout << "  e = (" << *e << ")"
02961             << " after substituting " << var.name_ref()
02962             << " = (";
02963         
02964         if (range)
02965             cout << *range;
02966         else
02967             cout << "[-Inf:Inf]";
02968 
02969         cout << ")\n";
02970         }
02971     }
02972     }
02973     
02974     /// ...  Replace any remaining variables to eliminate with omega
02975 
02976     if (vars_to_eliminate) {
02977     Iterator<Symbol> elim_iter = vars_to_eliminate;
02978     Expression *om = omega();
02979     bool ommed_a_var = false;
02980 
02981     for ( ; elim_iter.valid(); ++elim_iter)
02982         if (is_var_in_expr(*e, elim_iter.current())) {
02983         e = substitute_var(e, elim_iter.current(), *om);
02984         ommed_a_var = true;
02985         }
02986 
02987     delete om;
02988 
02989     if (ommed_a_var)
02990         e = simplify(pull_ranges_out(e, *this));
02991     }
02992     
02993     if (_debug_level >= 1)
02994     cout << "}  result(eliminate_vars): " << *e << endl;
02995 
02996     return e;
02997 }    
02998 
02999 
03000 ///  intersect_range
03001 
03002 void
03003 RangeComparator::intersect_range(const Symbol &var,
03004                  const Expression &inter_expr)
03005 {
03006     const Expression *old_range_ref = get_range_ref(var);
03007 
03008     if (! old_range_ref) {
03009       /// ...  This could establish a range SCC involving var... but
03010       /// ...  such a cycle would not lose pre-existing information
03011       /// ...  about var... there was none to lose
03012       set_range(var, inter_expr.clone());
03013       return;
03014     }
03015 
03016     if (_debug_level >= 1)
03017     cout << "Intersecting (" << *old_range_ref << ") with ("
03018         << inter_expr << ") for " << var.name_ref() << " {\n";
03019 
03020     /// ...  Insert dummy range for var to signal self-reference if the
03021     /// ...  replacement of var causes omega
03022 
03023     Expression *old_range = old_range_ref->clone();
03024     set_range(var, new RangeExpr(new InfinityExpr(-1), new InfinityExpr(+1)));
03025     Expression *result = intersect_ranges(old_range, *this,
03026                       &inter_expr, *this);
03027     delete old_range;
03028     set_range(var, result);
03029 
03030     if (_debug_level >= 1) {
03031     cout << "}  result(intersect): ";
03032 
03033     if (result)
03034         cout << *result;
03035     else
03036         cout << "NULL";
03037 
03038     cout << endl;
03039     }
03040 }
03041 
03042 
03043 ///  union_range
03044 
03045 void
03046 RangeComparator::union_range(const Symbol &var, const Expression &union_expr,
03047                  RangeComparator *union_comparator_ref GIV(0))
03048 {
03049     const Expression *old_range_ref = get_range_ref(var);
03050     
03051     if (! old_range_ref || old_range_ref->op() == OMEGA_OP
03052     || old_range_ref->compare(union_expr) == 0)
03053     return;
03054     
03055     if (_debug_level >= 1)
03056     cout << "Unioning (" << *old_range_ref << ") with ("
03057         << union_expr << ") for " << var.name_ref() << " {\n";
03058 
03059     Expression *result = 0;
03060 
03061     if (union_comparator_ref)
03062     result = union_ranges(old_range_ref, *this,
03063                   &union_expr, *union_comparator_ref);
03064     else
03065     result = union_ranges(old_range_ref, *this, &union_expr, *this);
03066 
03067     set_range(var, result);
03068 
03069     if (_debug_level >= 1) {
03070     cout << "}  result(union): ";
03071 
03072     if (result)
03073         cout << *result;
03074     else
03075         cout << "NULL";
03076 
03077     cout << endl;
03078     }
03079 }
03080 
03081 
03082 ///  operator =
03083 
03084 RangeComparator &
03085 RangeComparator::operator = (const RangeComparator &other)
03086 {
03087     if (this != &other) {
03088     _symtab_ref = other._symtab_ref;
03089     _compare_info = other._compare_info;
03090     _debug_level = other._debug_level;
03091     _range_join_accuracy = other._range_join_accuracy;
03092     _range_compare_accuracy = other._range_compare_accuracy;
03093     _use_the_big_guns = other._use_the_big_guns;
03094     _cache_expr_signs = other._cache_expr_signs;
03095     _cached_sign_exprs = other._cached_sign_exprs;
03096     _cached_expr_signs = other._cached_expr_signs;
03097     }
03098 
03099     return *this;
03100 }
03101 
03102 
03103 ///  symtab
03104 
03105 const Symtab &
03106 RangeComparator::symtab() const
03107 {
03108     return *_symtab_ref;
03109 }
03110 
03111 
03112 ///  range_join_accuracy
03113 
03114 int
03115 RangeComparator::range_join_accuracy()
03116 {
03117     return _range_join_accuracy;
03118 }
03119 
03120 void
03121 RangeComparator::range_join_accuracy(int acc)
03122 {
03123     _range_join_accuracy = acc;
03124 }
03125 
03126 
03127 ///  range_compare_accuracy
03128 
03129 int
03130 RangeComparator::range_compare_accuracy()
03131 {
03132     return _range_compare_accuracy;
03133 }
03134 
03135 void
03136 RangeComparator::range_compare_accuracy(int acc)
03137 {
03138     _range_compare_accuracy = acc;
03139     _use_the_big_guns = (_range_compare_accuracy >= 1);
03140 }
03141 
03142 
03143 ///  debug_level
03144 
03145 int
03146 RangeComparator::debug_level() const
03147 {
03148     return _debug_level;
03149 }
03150 
03151 void
03152 RangeComparator::debug_level(int level)
03153 {
03154     _debug_level = level;
03155 }
03156 
03157 
03158 ///  _are_vars_in_expr
03159 ///    Return true if the given expression uses any of the variables in the
03160 ///    given set.
03161 
03162 static bool
03163 _are_vars_in_expr(const Expression &e, const RefSet<Symbol> &vars)
03164 {
03165     if (e.op() == ID_OP)
03166     return vars.member(e.symbol());
03167     else {
03168     Iterator<Expression> iter = e.arg_list();
03169 
03170     for ( ; iter.valid(); ++iter)
03171         if (_are_vars_in_expr(iter.current(), vars))
03172         return true;
03173     }
03174 
03175     return false;
03176 }
03177 
03178 
03179 ///  _begin_caching_expr_signs
03180 ///    Start caching the signs of arbitrary expressions.
03181 
03182 void
03183 RangeComparator::_begin_caching_expr_signs()
03184 {
03185     ++_cache_expr_signs;
03186 }
03187 
03188 
03189 ///  _end_caching_expr_signs
03190 ///    Stop caching the signs of arbitrary expressions.
03191 
03192 void
03193 RangeComparator::_end_caching_expr_signs()
03194 {
03195     --_cache_expr_signs;
03196 
03197     if (_cache_expr_signs <= 0) {
03198     _cache_expr_signs = 0;
03199     _cached_sign_exprs.clear();
03200     _cached_expr_signs.clear();
03201     }
03202 }
03203 
03204 
03205 ///  _flush_sign_caches
03206 
03207 void
03208 RangeComparator::_flush_sign_caches()
03209 {
03210     _cache_expr_signs = 0;
03211     _cached_sign_exprs.clear();
03212     _cached_expr_signs.clear();
03213 
03214     KeyIterator<Symbol,CompareData> compare_iter = _compare_info;
03215 
03216     for ( ; compare_iter.valid(); ++compare_iter)
03217     compare_iter.current_data().sign_cache = UNKNOWN_SIGN;
03218 }
03219 
03220 
03221 ///  print
03222 
03223 void
03224 RangeComparator::print(ostream & o) const
03225 {
03226     o << "_compare_info={";
03227     KeyIterator<Symbol,CompareData> compare_iter = _compare_info;
03228 
03229     for ( ; compare_iter.valid(); ++compare_iter)
03230     o << compare_iter.current_key().name_ref()
03231         << ": " << compare_iter.current_data() << ", ";
03232 
03233     o << "}";
03234     o << ", ubg=" << _use_the_big_guns;
03235 }
03236 
03237 
03238 ///  structures_OK
03239 
03240 int
03241 RangeComparator::structures_OK() const
03242 {
03243     return _compare_info.structures_OK();
03244 }
 © 1995-2005 University of Illinois, Urbana-Champaign. All rights reserved.  Fri Mar 25 23:06:04 2005