00001
00002
00003
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
00029
00030
00031
00032
00033
00034
00035 #define HIST_SIZE 64
00036
00037
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
00054
00055 void start_compare();
00056
00057
00058 void making_a_var_subst();
00059
00060
00061 void end_compare();
00062
00063
00064 void print(ostream &o);
00065
00066 private:
00067 int _compare_level;
00068
00069 int _num_compares;
00070 int _num_top_level_compares;
00071 int _num_substs;
00072
00073 Timer _compare_time;
00074 int _num_subst_histogram[HIST_SIZE];
00075
00076 Timer _time_histogram[HIST_SIZE];
00077
00078
00079 };
00080
00081 static RangeComparatorStats *_stats = 0;
00082
00083
00084
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
00099
00100 CompareData::CompareData()
00101 {
00102 num_subst = 0;
00103 sign_cache = UNKNOWN_SIGN;
00104
00105 }
00106
00107 CompareData::CompareData(const CompareData &other)
00108 {
00109 num_subst = other.num_subst;
00110 sign_cache = other.sign_cache;
00111
00112 }
00113
00114 CompareData::~CompareData()
00115 {
00116
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
00147
00148 o << "]";
00149 }
00150
00151
00152
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
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
00247 }
00248 else
00249 o <<0<<"\t"
00250 <<0<<"\t"
00251 <<0;
00252
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
00277
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
00296
00297
00298 void
00299 collect_range_stats()
00300 {
00301 _stats = new RangeComparatorStats();
00302 }
00303
00304
00305
00306
00307
00308 void
00309 stop_range_stats()
00310 {
00311 if (_stats) {
00312 delete _stats;
00313 _stats = 0;
00314 }
00315 }
00316
00317
00318
00319
00320
00321 void
00322 print_range_stats(ostream &o)
00323 {
00324 if (_stats)
00325 _stats->print(o);
00326 }
00327
00328
00329
00330
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
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
00364
00365 RangeComparator::~RangeComparator()
00366 {
00367
00368 }
00369
00370
00371
00372
00373
00374
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
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
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
00412
00413 diff = e1.value() - e2.value();
00414 return true;
00415 }
00416 else if (e1.op() != ADD_OP && e2.op() != ADD_OP) {
00417
00418
00419
00420 diff = 0;
00421 return (e1.compare(e2) == 0);
00422 }
00423 else if (e1.op() != ADD_OP || e2.op() != ADD_OP) {
00424
00425
00426
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
00464
00465
00466
00467
00468
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
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
00513
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
00537
00538
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 ;
00552 else if (e1.op() == INFINITY_OP) {
00553
00554 rel = Relation(((InfinityExpr *) &e1)->sign() <= 0, true,
00555 ((InfinityExpr *) &e1)->sign() >= 0);
00556
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
00571 rel = Relation(((InfinityExpr *) &e2)->sign() >= 0, true,
00572 ((InfinityExpr *) &e2)->sign() <= 0);
00573
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
00653
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
00682
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
00703
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
00724
00725
00726
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
00734 else if ((e.op() == EXP_OP) && (e.left_guarded().op() == INTEGER_CONSTANT_OP))
00735 return true;
00736
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
00778
00779
00780
00781
00782
00783
00784
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 {
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
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
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
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
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 ;
00937 else {
00938 const RangeExpr &range = * (const RangeExpr *) δ
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 ;
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
00974
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
00993
00994
00995
00996
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
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069
01070
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
01110
01111
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
01146
01147
01148
01149
01150
01151
01152
01153
01154
01155
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
01204
01205
01206
01207
01208
01209
01210
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
01231
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
01247
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 ¶ms = *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
01281
01282
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
01305
01306
01307
01308 static Expression *
01309 _remove_truncates1(Expression *expr, const Symbol &var, bool &changed,
01310 Symtab &symtab)
01311 {
01312
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
01326
01327 if (expr->op() == MULT_OP) {
01328
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
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
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
01412
01413
01414
01415
01416
01417
01418
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
01453
01454
01455
01456
01457
01458
01459
01460
01461
01462
01463
01464
01465
01466
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
01566
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
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
01614
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
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
01642
01643
01644
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
01656
01657
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
01701
01702
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
01715
01716
01717
01718
01719
01720 Relation rel = _determine_relation(*delta, dummy_range_just_substituted, this);
01721 delete delta;
01722
01723 return rel;
01724 }
01725
01726
01727
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
01816
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
01960
01961
01962
01963
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
01977
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
02025
02026
02027
02028 enum _MONO_STATE {
02029 _NON_MONO,
02030 _MONO_DEC,
02031 _MONO_INC,
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
02062
02063
02064
02065
02066
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
02118
02119
02120
02121
02122
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
02167
02168
02169
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
02201
02202
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
02222
02223
02224
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
02256
02257
02258
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
02351
02352
02353
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
02373
02374
02375
02376 static Expression *
02377 _solve_linear_expr(Expression *e, const Symbol &var,
02378 RangeComparator &comparator)
02379 {
02380
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
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
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
02476
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
02489
02490
02491
02492
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
02504
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
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
02525
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
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
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
02604
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
02622
02623
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
02636
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
02701
02702
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
02721
02722
02723
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
02787
02788
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
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
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
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
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
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
03010
03011
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
03021
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
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
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
03104
03105 const Symtab &
03106 RangeComparator::symtab() const
03107 {
03108 return *_symtab_ref;
03109 }
03110
03111
03112
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
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
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
03159
03160
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
03180
03181
03182 void
03183 RangeComparator::_begin_caching_expr_signs()
03184 {
03185 ++_cache_expr_signs;
03186 }
03187
03188
03189
03190
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
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
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
03239
03240 int
03241 RangeComparator::structures_OK() const
03242 {
03243 return _compare_info.structures_OK();
03244 }