00001
00002
00003
00004
00005 #include "../Collection/Mutator.h"
00006 #include "../Collection/List.h"
00007 #include "../Collection/Set.h"
00008 #include "../Expression/Expression.h"
00009 #include "../Expression/InfinityExpr.h"
00010 #include "../Expression/NonBinaryExpr.h"
00011 #include "../Symbol/Symbol.h"
00012 #include "../Symbol/FunctionSymbol.h"
00013 #include "../utilities/switches_util.h"
00014 #include "../utilities/expression_util.h"
00015 #include "../Symtab.h"
00016 #include "../String.h"
00017 #include "../Traverser.h"
00018 #include "../macros.h"
00019
00020 #include "range_util.h"
00021 #include "RangeAccessor.h"
00022 #include "RangeComparator.h"
00023 #include "RangeExpr.h"
00024 #include "StmtRanges.h"
00025
00026 #include "../Constant/constant.h"
00027
00028
00029 static inline int min(int a, int b) { return (a < b) ? a : b; }
00030
00031 static Expression *_pull_min_max_out_top(Expression *e,
00032 RangeComparator &comparator);
00033
00034 static Expression *
00035 _elim_known_facts(Expression *e, RangeComparator &comparator);
00036
00037
00038
00039
00040
00041
00042 static Expression *
00043 _handle_range(RangeExpr *range, RANGE_HANDLING range_handling)
00044 {
00045 if (! range)
00046 return range;
00047
00048 Expression *new_range = 0;
00049
00050 switch (range_handling) {
00051
00052 case TAKE_RANGE_MIN:
00053 if (range->has_lb())
00054 new_range = range->grab_lb();
00055 break;
00056
00057 case TAKE_RANGE_MAX:
00058 if (range->has_ub())
00059 new_range = range->grab_ub();
00060 break;
00061
00062 default:
00063 if (range->has_lb() || range->has_ub()) {
00064 new_range = range;
00065 range = 0;
00066 }
00067 break;
00068 }
00069
00070 if (range)
00071 delete range;
00072
00073 return new_range;
00074 }
00075
00076
00077
00078
00079
00080 static void
00081 _swap_range_args(RangeExpr &range)
00082 {
00083 Expression *temp = range.grab_lb();
00084 range.lb(range.grab_ub());
00085 range.ub(temp);
00086
00087 if (range.lb().op() == INFINITY_OP)
00088 ((InfinityExpr *) &range.lb())->sign(-1);
00089
00090 if (range.ub().op() == INFINITY_OP)
00091 ((InfinityExpr *) &range.ub())->sign(+1);
00092 }
00093
00094
00095
00096
00097
00098 static void
00099 _negate_range(RangeExpr &range)
00100 {
00101 if (range.has_lb())
00102 range.lb(unary_minus(range.grab_lb()));
00103
00104 if (range.has_ub())
00105 range.ub(unary_minus(range.grab_ub()));
00106
00107 _swap_range_args(range);
00108 }
00109
00110
00111
00112
00113
00114
00115 static Expression *
00116 _p_r_o_of_add(Expression *e)
00117 {
00118
00119
00120 static Expression* _ugly_fix_l=0;
00121 static Expression* _ugly_fix_u=0;
00122 if (_ugly_fix_l==0){
00123 _ugly_fix_l=constant(0);
00124 _ugly_fix_u=infinity();
00125 }
00126
00127 if (e->op()==ADD_OP){
00128 if (e->arg_list().entries()==2){
00129 if (e->arg_list()[0].op()==RANGE_OP){
00130 if (e->arg_list()[1].op()==RANGE_OP){
00131 RangeExpr& e0=(RangeExpr&)e->arg_list()[0];
00132 RangeExpr& e1=(RangeExpr&)e->arg_list()[1];
00133 if (e0.lb()==*_ugly_fix_l &&
00134 e1.lb()==*_ugly_fix_l &&
00135 e0.ub()==*_ugly_fix_u &&
00136 e1.ub()==*_ugly_fix_u){
00137
00138 return new RangeExpr(constant(0), infinity());
00139 }
00140 }
00141 }
00142 }
00143 }
00144
00145 if (e->op()==ADD_OP){
00146 if (e->arg_list().entries()==2){
00147 if (e->arg_list()[0].op()==RANGE_OP){
00148 if (e->arg_list()[1].op()!=RANGE_OP){
00149 RangeExpr& e0=(RangeExpr&)e->arg_list()[0];
00150 RangeExpr& e1=(RangeExpr&)e->arg_list()[1];
00151 if (e0.lb()==*_ugly_fix_l &&
00152 e0.ub()==*_ugly_fix_u){
00153
00154 if (e1.type().data_type()==INTEGER_TYPE){
00155 return new RangeExpr(e1.clone(), infinity());
00156 } else {
00157 return new RangeExpr(infinity(-1), infinity());
00158 }
00159 }
00160 }
00161 }
00162 }
00163 }
00164
00165 if (e->op()==ADD_OP){
00166 if (e->arg_list().entries()==2){
00167 if (is_integer_one(e->arg_list()[0])){
00168 if (e->arg_list()[1].op()==RANGE_OP){
00169 RangeExpr& e1=(RangeExpr&)e->arg_list()[1];
00170 if (e1.lb().op()==INFINITY_OP &&
00171 e1.lb().sign()==-1){
00172
00173 return new RangeExpr(infinity(-1), simplify(add(e->arg_list()[1].clone(),
00174 e1.ub().clone())));
00175 }
00176 }
00177 }
00178 }
00179 }
00180
00181
00182
00183 RangeExpr *range = new RangeExpr(e, e->clone());
00184
00185 bool is_infinite = false;
00186 Mutator<Expression> arg_iter = range->lb().arg_list();
00187
00188 for ( ; arg_iter.valid() && ! is_infinite; ++arg_iter)
00189 if (arg_iter.current().op() == RANGE_OP) {
00190 RangeExpr &arg_range = * (RangeExpr *) &arg_iter.current();
00191
00192 if (arg_range.has_lb())
00193 arg_iter.modify(arg_range.grab_lb());
00194 else
00195 is_infinite = true;
00196 }
00197
00198 if (is_infinite)
00199 range->lb(0);
00200
00201 is_infinite = false;
00202 arg_iter = range->ub().arg_list();
00203
00204 for ( ; arg_iter.valid() && ! is_infinite; ++arg_iter)
00205 if (arg_iter.current().op() == RANGE_OP) {
00206 RangeExpr &arg_range = * (RangeExpr *) &arg_iter.current();
00207
00208 if (arg_range.has_ub())
00209 arg_iter.modify(arg_range.grab_ub());
00210 else
00211 is_infinite = true;
00212 }
00213
00214 if (is_infinite)
00215 range->ub(0);
00216
00217 return range;
00218 }
00219
00220
00221
00222
00223
00224
00225 static Expression *
00226 _range_bound_multiply(Expression *e1, Expression *e2)
00227 {
00228 if (! e1 || e1->op() == OMEGA_OP || e1->op() == INFINITY_OP
00229 || ! e2 || e2->op() == OMEGA_OP || e2->op() == INFINITY_OP) {
00230
00231 if (e1)
00232 delete e1;
00233
00234 if (e2)
00235 delete e2;
00236
00237 return 0;
00238 }
00239 else if (e1->op() == INTEGER_CONSTANT_OP
00240 && e2->op() == INTEGER_CONSTANT_OP) {
00241 e1->value(e1->value() * e2->value());
00242 delete e2;
00243 return e1;
00244 }
00245 else if (e2->op() == MULT_OP) {
00246 if (e1->op() == MULT_OP) {
00247 List<Expression> &e1_args = e1->arg_list();
00248 List<Expression> &e2_args = e2->arg_list();
00249
00250 while(e1_args.entries())
00251 e2_args.ins_first(e1_args.grab(*e1_args.last_ref()));
00252
00253 delete e1;
00254 }
00255 else
00256 e2->arg_list().ins_first(e1);
00257
00258 return e2;
00259 }
00260 else if (e1->op() == MULT_OP) {
00261 e1->arg_list().ins_last(e2);
00262 return e1;
00263 }
00264
00265 return mul(e1, e2);
00266 }
00267
00268
00269
00270
00271
00272
00273 static Expression *
00274 _mult_range_with_expr(RangeExpr *r, Expression *e, RangeComparator &comparator)
00275 {
00276 p_assert(r && e && r->op() == RANGE_OP && e->op() != RANGE_OP,
00277 "Invalid arguments passed to _mult_range_with_expr().");
00278
00279 if (e->op() == OMEGA_OP || e->op() == INFINITY_OP) {
00280 delete r;
00281 delete e;
00282 return 0;
00283 }
00284
00285
00286
00287 EXPR_SIGN e_sign = comparator.sign(*e);
00288
00289
00290
00291 if (e_sign == POS_NEG_EXPR) {
00292 if (e->op() == ADD_OP) {
00293
00294
00295
00296 Mutator<Expression> arg_iter = e->arg_list();
00297
00298 for ( ; arg_iter.valid(); ++arg_iter) {
00299 Assign<Expression> eas(arg_iter.assign());
00300 Expression *new_arg = _mult_range_with_expr((RangeExpr *) r->clone(),
00301 arg_iter.pull(),
00302 comparator);
00303
00304 if (! new_arg) {
00305 delete r;
00306 delete e;
00307 return 0;
00308 }
00309 else
00310 eas = new_arg;
00311 }
00312
00313 delete r;
00314 return _p_r_o_of_add(e);
00315 }
00316 else {
00317 delete r;
00318 delete e;
00319 return 0;
00320 }
00321 }
00322
00323
00324
00325 if (e_sign == NEG_EXPR)
00326 _swap_range_args(*r);
00327
00328 if (r->has_lb() && r->has_ub()) {
00329 r->lb(_range_bound_multiply(e->clone(), r->grab_lb()));
00330 r->ub(_range_bound_multiply(e, r->grab_ub()));
00331 }
00332 else if (r->has_lb())
00333 r->lb(_range_bound_multiply(e, r->grab_lb()));
00334 else if (r->has_ub())
00335 r->ub(_range_bound_multiply(e, r->grab_ub()));
00336 else
00337 delete e;
00338
00339 return r;
00340 }
00341
00342
00343
00344
00345
00346
00347
00348 static RangeExpr *
00349 _merge_range_mult_terms(Expression &e, RangeComparator &comparator)
00350 {
00351 p_assert(e.op() == MULT_OP,
00352 "_merge_range_mult_terms() expected a multiply expression.");
00353
00354 Set<RangeExpr> range_args;
00355 Mutator<Expression> arg_iter = e.arg_list();
00356
00357 for ( ; arg_iter.valid(); ++arg_iter)
00358 if (arg_iter.current().op() == RANGE_OP)
00359 range_args.ins((RangeExpr *) arg_iter.grab());
00360
00361 p_assert(range_args.entries() > 0,
00362 "_merge_range_mult_terms() was given an expression with no ranges");
00363
00364 RangeExpr *range_prod = 0;
00365
00366 if (range_args.entries() == 1)
00367 range_prod = range_args.grab();
00368 else {
00369 EXPR_SIGN range_prod_sign = POS_EXPR;
00370 Set<RangeExpr> pos_neg_range_args;
00371
00372 while (range_args.entries() > 0) {
00373 RangeExpr *range = 0;
00374 EXPR_SIGN range_sign = POS_NEG_EXPR;
00375
00376 while (! range && range_args.entries() > 0) {
00377 range = range_args.grab();
00378 range_sign = comparator.sign(*range);
00379
00380 if (range_sign == POS_NEG_EXPR) {
00381 pos_neg_range_args.ins(range);
00382 range = 0;
00383 }
00384 }
00385
00386 if (range) {
00387 if (! range_prod)
00388 range_prod = range;
00389 else {
00390 Expression *rp_lb = range_prod->grab_lb();
00391 Expression *rp_ub = range_prod->grab_ub();
00392 Expression *r_lb = range->grab_lb();
00393 Expression *r_ub = range->grab_ub();
00394 delete range;
00395
00396 if (range_prod_sign == POS_EXPR)
00397 if (range_sign == POS_EXPR) {
00398 range_prod->lb(_range_bound_multiply(rp_lb, r_lb));
00399 range_prod->ub(_range_bound_multiply(rp_ub, r_ub));
00400 }
00401 else {
00402 range_prod->lb(_range_bound_multiply(rp_ub, r_lb));
00403 range_prod->ub(_range_bound_multiply(rp_lb, r_ub));
00404 }
00405 else {
00406 if (range_sign == POS_EXPR) {
00407 range_prod->lb(_range_bound_multiply(rp_lb, r_ub));
00408 range_prod->ub(_range_bound_multiply(rp_ub, r_lb));
00409 }
00410 else {
00411 range_prod->lb(_range_bound_multiply(rp_ub, r_ub));
00412 range_prod->ub(_range_bound_multiply(rp_lb, r_lb));
00413 }
00414 }
00415 }
00416
00417 if (range_sign == NEG_EXPR)
00418 range_prod_sign = flip_sign(range_prod_sign);
00419 }
00420 }
00421
00422 if (pos_neg_range_args.entries() > 1) {
00423 if (range_prod)
00424 delete range_prod;
00425
00426 return 0;
00427 }
00428
00429 p_assert(range_prod, "Internal Error.");
00430
00431 if (pos_neg_range_args.entries() == 1) {
00432 RangeExpr *pos_neg_range = pos_neg_range_args.grab();
00433
00434 pos_neg_range->lb(_mult_range_with_expr((RangeExpr *) range_prod->clone(),
00435 pos_neg_range->grab_lb(),
00436 comparator));
00437 pos_neg_range->ub(_mult_range_with_expr(range_prod,
00438 pos_neg_range->grab_ub(),
00439 comparator));
00440
00441 if (pos_neg_range->has_lb()
00442 && pos_neg_range->lb().op() == RANGE_OP)
00443
00444 pos_neg_range->lb(
00445 ((RangeExpr &) pos_neg_range->lb()).grab_lb());
00446
00447 if (pos_neg_range->has_ub()
00448 && pos_neg_range->ub().op() == RANGE_OP)
00449
00450 pos_neg_range->ub(
00451 ((RangeExpr &) pos_neg_range->ub()).grab_ub());
00452
00453 if (! pos_neg_range->has_lb() && ! pos_neg_range->has_ub()) {
00454 delete pos_neg_range;
00455 pos_neg_range = 0;
00456 }
00457
00458 range_prod = pos_neg_range;
00459 }
00460 }
00461
00462 return range_prod;
00463 }
00464
00465
00466
00467
00468
00469 static Expression *
00470 _p_r_o_of_mult(Expression *e, RangeComparator &comparator)
00471 {
00472
00473
00474 RangeExpr *range_prod = _merge_range_mult_terms(*e, comparator);
00475
00476 if (! range_prod) {
00477 delete e;
00478 return 0;
00479 }
00480
00481 if (e->arg_list().entries() == 0) {
00482 delete e;
00483 return range_prod;
00484 }
00485 else if (e->arg_list().entries() == 1) {
00486 Expression *new_e = e->arg_list().grab(*e->arg_list().first_ref());
00487 delete e;
00488 e = new_e;
00489 }
00490
00491 return _mult_range_with_expr(range_prod, e, comparator);
00492 }
00493
00494
00495
00496
00497
00498 static Expression *
00499 _p_r_o_of_divide(Expression *e, RangeComparator &comparator)
00500 {
00501 RangeExpr *range = 0;
00502
00503 if (e->right_guarded().op() != RANGE_OP) {
00504 p_assert (e->left_guarded().op() == RANGE_OP,
00505 "Expression passed to _p_r_o_of_divide has no ranges");
00506
00507 EXPR_SIGN sign = comparator.signz(e->right_guarded());
00508
00509 if (sign == POS_NEG_EXPR || sign == ZERO_EXPR) {
00510 delete e;
00511 return 0;
00512 }
00513
00514 range = (RangeExpr *) e->grab_left();
00515 Expression *denom = e->grab_right();
00516 delete e;
00517
00518 if (range->has_lb() && range->has_ub()) {
00519 range->lb(div(range->grab_lb(), denom->clone()));
00520 range->ub(div(range->grab_ub(), denom));
00521 } else if (range->has_lb()) {
00522 range->lb(div(range->grab_lb(), denom));
00523 range->ub(0);
00524 } else if (range->has_ub()) {
00525 range->lb(0);
00526 range->ub(div(range->grab_ub(), denom));
00527 } else
00528 p_abort("Internal error in _p_r_o_of_divide()");
00529
00530 if (sign == NEG_EXPR)
00531 _swap_range_args(*range);
00532 }
00533 else if (e->left_guarded().op() != RANGE_OP) {
00534 p_assert (e->right_guarded().op() == RANGE_OP,
00535 "Expression passed to _p_r_o_of_divide has no ranges");
00536
00537 EXPR_SIGN numer_sign = comparator.sign(e->left_guarded());
00538 EXPR_SIGN denom_sign = comparator.signz(e->right_guarded());
00539
00540 if (numer_sign == POS_NEG_EXPR || denom_sign == POS_NEG_EXPR
00541 || denom_sign == ZERO_EXPR) {
00542 delete e;
00543 return 0;
00544 }
00545
00546 Expression *numer = e->grab_left();
00547 range = (RangeExpr *) e->grab_right();
00548 delete e;
00549
00550 if (range->has_lb() && range->has_ub()) {
00551 range->lb(div(numer->clone(), range->grab_lb()));
00552 range->ub(div(numer, range->grab_ub()));
00553 } else if (range->has_lb()) {
00554 range->lb(div(numer, range->grab_lb()));
00555 range->ub(constant(0));
00556 } else if (range->has_ub()) {
00557 range->lb(constant(0));
00558 range->ub(div(numer, range->grab_ub()));
00559 } else
00560 p_abort("Internal error in _p_r_o_of_divide()");
00561
00562 if (numer_sign == POS_EXPR)
00563 _swap_range_args(*range);
00564 }
00565 else {
00566 delete e;
00567 return 0;
00568 }
00569
00570 return range;
00571 }
00572
00573
00574
00575
00576
00577 static Expression *
00578 _p_r_o_of_exp(Expression *e, RangeComparator &comparator)
00579 {
00580 if (e->right_guarded().op() != INTEGER_CONSTANT_OP) {
00581 delete e;
00582 return 0;
00583 }
00584
00585 int power = e->right_guarded().value();
00586
00587 if (e->left_guarded().op() == OMEGA_OP) {
00588 delete e;
00589
00590 if (power % 2 == 0)
00591 return new RangeExpr(constant(0), 0);
00592 else
00593 return 0;
00594 }
00595
00596 p_assert (e->left_guarded().op() == RANGE_OP,
00597 "Expression passed to _p_r_o_of_exp has no ranges");
00598
00599 RangeExpr *range = (RangeExpr *) e->grab_left();
00600 delete e;
00601
00602 if (power % 2 == 0) {
00603
00604
00605 bool abs_lb_is_larger = false;
00606 EXPR_SIGN lb_sign = comparator.sign(range->lb());
00607
00608 if (lb_sign == POS_EXPR) {
00609
00610 }
00611 else {
00612 EXPR_SIGN ub_sign = comparator.sign(range->ub());
00613
00614 if (ub_sign == NEG_EXPR) {
00615
00616 abs_lb_is_larger = true;
00617 }
00618 else if (lb_sign == NEG_EXPR && ub_sign == POS_EXPR) {
00619
00620 Expression *diff = simplify(add(range->lb().clone(),
00621 range->ub().clone()));
00622 EXPR_SIGN diff_sign = comparator.sign(*diff);
00623 delete diff;
00624
00625 if (diff_sign == POS_EXPR) {
00626
00627 }
00628 else if (diff_sign == NEG_EXPR) {
00629
00630 abs_lb_is_larger = true;
00631 }
00632 else {
00633 delete range;
00634 return new RangeExpr(constant(0), 0);
00635 }
00636 }
00637 else {
00638 delete range;
00639 return new RangeExpr(constant(0), 0);
00640 }
00641 }
00642
00643 if (abs_lb_is_larger)
00644 _swap_range_args(*range);
00645 }
00646
00647 if (range->has_lb())
00648 range->lb(exponent(range->grab_lb(), constant(power)));
00649
00650 if (range->has_ub())
00651 range->ub(exponent(range->grab_ub(), constant(power)));
00652
00653 return range;
00654 }
00655
00656
00657
00658
00659
00660 static Expression *
00661 _p_r_o_of_range(Expression *e)
00662 {
00663 RangeExpr &range = * (RangeExpr *) e;
00664
00665 if (range.lb().op() == OMEGA_OP)
00666 range.lb(0);
00667 else if (range.lb().op() == RANGE_OP)
00668 range.lb(((RangeExpr *) &range.lb())->grab_lb());
00669
00670 if (range.ub().op() == OMEGA_OP)
00671 range.ub(0);
00672 else if (range.ub().op() == RANGE_OP)
00673 range.ub(((RangeExpr *) &range.ub())->grab_ub());
00674
00675 if (! range.has_lb() && ! range.has_ub()) {
00676 delete e;
00677 return 0;
00678 }
00679
00680 return e;
00681 }
00682
00683
00684
00685
00686
00687 static Expression *
00688 _p_r_o_of_min_max(Expression *e, bool is_min_op)
00689 {
00690 Expression *lb = e;
00691 Expression *ub = e->clone();
00692 Mutator<Expression> arg_iter = lb->parameters_guarded().arg_list();
00693
00694 bool is_infinite = false;
00695
00696 for ( ; arg_iter.valid() && ! is_infinite; ++arg_iter)
00697 if (arg_iter.current().op() == RANGE_OP) {
00698 RangeExpr &range = * (RangeExpr *) &arg_iter.current();
00699
00700 if (range.has_lb())
00701 arg_iter.modify(range.grab_lb());
00702 else if (! is_min_op)
00703 arg_iter.del();
00704 else
00705 is_infinite = true;
00706 }
00707 else if (arg_iter.current().op() == OMEGA_OP)
00708 if (! is_min_op)
00709 arg_iter.del();
00710 else
00711 is_infinite = true;
00712
00713 if (is_infinite || lb->parameters_guarded().arg_list().entries() == 0) {
00714 delete lb;
00715 lb = 0;
00716 }
00717
00718 is_infinite = false;
00719
00720 for (arg_iter = ub->parameters_guarded().arg_list();
00721 arg_iter.valid() && ! is_infinite;
00722 ++arg_iter)
00723
00724 if (arg_iter.current().op() == RANGE_OP) {
00725 RangeExpr &range = * (RangeExpr *) &arg_iter.current();
00726
00727 if (range.has_ub())
00728 arg_iter.modify(range.grab_ub());
00729 else if (is_min_op)
00730 arg_iter.del();
00731 else
00732 is_infinite = true;
00733 }
00734 else if (arg_iter.current().op() == OMEGA_OP)
00735 if (is_min_op)
00736 arg_iter.del();
00737 else
00738 is_infinite = true;
00739
00740 if (is_infinite || ub->parameters_guarded().arg_list().entries() == 0) {
00741 delete ub;
00742 ub = 0;
00743 }
00744
00745 return new RangeExpr(lb, ub);
00746 }
00747
00748
00749
00750
00751
00752
00753 static Expression *
00754 _p_r_o_of_ifix(Expression *e)
00755 {
00756 Expression *lb = e;
00757 Expression *ub = e->clone();
00758
00759 List<Expression> &lb_args = lb->parameters_guarded().arg_list();
00760 RangeExpr &lb_range = * (RangeExpr *) lb_args.first_ref();
00761 lb_args.modify(lb_range, lb_range.grab_lb());
00762
00763 List<Expression> &ub_args = ub->parameters_guarded().arg_list();
00764 RangeExpr &ub_range = * (RangeExpr *) ub_args.first_ref();
00765 ub_args.modify(ub_range, ub_range.grab_ub());
00766
00767 return new RangeExpr(lb, ub);
00768 }
00769
00770
00771
00772
00773
00774 static Expression *
00775 _min_abs_expr(const Expression &e, EXPR_SIGN sign)
00776 {
00777 Expression *min_abs_expr = 0;
00778
00779 if (e.op() == OMEGA_OP || sign == POS_NEG_EXPR)
00780 min_abs_expr = constant(0);
00781 else if (e.op() == RANGE_OP) {
00782 const RangeExpr &range = * (RangeExpr *) &e;
00783
00784 if (sign == POS_EXPR)
00785 min_abs_expr = range.lb().clone();
00786 else
00787 min_abs_expr = unary_minus(range.ub().clone());
00788 }
00789 else
00790 if (sign == POS_EXPR)
00791 min_abs_expr = e.clone();
00792 else
00793 min_abs_expr = unary_minus(e.clone());
00794
00795 return min_abs_expr;
00796 }
00797
00798
00799
00800
00801
00802 static Expression *
00803 _max_abs_expr(const Expression &e, EXPR_SIGN sign)
00804 {
00805 Expression *max_abs_expr = 0;
00806
00807 if (e.op() == OMEGA_OP)
00808 max_abs_expr = new InfinityExpr(+1);
00809 else if (e.op() == RANGE_OP) {
00810 const RangeExpr &range = * (RangeExpr *) &e;
00811
00812 if (! range.has_lb() || ! range.has_ub())
00813 max_abs_expr = new InfinityExpr(+1);
00814 else {
00815 switch (sign) {
00816 case POS_EXPR:
00817 max_abs_expr = range.ub().clone();
00818 break;
00819
00820 case NEG_EXPR:
00821 max_abs_expr = unary_minus(range.lb().clone());
00822 break;
00823
00824 case POS_NEG_EXPR: {
00825
00826
00827
00828 Expression *delta = sub(unary_minus(range.lb().clone()),
00829 range.ub().clone());
00830 delta = simplify(delta);
00831
00832 if (delta->op() == INTEGER_CONSTANT_OP)
00833 if (delta->value() <= 0)
00834 max_abs_expr = range.ub().clone();
00835 else
00836 max_abs_expr = unary_minus(range.lb().clone());
00837 else
00838 max_abs_expr = new InfinityExpr(+1);
00839
00840 delete delta;
00841 }
00842 default:
00843 break;
00844 }
00845 }
00846 }
00847 else {
00848 switch (sign) {
00849 case POS_EXPR:
00850 max_abs_expr = e.clone();
00851 break;
00852
00853 case NEG_EXPR:
00854 max_abs_expr = unary_minus(e.clone());
00855 break;
00856
00857 case POS_NEG_EXPR:
00858 max_abs_expr = new InfinityExpr(+1);
00859 break;
00860 default:
00861 break;
00862 }
00863 }
00864
00865 return max_abs_expr;
00866 }
00867
00868
00869
00870
00871
00872 static Expression *
00873 _handle_omega_in_mod(Expression *e, RangeComparator &comparator)
00874 {
00875 List<Expression> ¶ms = e->parameters_guarded().arg_list();
00876 p_assert(params.entries() == 2,
00877 "Wrong number of arguments in MOD intrinsic");
00878
00879 Expression *left_ref = params.first_ref();
00880 Expression *right_ref = params.last_ref();
00881
00882 if (left_ref->op() == OMEGA_OP && right_ref->op() == OMEGA_OP) {
00883 delete e;
00884 return 0;
00885 }
00886 else if (right_ref->op() == OMEGA_OP) {
00887 EXPR_SIGN left_sign = comparator.sign(*left_ref);
00888
00889 if (left_sign == POS_NEG_EXPR) {
00890 Expression *bound = _max_abs_expr(*left_ref, left_sign);
00891 delete e;
00892
00893 if (! bound || bound->op() == INFINITY_OP) {
00894 delete bound;
00895 return 0;
00896 }
00897
00898 return new RangeExpr(unary_minus(bound->clone()), bound);
00899 }
00900 else {
00901 RangeExpr *result = convert_to_range(params.grab(*left_ref));
00902 delete e;
00903
00904 if (left_sign == POS_EXPR)
00905 result->lb(constant(0));
00906 else
00907 result->ub(constant(0));
00908
00909 return result;
00910 }
00911 }
00912 else {
00913 p_assert(left_ref->op() == OMEGA_OP,
00914 "Expression passed to _handle_omega_in_mod has no omega expressions");
00915
00916 EXPR_SIGN right_sign = comparator.sign(*right_ref);
00917 Expression *bound = _max_abs_expr(*right_ref, right_sign);
00918 delete e;
00919
00920 if (! bound || bound->op() == INFINITY_OP
00921 || is_integer_zero(*bound)) {
00922 delete bound;
00923 return 0;
00924 }
00925
00926 bound = add(bound, constant(-1));
00927 return new RangeExpr(unary_minus(bound->clone()), bound);
00928 }
00929 }
00930
00931
00932
00933
00934
00935 static Expression *
00936 _p_r_o_of_mod(Expression *e, RangeComparator &comparator)
00937 {
00938 List<Expression> ¶ms = e->parameters_guarded().arg_list();
00939 p_assert(params.entries() == 2,
00940 "Wrong number of arguments in MOD intrinsic");
00941
00942 Expression &left = *params.first_ref();
00943 Expression &right = *params.last_ref();
00944 EXPR_SIGN left_sign = comparator.sign(left);
00945 EXPR_SIGN right_sign = comparator.signz(right);
00946
00947 if (right_sign == POS_NEG_EXPR || right_sign == ZERO_EXPR) {
00948 params.modify(right, omega());
00949 return _handle_omega_in_mod(e, comparator);
00950 }
00951
00952 Expression *max_abs_left = _max_abs_expr(left, left_sign);
00953 Expression *min_abs_right = _min_abs_expr(right, right_sign);
00954 Relation abs_rel = comparator.compare(*max_abs_left, *min_abs_right);
00955 delete max_abs_left;
00956 delete min_abs_right;
00957 Expression *result;
00958
00959
00960
00961
00962 if (abs_rel.is_less_than()) {
00963 result = params.grab(left);
00964 }
00965 else {
00966
00967
00968 if (left_sign == POS_NEG_EXPR) {
00969 params.modify(left, omega());
00970 return _handle_omega_in_mod(e, comparator);
00971 }
00972
00973 Expression *bound;
00974
00975 if (right.op() == RANGE_OP)
00976 if (right_sign == POS_EXPR)
00977 bound = ((RangeExpr *) &right)->grab_ub();
00978 else
00979 bound = ((RangeExpr *) &right)->grab_lb();
00980 else
00981 bound = params.grab(right);
00982
00983 if (right_sign == POS_EXPR)
00984 bound = sub(bound, constant(1));
00985 else
00986 bound = sub(constant(-1), bound);
00987
00988 if (left_sign == POS_EXPR)
00989 result = new RangeExpr(constant(0), bound);
00990 else
00991 result = new RangeExpr(unary_minus(bound), constant(0));
00992 }
00993
00994 delete e;
00995 return result;
00996 }
00997
00998
00999
01000
01001
01002 static Expression *
01003 _p_r_o_of_abs(Expression *e, RangeComparator &comparator)
01004 {
01005 List<Expression> ¶ms = e->parameters_guarded().arg_list();
01006 RangeExpr *range = (RangeExpr *) params.grab(*params.first_ref());
01007 delete e;
01008
01009 EXPR_SIGN sign = comparator.sign(*range);
01010 Expression *new_expr = 0;
01011
01012 switch (sign) {
01013 case POS_EXPR:
01014 new_expr = range;
01015 break;
01016
01017 case NEG_EXPR:
01018 _negate_range(*range);
01019 new_expr = range;
01020 break;
01021
01022 case POS_NEG_EXPR:
01023 new_expr = new RangeExpr(constant(0), _max_abs_expr(*range, sign));
01024 delete range;
01025 break;
01026
01027 default:
01028 p_abort("bad value in switch stmt");
01029 }
01030
01031 return new_expr;
01032 }
01033
01034
01035
01036
01037
01038
01039
01040 static Expression *
01041 _pull_ranges_out(Expression *e, RangeComparator &comparator,
01042 RANGE_HANDLING range_handling)
01043 {
01044 if (!e || e->arg_list().entries() == 0)
01045 return e;
01046
01047 if (comparator.debug_level() >= 50)
01048 cout << " pulling ranges out of " << *e << endl;
01049
01050
01051
01052
01053
01054 RANGE_HANDLING arg_range_handling;
01055
01056 switch (e->op()) {
01057 case ADD_OP:
01058 case COMMA_OP:
01059 arg_range_handling = range_handling;
01060 break;
01061
01062 case INTRINSIC_CALL_OP:
01063 {
01064 String intr_name = e->intrinsic().symbol().name_ref();
01065
01066 if (intr_name == "MIN" || intr_name == "MAX")
01067 arg_range_handling = range_handling;
01068 else if (intr_name == "MOD" || intr_name == "ABS"
01069 || intr_name == "IABS" || intr_name == "DABS")
01070 arg_range_handling = KEEP_WHOLE_RANGE;
01071 else {
01072 delete e;
01073 return 0;
01074 }
01075 }
01076 break;
01077
01078 case MULT_OP:
01079 case DIV_OP:
01080 case EXP_OP:
01081 case RANGE_OP:
01082 arg_range_handling = KEEP_WHOLE_RANGE;
01083 break;
01084
01085 case ARRAY_REF_OP:
01086 delete e;
01087 return 0;
01088
01089 default:
01090 arg_range_handling = KEEP_WHOLE_RANGE;
01091 break;
01092 }
01093
01094
01095
01096 Mutator<Expression> arg_iter = e->arg_list();
01097 bool has_range_in_args = false;
01098
01099 for ( ; arg_iter.valid(); ++arg_iter) {
01100 Assign<Expression> eas(arg_iter.assign());
01101 Expression *new_arg = _pull_ranges_out(arg_iter.pull(),
01102 comparator,
01103 arg_range_handling);
01104
01105 if (new_arg && new_arg->op() == OMEGA_OP) {
01106 delete new_arg;
01107 new_arg = 0;
01108 }
01109
01110 if (! new_arg)
01111 if (e->op() == COMMA_OP)
01112 new_arg = omega();
01113 else if (e->op() == EXP_OP || e->op() == RANGE_OP){
01114 new_arg = omega();
01115 has_range_in_args = true;
01116 }
01117 else {
01118 delete e;
01119 return 0;
01120 }
01121
01122 if (new_arg->op() == RANGE_OP) {
01123 has_range_in_args = true;
01124
01125 if (is_empty_range(*new_arg) && e->op() != COMMA_OP) {
01126 delete e;
01127 return new_arg;
01128 }
01129 }
01130
01131 eas = new_arg;
01132 }
01133
01134
01135
01136 Expression *new_expr = e;
01137
01138 if (has_range_in_args) {
01139 switch (e->op()) {
01140
01141 case ADD_OP:
01142 new_expr = _p_r_o_of_add(e);
01143 break;
01144
01145 case COMMA_OP:
01146
01147 break;
01148
01149 case MULT_OP:
01150 new_expr = _p_r_o_of_mult(e, comparator);
01151 break;
01152
01153 case DIV_OP:
01154 new_expr = _p_r_o_of_divide(e, comparator);
01155 break;
01156
01157 case EXP_OP:
01158 new_expr = _p_r_o_of_exp(e, comparator);
01159 break;
01160
01161 case RANGE_OP:
01162 new_expr = _p_r_o_of_range(e);
01163 break;
01164
01165 default:
01166 delete e;
01167 return 0;
01168 }
01169 }
01170 else if (e->op() == INTRINSIC_CALL_OP) {
01171 has_range_in_args = false;
01172 bool has_omega_in_args = false;
01173 Mutator<Expression> param_iter = e->parameters_guarded().arg_list();
01174
01175 for ( ; param_iter.valid() && ! has_range_in_args; ++param_iter)
01176 if (param_iter.current().op() == RANGE_OP) {
01177 has_range_in_args = true;
01178
01179 if (is_empty_range(param_iter.current())) {
01180 String intr_name = e->intrinsic().symbol().name_ref();
01181
01182 if (intr_name == "MIN" || intr_name == "MAX")
01183 param_iter.del();
01184 else {
01185 new_expr = param_iter.grab();
01186 delete e;
01187 return new_expr;
01188 }
01189 }
01190 }
01191 else if (param_iter.current().op() == OMEGA_OP)
01192 has_omega_in_args = true;
01193
01194 if (has_range_in_args || has_omega_in_args) {
01195 String intr_name = e->intrinsic().symbol().name_ref();
01196
01197 if (intr_name == "MIN" || intr_name == "MAX") {
01198 new_expr = _p_r_o_of_min_max(new_expr, intr_name == "MIN");
01199 }
01200 else if (intr_name == "IFIX" || intr_name == "INT") {
01201 if (has_omega_in_args) {
01202 delete e;
01203 return 0;
01204 }
01205
01206 new_expr = _p_r_o_of_ifix(e);
01207 }
01208 else if (intr_name == "MOD") {
01209 if (has_omega_in_args)
01210 new_expr = _handle_omega_in_mod(e, comparator);
01211 else
01212 new_expr = _p_r_o_of_mod(e, comparator);
01213 }
01214 else if (intr_name == "ABS" || intr_name == "IABS"
01215 || intr_name == "DABS") {
01216 if (has_omega_in_args) {
01217 delete e;
01218 new_expr = new RangeExpr(constant(0), 0);
01219 }
01220 else
01221 new_expr = _p_r_o_of_abs(e, comparator);
01222 }
01223 else {
01224 delete e;
01225 return 0;
01226 }
01227 }
01228 }
01229
01230 if (new_expr && new_expr->op() == RANGE_OP)
01231 new_expr = _handle_range((RangeExpr *) new_expr, range_handling);
01232
01233 if (new_expr)
01234 if (new_expr->op() == RANGE_OP) {
01235 RangeExpr &range = * (RangeExpr *) new_expr;
01236 range.lb(_pull_min_max_out_top(range.grab_lb(), comparator));
01237 range.ub(_pull_min_max_out_top(range.grab_ub(), comparator));
01238 }
01239 else
01240 new_expr = _pull_min_max_out_top(new_expr, comparator);
01241
01242 if (comparator.debug_level() >= 50 && new_expr)
01243 cout << " result(pull ranges out): " << *new_expr << endl;
01244
01245 return new_expr;
01246 }
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260
01261 Expression *
01262 pull_ranges_out(Expression * e, RangeComparator &comparator,
01263 RANGE_HANDLING range_handling GIV(KEEP_WHOLE_RANGE))
01264 {
01265 Expression *new_expr = e;
01266
01267
01268 if (e->op() == RANGE_OP && range_handling == KEEP_WHOLE_RANGE) {
01269 RangeExpr &range = * (RangeExpr *) e;
01270
01271 Expression *new_lb = _pull_ranges_out(range.grab_lb(),
01272 comparator, TAKE_RANGE_MIN);
01273 Expression *new_ub = _pull_ranges_out(range.grab_ub(),
01274 comparator, TAKE_RANGE_MAX);
01275
01276 if (! new_lb && ! new_ub) {
01277 delete new_expr;
01278 new_expr = omega();
01279 }
01280 else if (new_lb && is_empty_range(*new_lb)) {
01281 delete new_expr;
01282
01283 if (new_ub)
01284 delete new_ub;
01285
01286 return new_lb;
01287 }
01288 else if (new_ub && is_empty_range(*new_ub)) {
01289 delete new_expr;
01290
01291 if (new_lb)
01292 delete new_lb;
01293
01294 return new_ub;
01295 }
01296 else {
01297 range.lb(new_lb);
01298 range.ub(new_ub);
01299 }
01300 }
01301 else {
01302 new_expr = _pull_ranges_out(e, comparator, range_handling);
01303
01304 if (! new_expr)
01305 new_expr = omega();
01306 }
01307
01308 return new_expr;
01309 }
01310
01311
01312
01313
01314
01315
01316 Expression *
01317 min_expr(Expression *e1, Expression *e2, const Symtab &symtab)
01318 {
01319 if (! e1)
01320 return e2;
01321
01322 if (! e2)
01323 return e1;
01324
01325 if (e1->op() == OMEGA_OP
01326 || (e1->op() == INFINITY_OP && e1->sign() < 0)
01327 || (e2->op() == INFINITY_OP && e2->sign() > 0))
01328 return e1;
01329
01330 if (e2->op() == OMEGA_OP
01331 || (e2->op() == INFINITY_OP && e2->sign() < 0)
01332 || (e1->op() == INFINITY_OP && e1->sign() > 0))
01333 return e2;
01334
01335 Symbol *s = (Symbol*) symtab.find_ref("MIN");
01336 p_assert(s, "MIN intrinsic is not in symbol table.");
01337
01338 return intrinsic_call(id(*s), comma(e1, e2));
01339 }
01340
01341
01342
01343
01344
01345 Expression *
01346 max_expr(Expression *e1, Expression *e2, const Symtab &symtab)
01347 {
01348 if (! e1)
01349 return e2;
01350
01351 if (! e2)
01352 return e1;
01353
01354 if (e1->op() == OMEGA_OP
01355 || (e1->op() == INFINITY_OP && e1->sign() > 0)
01356 || (e2->op() == INFINITY_OP && e2->sign() < 0))
01357 return e1;
01358
01359 if (e2->op() == OMEGA_OP
01360 || (e2->op() == INFINITY_OP && e2->sign() > 0)
01361 || (e1->op() == INFINITY_OP && e1->sign() < 0))
01362 return e2;
01363
01364 Symbol *s = (Symbol*) symtab.find_ref("MAX");
01365 p_assert(s, "MAX intrinsic is not in symbol table.");
01366
01367 return intrinsic_call(id(*s), comma(e1, e2));
01368 }
01369
01370
01371
01372
01373
01374 Expression *
01375 mod_expr(Expression *e1, Expression *e2, Symtab &symtab)
01376 {
01377 p_assert(e1 && e2, "A NULL argument was passed to mod_expr().");
01378 Symbol *mod_sym = (Symbol*) symtab.find_ref("MOD");
01379 if (mod_sym) {
01380 if (mod_sym->intrinsic() == NOT_INTRINSIC) {
01381 Symbol *mod_sym_var = symtab.grab("MOD");
01382 mod_sym = new FunctionSymbol("MOD", make_type(INTEGER_TYPE),
01383 NOT_EXTERNAL, IS_INTRINSIC, NOT_FORMAL);
01384 symtab.rename_and_ins(mod_sym_var);
01385 }
01386 } else {
01387 mod_sym = new FunctionSymbol("MOD", make_type(INTEGER_TYPE),
01388 NOT_EXTERNAL, IS_INTRINSIC, NOT_FORMAL);
01389 symtab.ins(mod_sym);
01390 }
01391 Expression *mod_expr = intrinsic_call(id(*mod_sym), comma(e1, e2));
01392 mod_expr->type(e1->type());
01393
01394 return mod_expr;
01395 }
01396
01397
01398
01399
01400
01401 bool
01402 is_min(const Expression &e)
01403 {
01404 return (e.op() == INTRINSIC_CALL_OP
01405 && strcmp(e.intrinsic().symbol().name_ref(), "MIN") == 0);
01406 }
01407
01408
01409
01410
01411
01412 bool
01413 is_max(const Expression &e)
01414 {
01415 return (e.op() == INTRINSIC_CALL_OP
01416 && strcmp(e.intrinsic().symbol().name_ref(), "MAX") == 0);
01417 }
01418
01419
01420
01421
01422
01423 bool
01424 is_mod(const Expression &e)
01425 {
01426 return (e.op() == INTRINSIC_CALL_OP
01427 && strcmp(e.intrinsic().symbol().name_ref(), "MOD") == 0);
01428 }
01429
01430
01431
01432
01433
01434 bool
01435 is_abs(const Expression &e)
01436 {
01437 return (e.op() == INTRINSIC_CALL_OP
01438 && (strcmp(e.intrinsic().symbol().name_ref(), "ABS") == 0
01439 || strcmp(e.intrinsic().symbol().name_ref(), "IABS") == 0
01440 || strcmp(e.intrinsic().symbol().name_ref(), "DABS") == 0));
01441 }
01442
01443
01444
01445
01446
01447 bool
01448 is_min_or_max(const Expression &e)
01449 {
01450 if (e.op() == INTRINSIC_CALL_OP) {
01451 const char *intr_name = e.intrinsic().symbol().name_ref();
01452
01453 return (strcmp(intr_name, "MIN") == 0
01454 || strcmp(intr_name, "MAX") == 0);
01455 }
01456
01457 return false;
01458 }
01459
01460
01461
01462
01463
01464 bool
01465 contains_min_or_max(const Expression &e)
01466 {
01467 if (is_min_or_max(e))
01468 return true;
01469 else {
01470 Iterator<Expression> iter = e.arg_list();
01471
01472 for ( ; iter.valid(); ++iter)
01473 if (contains_min_or_max(iter.current()))
01474 return true;
01475 }
01476
01477 return false;
01478 }
01479
01480
01481
01482
01483
01484 Expression *
01485 abs_to_max(Expression *e, const Symtab &symtab)
01486 {
01487 if (! e)
01488 return e;
01489
01490 if (is_abs(*e)) {
01491 Expression *arg = e->parameters_guarded().arg_list().grab(0);
01492 delete e;
01493 e = max_expr(arg, simplify(unary_minus(arg->clone())), symtab);
01494 e->parameters_guarded().arg_list().ins_first(constant(0));
01495 }
01496 else {
01497 Mutator<Expression> iter = e->arg_list();
01498
01499 for ( ; iter.valid(); ++iter) {
01500 Assign<Expression> eas(iter.assign());
01501 eas = abs_to_max(iter.pull(), symtab);
01502 }
01503 }
01504
01505 return e;
01506 }
01507
01508
01509
01510
01511
01512 void
01513 swap_min_max(Expression &e, const Symtab &symtab)
01514 {
01515 p_assert(is_min_or_max(e),
01516 "Expression must be a MIN or MAX intrinsic");
01517
01518 const char *new_intrin;
01519
01520 if (is_min(e))
01521 new_intrin = "MAX";
01522 else
01523 new_intrin = "MIN";
01524
01525 const Symbol *s = symtab.find_ref(new_intrin);
01526 p_assert(s, "Couldn't find MIN or MAX intrinsic in symbol table.");
01527 e.intrinsic().symbol(*s);
01528 }
01529
01530
01531
01532
01533
01534 static void
01535 _append_list(List<Expression> &to, List<Expression> &from)
01536 {
01537 while (from.entries())
01538 to.ins_last(from.grab(*from.first_ref()));
01539 }
01540
01541
01542
01543
01544
01545 static Expression *
01546 _join_nonbinary_exprs(OP_TYPE op, Expression *e1, Expression *e2)
01547 {
01548 if (e1->op() == op) {
01549 e1->arg_list().ins_last(e2);
01550 return e1;
01551 }
01552 else if (e2->op() == op) {
01553 e2->arg_list().ins_first(e1);
01554 return e2;
01555 }
01556 else
01557 return new NonBinaryExpr(op, e1->type(), e1, e2);
01558 }
01559
01560
01561
01562
01563
01564
01565 static void
01566 _pull_in_add_expr(Expression &min_or_max, const Expression &add_term)
01567 {
01568 bool add_term_is_min_max = is_min_or_max(add_term);
01569 Mutator<Expression> arg_iter = min_or_max.parameters_guarded().arg_list();
01570
01571 for ( ; arg_iter.valid(); ++arg_iter)
01572 if (is_min_or_max(arg_iter.current()))
01573 _pull_in_add_expr(arg_iter.current(), add_term);
01574 else if (add_term_is_min_max) {
01575 Assign<Expression> eas(arg_iter.assign());
01576 Expression *new_arg = add_term.clone();
01577 _pull_in_add_expr(*new_arg, arg_iter.current());
01578 delete arg_iter.pull();
01579 eas = new_arg;
01580 }
01581 else {
01582 Assign<Expression> eas2(arg_iter.assign());
01583 eas2 = _join_nonbinary_exprs(ADD_OP, arg_iter.pull(),
01584 add_term.clone());
01585 }
01586 }
01587
01588
01589
01590
01591
01592
01593 static Expression *
01594 _p_mm_o_of_add(Expression *e)
01595 {
01596 List<Expression> min_max_args;
01597
01598 Mutator<Expression> arg_iter = e->arg_list();
01599
01600 for ( ; arg_iter.valid(); ++arg_iter)
01601 if (is_min_or_max(arg_iter.current()))
01602 min_max_args.ins_last(arg_iter.grab());
01603
01604 Expression *result = e;
01605
01606 if (e->arg_list().entries() == 0) {
01607 delete e;
01608 result = min_max_args.grab(*min_max_args.first_ref());
01609 }
01610
01611 Mutator<Expression> mm_iter = min_max_args;
01612
01613 for ( ; mm_iter.valid(); ++mm_iter) {
01614 Expression *min_or_max = mm_iter.grab();
01615 _pull_in_add_expr(*min_or_max, *result);
01616 delete result;
01617 result = min_or_max;
01618 }
01619
01620 return result;
01621 }
01622
01623
01624
01625
01626
01627
01628 static void
01629 _pull_in_mult_expr(Expression &min_or_max, const Expression &mult_term,
01630 EXPR_SIGN mult_term_sign, RangeComparator &comparator)
01631 {
01632 bool mult_term_is_min_max = is_min_or_max(mult_term);
01633 Mutator<Expression> arg_iter = min_or_max.parameters_guarded().arg_list();
01634
01635 if (mult_term_sign == NEG_EXPR)
01636 swap_min_max(min_or_max, comparator.symtab());
01637
01638 for ( ; arg_iter.valid(); ++arg_iter)
01639 if (is_min_or_max(arg_iter.current()))
01640 _pull_in_mult_expr(arg_iter.current(), mult_term, mult_term_sign,
01641 comparator);
01642 else if (mult_term_is_min_max) {
01643 EXPR_SIGN arg_sign = comparator.sign(arg_iter.current());
01644
01645 if (arg_sign == POS_NEG_EXPR) {
01646 Assign<Expression> eas(arg_iter.assign());
01647 eas = _join_nonbinary_exprs(MULT_OP,
01648 arg_iter.pull(),
01649 mult_term.clone());
01650 } else {
01651 Assign<Expression> eas2(arg_iter.assign());
01652 Expression *new_arg = mult_term.clone();
01653 _pull_in_mult_expr(*new_arg, arg_iter.current(),
01654 arg_sign, comparator);
01655 delete arg_iter.pull();
01656 eas2 = new_arg;
01657 }
01658 }
01659 else {
01660 Assign<Expression> eas3(arg_iter.assign());
01661 eas3 = _join_nonbinary_exprs(MULT_OP, arg_iter.pull(),
01662 mult_term.clone());
01663 }
01664 }
01665
01666
01667
01668
01669
01670
01671 static Expression *
01672 _p_mm_o_of_mult(Expression *e, RangeComparator &comparator)
01673 {
01674 List<Expression> min_max_args;
01675
01676 Mutator<Expression> arg_iter = e->arg_list();
01677
01678 for ( ; arg_iter.valid(); ++arg_iter)
01679 if (is_min_or_max(arg_iter.current()))
01680 min_max_args.ins_last(arg_iter.grab());
01681
01682
01683
01684 Expression *result = e;
01685 EXPR_SIGN result_sign = UNKNOWN_SIGN;
01686
01687 if (e->arg_list().entries()) {
01688 result_sign = comparator.sign(*e);
01689
01690 if (result_sign == POS_NEG_EXPR) {
01691 _append_list(e->arg_list(), min_max_args);
01692 return e;
01693 }
01694 }
01695 else {
01696 result_sign = comparator.sign(*min_max_args.first_ref());
01697
01698 if (result_sign == POS_NEG_EXPR) {
01699 _append_list(e->arg_list(), min_max_args);
01700 return e;
01701 }
01702
01703 delete e;
01704 result = min_max_args.grab(*min_max_args.first_ref());
01705 }
01706
01707 Mutator<Expression> mm_iter = min_max_args;
01708 bool first_iter = true;
01709
01710 for ( ; mm_iter.valid(); ++mm_iter) {
01711
01712
01713 if (first_iter)
01714 first_iter = false;
01715 else {
01716 result_sign = comparator.sign(mm_iter.current());
01717
01718 if (result_sign == POS_NEG_EXPR) {
01719 result = mul(result, mm_iter.grab());
01720 _append_list(result->arg_list(), min_max_args);
01721 return result;
01722 }
01723 }
01724
01725
01726
01727
01728 Expression *min_or_max = mm_iter.grab();
01729 _pull_in_mult_expr(*min_or_max, *result, result_sign, comparator);
01730 delete result;
01731 result = min_or_max;
01732 }
01733
01734 return result;
01735 }
01736
01737
01738
01739
01740
01741
01742 static void
01743 _pull_in_div_expr(Expression &min_or_max, const Expression &denom,
01744 EXPR_SIGN denom_sign, const Symtab &symtab)
01745 {
01746 Mutator<Expression> arg_iter = min_or_max.parameters_guarded().arg_list();
01747
01748 if (denom_sign == NEG_EXPR)
01749 swap_min_max(min_or_max, symtab);
01750
01751 for ( ; arg_iter.valid(); ++arg_iter)
01752 if (is_min_or_max(arg_iter.current()))
01753 _pull_in_div_expr(arg_iter.current(), denom, denom_sign,
01754 symtab);
01755 else {
01756 Assign<Expression> eas(arg_iter.assign());
01757 eas = div(arg_iter.pull(), denom.clone());
01758 }
01759 }
01760
01761
01762
01763
01764
01765
01766 static Expression *
01767 _p_mm_o_of_divide(Expression *e, RangeComparator &comparator)
01768 {
01769 if (! is_min_or_max(e->left_guarded()))
01770 return e;
01771
01772 EXPR_SIGN denom_sign = comparator.signz(e->right_guarded());
01773
01774 if (denom_sign == POS_NEG_EXPR || denom_sign == ZERO_EXPR)
01775 return e;
01776
01777 Expression *result = e->grab_left();
01778 Expression *denom = e->grab_right();
01779 delete e;
01780 _pull_in_div_expr(*result, *denom, denom_sign, comparator.symtab());
01781 delete denom;
01782
01783 return result;
01784 }
01785
01786
01787
01788
01789
01790
01791 static void
01792 _pull_in_exp_expr(Expression &min_or_max, int power, EXPR_SIGN base_sign,
01793 const Symtab &symtab)
01794 {
01795 Mutator<Expression> arg_iter = min_or_max.parameters_guarded().arg_list();
01796
01797 if (base_sign == NEG_EXPR)
01798 swap_min_max(min_or_max, symtab);
01799
01800 for ( ; arg_iter.valid(); ++arg_iter)
01801 if (is_min_or_max(arg_iter.current()))
01802 _pull_in_exp_expr(arg_iter.current(), power, base_sign, symtab);
01803 else {
01804 Assign<Expression> eas(arg_iter.assign());
01805 eas = exponent(arg_iter.pull(), constant(power));
01806 }
01807 }
01808
01809
01810
01811
01812
01813 static Expression *
01814 _p_mm_o_of_exp(Expression *e, RangeComparator &comparator)
01815 {
01816 if (e->right_guarded().op() != INTEGER_CONSTANT_OP)
01817 return e;
01818
01819 int power = e->right_guarded().value();
01820
01821 if (! is_min_or_max(e->left_guarded()))
01822 return e;
01823
01824 EXPR_SIGN base_sign;
01825
01826 if (power % 2 == 1)
01827 base_sign = POS_EXPR;
01828 else {
01829 base_sign = comparator.sign(e->left_guarded());
01830
01831 if (base_sign == POS_NEG_EXPR)
01832 return e;
01833 }
01834
01835 Expression *result = e->grab_left();
01836 delete e;
01837 _pull_in_exp_expr(*result, power, base_sign, comparator.symtab());
01838
01839 return result;
01840 }
01841
01842
01843
01844
01845
01846 static Expression *
01847 _pull_min_max_out_top(Expression *e, RangeComparator &comparator)
01848 {
01849
01850
01851 if (!e || e->arg_list().entries() == 0)
01852 return e;
01853
01854
01855
01856 Iterator<Expression> arg_iter = e->arg_list();
01857 bool has_min_max_in_args = false;
01858
01859 for ( ; arg_iter.valid(); ++arg_iter)
01860 if (is_min_or_max(arg_iter.current()))
01861 has_min_max_in_args = true;
01862
01863
01864
01865 Expression *new_expr = e;
01866
01867 if (has_min_max_in_args) {
01868 switch (e->op()) {
01869
01870 case ADD_OP:
01871 new_expr = _p_mm_o_of_add(e);
01872 break;
01873
01874 case MULT_OP:
01875 new_expr = _p_mm_o_of_mult(e, comparator);
01876 break;
01877
01878 case DIV_OP:
01879 new_expr = _p_mm_o_of_divide(e, comparator);
01880 break;
01881
01882 case EXP_OP:
01883 new_expr = _p_mm_o_of_exp(e, comparator);
01884 break;
01885
01886 default:
01887
01888 break;
01889 }
01890 }
01891
01892 return new_expr;
01893 }
01894
01895
01896
01897
01898
01899 Expression *
01900 pull_min_max_out(Expression *e, RangeComparator &comparator)
01901 {
01902
01903
01904 if (!e || e->arg_list().entries() == 0)
01905 return e;
01906
01907
01908
01909 Mutator<Expression> arg_iter = e->arg_list();
01910
01911 for ( ; arg_iter.valid(); ++arg_iter) {
01912 Assign<Expression> eas(arg_iter.assign());
01913 eas = pull_min_max_out(arg_iter.pull(), comparator);
01914 }
01915
01916
01917
01918 return _pull_min_max_out_top(e, comparator);
01919 }
01920
01921
01922
01923
01924
01925
01926
01927 Expression *
01928 remove_redundant_min_max_terms(Expression *expr, RangeComparator &comparator)
01929 {
01930 if (! expr)
01931 return expr;
01932
01933 if (is_min_or_max(*expr)) {
01934 bool expr_is_max = is_max(*expr);
01935 List<Expression> &expr_terms = expr->parameters_guarded().arg_list();
01936 List<Expression> examined_terms;
01937
01938 while (expr_terms.entries() > 0) {
01939 Expression *term = expr_terms.grab(*expr_terms.first_ref());
01940 Mutator<Expression> term_iter = expr_terms;
01941
01942 for ( ; term_iter.valid() && term; ++term_iter) {
01943 Relation rel = comparator.compare(*term, term_iter.current());
01944
01945 if (rel.is_less_equal())
01946 if (expr_is_max) {
01947 delete term;
01948 term = 0;
01949 }
01950 else
01951 term_iter.del();
01952 else if (rel.is_greater_equal())
01953 if (expr_is_max)
01954 term_iter.del();
01955 else {
01956 delete term;
01957 term = 0;
01958 }
01959 }
01960
01961 if (term)
01962 examined_terms.ins_last(term);
01963 }
01964
01965 if (examined_terms.entries() == 1) {
01966 delete expr;
01967 expr = examined_terms.grab(0);
01968 }
01969 else
01970 while (examined_terms.entries())
01971 expr_terms.ins_last(examined_terms.grab(0));
01972 }
01973 else {
01974 Mutator<Expression> iter = expr->arg_list();
01975
01976 for ( ; iter.valid(); ++iter) {
01977 Assign<Expression> eas(iter.assign());
01978 eas = remove_redundant_min_max_terms(iter.pull(),
01979 comparator);
01980 }
01981 }
01982
01983 return expr;
01984 }
01985
01986
01987
01988
01989
01990
01991 static bool
01992 _delete_expr_in_list(Expression &expr, List<Expression> &list)
01993 {
01994 Mutator<Expression> iter = list;
01995
01996 for ( ; iter.valid(); ++iter)
01997 if (expr == iter.current()) {
01998 iter.del();
01999 return true;
02000 }
02001
02002 return false;
02003 }
02004
02005
02006
02007
02008
02009
02010
02011
02012 static Expression *
02013 _pull_out_common_min_max1(Expression *& expr1, Expression *& expr2,
02014 bool pull_out_max)
02015 {
02016 Expression *common_bound = 0;
02017
02018 if ((pull_out_max && is_max(*expr1) && is_max(*expr2))
02019 || (! pull_out_max && is_min(*expr1) && is_min(*expr2))) {
02020
02021 List<Expression> *common_terms = new List<Expression>;
02022 List<Expression> &expr1_args = expr1->parameters_guarded().arg_list();
02023 List<Expression> &expr2_args = expr2->parameters_guarded().arg_list();
02024 Symbol &min_max_symbol = expr1->intrinsic().symbol();
02025 Mutator<Expression> iter = expr1_args;
02026
02027 for ( ; iter.valid(); ++iter)
02028 if (_delete_expr_in_list(iter.current(), expr2_args))
02029 common_terms->ins_last(iter.grab());
02030
02031 if (expr1_args.entries() == 0) {
02032 delete expr1;
02033 expr1 = 0;
02034 }
02035 else if (expr1_args.entries() == 1) {
02036 Expression *new_expr1
02037 = expr1_args.grab(*expr1_args.first_ref());
02038 delete expr1;
02039 expr1 = new_expr1;
02040 }
02041
02042 if (expr2_args.entries() == 0) {
02043 delete expr2;
02044 expr2 = 0;
02045 }
02046 else if (expr1_args.entries() == 1) {
02047 Expression *new_expr2
02048 = expr1_args.grab(*expr2_args.first_ref());
02049 delete expr2;
02050 expr2 = new_expr2;
02051 }
02052
02053 if (common_terms->entries() == 1) {
02054 common_bound = common_terms->grab(*common_terms->first_ref());
02055 delete common_terms;
02056 }
02057 else if (common_terms->entries() >= 2) {
02058 common_bound = intrinsic_call(id(min_max_symbol),
02059 comma(common_terms));
02060 }
02061 else
02062 delete common_terms;
02063 }
02064 else if ((pull_out_max && is_max(*expr1))
02065 || (! pull_out_max && is_min(*expr1))) {
02066 List<Expression> &expr1_args = expr1->parameters_guarded().arg_list();
02067
02068 if (_delete_expr_in_list(*expr2, expr1_args)) {
02069 common_bound = expr2;
02070 expr2 = 0;
02071
02072 if (expr1_args.entries() == 1) {
02073 Expression *new_expr1
02074 = expr1_args.grab(*expr1_args.first_ref());
02075 delete expr1;
02076 expr1 = new_expr1;
02077 }
02078 }
02079 }
02080 else if ((pull_out_max && is_max(*expr2))
02081 || (! pull_out_max && is_min(*expr2))) {
02082 List<Expression> &expr2_args = expr2->parameters_guarded().arg_list();
02083
02084 if (_delete_expr_in_list(*expr1, expr2_args)) {
02085 common_bound = expr1;
02086 expr1 = 0;
02087
02088 if (expr2_args.entries() == 1) {
02089 Expression *new_expr2
02090 = expr2_args.grab(*expr2_args.first_ref());
02091 delete expr2;
02092 expr2 = new_expr2;
02093 }
02094 }
02095 }
02096
02097 return common_bound;
02098 }
02099
02100 static RangeExpr *
02101 _pull_out_common_min_max(RangeExpr &range1, RangeExpr &range2)
02102 {
02103 Expression *common_lb = 0;
02104 Expression *common_ub = 0;
02105
02106 if (range1.has_lb() && range2.has_lb()) {
02107 Expression *lb1 = range1.grab_lb();
02108 Expression *lb2 = range2.grab_lb();
02109 common_lb = _pull_out_common_min_max1(lb1, lb2, true);
02110 range1.lb(lb1);
02111 range2.lb(lb2);
02112 }
02113
02114 if (range1.has_ub() && range2.has_ub()) {
02115 Expression *ub1 = range1.grab_ub();
02116 Expression *ub2 = range2.grab_ub();
02117 common_ub = _pull_out_common_min_max1(ub1, ub2, false);
02118 range1.ub(ub1);
02119 range2.ub(ub2);
02120 }
02121
02122 if (common_lb || common_ub)
02123 return new RangeExpr(common_lb, common_ub);
02124
02125 return 0;
02126 }
02127
02128
02129
02130
02131
02132 static RangeExpr *
02133 _join_ranges(RangeExpr *range1, RangeExpr *range2, const Symtab &symtab)
02134 {
02135 if (! range1)
02136 return range2;
02137
02138 if (! range2)
02139 return range1;
02140
02141 if (range1->has_lb()) {
02142 if (range2->has_lb())
02143 range1->lb(max_expr(range1->grab_lb(), range2->grab_lb(), symtab));
02144 }
02145 else
02146 range1->lb(range2->grab_lb());
02147
02148 if (range1->has_ub()) {
02149 if (range2->has_ub())
02150 range1->ub(min_expr(range1->grab_ub(), range2->grab_ub(), symtab));
02151 }
02152 else
02153 range1->ub(range2->grab_ub());
02154
02155 delete range2;
02156 range1->standardize();
02157
02158 return range1;
02159 }
02160
02161
02162
02163
02164 Expression *
02165 intersect_ranges(const Expression *range1_ref, RangeComparator &comparator1,
02166 const Expression *range2_ref, RangeComparator &comparator2)
02167 {
02168 if (! range1_ref || range1_ref->op() == OMEGA_OP)
02169 if (range2_ref)
02170 return range2_ref->clone();
02171 else
02172 return 0;
02173 else if (! range2_ref || range2_ref->op() == OMEGA_OP)
02174 return range1_ref->clone();
02175 else if (is_empty_range(*range1_ref))
02176 return range1_ref->clone();
02177 else if (is_empty_range(*range2_ref))
02178 return range2_ref->clone();
02179 else if (range1_ref->compare(*range2_ref) == 0)
02180 return range1_ref->clone();
02181
02182 RangeExpr *range1 = convert_to_range(range1_ref->clone());
02183 RangeExpr *range2 = convert_to_range(range2_ref->clone());
02184 RangeExpr *common_range = _pull_out_common_min_max(*range1, *range2);
02185 bool range_modified = false;
02186 int range_join_acc = min(comparator1.range_join_accuracy(),
02187 comparator2.range_join_accuracy());
02188
02189 Relation lb_rel = compare(range1->lb(), comparator1,
02190 range2->lb(), comparator2);
02191
02192 if (! lb_rel.is_equal() && lb_rel.is_less_equal() &&
02193 ! lb_rel.is_circular()) {
02194 range1->lb(range2->grab_lb());
02195 range_modified = true;
02196 }
02197 else if (lb_rel.is_unknown() && ! lb_rel.is_circular() &&
02198 range_join_acc >= 1) {
02199 range1->lb(max_expr(range1->grab_lb(), range2->grab_lb(),
02200 comparator1.symtab()));
02201 range_modified = true;
02202 }
02203
02204 Relation ub_rel = compare(range1->ub(), comparator1,
02205 range2->ub(), comparator2);
02206
02207 if (! ub_rel.is_equal() && ub_rel.is_greater_equal() &&
02208 ! ub_rel.is_circular()) {
02209 range1->ub(range2->grab_ub());
02210 range_modified = true;
02211 }
02212 else if (ub_rel.is_unknown() && ! ub_rel.is_circular() &&
02213 range_join_acc >= 1) {
02214 range1->ub(min_expr(range1->grab_ub(), range2->grab_ub(),
02215 comparator1.symtab()));
02216 range_modified = true;
02217 }
02218
02219 delete range2;
02220 range1 = _join_ranges(range1, common_range, comparator1.symtab());
02221
02222 Expression *result = range1;
02223
02224 if (range1->lb() == range1->ub()) {
02225
02226 result = range1->grab_lb();
02227 delete range1;
02228 }
02229 else if (range_modified && range1->compare(*range2_ref) != 0) {
02230 Relation lub_rel = compare(range1->lb(), comparator1,
02231 range1->ub(), comparator2);
02232
02233 if (lub_rel.is_greater_than()) {
02234
02235 result = new RangeExpr(constant(1), constant(0));
02236 delete range1;
02237 }
02238 }
02239
02240 result = expr_expand_substituted(result);
02241 result = simplify(result);
02242
02243 return result;
02244 }
02245
02246
02247
02248
02249 Expression *
02250 union_ranges(const Expression *range1_ref, RangeComparator &comparator1,
02251 const Expression *range2_ref, RangeComparator &comparator2)
02252 {
02253 if (! range1_ref || range1_ref->op() == OMEGA_OP
02254 || ! range2_ref || range2_ref->op() == OMEGA_OP)
02255 return 0;
02256 else if (is_empty_range(*range1_ref))
02257 return range2_ref->clone();
02258 else if (is_empty_range(*range2_ref))
02259 return range1_ref->clone();
02260 else if (range1_ref->compare(*range2_ref) == 0)
02261 return range1_ref->clone();
02262
02263 RangeExpr *range1 = convert_to_range(range1_ref->clone());
02264 RangeExpr *range2 = convert_to_range(range2_ref->clone());
02265 RangeExpr *common_range = _pull_out_common_min_max(*range1, *range2);
02266 int range_join_acc = min(comparator1.range_join_accuracy(),
02267 comparator2.range_join_accuracy());
02268
02269 Relation lb_rel = compare(range1->lb(), comparator1,
02270 range2->lb(), comparator2);
02271
02272 if (! lb_rel.is_equal() && lb_rel.is_greater_equal())
02273 range1->lb(range2->grab_lb());
02274 else if (! lb_rel.is_less_equal())
02275 if (range_join_acc <= 1)
02276 range1->lb(0);
02277 else
02278 range1->lb(min_expr(range1->grab_lb(), range2->grab_lb(),
02279 comparator1.symtab()));
02280
02281 Relation ub_rel = compare(range1->ub(), comparator1,
02282 range2->ub(), comparator2);
02283
02284 if (! ub_rel.is_equal() && ub_rel.is_less_equal())
02285 range1->ub(range2->grab_ub());
02286 else if (! ub_rel.is_greater_equal())
02287 if (range_join_acc <= 1)
02288 range1->ub(0);
02289 else
02290 range1->ub(max_expr(range1->grab_ub(), range2->grab_ub(),
02291 comparator1.symtab()));
02292
02293 delete range2;
02294 range1 = _join_ranges(range1, common_range, comparator1.symtab());
02295
02296 Expression *result = range1;
02297
02298 if (! range1->has_lb() && ! range1->has_ub()) {
02299 delete range1;
02300 result = 0;
02301 }
02302 else if (range1->lb() == range1->ub()) {
02303
02304 result = range1->grab_lb();
02305 delete range1;
02306 }
02307
02308 result = expr_expand_substituted(result);
02309 result = simplify(result);
02310
02311 return result;
02312 }
02313
02314
02315
02316
02317 Expression *
02318 widen_range(const Expression *expr_ref, const Expression *widener_ref,
02319 RangeComparator &comparator)
02320 {
02321 if (! expr_ref || expr_ref->op() == OMEGA_OP
02322 || ! widener_ref || widener_ref->op() == OMEGA_OP)
02323 return 0;
02324 else if (is_empty_range(*expr_ref))
02325 return widener_ref->clone();
02326 else if (is_empty_range(*widener_ref))
02327 return expr_ref->clone();
02328
02329 RangeExpr *result = convert_to_range(expr_ref->clone());
02330 RangeExpr *widen_range = convert_to_range(widener_ref->clone());
02331 RangeExpr *common_range = _pull_out_common_min_max(*result, *widen_range);
02332
02333 if (result->lb() != widen_range->lb())
02334 result->lb(0);
02335
02336 if (result->ub() != widen_range->ub())
02337 result->ub(0);
02338
02339 delete widen_range;
02340 result = _join_ranges(result, common_range, comparator.symtab());
02341
02342 if (! result->has_lb() && ! result->has_ub()) {
02343 delete result;
02344 result = 0;
02345 }
02346 else if (result->lb() == result->ub()) {
02347
02348 Expression *temp = result->grab_lb();
02349 delete result;
02350 return temp;
02351 }
02352
02353 return result;
02354 }
02355
02356
02357
02358
02359 Expression *
02360 narrow_range(const Expression *expr_ref, const Expression *narrow_ref,
02361 RangeComparator &comparator)
02362 {
02363 if (! narrow_ref || narrow_ref->op() == OMEGA_OP) {
02364 if (expr_ref)
02365 return expr_ref->clone();
02366 else
02367 return 0;
02368 }
02369 else if (! expr_ref || expr_ref->op() == OMEGA_OP
02370 || narrow_ref->op() != RANGE_OP)
02371 return narrow_ref->clone();
02372
02373 RangeExpr *result = convert_to_range(expr_ref->clone());
02374 RangeExpr *narrow_range = convert_to_range(narrow_ref->clone());
02375 RangeExpr *common_range = _pull_out_common_min_max(*result, *narrow_range);
02376
02377 if (narrow_range->has_lb())
02378 result->lb(narrow_range->grab_lb());
02379
02380 if (narrow_range->has_ub())
02381 result->ub(narrow_range->grab_ub());
02382
02383 delete narrow_range;
02384
02385 result = _join_ranges(result, common_range, comparator.symtab());
02386
02387 if (result->lb() == result->ub()) {
02388
02389 Expression *temp = result->grab_lb();
02390 delete result;
02391 return temp;
02392 }
02393
02394 return result;
02395 }
02396
02397
02398
02399
02400 Relation compare(const Expression &e1, RangeComparator &c1,
02401 const Expression &e2, RangeComparator &c2)
02402 {
02403 Relation rel = c1.compare(e1, e2);
02404
02405 if (! rel.is_unknown() && &c1 != &c2)
02406 rel &= c2.compare(e1, e2);
02407
02408 return rel;
02409 }
02410
02411
02412
02413
02414
02415 static OP_TYPE
02416 _negate_rel_op(OP_TYPE rel_op)
02417 {
02418 switch(rel_op) {
02419 case LT_OP:
02420 return GT_OP;
02421
02422 case LE_OP:
02423 return GE_OP;
02424
02425 case GT_OP:
02426 return LT_OP;
02427
02428 case GE_OP:
02429 return LE_OP;
02430
02431 default:
02432 return rel_op;
02433 }
02434 }
02435
02436 #if 0
02437
02438
02439
02440
02441
02442 static Expression *
02443 _remove_div(Expression *expr, int &factor, bool take_max)
02444 {
02445 factor = expr->right_guarded().value();
02446 Expresion *numer = expr->grab_left();
02447 delete expr;
02448
02449 if ((factor >= 0 && ! take_max) || (factor < 0 && take_max)) {
02450 int truncate = -factor;
02451
02452 if (truncate >= 0)
02453 --truncate;
02454 else
02455 ++truncate;
02456
02457 numer = add(constant(truncate), numer);
02458 }
02459
02460 return numer;
02461 }
02462
02463 static Expression *
02464 _remove_divs_from_term(Expression *expr, int &factor, bool take_max)
02465 {
02466 factor = 1;
02467
02468 if (expr->op() == DIV_OP
02469 && expr->right_guarded().op() == INTEGER_CONSTANT_OP) {
02470
02471 expr = _remove_div(expr, factor, take_max);
02472 }
02473 else if (expr->op() == MULT_OP
02474 && expr->arg_list().entries() == 2) {
02475 if (expr->arg_list()[1].op() == INTEGER_CONSTANT_OP) {
02476 Expression *swap = expr->arg_list().grab(1);
02477 expr->arg_list().ins_first(swap);
02478 }
02479
02480 if (expr->arg_list()[0].op() == INTEGER_CONSTANT_OP
02481 && expr->arg_list()[1].op() == DIV_OP
02482 && expr->arg_list()[1].right_guarded().op() == INTEGER_CONSTANT_OP) {
02483
02484 int term_factor = expr->arg_list()[0].value();
02485
02486 if (term_factor >= 0)
02487 expr->arg_list().ins(1, _remove_div(expr->arg_list().grab(1),
02488 factor, take_max));
02489 else
02490 expr->arg_list().ins(1, _remove_div(expr->arg_list().grab(1),
02491 factor, ! take_max));
02492
02493 if (term_factor % factor == 0) {
02494 expr->arg_list()[0].value(term_factor / abs(factor));
02495 factor = (factor >= 0) ? +1; -1;
02496 }
02497 else if (factor % term_factor == 0) {
02498 factor = factor / abs(term_factor);
02499 term_factor = (term_factor >= 0) ? +1; -1;
02500 }
02501 }
02502 }
02503
02504 return expr;
02505 }
02506
02507
02508
02509
02510
02511 static void
02512 _remove_divs_from_rel(Expression &expr)
02513 {
02514 Expression &rel_expr = expr.left_guarded();
02515
02516 if (rel_expr.op() == ADD_OP) {
02517 List<Expression> &rel_args = rel_expr.arg_list();
02518 Mutator<Expression> arg_iter = rel_args;
02519
02520 for ( ; arg_iter.valid(); ++arg_iter) {
02521 Expression *prev = rel_args.prev_ref(arg_iter.current());
02522 Expression *curr = rel_args.grab(arg_iter.current());
02523 _extract_a_range(*curr, expr.op(), &rel_expr, ranges);
02524 rel_args.ins_after(curr, prev);
02525 }
02526 }
02527 }
02528 #endif
02529
02530
02531
02532
02533
02534
02535
02536
02537 static void
02538 _extract_a_range(const Expression &var_term, OP_TYPE rel_op,
02539 const Expression *other_terms,
02540 Map< Symbol, Set<Expression> > &ranges)
02541 {
02542
02543
02544
02545 int factor = 1;
02546 const Symbol *var = 0;
02547
02548 if (var_term.op() == MULT_OP && var_term.arg_list().entries() == 2) {
02549 const Expression &left = *var_term.arg_list().first_ref();
02550 const Expression &right = *var_term.arg_list().last_ref();
02551
02552 if (left.op() == INTEGER_CONSTANT_OP && right.op() == ID_OP) {
02553 factor = left.value();
02554 var = &right.symbol();
02555 }
02556 else if (left.op() == ID_OP && right.op() == INTEGER_CONSTANT_OP) {
02557 var = &left.symbol();
02558 factor = right.value();
02559 }
02560 }
02561 else if (var_term.op() == ID_OP) {
02562 var = &var_term.symbol();
02563 }
02564
02565 if (! var)
02566 return;
02567
02568
02569
02570 if (other_terms && is_var_in_expr(*other_terms, *var))
02571 return;
02572
02573
02574
02575 Expression *bound;
02576
02577 if (! other_terms)
02578 bound = constant(0);
02579 else
02580 bound = other_terms->clone();
02581
02582 if (factor >= 0) {
02583 bound = unary_minus(bound);
02584 }
02585 else {
02586 factor = -factor;
02587 rel_op = _negate_rel_op(rel_op);
02588 }
02589
02590 if (factor != 1)
02591 bound = div(bound, constant(factor));
02592
02593
02594
02595 if (rel_op == LT_OP) {
02596 bound = add(bound, constant(-1));
02597 rel_op = LE_OP;
02598 }
02599 else if (rel_op == GT_OP) {
02600 bound = add(bound, constant(1));
02601 rel_op = GE_OP;
02602 }
02603
02604 bound = simplify(bound);
02605
02606
02607
02608 Expression *range = NULL;
02609
02610 switch (rel_op) {
02611 case EQ_OP:
02612 range = bound;
02613 break;
02614
02615 case LE_OP:
02616 range = new RangeExpr(0, bound);
02617 break;
02618
02619 case GE_OP:
02620 range = new RangeExpr(bound, 0);
02621 break;
02622
02623 default:
02624 p_abort("Internal error: _extract_a_range received a non relation EXPR_OP");
02625 break;
02626 }
02627
02628
02629
02630 Set<Expression> *var_ranges = ranges.find_ref(*var);
02631
02632 if (! var_ranges) {
02633 var_ranges = new Set<Expression>;
02634 ranges.ins(*var, var_ranges);
02635 }
02636
02637 var_ranges->ins(range);
02638 }
02639
02640
02641
02642
02643
02644
02645 static void
02646 _extract_ranges_rel(Expression &expr,
02647 Map< Symbol, Set<Expression> > &ranges)
02648 {
02649 if (expr.left_guarded().type().data_type() != INTEGER_TYPE
02650 || expr.right_guarded().type().data_type() != INTEGER_TYPE)
02651 return;
02652
02653 if (! is_integer_zero(expr.right_guarded()))
02654 if (is_integer_zero(expr.left_guarded())) {
02655 Expression *temp = expr.grab_left();
02656 expr.left(expr.grab_right());
02657 expr.right(temp);
02658
02659 switch (expr.op()) {
02660 case LT_OP: expr.op(GT_OP); break;
02661 case GE_OP: expr.op(LE_OP); break;
02662 case LE_OP: expr.op(GE_OP); break;
02663 case GT_OP: expr.op(LT_OP); break;
02664 default: break;
02665 }
02666 }
02667 else
02668 p_abort("Internal Error: _extract_ranges_rel received an unsimplified relation expr");
02669
02670 Expression &rel_expr = expr.left_guarded();
02671
02672 if (rel_expr.op() == ADD_OP) {
02673 List<Expression> &rel_args = rel_expr.arg_list();
02674 Mutator<Expression> arg_iter = rel_args;
02675
02676 for ( ; arg_iter.valid(); ++arg_iter) {
02677 Expression *prev = rel_args.prev_ref(arg_iter.current());
02678 Expression *curr = rel_args.grab(arg_iter.current());
02679 _extract_a_range(*curr, expr.op(), &rel_expr, ranges);
02680 rel_args.ins_after(curr, prev);
02681 }
02682 }
02683 else
02684 _extract_a_range(rel_expr, expr.op(), 0, ranges);
02685 }
02686
02687
02688
02689
02690 void
02691 _extract_ranges(Expression &expr, Map< Symbol, Set<Expression> > &ranges)
02692 {
02693 switch (expr.op()) {
02694 case AND_OP:
02695 case PAREN_OP:
02696 {
02697 Iterator<Expression> arg_iter = expr.arg_list();
02698
02699 for ( ; arg_iter.valid(); ++arg_iter)
02700 _extract_ranges(arg_iter.current(), ranges);
02701 }
02702 break;
02703
02704 case EQ_OP:
02705 case LT_OP:
02706 case LE_OP:
02707 case GT_OP:
02708 case GE_OP:
02709 _extract_ranges_rel(expr, ranges);
02710 break;
02711
02712 default:
02713 break;
02714 }
02715 }
02716
02717
02718
02719
02720 Map< Symbol, Set<Expression> > *
02721 extract_ranges(const Expression &expr, bool complement_expr GIV(false))
02722 {
02723 Map< Symbol, Set<Expression> > *ranges = new Map< Symbol, Set<Expression> >;
02724
02725 Expression *new_expr = expr.clone();
02726
02727 if (complement_expr)
02728 new_expr = not(new_expr);
02729
02730 new_expr = expr_expand_substituted(new_expr);
02731 new_expr = simplify(new_expr);
02732 _extract_ranges(*new_expr, *ranges);
02733 delete new_expr;
02734
02735 return ranges;
02736 }
02737
02738
02739
02740
02741 void
02742 pretty_print_range(ostream &o, const Expression &expr, const Symbol &var)
02743 {
02744 if (expr.op() == RANGE_OP) {
02745 RangeExpr &range = * (RangeExpr *) &expr;
02746
02747 if (range.has_lb() && range.has_ub())
02748 o << range.lb() << "<=" << var.name_ref()
02749 << "<=" << range.ub();
02750 else if (range.has_lb())
02751 o << var.name_ref() << ">=" << range.lb();
02752 else if (range.has_ub())
02753 o << var.name_ref() << "<=" << range.ub();
02754 else
02755 o << var.name_ref() << "=???";
02756 }
02757 else if (expr.op() == OMEGA_OP)
02758 o << var.name_ref() << "=???";
02759 else
02760 o << var.name_ref() << "=" << expr;
02761 }
02762
02763
02764
02765
02766
02767
02768
02769
02770
02771 Expression *
02772 elim_known_facts (Expression *e, RangeComparator &comparator)
02773 {
02774 Expression * new_expr = _elim_known_facts (e, comparator);
02775
02776 new_expr = simplify(new_expr);
02777 return new_expr;
02778 }
02779
02780
02781
02782
02783
02784
02785
02786
02787
02788
02789
02790
02791
02792
02793
02794
02795
02796
02797
02798 static Expression *
02799 _elim_known_facts(Expression *e, RangeComparator &comparator)
02800 {
02801 Expression * new_expr;
02802
02803 if (is_relational_op(e->op())) {
02804 Relation relate =
02805 comparator.compare(e->arg_list()[0],e->arg_list()[1]);
02806 switch (e->op())
02807 {
02808 case LT_OP:
02809 if (relate.is_less_than()) {
02810 new_expr = constant(".TRUE.");
02811 delete e;
02812 } else if (relate.is_greater_equal()) {
02813 new_expr = constant(".FALSE.");
02814 delete e;
02815 } else {
02816 new_expr = e;
02817 }
02818 break;
02819 case GT_OP:
02820 if (relate.is_greater_than()) {
02821 new_expr = constant(".TRUE.");
02822 delete e;
02823 } else if (relate.is_less_equal()) {
02824 new_expr = constant(".FALSE.");
02825 delete e;
02826 } else {
02827 new_expr = e;
02828 }
02829 break;
02830 case LE_OP:
02831 if (relate.is_less_equal()) {
02832 new_expr = constant(".TRUE.");
02833 delete e;
02834 } else if (relate.is_greater_than()) {
02835 new_expr = constant(".FALSE.");
02836 delete e;
02837 } else {
02838 new_expr = e;
02839 }
02840 break;
02841 case GE_OP:
02842 if (relate.is_greater_equal()) {
02843 new_expr = constant(".TRUE.");
02844 delete e;
02845 } else if (relate.is_less_than()) {
02846 new_expr = constant(".FALSE.");
02847 delete e;
02848 } else {
02849 new_expr = e;
02850 }
02851 break;
02852 case EQ_OP:
02853 if (relate.is_equal()) {
02854 new_expr = constant(".TRUE.");
02855 delete e;
02856 } else if (relate.is_not_equal()) {
02857 new_expr = constant(".FALSE.");
02858 delete e;
02859 } else {
02860 new_expr = e;
02861 }
02862 break;
02863 case NE_OP:
02864 if (relate.is_not_equal()) {
02865 new_expr = constant(".TRUE.");
02866 delete e;
02867 } else if (relate.is_equal()) {
02868 new_expr = constant(".FALSE.");
02869 delete e;
02870 } else {
02871 new_expr = e;
02872 }
02873 break;
02874 default:
02875 new_expr = e;
02876 break;
02877 }
02878
02879
02880
02881 } else if (is_min(*e)) {
02882 if (e->parameters_valid()) {
02883 Expression & expr_left =
02884 e->parameters_guarded().arg_list()[0];
02885
02886 Expression & expr_right =
02887 e->parameters_guarded().arg_list()[1];
02888
02889 Relation relate2 =
02890 comparator.compare(expr_left, expr_right);
02891
02892 if (relate2.is_greater_than() ||
02893 relate2.is_greater_equal() ||
02894 relate2.is_equal()) {
02895 new_expr = expr_right.clone();
02896 delete e;
02897 } else if (relate2.is_less_than() ||
02898 relate2.is_less_equal()) {
02899 new_expr = expr_left.clone();
02900 delete e;
02901 } else {
02902 new_expr = e;
02903 }
02904 } else {
02905 new_expr = e;
02906 }
02907
02908
02909
02910 } else if (is_max(*e)) {
02911 if (e->parameters_valid()) {
02912 Expression & expr_left =
02913 e->parameters_guarded().arg_list()[0];
02914
02915 Expression & expr_right =
02916 e->parameters_guarded().arg_list()[1];
02917
02918 Relation relate2 =
02919 comparator.compare(expr_left, expr_right);
02920
02921 if (relate2.is_greater_than() ||
02922 relate2.is_greater_equal() ||
02923 relate2.is_equal()) {
02924 new_expr = expr_left.clone();
02925 delete e;
02926 } else if (relate2.is_less_than() ||
02927 relate2.is_less_equal()) {
02928 new_expr = expr_right.clone();
02929 delete e;
02930 } else {
02931 new_expr = e;
02932 }
02933 } else {
02934 new_expr = e;
02935 }
02936
02937 } else {
02938 Mutator<Expression> arg_iter = e->arg_list();
02939
02940 for ( ; arg_iter.valid(); ++arg_iter) {
02941 Assign<Expression> eas(arg_iter.assign());
02942 Expression *new_arg = _elim_known_facts (arg_iter.pull(),
02943 comparator);
02944 eas = new_arg;
02945 }
02946 new_expr = e;
02947 }
02948
02949 return new_expr;
02950 }
02951
02952 static Boolean
02953 is_scalar_id (const Expression & expr)
02954 {
02955 if (expr.op() == ID_OP) {
02956 if (expr.symbol().is_scalar()) return True;
02957 }
02958 return False;
02959 }
02960
02961 void
02962 copy_expr_ranges (Expression & expr,
02963 RangeAccessor & orig_ranges,
02964 StmtRanges & new_ranges)
02965 {
02966 Traverser tr(expr, is_scalar_id);
02967
02968 for ( ; tr.valid(); ++tr) {
02969 const Symbol & sym = tr.current().symbol();
02970
02971 if (new_ranges.get_range_ref(sym)) continue;
02972
02973 const Expression * old_range = orig_ranges.get_range_ref(sym);
02974
02975 if (old_range) {
02976 Expression * new_range = old_range->clone();
02977 new_ranges.set_range(tr.current().symbol(), new_range);
02978
02979 copy_expr_ranges(*new_range, orig_ranges, new_ranges);
02980 }
02981 }
02982 }
02983
02984
02985 static Boolean
02986 is_ID_OP (const Expression & expr)
02987 {
02988 if (expr.op() == ID_OP) {
02989 return True;
02990 } else {
02991 return False;
02992 }
02993 }
02994
02995
02996
02997
02998
02999
03000
03001
03002 void
03003 apply_limits(Expression & expr,
03004 Expression * lower, Expression * upper,
03005 StmtRanges & ranges,
03006 RefSet<Symbol> & set)
03007 {
03008
03009
03010
03011
03012 int ids = 0;
03013 const Symbol * sym = 0;
03014 if (expr.op() == ID_OP) {
03015 sym = expr.base_variable_ref();
03016 ids = 1;
03017 } else {
03018 Traverser exprtr(expr, is_ID_OP);
03019 for ( ; exprtr.valid(); ++exprtr) {
03020 ++ids;
03021 sym = exprtr.current().base_variable_ref();
03022 }
03023 }
03024 if (ids == 1) {
03025
03026 if (set.member(*sym)) return;
03027
03028 const Expression * expr_range1 = ranges.get_range_ref(*sym);
03029 if (expr_range1) {
03030 const Expression * expr_range = expr_range1->clone();
03031 if (expr_range->op() == RANGE_OP) {
03032
03033 if (lower) {
03034
03035 if (((RangeExpr *)expr_range)->lb().op() == INFINITY_OP) {
03036 set_ranges_for_symbol(*(ge(expr.clone(),lower->clone())),
03037 *sym, ranges);
03038 } else {
03039 Expression *lb = substitute_var(expr.clone(), *sym,
03040 ((RangeExpr *)expr_range)->lb());
03041 set.ins(*sym);
03042 apply_limits(*lb, lower, upper, ranges, set);
03043 delete lb;
03044 }
03045 }
03046 if (upper) {
03047
03048 if (((RangeExpr *)expr_range)->ub().op() == INFINITY_OP) {
03049 set_ranges_for_symbol(*(le(expr.clone(),upper->clone())),
03050 *sym, ranges);
03051 } else {
03052 Expression *ub = substitute_var(expr.clone(), *sym,
03053 ((RangeExpr *)expr_range)->ub());
03054 set.ins(*sym);
03055 apply_limits(*ub, lower, upper, ranges, set);
03056 delete ub;
03057 }
03058 }
03059 } else {
03060 Expression *ex = substitute_var(expr.clone(), *sym, *expr_range);
03061 set.ins(*sym);
03062 apply_limits(*ex, lower, upper, ranges, set);
03063 delete ex;
03064 }
03065 delete expr_range;
03066 } else {
03067 if (lower && upper) {
03068 set_ranges_for_symbol(*and(ge(expr.clone(),lower->clone()),
03069 le(expr.clone(),upper->clone())),
03070 *sym, ranges);
03071 } else if (lower) {
03072 set_ranges_for_symbol(*ge(expr.clone(),lower->clone()),
03073 *sym, ranges);
03074 } else if (upper) {
03075 set_ranges_for_symbol(*le(expr.clone(),upper->clone()),
03076 *sym, ranges);
03077 }
03078 }
03079 } else if (expr.op() == INTEGER_CONSTANT_OP) {
03080 RefSet<Symbol> tightset;
03081 if (upper)
03082 tighten_upper_bound(expr, upper, ranges, tightset);
03083 tightset.clear();
03084 if (lower)
03085 tighten_lower_bound(expr, lower, ranges, tightset);
03086 }
03087 }
03088
03089
03090
03091
03092 void
03093 set_ranges_for_symbol(Expression & expr, const Symbol & sym, StmtRanges & ranges)
03094 {
03095 Map<Symbol, Set<Expression> > * map =
03096 extract_ranges(expr);
03097 Set<Expression> *set = map->find_ref(sym);
03098 if (set) {
03099 Iterator<Expression> iter = *set;
03100 Expression * new_lb = 0;
03101 Expression * new_ub = 0;
03102 const Expression * expr_range = 0;
03103
03104 for ( ; iter.valid(); ++iter) {
03105 Expression & range = iter.current();
03106 if (range.op() != RANGE_OP) {
03107 if (new_lb == 0) new_lb = range.clone();
03108 if (new_ub == 0) new_ub = range.clone();
03109 } else {
03110 if ((((RangeExpr &)range).lb().op() != INFINITY_OP) &&
03111 (new_lb == 0)) {
03112 new_lb = ((RangeExpr &)range).lb().clone();
03113 } else {
03114 if (expr_range == 0) expr_range = ranges.get_range_ref(sym);
03115 if (expr_range && (expr_range->op() == RANGE_OP)) {
03116 new_lb = ((RangeExpr *)expr_range)->lb().clone();
03117 }
03118 }
03119 if ((((RangeExpr &)range).ub().op() != INFINITY_OP) &&
03120 (new_ub == 0)) {
03121 new_ub = ((RangeExpr &)range).ub().clone();
03122 } else {
03123 if (expr_range == 0) expr_range = ranges.get_range_ref(sym);
03124 if (expr_range && (expr_range->op() == RANGE_OP)) {
03125 new_ub = ((RangeExpr *)expr_range)->ub().clone();
03126 }
03127 }
03128 }
03129 }
03130 RangeExpr * new_range = new RangeExpr(new_lb, new_ub);
03131 ranges.set_range(sym, new_range);
03132 }
03133 }
03134 void
03135 tighten_upper_bound(Expression & expr, const Expression *upper, StmtRanges & ranges, RefSet<Symbol> & set)
03136 {
03137 int ids = 0;
03138 const Symbol * sym = 0;
03139 if (upper->op() == ID_OP) {
03140 sym = upper->base_variable_ref();
03141 ids = 1;
03142 } else {
03143 Traverser exprtr(*upper, is_ID_OP);
03144 for ( ; exprtr.valid(); ++exprtr) {
03145 ++ids;
03146 sym = exprtr.current().base_variable_ref();
03147 }
03148 }
03149 if (ids == 1) {
03150
03151 if (set.member(*sym)) return;
03152
03153 const Expression * expr_range = ranges.get_range_ref(*sym);
03154 if (expr_range) {
03155 if (expr_range->op() == RANGE_OP) {
03156 if (((RangeExpr *)expr_range)->lb().op() == INTEGER_CONSTANT_OP) {
03157 if (expr.value() > ((RangeExpr *)expr_range)->lb().value()) {
03158 ((RangeExpr *)expr_range)->lb(expr.clone());
03159 }
03160 }
03161 if (((RangeExpr *)expr_range)->lb().op() != INFINITY_OP) {
03162 set.ins(*sym);
03163 tighten_lower_bound(expr, &(((RangeExpr *)expr_range)->lb()),
03164 ranges, set);
03165 }
03166 if (((RangeExpr *)expr_range)->ub().op() != INFINITY_OP) {
03167 set.ins(*sym);
03168 tighten_upper_bound(expr, &(((RangeExpr *)expr_range)->ub()),
03169 ranges, set);
03170 }
03171 } else {
03172 set.ins(*sym);
03173 tighten_upper_bound(expr, expr_range, ranges, set);
03174 }
03175 }
03176 }
03177 }
03178 void
03179 tighten_lower_bound(Expression & expr, const Expression *lower, StmtRanges & ranges, RefSet<Symbol> & set)
03180 {
03181 int ids = 0;
03182 const Symbol * sym = 0;
03183 if (lower->op() == ID_OP) {
03184 sym = lower->base_variable_ref();
03185 ids = 1;
03186 } else {
03187 Traverser exprtr(*lower, is_ID_OP);
03188 for ( ; exprtr.valid(); ++exprtr) {
03189 ++ids;
03190 sym = exprtr.current().base_variable_ref();
03191 }
03192 }
03193 if (ids == 1) {
03194
03195 if (set.member(*sym)) return;
03196
03197 const Expression * expr_range = ranges.get_range_ref(*sym);
03198 if (expr_range) {
03199 if (expr_range->op() == RANGE_OP) {
03200 if (((RangeExpr *)expr_range)->ub().op() == INTEGER_CONSTANT_OP) {
03201 if (expr.value() < ((RangeExpr *)expr_range)->ub().value()) {
03202 ((RangeExpr *)expr_range)->ub(expr.clone());
03203 }
03204 }
03205 if (((RangeExpr *)expr_range)->lb().op() != INFINITY_OP) {
03206 set.ins(*sym);
03207 tighten_lower_bound(expr, &(((RangeExpr *)expr_range)->lb()),
03208 ranges, set);
03209 }
03210 if (((RangeExpr *)expr_range)->ub().op() != INFINITY_OP) {
03211 set.ins(*sym);
03212 tighten_upper_bound(expr, &(((RangeExpr *)expr_range)->ub()),
03213 ranges, set);
03214 }
03215 } else {
03216 set.ins(*sym);
03217 tighten_lower_bound(expr, expr_range, ranges, set);
03218 }
03219 }
03220 }
03221 }