Polaris: guarded_values.cc Source File

guarded_values.cc

Go to the documentation of this file.
00001 ///
00002 #include <vector>
00003 #include <map>
00004 #include <hash_map.h>
00005 
00006 #include "Statement/DoStmt.h"
00007 #include "Range/AIRangeDict.h"
00008 #include "Range/RangeExpr.h"
00009 #include "Range/RangeAccessor.h"
00010 #include "ip_ssa/trans_util.h"
00011 #include "Evolution/eg_utils.h"
00012 #include "Evolution/evolution_graph.h"
00013 #include "utilities/stmt_util.h"
00014 
00015 #include "predicates.h"
00016 
00017 
00018 typedef vector<pair<ProgramUnit*, Statement*> > CallStack;
00019 
00020 
00021 /*!
00022   These situations are recognized:
00023   1.      x       .EQ. 0
00024   2.      x + exp .EQ. 0 (terms may be in reverse order)
00025   3.      x       .LE. 0
00026   4.      x + exp .LE. 0 (terms may be in reverse order)
00027   5. (-1)*x       .LE. 0
00028   6. (-1)*x + exp .LE. 0 (terms may be in reverse order)
00029 
00030   Returns values:
00031   eq   = it recognized an .EQ. and not a .LE.
00032   sign = the LH value appears with this sign
00033   x    = the LH value
00034   exp  = the RH value
00035 */
00036 static bool _recognize(Expression& conditional, bool& eq, 
00037                int& sign, Symbol*& x, Expression*& exp){
00038   eq=true;
00039   sign=-1;
00040   x=0;
00041   exp=0;
00042   switch (conditional.op()){
00043   case EQ_OP:
00044     eq = true;
00045     break;
00046   case LE_OP:
00047     eq = false;
00048     break;
00049   default:
00050     return false; 
00051   }
00052 
00053 /// Quick checks
00054   if (conditional.arg_list()[0].type().data_type()!=INTEGER_TYPE){
00055     return false;
00056   }
00057   if (!is_integer_constant(conditional.arg_list()[1], 0)){
00058     /// ...  Not normalized.
00059 ///     cerr<<"\nConditional expr should have been simplified: "<<conditional;
00060     return false;
00061   }
00062   
00063 
00064   sign=1;
00065   switch(conditional.arg_list()[0].op()){
00066   case ID_OP:
00067     /// ...  1,3.
00068     x = &conditional.arg_list()[0].symbol();
00069     exp = 0;
00070     return true;
00071   case MULT_OP:
00072     {
00073       Expression& mult=conditional.arg_list()[0];
00074       if (mult.arg_list().entries()!=2){
00075     return false;
00076       }
00077       if (is_integer_constant(mult.arg_list()[0], -1)){
00078     if (mult.arg_list()[1].op()==ID_OP){
00079       // 5.
00080       sign=-1;
00081       x=&mult.arg_list()[1].symbol();
00082       exp=0;
00083       return true;
00084     } else {
00085       return false;
00086     }
00087       } else {
00088     return false;
00089       }
00090     }
00091   case ADD_OP:
00092     {
00093       Expression& aexpr=conditional.arg_list()[0];
00094       if (aexpr.arg_list().entries()!=2){
00095     return false;
00096       } else {
00097     if (aexpr.arg_list()[0].op()==ID_OP){
00098       // 2, 4.
00099       x=&aexpr.arg_list()[0].symbol();
00100       exp=&aexpr.arg_list()[1];
00101       return true;
00102     }
00103     if (aexpr.arg_list()[1].op()==ID_OP){
00104       // 2, 4 reversed.
00105       x=&aexpr.arg_list()[1].symbol();
00106       exp=&aexpr.arg_list()[0];
00107       return true;
00108     }
00109     if (aexpr.arg_list()[0].op()==MULT_OP){
00110       Expression& mult=aexpr.arg_list()[0];
00111       if (mult.arg_list().entries()==2){
00112         if (is_integer_constant(mult.arg_list()[0], -1)){
00113           /// ...  6.
00114           sign=-1;
00115           if (mult.arg_list()[1].op()==ID_OP){
00116         x=&mult.arg_list()[1].symbol();
00117         exp=&aexpr.arg_list()[1];
00118         return true;
00119           }
00120         }
00121       }
00122     }
00123     if (aexpr.arg_list()[1].op()==MULT_OP){
00124       Expression& mult=aexpr.arg_list()[1];
00125       if (mult.arg_list().entries()==2){
00126         if (is_integer_constant(mult.arg_list()[0], -1)){
00127           /// ...  6 reversed.
00128           sign=-1;
00129           if (mult.arg_list()[1].op()==ID_OP){
00130         x=&mult.arg_list()[1].symbol();
00131         exp=&aexpr.arg_list()[0];
00132         return true;
00133           }
00134         }
00135       }
00136     }
00137     /// ...  If it gets here, something did not match.
00138     return false;
00139       }
00140     }
00141   default:
00142     return false;
00143   }
00144 }
00145 
00146 
00147 static RangeExpr* _make_range(bool eq, int sign, Expression* exp){
00148   if (eq){
00149     if (exp){
00150       if (sign==-1){  /// ...  -x + exp .EQ.0 ====>  x = [exp:exp]
00151     return new RangeExpr(exp->clone(), exp->clone());
00152       } else {
00153     Expression* neg=simplify(mul(constant(-1), exp->clone()));
00154     return new RangeExpr(neg->clone(), neg);
00155       }
00156     } else {
00157       return new RangeExpr(constant(0), constant(0));
00158     }
00159   } else {
00160     if (exp){
00161       if (sign==1){
00162     Expression* neg=simplify(mul(constant(-1), exp->clone()));
00163     return new RangeExpr(infinity(-1), neg);
00164       } else {
00165     return new RangeExpr(exp->clone(), infinity(1));
00166       }
00167     } else {
00168       if (sign==1){
00169     return new RangeExpr(infinity(-1), constant(0));
00170       } else {
00171     return new RangeExpr(constant(0), infinity(1));
00172       }
00173     }
00174   }
00175 }
00176 
00177 void _print_range(const char* sname, const pair<RangeExpr*, bool>& r){
00178   if (r.first){
00179     cerr<<sname<<": "<<*r.first<<"<"<<r.second<<">";  
00180   } else {
00181     cerr<<sname<<": "<<"NULL"<<"<"<<r.second<<">";      
00182   }
00183 }
00184 
00185 /// Return 0 if ranges are incompatible.
00186 /// The boolean value tells us whether the complement of the range
00187 /// should be considered instead of the range (false value).
00188 /// The conservative approximation returns a superset of the intersection.
00189 static pair<RangeExpr*, bool> 
00190 _intersect_ranges(ProgramUnit& pgm,
00191           Symbol& sym,
00192           pair<RangeExpr*, bool> range1,
00193           pair<RangeExpr*, bool> range2){
00194 
00195   if (range1.first==0){
00196     if (range2.first==0){
00197       delete range2.first;
00198     }
00199     return range1;
00200   }
00201   if (range2.first==0){
00202     if (range1.first==0){
00203       delete range1.first;
00204     }
00205     return range2;
00206   }
00207 
00208 /// Get a comparison object.
00209   Statement* def=0;
00210   DefLocMap& deflocmap=pgm.gsa_deflocs_guarded();
00211   DefLoc* defloc=deflocmap.find_ref(sym);
00212   if (defloc) {
00213     if (defloc->stmt_valid()){
00214       def=&defloc->stmt_guarded();
00215     }
00216   }
00217   if (def==0){
00218     def=pgm.stmts().last_ref();
00219   }
00220   
00221   if (!pgm.range_dict_valid()){
00222     pgm.range_dict(new AIRangeDict(pgm));
00223   }  
00224   RangeAccessor ra(pgm.range_dict_guarded(), *range_stmt(*def));
00225 
00226 ///   cerr<<"\nEnter _intersect_ranges with ";
00227 ///   cerr<<"\n\t";
00228 ///   _print_range(sym.name_ref(), range1);
00229 ///   cerr<<"\n\t";
00230 ///   _print_range(sym.name_ref(), range2);
00231 
00232 /// Check for complementarity.
00233   if (range1.second && !range2.second){
00234     /// ...  Hope that range1 <= range2.true.
00235     if (p_greater_equal(range1.first->lb(),
00236             range2.first->lb(), &ra) &&
00237     p_less_equal(range1.first->ub(),
00238              range2.first->ub(), &ra)){
00239       delete range1.first;
00240       delete range2.first;
00241       return make_pair((RangeExpr*)0, true);
00242     } else {
00243       delete range2.first;
00244       return range1;
00245     }
00246   }
00247   if (!range1.second && range2.second){
00248     /// ...  Hope that range1.true => range2.
00249     if (p_less_equal(range1.first->lb(),
00250              range2.first->lb(), &ra) &&
00251     p_greater_equal(range1.first->ub(),
00252             range2.first->ub(), &ra)){
00253       delete range1.first;
00254       delete range2.first;
00255       return make_pair((RangeExpr*)0, true);
00256     } else {
00257       delete range2.first;
00258       return range1;
00259     }
00260   }
00261   if (!range1.second && !range2.second){
00262     delete range2.first;
00263     return range1;    
00264   }
00265   //silvius: could do better than this.
00266 
00267 
00268 /// At this point both ranges are for real (not complemented).
00269 
00270   Symbol* dummy=new VariableSymbol("DUMMY", make_type(INTEGER_TYPE),
00271                    NOT_FORMAL, NOT_SAVED);
00272   ra.set_range(*dummy, range2.first);
00273   ra.intersect_range(*dummy, *range1.first);
00274   const Expression* inter=ra.get_range_ref(*dummy);
00275   delete dummy;
00276   if (inter==0){
00277     /// ...  Cannot intersect them.
00278     return range1;
00279   } else {
00280     delete range1.first;
00281     const Expression* lb=inter;
00282     if (inter->op()==RANGE_OP){
00283       lb=&((const RangeExpr*)inter)->lb();
00284     }
00285     const Expression* ub=inter;
00286     if (inter->op()==RANGE_OP){
00287       ub=&((const RangeExpr*)inter)->ub();
00288     }
00289     Relation r=ra.compare(*lb, *ub);
00290     if (r.is_greater_than()){
00291       /// ...  Incompatible ranges.
00292       return make_pair((RangeExpr*)0, true);
00293     } else {
00294       if (inter->op()==RANGE_OP){
00295     return make_pair((RangeExpr*)inter->clone(), true);
00296       } else {
00297     return make_pair(new RangeExpr(inter->clone(), inter->clone()), true);
00298       }
00299     }
00300   }
00301 }
00302 
00303 
00304 /*!
00305   \brief Extracts values for integer scalars from boolean statements.
00306 
00307   Multiple comparisons are recognized as long as they are AND-ed together.
00308 */
00309 void extract_ranges(ProgramUnit& pgm, Expression& conditional,
00310             map<Symbol*, pair<RangeExpr*, bool> >& ranges){
00311 ///   cerr<<"\nExtract ranges for "<<conditional;
00312   if (conditional.op()==AND_OP) {
00313     Iterator<Expression> expit = conditional.arg_list();
00314     for ( ; expit.valid(); ++expit) {
00315       extract_ranges(pgm, expit.current(), ranges);
00316     }
00317   } else {
00318     /// ...  Let's see what we've got.
00319     bool eq;             /// ...  Is it equality or inequality?
00320     int sign;            /// ...  What is the sign of the symbol?
00321     Symbol* x=0;         /// ...  What is the symbol?
00322     Expression* exp=0;   /// ...  What is the value?
00323     bool complementary_range;
00324     Expression* ncond=0;
00325     if (!_recognize(conditional, eq, sign, x, exp)){
00326       /// ...  Check for .NE.
00327       if (conditional.op()==NE_OP){
00328     ncond=simplify(not(conditional.clone()));
00329     if (!_recognize(*ncond, eq, sign, x, exp)){
00330       // Did not recognize anything.
00331       return;
00332     } else {
00333       // Recognized .NE.
00334       complementary_range=true;
00335     }
00336       } else {
00337     /// ...  Did not recognize anything.
00338     return; 
00339       }
00340     } else {
00341       /// ...  Recognized .EQ. or .LE.
00342       complementary_range=false;
00343     }
00344 
00345 ///     cerr<<"\neq: "<<eq<<", sign: "<<sign<<", exp: "<<*exp;
00346 
00347     /// ...  If it gets here, the range was found.
00348     RangeExpr* newrange=_make_range(eq, sign, exp);
00349 ///     cerr<<"\n\tAdding range ";
00350 ///     _print_range(x->name_ref(), make_pair(newrange, complementary_range));
00351     if (ranges.find(x)==ranges.end()){
00352       ranges[x]=make_pair(newrange, complementary_range);
00353     } else {
00354       /// ...  Intersect ranges.
00355       ranges[x]=_intersect_ranges(pgm, *x, 
00356                   make_pair(newrange, complementary_range),
00357                   ranges[x]);
00358     }
00359 ///     cerr<<"\n\tAfter addition: ";
00360 ///     _print_range(x->name_ref(), ranges[x]);
00361     
00362     if (ncond) {
00363       delete ncond;
00364     }
00365 ///     cerr<<"\nExtracted for symbol "<<x->name_ref()
00366 ///     <<" range "<<*ranges[x].first;
00367   }
00368 }
00369 
00370 
00371 
00372 
00373 /// Returns 0 if the given expression evaluates to .FALSE.
00374 static Expression* 
00375 _simplify_using_ranges(ProgramUnit& pgm, Expression& given,
00376                map<Symbol*, pair<RangeExpr*, bool> >& ranges){
00377   Expression& conditional=given;
00378   if (conditional.op()==AND_OP) {
00379     Iterator<Expression> expit = conditional.arg_list();
00380     for ( ; expit.valid(); ++expit) {
00381       if (_simplify_using_ranges(pgm, expit.current(), ranges)==0){
00382     return 0;
00383       }
00384     }
00385   } else {
00386     /// ...  Let's see what we've got.
00387     bool eq;
00388     int sign; 
00389     Symbol* x;
00390     Expression* exp;
00391     bool complementary_range;
00392     Expression* ncond=0;
00393     if (!_recognize(conditional, eq, sign, x, exp)){
00394       /// ...  Check for .NE.
00395       if (conditional.op()==NE_OP){
00396     ncond=simplify(not(conditional.clone()));
00397     if (!_recognize(*ncond, eq, sign, x, exp)){
00398       // Did not recognize anything.
00399       return &given;
00400     } else {
00401       // Recognized .NE.
00402       complementary_range=true;
00403     }
00404       } else {
00405     /// ...  Did not recognize anything.
00406     return &given;
00407       }
00408     } else {
00409       /// ...  Recognized .EQ. or .LE.
00410       complementary_range=false;
00411     }
00412 
00413     /// ...  If it gets here, the range was found.
00414     RangeExpr* newrange=_make_range(eq, sign, exp);
00415     if (ranges.find(x)==ranges.end()){
00416       ranges[x]=make_pair(newrange, complementary_range);
00417     } else {
00418       /// ...  Intersect ranges.
00419       pair<RangeExpr*, bool> ret=
00420     _intersect_ranges(pgm, *x, 
00421               make_pair(newrange, complementary_range), 
00422               ranges[x]);
00423       if (ret.first==0){
00424     /// ...  Found incompatible ranges.
00425     return 0;
00426       }
00427       ranges[x]=ret;
00428     }
00429     if (ncond) {
00430       delete ncond;
00431     }
00432   }
00433   
00434 /// Did not simplify.
00435   return &given;
00436 }
00437 
00438 Expression* simplify_using_ranges(ProgramUnit& pgm, Expression& given){
00439   map<Symbol*, pair<RangeExpr*, bool> > ranges;
00440   return _simplify_using_ranges(pgm, given, ranges);
00441 }
00442 
00443 
00444 /// Returns true if the given range is outside the possible range of
00445 /// values for symbol cand in program pgm, at the loop level where it is 
00446 /// defined.
00447 /// A returned value of false does not necessarily 
00448 /// mean the ranges are compatible.
00449 static bool incompatible_range(ProgramUnit& pgm, 
00450                    Statement& def,
00451                    Symbol& cand,
00452                    pair<RangeExpr*, bool>& range){
00453   if (!pgm.range_dict_valid()){
00454     pgm.range_dict(new AIRangeDict(pgm));
00455   }  
00456   RangeAccessor ra(pgm.range_dict_guarded(), *range_stmt(def));
00457   DoStmt* loop=def_loop(cand, pgm);
00458   Expression* ecand=id(cand);
00459   Expression* arange=eg_range(*ecand, pgm, loop);
00460   RangeExpr* actual_range=0;
00461 ///   cerr<<"\nFor symbol "<<cand.name_ref();
00462 ///   cerr<<"\n\tactual_range = "<<*arange;
00463   if (arange->op()==RANGE_OP){
00464     actual_range=(RangeExpr*)arange;
00465   } else {
00466     actual_range=new RangeExpr(arange->clone(), arange);
00467   }
00468   delete ecand;
00469 
00470   pair<RangeExpr*, bool>& range1=range;
00471   pair<RangeExpr*, bool> range2=make_pair(actual_range, false);
00472 
00473 /// Check for complementarity.
00474   if (!range1.second){
00475     if (p_less_than(range2.first->ub(), 
00476             range1.first->lb())){
00477       delete actual_range;
00478       return true;
00479     }
00480     if (p_greater_than(range2.first->lb(), 
00481                range1.first->ub())){
00482       delete actual_range;
00483       return true;
00484     }
00485     /// ...  Conservative.
00486     delete actual_range;
00487     return false;
00488   } else {
00489     /// ...  Hope that complementary(range1) includes range2.
00490 ///     cerr<<"\nr1 = "<<*range1.first;
00491 ///     cerr<<"\nr2 = "<<*range2.first;
00492     if (p_less_equal(range1.first->lb(),
00493              range2.first->lb(), &ra) &&
00494     p_greater_equal(range1.first->ub(),
00495             range2.first->ub(), &ra)){
00496       delete range2.first;
00497       return true;
00498     } else {
00499       delete range2.first;
00500       return false;
00501     }
00502   }
00503 
00504   p_abort("Sanity check failed: control should have not gotten here.");
00505 }
00506 
00507 
00508 
00509 
00510 /// Discrimnate between possible origins of 'def': cand1 or cand2.
00511 /// Solution based on Evolution Graphs and given range.
00512 /// Return:
00513 /// 0 = could not dicriminate
00514 /// 1 = cand1
00515 /// 2 = cand2
00516 int discriminate_gamma(ProgramUnit& pgm, pair<RangeExpr*, bool>& range,
00517                Statement& stmt,
00518                Symbol& def, Symbol& cand1, Symbol& cand2){
00519 ///   cerr<<"\n\nIn pgm "<<pgm.routine_name_ref();
00520 ///   cerr<<"\n\tDef: "<<def.name_ref();
00521 ///   cerr<<"\n\tArg 1: "<<cand1.name_ref();
00522 ///   cerr<<"\n\tArg 2: "<<cand2.name_ref();
00523 ///   cerr<<"\n\tRange: "<<range;
00524   bool check1=incompatible_range(pgm, stmt, cand1, range);
00525   bool check2=incompatible_range(pgm, stmt, cand2, range);
00526   if (check1 && check2){
00527     cerr<<"\n\nIn pgm "<<pgm.routine_name_ref();
00528     cerr<<"\n\tDef: "<<def.name_ref();
00529     cerr<<"\n\tArg 1: "<<cand1.name_ref();
00530     cerr<<"\n\tArg 2: "<<cand2.name_ref();
00531     cerr<<"\n\tRange: "<<*range.first;
00532     p_abort("None of the GAMMA args match query range.");
00533   }
00534   if (check1){
00535     return 2;
00536   }
00537   if (check2){
00538     return 1;
00539   }
00540   return 0;
00541 }
00542 
00543 /// Discrimnate between possible origins of 'def': cand1 or cand2.
00544 /// Solution based on Evolution Graphs and given range.
00545 /// Return:
00546 /// 0 = could not dicriminate
00547 /// 1 = cand1
00548 /// 2 = cand2
00549 int discriminate_eta(ProgramUnit& pgm, pair<RangeExpr*, bool>& range,
00550              Statement& stmt,
00551              Symbol& def, Symbol& cand1, Symbol& cand2){
00552 ///   cerr<<"\n\nIn pgm "<<pgm.routine_name_ref();
00553 ///   cerr<<"\n\tDef: "<<def.name_ref();
00554 ///   cerr<<"\n\tArg 1: "<<cand1.name_ref();
00555 ///   cerr<<"\n\tArg 2: "<<cand2.name_ref();
00556 ///   cerr<<"\n\tRange: "<<range;
00557   bool check1=incompatible_range(pgm, stmt, cand1, range);
00558   bool check2=incompatible_range(pgm, stmt, cand2, range);
00559   if (check1 && check2){
00560     cerr<<"\n\nIn pgm "<<pgm.routine_name_ref();
00561     cerr<<"\n\tDef: "<<def.name_ref();
00562     cerr<<"\n\tArg 1: "<<cand1.name_ref();
00563     cerr<<"\n\tArg 2: "<<cand2.name_ref();
00564     cerr<<"\n\tRange: "<<*range.first;
00565     p_abort("None of the ETA args match query range.");
00566   }
00567   if (check1){
00568     return 2;
00569   }
00570   if (check2){
00571     return 1;
00572   }
00573   return 0;
00574 }
00575 
00576 
00577 
00578 
00579 /// Discriminate between possible origins of 'def': cand1 or cand2.
00580 /// Solution based on Evolution Graphs and given range.
00581 /// Return:
00582 /// 0 = could not dicriminate
00583 /// 1 = cand1
00584 /// 2 = cand2
00585 int discriminate_mu(ProgramUnit& pgm, pair<RangeExpr*, bool>& range,
00586             Statement& stmt,
00587             Symbol& def, Symbol& cand1, Symbol& cand2){
00588 ///   cerr<<"\n\nIn pgm "<<pgm.routine_name_ref();
00589 ///   cerr<<"\n\tDef: "<<def.name_ref();
00590 ///   cerr<<"\n\tArg 1: "<<cand1.name_ref();
00591 ///   cerr<<"\n\tArg 2: "<<cand2.name_ref();
00592 ///   cerr<<"\n\tRange: "<<*range.first<<": "<<range.second;
00593   bool check1=incompatible_range(pgm, stmt, cand1, range);
00594   bool check2=incompatible_range(pgm, stmt, cand2, range);
00595 ///   cerr<<"\ncheck1 = "<<check1;
00596 ///   cerr<<"\ncheck2 = "<<check2;
00597   if (check1 && check2){
00598     cerr<<"\n\nIn pgm "<<pgm.routine_name_ref();
00599     cerr<<"\n\tDef: "<<def.name_ref();
00600     cerr<<"\n\tArg 1: "<<cand1.name_ref();
00601     cerr<<"\n\tArg 2: "<<cand2.name_ref();
00602     cerr<<"\n\tRange: "<<*range.first<<":"<<range.second;
00603     p_abort("None of the MU args match query range.");
00604   }
00605   if (check1){
00606     return 2;
00607   }
00608   if (check2){
00609     return 1;
00610   }
00611   return 0;
00612 }
00613 
00614 
00615 /// Discriminates MU and GAMMA reaching def based on given predicate set.
00616 int discriminate_phi(ProgramUnit& pgm, 
00617              vector<pair<ProgramUnit*, 
00618              pair<Statement*, int> > >& preds,
00619              Statement& stmt,
00620              Symbol& def, Symbol& cand1, Symbol& cand2){
00621 ///   cerr<<"\n\nIn pgm "<<pgm.routine_name_ref();
00622 ///   cerr<<"\n\tDef: "<<def.name_ref();
00623 ///   cerr<<"\n\tArg 1: "<<cand1.name_ref();
00624 ///   cerr<<"\n\tArg 2: "<<cand2.name_ref();
00625 ///   cerr<<"\n\tRange: "<<range;
00626   Statement* ps=&stmt;
00627   while(ps->stmt_class()==ASSIGNMENT_STMT) ps=ps->prev_ref();
00628   vector<pair<ProgramUnit*, pair<Statement*, int> > >::iterator it;
00629   for (it=preds.begin(); it!=preds.end(); ++it){
00630     if ((*it).first==&pgm && (*it).second.first==ps){
00631       return 1+(*it).second.second;
00632     }
00633   }
00634   return 0;
00635 }
00636 
00637 
00638 
00639 void trace_defs(pair<RangeExpr*, bool>& range,
00640         DefTrace::DTrace& def_trace,
00641         DefTrace::TransMap& trans_map);
00642 
00643 
00644 /// Translates the last def in the trace into the callee and adds
00645 /// it to the trace.
00646 /// Then calls trace_defs until it gtes to the beginning of the callee.
00647 /// Return true if the trace got to the incoming value GSA id 0,
00648 /// and false if the trace stopped on the way back.
00649 bool trace_into_called_pgm(ProgramUnit& callee,
00650                Statement& callsite,
00651                pair<RangeExpr*, bool>& range,
00652                DefTrace::DTrace& def_trace, 
00653                DefTrace::TransMap& trans_map){
00654   DefTrace::DTrace::iterator lit=def_trace.end();
00655   p_assert(lit!=def_trace.begin(), "Empty list given input to find_defs.");
00656   --lit;
00657   ProgramUnit& caller=*(*lit).first;
00658   Symbol& sym=*(*lit).second;
00659 
00660 ///   cerr<<"\nCaller: "<<caller.routine_name_ref()
00661 ///       <<"\nCallsite: "<<callsite
00662 ///       <<"\nSymbol "<<sym;
00663 
00664 /// Translate symbol.
00665   RefList<Symbol> outs=untranslate_var((VariableSymbol&)sym, 
00666                        callee, caller, callsite);
00667   if (outs.entries()!=1){
00668     return false;
00669   }
00670   Symbol& sym_callee=outs[0];
00671   Symbol* symgsa_callee=last_gsa_symbol(callee, sym_callee);
00672 
00673 ///   cerr<<"\nSym callee: "<<sym_callee
00674 ///       <<"\ngsa callee: "<<*symgsa_callee;
00675 
00676 /// Translate range.
00677   Expression* range_callee=range.first->clone();
00678   RefList<Symbol> syms;
00679   referred_symbols(*range.first, syms);
00680   for(Iterator<Symbol> sit=syms; sit.valid(); ++sit){
00681     Symbol& s=sit.current();
00682     
00683     RefList<Symbol> outs=untranslate_var(s, callee, caller, callsite);
00684     if (outs.entries()!=1){
00685       delete range_callee;
00686       return false;
00687     }
00688     Symbol& s_callee=outs[0];
00689     Symbol* sgsa_callee=last_gsa_symbol(callee, s_callee);
00690     substitute_var(*range_callee, s, *sgsa_callee);
00691   }
00692 
00693 /// Extend the trace.
00694   def_trace.push_back(make_pair(&callee, symgsa_callee));
00695 /// Save call site in the trans map.
00696   lit=def_trace.end();  
00697   --lit;
00698   trans_map[lit-def_trace.begin()]=&callsite;
00699 
00700 /// Trace back into the callee.
00701   pair<RangeExpr*, bool> new_range=
00702     make_pair((RangeExpr*)range_callee, range.second);
00703   trace_defs(new_range, def_trace, trans_map);
00704   delete range_callee;
00705   lit=def_trace.end();
00706   --lit;
00707   if (gsa_base(*(*lit).second)==(*lit).second){
00708     return true;
00709   } else {
00710     return false;
00711   }
00712 }
00713 
00714 void trace_defs(vector<pair<ProgramUnit*, 
00715         pair<Statement*, int> > >& preds,
00716         DefTrace::DTrace& def_trace, 
00717         DefTrace::TransMap& trans_map);
00718 
00719 bool trace_into_called_pgm(ProgramUnit& callee,
00720                Statement& callsite,
00721                vector<pair<ProgramUnit*, 
00722                pair<Statement*, int> > >& preds,
00723                DefTrace::DTrace& def_trace, 
00724                DefTrace::TransMap& trans_map){
00725   DefTrace::DTrace::iterator lit=def_trace.end();
00726   p_assert(lit!=def_trace.begin(), "Empty list given input to find_defs.");
00727   --lit;
00728   ProgramUnit& caller=*(*lit).first;
00729   Symbol& sym=*(*lit).second;
00730 
00731 /// Translate symbol.
00732   RefList<Symbol> outs=untranslate_var((VariableSymbol&)sym, 
00733                        callee, caller, callsite);
00734   if (outs.entries()!=1){
00735     return false;
00736   }
00737   Symbol& sym_callee=outs[0];
00738   Symbol* symgsa_callee=last_gsa_symbol(callee, sym_callee);
00739 
00740 /// Extend the trace.
00741   def_trace.push_back(make_pair(&callee, symgsa_callee));
00742 /// Save call site in the trans map.
00743   lit=def_trace.end();  
00744   --lit;
00745   trans_map[lit-def_trace.begin()]=&callsite;
00746 
00747 /// Trace back into the callee.
00748   trace_defs(preds, def_trace, trans_map);
00749   lit=def_trace.end();
00750   --lit;
00751   if (gsa_base(*(*lit).second)==(*lit).second){
00752     return true;
00753   } else {
00754     return false;
00755   }
00756 }
00757 
00758 
00759 
00760 
00761 /// Look back for definition and try to do better than just pick the 
00762 /// GSA defloc.  Try to narrow it down based on the given range.
00763 /// Stop when we cannot discriminate between two possible sources in a
00764 /// GAMMA, ETA, or MU.
00765 /// Return the definitions as pairs <ProgramUnit, GSA Name>
00766 void trace_defs(pair<RangeExpr*, bool>& range,
00767         DefTrace::DTrace& def_trace,
00768         DefTrace::TransMap& trans_map){
00769   DefTrace::DTrace::iterator lit=def_trace.end();
00770   p_assert(lit!=def_trace.begin(), "Empty list given input to find_defs.");
00771   --lit;
00772   ProgramUnit& pgm=*(*lit).first;
00773   Symbol& sym=*(*lit).second;
00774   DefLocMap& deflocmap=pgm.gsa_deflocs_guarded();
00775   DefLoc* defloc=deflocmap.find_ref(sym);
00776   if (!defloc) {
00777     /// ...  Must be either formal or common with GSA number=0.
00778     return;
00779   }
00780   if (!defloc->stmt_valid()){
00781     /// ...  Must be either formal or common with GSA number=0.
00782     return;
00783   }
00784   Statement& def=defloc->stmt_guarded();
00785   switch(def.stmt_class()){
00786   case ASSIGNMENT_STMT:
00787     {
00788       switch(def.rhs().op()){
00789       case GAMMA_OP:
00790     {
00791       List<Expression>& params=def.rhs().parameters_guarded().arg_list();
00792       int d=discriminate_gamma(pgm, range, def, def.lhs().symbol(),
00793                    params[0].symbol(), params[1].symbol());
00794       if (d>0){
00795         def_trace.push_back(make_pair(&pgm, &params[d-1].symbol()));
00796         trace_defs(range, def_trace, trans_map);
00797       }
00798     }
00799     break;
00800       case ETA_OP:
00801     {
00802       List<Expression>& params=def.rhs().parameters_guarded().arg_list();
00803       int d=discriminate_eta(pgm, range, def, def.lhs().symbol(),
00804                  params[0].symbol(), params[1].symbol());
00805       if (d>0){
00806         def_trace.push_back(make_pair(&pgm, &params[d-1].symbol()));
00807         trace_defs(range, def_trace, trans_map);
00808       }
00809     }
00810     break;
00811       case MU_OP:
00812     {
00813       List<Expression>& params=def.rhs().parameters_guarded().arg_list();
00814       int d=discriminate_mu(pgm, range, def, def.lhs().symbol(),
00815                 params[0].symbol(), params[1].symbol());
00816       if (d==2){
00817         /// ...  Loop-back value.  That means it can only come from within the
00818         /// ...  loop.  It must come from an INPUT value in the EG for this loop.
00819         /// ...  Get trace from EG.
00820         def_trace.push_back(make_pair(&pgm, &params[d-1].symbol()));
00821         eg_trace_from_input(pgm, (DoStmt*)def.outer_ref(), range, 
00822                 &params[d-1].symbol(), def_trace);
00823       }
00824       if (d==1){
00825         /// ...  Incoming value.  Trace it.
00826         def_trace.push_back(make_pair(&pgm, &params[d-1].symbol()));
00827         trace_defs(range, def_trace, trans_map);
00828       }
00829     }
00830     break;
00831       case THETA_OP:
00832     {
00833       // Find call site.
00834       Statement* ps=&def;
00835       ProgramUnit* callee=0;
00836       while((callee=called_pgm(*ps))==0){
00837         ps=ps->prev_ref();
00838       }
00839       // Go into called subroutine.
00840       if (trace_into_called_pgm(*callee, *ps, range, 
00841                     def_trace, trans_map)){
00842         /// ...  Got back into pgm.  Go after THETA param.
00843         Symbol* in;
00844         Symbol* out;
00845         get_in_out(pgm, *ps, *gsa_base(sym), in, out);
00846         def_trace.push_back(make_pair(&pgm, in));
00847         trace_defs(range, def_trace, trans_map);
00848       } else {
00849         /// ...  Have to stop here.
00850         return;
00851       }
00852     }
00853     break;
00854       case FUNCTION_CALL_OP:
00855     {
00856       // Go into called subroutine.
00857       if (trace_into_called_pgm(*called_pgm(def), def, range, 
00858                     def_trace, trans_map)){
00859         /// ...  Got back into pgm.
00860         Symbol* in;
00861         Symbol* out;
00862         get_in_out(pgm, def, *gsa_base(sym), in, out);
00863         def_trace.push_back(make_pair(&pgm, in));
00864         trace_defs(range, def_trace, trans_map);
00865       } else {
00866         /// ...  Have to stop here.
00867         return;
00868       }
00869     }
00870     break;
00871       default:
00872     /// ...  Cannot do anything, the trace breaks here.
00873     return;
00874       }
00875     }
00876     break;
00877   case CALL_STMT:
00878     {
00879       if (trace_into_called_pgm(*called_pgm(def), def, range, 
00880                 def_trace, trans_map)){
00881     /// ...  Got back into pgm.
00882     Symbol* in;
00883     Symbol* out;
00884     get_in_out(pgm, def, *gsa_base(sym), in, out);
00885     def_trace.push_back(make_pair(&pgm, in));
00886     trace_defs(range, def_trace, trans_map);
00887       } else {
00888     /// ...  Have to stop here.
00889     return;
00890       }
00891       /// ...  Go into called subprogram.
00892     }
00893   }
00894 }
00895 
00896 
00897 
00898 
00899 /// Look back for definition and try to do better than just pick the 
00900 /// GSA defloc.  Try to narrow it down based on the given range.
00901 /// Stop when we cannot discriminate between two possible sources in a
00902 /// GAMMA, or MU.
00903 /// Return the definitions as pairs <ProgramUnit, GSA Name>
00904 void trace_defs(vector<pair<ProgramUnit*, 
00905         pair<Statement*, int> > >& preds,
00906         DefTrace::DTrace& def_trace, 
00907         DefTrace::TransMap& trans_map){
00908   DefTrace::DTrace::iterator lit=def_trace.end();
00909   p_assert(lit!=def_trace.begin(), "Empty list given input to find_defs.");
00910   --lit;
00911   ProgramUnit& pgm=*(*lit).first;
00912   Symbol& sym=*(*lit).second;
00913   DefLocMap& deflocmap=pgm.gsa_deflocs_guarded();
00914   DefLoc* defloc=deflocmap.find_ref(sym);
00915   if (!defloc) {
00916     /// ...  Must be either formal or common with GSA number=0.
00917     return;
00918   }
00919   if (!defloc->stmt_valid()){
00920     /// ...  Must be either formal or common with GSA number=0.
00921     return;
00922   }
00923   Statement& def=defloc->stmt_guarded();
00924   switch(def.stmt_class()){
00925   case ASSIGNMENT_STMT:
00926     {
00927       switch(def.rhs().op()){
00928       case GAMMA_OP:
00929     {
00930       List<Expression>& params=def.rhs().parameters_guarded().arg_list();
00931       int d=discriminate_phi(pgm, preds, def, def.lhs().symbol(),
00932                  params[0].symbol(), params[1].symbol());
00933       if (d>0){
00934         def_trace.push_back(make_pair(&pgm, &params[d-1].symbol()));
00935         trace_defs(preds, def_trace, trans_map);
00936       }
00937     }
00938     break;
00939       case ETA_OP:
00940     {
00941       List<Expression>& params=def.rhs().parameters_guarded().arg_list();
00942       int d=discriminate_phi(pgm, preds, def, def.lhs().symbol(),
00943                  params[0].symbol(), params[1].symbol());
00944       if (d>0){
00945         def_trace.push_back(make_pair(&pgm, &params[d-1].symbol()));
00946         trace_defs(preds, def_trace, trans_map);
00947       }
00948     }
00949     break;
00950       case MU_OP:
00951     {
00952       List<Expression>& params=def.rhs().parameters_guarded().arg_list();
00953       int d=discriminate_phi(pgm, preds, def, def.lhs().symbol(),
00954                  params[0].symbol(), params[1].symbol());
00955       if (d>0){
00956         /// ...  Incoming value.  Trace it.
00957         def_trace.push_back(make_pair(&pgm, &params[d-1].symbol()));
00958         trace_defs(preds, def_trace, trans_map);
00959       }
00960     }
00961     break;
00962       case THETA_OP:
00963     {
00964       // Find call site.
00965       Statement* ps=&def;
00966       ProgramUnit* callee=0;
00967       while((callee=called_pgm(*ps))==0){
00968         ps=ps->prev_ref();
00969       }
00970       // Go into called subroutine.
00971       if (trace_into_called_pgm(*callee, *ps, preds, 
00972                     def_trace, trans_map)){
00973         /// ...  Got back into pgm.  Go after THETA param.
00974         Symbol* in;
00975         Symbol* out;
00976         get_in_out(pgm, *ps, *gsa_base(sym), in, out);
00977         def_trace.push_back(make_pair(&pgm, in));
00978         trace_defs(preds, def_trace, trans_map);
00979       } else {
00980         /// ...  Have to stop here.
00981         return;
00982       }
00983     }
00984     break;
00985       case FUNCTION_CALL_OP:
00986     {
00987       // Go into called subroutine.
00988       if (trace_into_called_pgm(*called_pgm(def), def, preds, 
00989                     def_trace, trans_map)){
00990         /// ...  Got back into pgm.
00991         Symbol* in;
00992         Symbol* out;
00993         get_in_out(pgm, def, *gsa_base(sym), in, out);
00994         def_trace.push_back(make_pair(&pgm, in));
00995         trace_defs(preds, def_trace, trans_map);
00996       } else {
00997         /// ...  Have to stop here.
00998         return;
00999       }
01000     }
01001     break;
01002       default:
01003     /// ...  Cannot do anything, the trace breaks here.
01004     return;
01005       }
01006     }
01007     break;
01008   case CALL_STMT:
01009     {
01010       if (trace_into_called_pgm(*called_pgm(def), def, preds, 
01011                 def_trace, trans_map)){
01012     /// ...  Got back into pgm.
01013     Symbol* in;
01014     Symbol* out;
01015     get_in_out(pgm, def, *gsa_base(sym), in, out);
01016     def_trace.push_back(make_pair(&pgm, in));
01017     trace_defs(preds, def_trace, trans_map);
01018       } else {
01019     /// ...  Have to stop here.
01020     return;
01021       }
01022       /// ...  Go into called subprogram.
01023     }
01024   }
01025 }
01026 
01027 
01028 
01029 Expression* translate(Expression* expr, CallStack& call_stack){
01030   int sit=call_stack.size();
01031   if (sit==0){
01032     return expr;
01033   }
01034 
01035   --sit;
01036   for( ; sit>=0; --sit){
01037     ProgramUnit& caller=*call_stack[sit].first;
01038     Statement& call_site=*call_stack[sit].second;
01039     ProgramUnit& callee=*called_pgm(call_site);
01040 ///     cerr<<"\n\tCaller = "<<caller.routine_name_ref();
01041 ///     cerr<<"\n\tCallee = "<<callee.routine_name_ref();
01042     Translator translator(caller, call_site);
01043     RefList<Symbol> syms, can, cannot;
01044     referred_symbols(*expr, syms);
01045     if (can_translate(syms, can, cannot, translator, 
01046               callee, caller, call_site)){
01047       expr=translate_and_reshape(translator, callee, caller, call_site, expr);
01048       if (expr==0){
01049     return 0;
01050       }
01051     } else {
01052       /// ...  Not translatable.
01053       delete expr;
01054       return 0;
01055     }
01056   }
01057   return expr;
01058 }
01059 
01060 void get_preds_from_trace(DefTrace::DTrace& def_trace, DefTrace::TransMap& trans_map,
01061               vector<pair<ProgramUnit*, 
01062               pair<Statement*, int> > >& preds){
01063 /// The first definition in the trace sets the initial context.
01064   DefTrace::DTrace::iterator lit=def_trace.begin();
01065   p_assert(lit!=def_trace.end(), "Empty list given input to get_gates.");
01066   ProgramUnit& initial_pgm=*(*lit).first;
01067 
01068 /// Follow the trace and extract conditions from GAMMA statements.
01069   ProgramUnit* last_pgm=&initial_pgm;
01070   Symbol* last_sym=(*lit).second;
01071   for( ; lit!=def_trace.end(); ++lit){
01072     ProgramUnit& pgm=*(*lit).first;
01073     Symbol& sym=*(*lit).second;
01074     if (&pgm==last_pgm){
01075       /// ...  Find the GSA gate associated with the current definition, if any.
01076       DefLocMap& deflocmap=pgm.gsa_deflocs_guarded();
01077       DefLoc* defloc=deflocmap.find_ref(*last_sym);
01078       if (defloc) {
01079     if (defloc->stmt_valid()){
01080       Statement& def=defloc->stmt_guarded();
01081       if(def.stmt_class()==ASSIGNMENT_STMT){
01082         if(def.rhs().op()==ETA_OP || 
01083            def.rhs().op()==GAMMA_OP || 
01084            def.rhs().op()==MU_OP){
01085           Statement* ps=&def;
01086           while (ps->stmt_class()==ASSIGNMENT_STMT){
01087         ps=ps->prev_ref();
01088           }
01089           int tv=-1;
01090           List<Expression>& params=
01091         def.rhs().parameters_guarded().arg_list();
01092           if (&params[0].symbol()==&sym){
01093         tv=0;
01094           } else {
01095         if (&params[1].symbol()==&sym){
01096           tv=1;
01097         }
01098           }
01099           if (tv>=0){
01100         preds.push_back(make_pair(&pgm, make_pair(ps, tv)));
01101           }
01102         }
01103       }
01104     }
01105       }
01106     }
01107     last_pgm=&pgm;
01108     last_sym=&sym;
01109   }
01110 }
01111 
01112 
01113 /// Gets backwards definition trace based on the given GAMMA/MU disambiguation.
01114 /// silvius: for now return furthest def in the same pgm.
01115 pair<ProgramUnit*, Symbol*>
01116 get_backtrace_given_preds(ProgramUnit& pgm, Symbol& sym,
01117               vector<pair<ProgramUnit*, 
01118               pair<Statement*, int> > >& preds){
01119   DefTrace::DTrace def_trace;
01120   DefTrace::TransMap trans_map;
01121   def_trace.push_back(make_pair(&pgm, &sym));
01122   trace_defs(preds, def_trace, trans_map);
01123   for(unsigned i=def_trace.size()-1; i>=0; --i){
01124     if (def_trace[i].first==&pgm){
01125       return def_trace[i];
01126     }
01127   }
01128   return def_trace[0];
01129 }
01130 
01131 
01132 
01133 void get_gates_from_trace(DefTrace::DTrace& def_trace, 
01134               DefTrace::TransMap& trans_map,
01135               List<Expression>& gate_list){
01136 /// Call stack.
01137   CallStack call_stack;
01138 
01139 ///   cerr<<"\nDef trace: ";
01140 ///   for(DefTrace::DTrace::iterator lit=def_trace.begin(); lit!=def_trace.end(); ++lit){
01141 ///     ProgramUnit& pgm=*(*lit).first;
01142 ///     Symbol& sym=*(*lit).second;
01143 ///     cerr<<"\n\t"<<pgm.routine_name_ref()<<" : "<<sym.name_ref();
01144 ///     if (trans_map.find(lit-def_trace.begin())!=trans_map.end()){
01145 ///       cerr<<"\n\t\tCS";
01146 ///     }
01147 ///   }
01148 
01149 /// The first definition in the trace sets the initial context.
01150   DefTrace::DTrace::iterator lit=def_trace.begin();
01151   p_assert(lit!=def_trace.end(), "Empty list given input to get_gates.");
01152   ProgramUnit& initial_pgm=*(*lit).first;
01153 
01154 /// Follow the trace and extract conditions from GAMMA statements.
01155   ProgramUnit* last_pgm=&initial_pgm;
01156   Symbol* last_sym=(*lit).second;
01157   for( ; lit!=def_trace.end(); ++lit){
01158     ProgramUnit& pgm=*(*lit).first;
01159     Symbol& sym=*(*lit).second;
01160     if (&pgm!=last_pgm){
01161       /// ...  New subprogram.
01162       /// ...  If it has an entry in trans_map, then it is a call site.
01163       /// ...  Otherwise, it is a return site.
01164       DefTrace::TransMap::iterator mit=trans_map.find(lit-def_trace.begin());
01165       if (mit!=trans_map.end()){
01166     call_stack.push_back(make_pair(last_pgm, (*mit).second));
01167       } else {
01168     call_stack.pop_back();
01169       }
01170     } else {
01171       /// ...  Same subprogram.
01172       /// ...  Find the GSA gate associated with the current definition, if any.
01173       DefLocMap& deflocmap=pgm.gsa_deflocs_guarded();
01174       DefLoc* defloc=deflocmap.find_ref(*last_sym);
01175       if (defloc) {
01176     if (defloc->stmt_valid()){
01177       Statement& def=defloc->stmt_guarded();
01178       if(def.stmt_class()==ASSIGNMENT_STMT){
01179         if(def.rhs().op()==GAMMA_OP){
01180           Expression* gate=def.rhs().gate().clone();
01181           List<Expression>& params=
01182         def.rhs().parameters_guarded().arg_list();
01183           if (&params[1].symbol()==&sym){
01184         /// ...  The gate must be negated, the second argument is 
01185         /// ...  the right one.
01186         gate=simplify(not(gate));
01187           }
01188 ///           cerr<<"\ngate = "<<*gate;
01189 ///           cerr<<"\nEnter translate with "<<*gate;
01190 ///           cerr<<"\nCall stack follows: ";
01191           for(unsigned int i=0; i<call_stack.size(); ++i){
01192 ///         ProgramUnit& caller=*call_stack[i].first;
01193 ///         Statement& call_site=*call_stack[i].second;
01194 ///         cerr<<"\n\tCaller = "<<caller.routine_name_ref();
01195 ///         cerr<<"\tCall site = "<<call_site;
01196           }
01197           Expression* translated_gate=translate(gate, call_stack);
01198           if (translated_gate){
01199         gate_list.ins_last(translated_gate);
01200           }
01201         }
01202       }
01203     }
01204       }
01205     }
01206     last_pgm=&pgm;
01207     last_sym=&sym;
01208   }
01209 }
01210 
01211 
01212 /// Look back for definitions and try to do better than just pick the 
01213 /// GSA defloc.  Try to narrow them down based on the given ranges.
01214 void find_defs(ProgramUnit& pgm, map<Symbol*, pair<RangeExpr*, bool> >& ranges,
01215            vector<DefTrace::DTrace>& def_traces,
01216            vector<DefTrace::TransMap>& trans_maps){
01217   for(map<Symbol*, pair<RangeExpr*, bool> >::iterator rit=ranges.begin(); 
01218       rit!=ranges.end(); ++rit){
01219 
01220     if ((*rit).second.first==0){
01221       /// ...  Incompatible ranges.
01222       continue;
01223     }
01224 
01225     /// ...  Setup.
01226     def_traces.push_back(DefTrace::DTrace());
01227     DefTrace::DTrace& def_trace=def_traces[def_traces.size()-1];
01228     def_trace.push_back(make_pair(&pgm, (*rit).first));
01229     trans_maps.push_back(DefTrace::TransMap());
01230     DefTrace::TransMap& trans_map=trans_maps[trans_maps.size()-1];
01231 
01232     /// ...  Get trace.
01233     trace_defs((*rit).second, def_trace, trans_map);
01234 ///     cerr<<"\n\n\nFor variable "<<(*rit).first->name_ref()
01235 ///     <<" and range "<<*(*rit).second.first
01236 ///     <<"("<<(*rit).second.second<<")"
01237 ///     <<", def trace is: ";
01238 ///     for(DefTrace::DTrace::iterator lit=def_trace.begin();
01239 ///     lit!=def_trace.end(); ++lit){
01240 ///       cerr<<"\n\t"<<(*lit).first->routine_name_ref()
01241 ///       <<" : "<<(*lit).second->name_ref();
01242 ///     }
01243   }
01244 }
01245 
01246 
01247 typedef hash_map<Expression*,                  /// ...  Condition.
01248          pair<vector<DefTrace::DTrace>, 
01249               vector<DefTrace::TransMap> >,      /// ...  Definition traces for
01250                                        /// ...  extracted variable ranges.
01251          expr_hash,
01252          expr_eq> GateInferences;
01253 
01254 
01255 /// Silvius: should clean this up once in a while.
01256 static map<ProgramUnit*, GateInferences> _gate_inferences;
01257 
01258 
01259 void cleanup_gate_inferences(ProgramUnit& pgm){
01260   map<ProgramUnit*, GateInferences>::iterator found=
01261     _gate_inferences.find(&pgm);
01262   if (found!=_gate_inferences.end()){
01263     GateInferences::iterator it;
01264     List<Expression> todel;
01265     /// ...  Put the expression pointers in the list, the destructor will free them.
01266     for(it=(*found).second.begin(); it!=(*found).second.end(); ++it){
01267       todel.ins_last((*it).first);
01268     }
01269     (*found).second.clear();
01270   }
01271 }
01272 
01273 
01274 
01275 /// Find the definition var = expr, where 'var' has the same gsa base as 'sym'.
01276 Statement* trace_unique_def(ProgramUnit& pgm, Symbol& sym, Expression& expr){
01277   Statement* def=0;
01278   DefLocMap& deflocmap=pgm.gsa_deflocs_guarded();
01279   DefLoc* defloc=deflocmap.find_ref(sym);
01280   if (defloc) {
01281     if (defloc->stmt_valid()){
01282       def=&defloc->stmt_guarded();
01283     }
01284   }
01285   if (def){
01286     if (def->stmt_class()==ASSIGNMENT_STMT){
01287       switch (def->rhs().op()){
01288       case MU_OP:
01289       case GAMMA_OP:
01290       case ETA_OP:
01291     {
01292       RefList<Symbol> entries;
01293       get_phinode_entries(def->rhs(), entries);
01294       for(Iterator<Symbol> sit=entries; sit.valid(); ++sit){
01295         Statement* d=trace_unique_def(pgm, sit.current(), expr);
01296         if (d){
01297           return d;
01298         }
01299       }
01300     }
01301     break;
01302       default:
01303     if (def->rhs()==expr){
01304       return def;
01305     } else {
01306       return 0;
01307     }
01308       }
01309     }
01310   }
01311   return 0;
01312 }
01313 
01314 
01315 /// Find the definitions that must happen in order for gate to be true.
01316 void trace_defs(ProgramUnit& pgm, Expression& gate, 
01317         vector<DefTrace::DTrace>*& pdt, vector<DefTrace::TransMap>*& ptm){
01318   pdt=0;
01319   ptm=0;
01320   map<ProgramUnit*, GateInferences>::iterator found=
01321     _gate_inferences.find(&pgm);
01322   if (found!=_gate_inferences.end()){
01323     GateInferences::iterator git=(*found).second.find(&gate);
01324     if (git!=(*found).second.end()){
01325       /// ...  Found it.
01326       pdt=&(*git).second.first;
01327       ptm=&(*git).second.second;
01328     }
01329   } 
01330 
01331   if (pdt==0){
01332     map<Symbol*, pair<RangeExpr*, bool> > ranges;
01333     extract_ranges(pgm, gate, ranges);
01334     vector<DefTrace::DTrace> def_trace;
01335     vector<DefTrace::TransMap> trans_map;
01336     pair<GateInferences::iterator, bool> git=
01337       _gate_inferences[&pgm].insert(make_pair(gate.clone(),
01338                           make_pair(vector<DefTrace::DTrace>(), 
01339                             vector<DefTrace::TransMap>())));
01340     p_assert(git.second, "Could not cache gate inferences.");
01341     pdt=&(*git.first).second.first;
01342     ptm=&(*git.first).second.second;
01343 
01344     /// ...  Get definitions from ranges.
01345     find_defs(pgm, ranges, *pdt, *ptm);
01346 
01347     /// ...  Clean-up.
01348     map<Symbol*, pair<RangeExpr*, bool> >::iterator it;
01349     for(it=ranges.begin(); it!=ranges.end(); ++it){
01350       delete (*it).second.first;
01351     }
01352   }  
01353 }
01354 
01355 
01356 void infer_gates(ProgramUnit& pgm, Expression& gate, 
01357          List<Expression>& inferences){
01358 /// Trace back.
01359   vector<DefTrace::DTrace>* pdt;
01360   vector<DefTrace::TransMap>* ptm;
01361   trace_defs(pgm, gate, pdt, ptm);
01362 
01363 /// Get gates.
01364   for(unsigned i=0; i<pdt->size(); ++i){
01365     get_gates_from_trace((*pdt)[i], (*ptm)[i], inferences);
01366   }
01367 }
01368 
01369 
01370 void find_preds(ProgramUnit& pgm, Expression& gate, 
01371         vector<pair<ProgramUnit*, pair<Statement*, int> > >& preds){
01372 ///   cerr<<"\nEnter find_preds "<<gate
01373 ///       <<"\npgm = "<<pgm.routine_name_ref();
01374   if (gate.op()==AND_OP){
01375     Iterator<Expression> fit = gate.arg_list();
01376     for ( ; fit.valid(); ++fit) {
01377       find_preds(pgm, fit.current(), preds);
01378     }
01379   } else {
01380     Symbol* var=0;
01381     bool truth=true;
01382     switch (gate.op()){
01383     case ID_OP:
01384       var=&gate.symbol();
01385       break;
01386     case NOT_OP:
01387       if (gate.expr_guarded().op()==ID_OP){
01388     var=&gate.expr_guarded().symbol();
01389     truth=false;
01390       }
01391     }
01392     if (var){
01393       String ref("PE_FLAG");
01394       String name(var->name_ref(), ref.len());
01395       if (name==ref){
01396     if (truth==false){
01397       // Bingo.
01398       // This means the loop corresponding to pe_flag was not left
01399       // via a premature exit.  That means the check IF (skip_flag)
01400       // was always .TRUE.
01401       // Add three things:
01402       // 1. The predicate that controls the def site for pe_flag=.FALSE.
01403       // 2. The DO after it.
01404       // 3. The IF right after the DO (skip_flag) with the .TRUE. branch.
01405 ///       cerr<<"\n\nBINGO "<<var->name_ref();
01406       
01407       Expression* f=constant(".FALSE.");
01408       Statement* def=trace_unique_def(pgm, *var, *f);
01409       delete f;
01410       // 1. 
01411       // silvius: do it later
01412       // 2.
01413       Statement* ps=def;
01414 ///       cerr<<"\nps= "<<*ps;
01415       while(ps->stmt_class()!=DO_STMT){
01416         ps=ps->next_ref();
01417       }
01418 ///       cerr<<"\nAdding "<<*ps;
01419       preds.push_back(make_pair(&pgm, make_pair(ps, 0)));
01420       // 3.
01421       while(ps->stmt_class()!=IF_STMT){
01422         ps=ps->next_ref();
01423       }
01424 ///       cerr<<"\nAdding "<<*ps;
01425       preds.push_back(make_pair(&pgm, 
01426                     make_pair(ps->matching_endif_ref(), 
01427                           0)));
01428     }
01429       }
01430     }
01431   }
01432 }
01433 
01434 
01435 
01436 /// Add it to the pred list and return true if it is not already in.
01437 bool add_pred(pair<ProgramUnit*, pair<Statement*, int> >& given,
01438           vector<pair<ProgramUnit*, pair<Statement*, int> > >& preds){
01439   vector<pair<ProgramUnit*, pair<Statement*, int> > >::iterator it;
01440   for(it=preds.begin(); it!=preds.end(); ++it){
01441     pair<ProgramUnit*, pair<Statement*, int> >& pred=*it;
01442     if (pred==given){
01443       return false;
01444     }
01445   }
01446   preds.push_back(given);
01447   return true;
01448 }
01449 
01450 void infer_preds(ProgramUnit& pgm, Expression& gate, 
01451          vector<pair<ProgramUnit*, pair<Statement*, int> > >& preds){
01452 
01453   List<Expression> gates;
01454   gates.ins_last(gate.clone());
01455 
01456   do {
01457 ///     cerr<<"\ngates = "<<gates;
01458     List<Expression> newgates;
01459     vector<pair<ProgramUnit*, pair<Statement*, int> > > newpreds;
01460     for(Iterator<Expression> eit=gates; eit.valid(); ++eit){
01461       /// ...  Trace back.
01462       vector<DefTrace::DTrace>* pdt;
01463       vector<DefTrace::TransMap>* ptm;
01464       trace_defs(pgm, eit.current(), pdt, ptm);
01465       
01466       /// ...  Get preds using ranges.
01467       for(unsigned i=0; i<pdt->size(); ++i){
01468     get_preds_from_trace((*pdt)[i], (*ptm)[i], newpreds);
01469       }
01470 ///       cerr<<"\nnewpreds.size="<<newpreds.size();
01471 
01472       /// ...  Get preds using pe_exit flags.
01473       find_preds(pgm, eit.current(), newpreds);
01474 
01475       /// ...  Collect gates for new predicates.
01476       vector<pair<ProgramUnit*, pair<Statement*, int> > >::iterator it;
01477       for(it=newpreds.begin(); it!=newpreds.end(); ++it){
01478     pair<ProgramUnit*, pair<Statement*, int> >& pred=*it;
01479     /// ...  silvius: for now, stay within the pgm.
01480     if (pred.first!=&pgm) continue;
01481     if (add_pred(pred, preds)){
01482       // It is a new one.
01483       if (pred.second.first->stmt_class()==ENDIF_STMT){
01484         Statement* ifstmt=pred.second.first->matching_if_ref();
01485         Expression* e=ifstmt->expr().clone();
01486         if (pred.second.second==1){
01487           e=simplify(not(e));
01488         }
01489         newgates.ins_last(e);
01490       }
01491     }
01492       }
01493     }
01494     
01495     gates=newgates;
01496   } while (gates.entries());
01497 
01498 ///   cerr<<"\nPred count for gate "<<gate<<" is "<<preds.size();
01499 }
01500 
01501 
01502 static bool incompatible_gates(ProgramUnit& pgm,
01503                    Expression& gate1, Expression& gate2){
01504 ///   cerr<<"\n\tleft = "<<gate1;
01505 ///   cerr<<"\n\tright = "<<gate2;
01506   List<Expression>* inferences=new List<Expression>;
01507   infer_gates(pgm, gate1, *inferences);
01508   if (inferences->entries()){
01509     Expression* anded=simplify(and(and(and(inferences),
01510                        not(gate2.clone())),
01511                    gate1.clone()));
01512     /// ...  silvius: should do the same with right and left (in this order).
01513     if(simplify_using_ranges(pgm, *anded)){
01514       return true;
01515     } else {
01516       return false;
01517     }
01518   } else {
01519     delete inferences;
01520     return false;
01521   }
01522 }
01523 
01524 
01525 
01526 static bool same_commutative(Expression& e1, Expression& e2){
01527   if (e1.op()!=e2.op()){
01528     return false;
01529   }
01530   if (!is_commutative(e1.op())){
01531     return false;
01532   }
01533   map<int, Expression*> sorter1, sorter2;
01534   for(Iterator<Expression> eit=e1.arg_list(); eit.valid(); ++eit){
01535     sorter1.insert(make_pair(get_hash(eit.current()), &eit.current()));
01536   }
01537   for(Iterator<Expression> eit=e2.arg_list(); eit.valid(); ++eit){
01538     sorter2.insert(make_pair(get_hash(eit.current()), &eit.current()));
01539   }
01540   if (sorter1.size()!=sorter2.size()){
01541     return false;
01542   }
01543   map<int, Expression*>::iterator it1=sorter1.begin();
01544   map<int, Expression*>::iterator it2=sorter2.begin();
01545   for( ; it1!=sorter1.end() && it2!=sorter2.end(); ++it1, ++it2){
01546     if ((*it1).first!=(*it2).first){
01547       return false;
01548     }
01549     if (! (*(*it1).second == *(*it2).second) ){
01550       return false;
01551     }
01552   }
01553   return true;
01554 }
01555 
01556 
01557 bool same_gate(Expression& e1, Expression& e2){
01558   if (e1==e2){
01559     return true;
01560   }
01561   
01562 /// Check for commutative patterns.
01563   if (e1.op()==NE_OP && e2.op()==NE_OP ||
01564       e1.op()==EQ_OP && e2.op()==EQ_OP){
01565     if (e1.left_guarded().type().data_type()==INTEGER_TYPE &&
01566     e2.left_guarded().type().data_type()==INTEGER_TYPE){
01567       Expression* t1=simplify(sub(e1.left_guarded().clone(),
01568                   e1.right_guarded().clone()));
01569       Expression* t2=simplify(sub(e2.left_guarded().clone(),
01570                   e2.right_guarded().clone()));
01571       if (same_commutative(*t1, *t2)){
01572     delete t1;
01573     delete t2;
01574     return true;
01575       } else {
01576     t1=simplify(mul(constant(-1), t1));
01577     if (same_commutative(*t1, *t2)){
01578       delete t1;
01579       delete t2;
01580       return true;
01581     } else {
01582       delete t1;
01583       delete t2;
01584     }
01585       }
01586     }
01587   }
01588 
01589   return false;
01590 }
01591 
01592 
01593 /// Returns true if e1==e3, and e2=....AND.e3.AND....
01594 static bool included_gates(Expression& e1, Expression& e2){
01595   if (same_gate(e1, e2)){
01596     return true;
01597   }
01598   if (e2.op()!=AND_OP){
01599     return false;
01600   }
01601   for(Iterator<Expression> eit=e2.arg_list(); eit.valid(); ++eit){
01602     if (same_gate(e1, eit.current())){
01603       return true;
01604     }
01605   }
01606   return false;
01607 }
01608 
01609 
01610 
01611 /// Returns true if gate1->gate2
01612 /// Based on:
01613 /// a -> b <=> .NOT.a.OR.b <=> .NOT.(a.AND..NOT.b)
01614 bool implies(ProgramUnit& pgm, Expression& gate1, Expression& gate2){
01615   Expression* not_gate2=not(gate2.clone());
01616   bool result=incompatible_gates(pgm, gate1, *not_gate2);
01617   delete not_gate2;
01618   if (result){
01619     /// ...  We just proved .NOT.(a.AND..NOT.b)
01620     return true;
01621   } else {
01622     if (included_gates(gate2, gate1)){
01623       /// ...  gate2 is a part of gate1
01624       return true;
01625     }
01626   }
01627   return false;
01628 }
01629 
 © 1995-2005 University of Illinois, Urbana-Champaign. All rights reserved.  Fri Mar 25 23:05:54 2005