Polaris: range_util.cc Source File

range_util.cc

Go to the documentation of this file.
00001 ///
00002 ///
00003 /// \file range_util.cc
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 ///  _handle_range
00039 ///    Return the desired component of the range, as indicated by the
00040 ///    range_handling flag.
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 ///  _swap_range_args
00078 ///    Swap the lower and upper bounds of the given range_expression
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 ///  _negate_range
00096 ///    Negate the given range.
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 ///  _p_r_o_of_add
00112 ///    Convert an addition expression whose arguments contain ranges into
00113 ///    a range expression.
00114 
00115 static Expression *
00116 _p_r_o_of_add(Expression *e)
00117 {
00118 /// silvius: not sure how to fix this cleanly, but it breaks
00119 /// on [0:Inf]+[0:Inf]
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 ///   cerr<<"\n *e= "<<*e<<"\t*_u_f= "<<*_ugly_fix_l<<", "<<*_ugly_fix_u;
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 ///         cerr<<"\nBug fix for function  _p_r_o_of_add("<<*e<<").";
00138         return new RangeExpr(constant(0), infinity());
00139       }
00140     }
00141       }
00142     }
00143   }
00144 /// silvius: it also breaks on [0:Inf]+(-1)*ABS(biga@4)
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 ///         cerr<<"\nBug fix for function  _p_r_o_of_add("<<*e<<").";
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 /// silvius: it also breaks on 1+[-Inf:0]
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         /// ...         cerr<<"\nBug fix for function  _p_r_o_of_add("<<*e<<").";
00173         return new RangeExpr(infinity(-1), simplify(add(e->arg_list()[1].clone(),
00174                                   e1.ub().clone())));
00175       }
00176     }
00177       }
00178     }
00179   }  
00180 /// end silvius fix
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 ///  _range_bound_multiply
00222 ///    Multiply the two expressions and return the result.  Return 0 if the
00223 ///    expression turns out to be infinite or undefined.
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 ///  _mult_range_with_expr
00270 ///    Multiply the given range with the given non-range Expression and return
00271 ///    the result.  Return 0 if the result is infinite or undefined.
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     /// ...  Determine the sign of the expression.
00286 
00287     EXPR_SIGN e_sign = comparator.sign(*e);
00288 
00289     /// ...  Quit if the sign of the non-range arguments cannot be determined.
00290 
00291     if (e_sign == POS_NEG_EXPR) {
00292     if (e->op() == ADD_OP) {
00293         /// ...  Handle folded expressions (e.g. [a:b]*(c+d)) as a special case.
00294         /// ...  Rather than quitting, distribute the expression and try again.
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;       /// ...  Couldn't determine sign, so give up.
00320     }
00321     }
00322 
00323     /// ...  Multiply the range with the nonrange arguments.
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 ///  _merge_range_mult_terms
00344 ///    Pull all the range terms of the given multiply expression, multiply
00345 ///    them togethor and return the result.  Return 0 if the result turns out
00346 ///    to be infinite or undefined.
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 {      /// ...  range_sign == NEG_EXPR
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 {          /// ...  range_prod_sign = NEG_EXPR
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 {      /// ...  range_sign == NEG_EXPR
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 ///  _p_r_o_of_mult
00467 ///    Pull the range out of a multiply statement.
00468 
00469 static Expression *
00470 _p_r_o_of_mult(Expression *e, RangeComparator &comparator)
00471 {
00472     /// ...  Pull out and multiply all the range terms in the given expression.
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 ///  _p_r_o_of_divide
00496 ///    Pull the range out of a divide statement.
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;       /// ...  Couldn't determine sign, so give up.
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;       /// ...  Couldn't determine sign, so give up.
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 ///  _p_r_o_of_exp
00575 ///    Pull the range out of an exponentiation statement.
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     /// ...  Power is even.
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         /// ...  lb and ub are both positive, so abs(lb) <= abs(ub).
00610     }
00611     else {
00612         EXPR_SIGN ub_sign = comparator.sign(range->ub());
00613     
00614         if (ub_sign == NEG_EXPR) {
00615         /// ...  lb and ub are both negative, so abs(lb) >= abs(ub).
00616         abs_lb_is_larger = true;
00617         }
00618         else if (lb_sign == NEG_EXPR && ub_sign == POS_EXPR) {
00619         /// ...  Compare abs(lb) == -lb with abs(ub) == ub.
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             /// ...  abs(lb) <= abs(ub).
00627         }
00628         else if (diff_sign == NEG_EXPR) {
00629             /// ...  abs(lb) >= abs(ub).
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 ///  _p_r_o_of_range
00658 ///    Pull the range out of a range expression
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 ///  _p_r_o_of_min_max(Expression *e)
00685 ///    Pull the range out of the MIN or MAX intrinsic operator.
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 ///  _p_r_o_of_ifix
00750 ///    Convert an IFIX intrinsic expression whose argument is a range into
00751 ///    a range expression.
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 ///  _min_abs_expr
00772 ///    Calculate and return the smallest absolute value for the given range.
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 ///  _max_abs_expr
00800 ///    Calculate and return the smallest absolute value for the given range.
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         /// ...  We don't want to do a compare() here because we may go into
00826         /// ...  an infinite recursive loop.
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 ///  _handle_omega_in_mod
00870 ///    Generate the proper range for an MOD intrinsic that contains
00871 
00872 static Expression *
00873 _handle_omega_in_mod(Expression *e, RangeComparator &comparator)
00874 {
00875     List<Expression> &params = 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 ///  _p_r_o_of_mod
00933 ///    Pull ranges out of a MOD intrinsic expression.
00934 
00935 static Expression *
00936 _p_r_o_of_mod(Expression *e, RangeComparator &comparator)
00937 {
00938     List<Expression> &params = 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     /// ...  Return A if max(|A|) < min(|B|) for the expression mod(A, B)
00960     /// ...  Note: mod(A, B) < 0 iff A < 0.
00961 
00962     if (abs_rel.is_less_than()) {
00963     result = params.grab(left);
00964     }
00965     else {
00966     /// ...  Otherwise, return [0:B-1] for the expression mod(A, B).
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 ///  _p_r_o_of_abs
01000 ///    Pull ranges out of an ABS intrinsic expression.
01001 
01002 static Expression *
01003 _p_r_o_of_abs(Expression *e, RangeComparator &comparator)
01004 {
01005     List<Expression> &params = 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 ///  _pull_ranges_out
01036 ///    Recursive function that does most of the work of pull_ranges_out above.
01037 ///    If ranges couldn't be pulled out by the expression, or if the resulting
01038 ///    expression becomes unconstrained, this function returns 0.
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     /// ...  Determine whether ranges can be pulled out of the expression.  If not,
01051     /// ...  return 0.  Otherwise, determine what range handling protocol should
01052     /// ...  be used when pulling the ranges out of the expression's arguments.
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:  // Added 5/12/98 jh
01086     delete e;
01087     return 0;
01088 
01089     default:
01090     arg_range_handling = KEEP_WHOLE_RANGE;
01091     break;
01092     }
01093 
01094     /// ...  Pull out the ranges from the expression's arguments.
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     /// ...  Pull out the ranges from the expression itself.
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         /// ...  Don't pull ranges out of comma expressions.
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 ///  pull_ranges_out
01250 ///    Pull the range subexpressions out of the expression.  The range_handling
01251 ///    argument describes exactly how this is done.
01252 ///      TAKE_RANGE_MIN:   Generate the smallest possible value of the
01253 ///                        expression. (e.g. 2*[1:A]+B --> 2+B)
01254 ///      TAKE_RANGE_MAX:   Generate the largest possible value of the
01255 ///                        expression. (e.g. 2*[1:A]+B --> 2*A+B)
01256 ///      KEEP_WHOLE_RANGE: Pull the ranges out so that they are outermost.
01257 ///                        (e.g. 2*[1:A]+B --> [2+B:2*A+B])
01258 ///    If ranges couldn't be pulled out by the expression, or if the resulting
01259 ///    expression becomes unconstrained, expression e is set to omega.
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 ///  bool delete_expr = false;
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 ///  _min
01314 ///    Create a new MIN intrinsic with the given arguments.
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 ///  max_expr
01343 ///    Create a new MAX intrinsic with the given arguments.
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 ///  mod_expr
01372 ///    Create a new MOD intrinsic with the given arguments.
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 ///  _is_min
01399 ///    Return true if the given expression is a MIN intrinsic
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 ///  _is_max
01410 ///    Return true if the given expression is a MAX intrinsic
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 ///  _is_mod
01421 ///    Return true if the given expression is a MOD intrinsic
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 ///  _is_abs
01432 ///    Return true if the given expression is a ABS intrinsic
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 ///  _is_min_max
01445 ///    Return true if the given expression is a MIN or MAX intrinsic
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 ///  _is_min_max
01462 ///    Return true if the given expression is a MIN or MAX intrinsic
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 ///  abs_to_max
01482 ///    Convert any ABS expressions in the given expression to MAX expressions.
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 ///  swap_min_max
01510 ///    Change a MIN intrinsic into a MAX intrinsic or vice_versa
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 ///  _append_to_list
01532 ///    Grab and append all elements of list from to list to
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 ///  _join_nonbinary_exprs
01543 ///    Create a new nonbinary expression of the given op type.
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 ///  _pull_in_add_expr
01562 ///    Add the given expression to the arguments of the given min or max
01563 ///    intrinsic.
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 ///  _p_mm_o_of_add
01590 ///    Pull the min or max expressions out to the top level of the add
01591 ///    expression.
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 ///  _pull_in_mult_expr
01625 ///    Add the given expression to the arguments of the given min or max
01626 ///    intrinsic.
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 ///  _p_mm_o_of_mult
01668 ///    Pull the min or max intrinsics to the outermost part of the given
01669 ///    multiplication expression.
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     /// ...  Determine the sign of the non- min or max part
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     /// ...  Calculate the sign of result, if it hasn't already been done;
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     // Pull the multiplication terms of result into the current min/max
01726     /// ...  intrinsic
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 ///  _pull_in_div_expr
01739 ///    Add the given expression to the arguments of the given min or max
01740 ///    intrinsic.
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 ///  _p_mm_o_of_divide
01763 ///    Pull the min/max intrinsics out of a divide statement.
01764 ///    This function will only pull min or max expressions out of the numerator
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 ///  _pull_in_exp_expr
01788 ///    Add the given expression to the arguments of the given min or max
01789 ///    intrinsic.
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 ///  _p_mm_o_of_exp
01811 ///    Pull the min/max intrinsics out of an exponentiation statement.
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 ///  pull_min_max_out_top
01844 ///    Pull all MIN or MAX intrinsics to the top levels of the expression.
01845 
01846 static Expression *
01847 _pull_min_max_out_top(Expression *e, RangeComparator &comparator)
01848 {
01849     /// ...  Handle the base cases.  (Expression leaves and ranges.)
01850 
01851     if (!e || e->arg_list().entries() == 0)
01852     return e;
01853 
01854     /// ...  Pull out the min's or max's from the expression's arguments.
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     /// ...  Pull out the min or max expressions from the expression itself.
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         /// ...  Do nothing
01888         break;
01889     }
01890     }
01891 
01892     return new_expr;
01893 }
01894 
01895 
01896 ///  pull_min_max_out
01897 ///    Pull all MIN or MAX intrinsics to the top levels of the expression.
01898 
01899 Expression *
01900 pull_min_max_out(Expression *e, RangeComparator &comparator)
01901 {
01902     /// ...  Handle the base cases.  (Expression leaves and ranges.)
01903 
01904     if (!e || e->arg_list().entries() == 0)
01905     return e;
01906 
01907     /// ...  Pull out the min's or max's from the expression's arguments.
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     /// ...  Pull out the min or max expressions from the expression itself.
01917 
01918     return _pull_min_max_out_top(e, comparator);
01919 }
01920 
01921 
01922 ///  remove_redundant_min_max_terms
01923 ///    Eliminate all terms of MIN or MAX subexpressions of the given
01924 ///    expression which can be proved to never be the minimum or maximum
01925 ///    value respectively.
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 ///  delete_expr_in_list
01988 ///    Determine whether the given expression equals an expression in the given
01989 ///    list.  If so, delete the expression in the list and return true.
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 ///  _pull_out_common_min_max
02007 ///   Pull out any common terms of the max expressions in the two range's
02008 ///   lower bounds and pull out any common terms in the min expressions
02009 ///   in the upper bounds and return the range containing these common
02010 ///   terms.
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 ///  join_ranges
02130 ///    Form the intersection of the two given ranges without any tests.
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 ///  intersect_ranges
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     /// ...  New range has one element.
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         /// ...  New range has no elements.
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 ///  union_ranges
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     /// ...  New range has one element.
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 ///  widen_range
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     /// ...  New range has one element.
02348     Expression *temp = result->grab_lb();
02349     delete result;
02350     return temp;
02351     }
02352 
02353     return result;
02354 }
02355 
02356 
02357 ///  narrow_ranges
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     /// ...  New range has one element.
02389     Expression *temp = result->grab_lb();
02390     delete result;
02391     return temp;
02392     }
02393 
02394     return result;
02395 }
02396 
02397 
02398 ///  compare
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 ///  _negate_rel_op
02413 ///    Return the inverse of the given relational operator.
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 ///  _remove_divs_from_term --
02439 ///    Remove all integer divisions from the given expression and return
02440 ///    the term.
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 ///  _remove_divs_from_rel --
02509 ///    Multiply out all integer divisions from the given comparison expression.
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 ///  _extract_a_range --
02532 ///    Extract and returns a single range from a binary relation.
02533 ///    The arguments assume that the relation:
02534 ///            (var_term + other_terms) rel_op 0
02535 ///    holds.
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     /// ...  Determine the variable to constrain and its optional multiplicative
02543     /// ...  factor
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     /// ...  Make sure that the variable doesn't occur on the right hand expression
02569 
02570     if (other_terms && is_var_in_expr(*other_terms, *var))
02571     return;
02572 
02573     /// ...  Calculate the constraint's bound
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     /// ...  Convert < to <= and > to >=
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     /// ...  Calculate the proper range expression from this bound
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     /// ...  Add this range to the set of ranges
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 ///  _extract_ranges_rel --
02642 ///    Extract all ranges from a binary relation.  Assumes that the relation
02643 ///    has been simplified.
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 ///  _extract_ranges
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 ///  extract_ranges
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 ///  pretty_print_range
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 /// elim_known_facts
02765 ///
02766 ///   This routine uses a static recursive routine to turn relational expressions
02767 ///   inside the given expression into .TRUE. or .FALSE., based on the facts 
02768 ///   passed in the RangeComparator.  If the truth of a given relational expression 
02769 ///   cannot be determined, it is unchanged by this routine.
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 ///  _elim_known_facts
02782 ///    Recursive function that does most of the work of elim_known_facts above.
02783 ///    This routine recursively examines the given expression and 
02784 ///    whenever it finds a piece that it can eliminate based on Range 
02785 ///    information, it does that.  
02786 ///
02787 ///    Whenever it finds a relational expression, uses the RangeComparator 
02788 ///    to determine whether the expression is true or false or unknown.  
02789 ///    If it is true, the expression is replaced by .TRUE.  Whenever it is 
02790 ///    false, the expression is replaced by .FALSE. .  Whenever it is unknown, 
02791 ///    the expression is unchanged.
02792 ///
02793 ///    Whenever if finds a MAX or MIN expression inside, it compares the 
02794 ///    two arguments and if it can determine a clear relationship between
02795 ///    the two (based on the Range info), it replaces the intrinsic call
02796 ///    accordingly.
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     /// ...  Is this a MIN intrinsic?
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     /// ...  Is this a MAX intrinsic?
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 /// This routine checks expr for containing exactly one variable, and 
02996 /// if it does, applies the [lower:upper] range to it.  If the variable
02997 /// already has an upper or lower bound associated with it, then
02998 /// apply the limits to that bound.
02999 ///
03000 //Note: this routine does not take possesion of lower or upper
03001 
03002 void
03003 apply_limits(Expression & expr, 
03004          Expression * lower, Expression * upper, 
03005          StmtRanges & ranges, 
03006          RefSet<Symbol> & set)
03007 {
03008     /// ...  Now, if expr is just an ID_OP, assert that its range bounds are
03009     /// ...  within the bounds of the declaration, or if one of its range bounds
03010     /// ...  is an InfinityExpr, change that to the declaration bounds.
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     /// ...  Don't allow infinite recursion
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             /// ...  Check for Infinity in lower bound
03035             if (((RangeExpr *)expr_range)->lb().op() == INFINITY_OP) {
03036             set_ranges_for_symbol(*(ge(expr.clone(),lower->clone())), 
03037                          *sym, ranges);
03038             } else {  /// ...  if not, constrain the lower bound to be within the declaration bound
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             /// ...  Check for infinity in upper bound
03048             if (((RangeExpr *)expr_range)->ub().op() == INFINITY_OP) {
03049             set_ranges_for_symbol(*(le(expr.clone(),upper->clone())),
03050                           *sym, ranges);
03051             } else { /// ...  if not, constrain the upper bound to be within the declaration bound
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 { /// ...  Range is a single value - KDIM: kmax
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 /// This routine extracts ranges for a particular symbol from an expression
03090 /// and sets them in the given StmtRanges object.  It doesn't disturb the
03091 /// ranges of any other variable in the StmtRanges object.
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 {  /// ...  Get the existing range
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 {  /// ...  Get the existing range
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     /// ...  Don't allow infinite recursion
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 { /// ...  Range is a single value - KDIM: kmax
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     /// ...  Don't allow infinite recursion
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 { /// ...  Range is a single value - KDIM: kmax
03216         set.ins(*sym);
03217         tighten_lower_bound(expr, expr_range, ranges, set);
03218         }
03219     }
03220     }
03221 }           
 © 1995-2005 University of Illinois, Urbana-Champaign. All rights reserved.  Fri Mar 25 23:06:03 2005