Polaris: evolution_graph.cc Source File

evolution_graph.cc

Go to the documentation of this file.
00001 ///
00002 ///
00003 #include "EvolutionGraph.h"
00004 #include "eg_utils.h"
00005 #include "evolution_graph.h"
00006 #include "affine.h"
00007 #include "BackTrace.h"
00008 
00009 #include "ip_ssa/trans_util.h"
00010 #include "ip_ssa/optimize_ssa.h"
00011 
00012 #include "guarded_values.h"
00013 
00014 EvolutionGraph* _get_eg(ProgramUnit* pgm, Statement* loop);
00015 
00016 bool _is_useless(const Evolution<Expression>& ev){
00017   if (ev.min_difference()->op()==INFINITY_OP &&
00018       ev.max_difference()->op()==INFINITY_OP){
00019     if (ev.min_difference()->value()==-1 &&
00020     ev.max_difference()->value()==1){
00021       return true;
00022     }
00023   }
00024   return false;
00025 }
00026 
00027 bool _is_useless(const Expression& e){
00028   if (e.op()!=RANGE_OP){
00029     return false;
00030   }
00031   const RangeExpr& ev=(const RangeExpr&)e;
00032   if (ev.lb().op()==INFINITY_OP &&
00033       ev.ub().op()==INFINITY_OP){
00034     if (ev.lb().sign()==-1 &&
00035     ev.ub().sign()==1){
00036       return true;
00037     }
00038   }
00039   return false;
00040 }
00041 
00042 
00043 
00044 
00045 /// Will not return the range over the whole loop, but for just an iteration.
00046 /// Will only return a range if input values are the only way to generate 'e'.
00047 Expression* eg_range_from_input(Expression& e, 
00048                 ProgramUnit& pgm, 
00049                 Statement* loop){
00050   
00051   RefList<Symbol> syms;
00052   referred_symbols(e, syms);
00053   RangeAccessor ra(pgm.range_dict_guarded(), *pgm.stmts().first_ref());
00054   RefSet<Symbol> vars_to_eliminate;
00055   for(Iterator<Symbol> sit=syms; sit.valid(); ++sit){
00056     Expression* r=_get_eg(&pgm, loop)->range_from_input(sit.current());
00057     if (r){
00058       ra.set_range(sit.current(), r);
00059       vars_to_eliminate.ins(sit.current());
00060     }
00061   }
00062 ///   cerr<<"\nBEFORE subst: "<<e;
00063   Expression* toret=e.clone();
00064   if (vars_to_eliminate.entries()){
00065     toret=ra.eliminate_vars(toret, &vars_to_eliminate);
00066   }
00067 ///   cerr<<"\nAFTER subst: "<<*toret;
00068   return toret;
00069 }
00070 
00071 /// 'sym' is the gsa base of a symbol.
00072 bool is_defined(Symbol& sym, Statement& stmt){
00073   if (called_pgm(stmt)){
00074     /// ...  Call or entry site.
00075     if (stmt.stmt_class()==ENTRY_STMT){
00076       return false;
00077     }
00078     if (!has_maymod(stmt)){
00079       return true;
00080     }
00081     if (is_var_in_maymod(sym, stmt)){
00082       return true;
00083     }
00084     if (stmt.stmt_class()==ASSIGNMENT_STMT){
00085       if (&sym==gsa_base(*stmt.lhs().base_variable_ref())){
00086     return true;
00087       } else {
00088     return false;
00089       }
00090     } else {
00091       return false;
00092     }
00093   } else {
00094     /// ...  Not a call site.
00095     for(Iterator<Expression> eit=stmt.out_refs(); eit.valid(); ++eit){
00096       if (&sym==gsa_base(*eit.current().base_variable_ref())){
00097     return true;
00098       } else {
00099     return false;
00100       }
00101     }
00102     return false;
00103   }
00104 }
00105 
00106 /// Find all scalar sources for the given array.
00107 /// Return true only if all its value sources are scalar.
00108 /// Return values relative to the body of the given loop.
00109 /// Since this is an array, must take into account all iterations
00110 /// from 1 to i.
00111 /// silvius: for now, this is intraprocedural.  
00112 /// Also, when we extend the VEG to 
00113 /// array references, this function should not be needed anymore.
00114 bool _find_scalar_sources(ProgramUnit& pgm, Statement* loop,
00115               Expression& expr, List<Expression>& sources){
00116   
00117   p_assert(expr.op()==ARRAY_REF_OP, "Not an array.");
00118   if (loop){
00119     p_assert(loop->stmt_class()==DO_STMT, "Not a loop.");
00120   }
00121   Symbol* sym=gsa_base(expr.array().symbol());
00122 
00123 /// 1. The array must not be defined outside the loop.
00124   if (loop!=0){
00125     for (Statement* ps=pgm.stmts().first_ref(); ps!=loop; ps=ps->next_ref()){
00126       if (is_defined(*sym, *ps)){
00127 ///     cerr<<"\n\t"<<sym->name_ref()<<" "<<*ps;
00128 ///     cerr<<"\n\tRET 1";
00129     return false;
00130       }
00131     }
00132     for (Statement* ps=loop->follow_ref(); ps; ps=ps->next_ref()){
00133       if (is_defined(*sym, *ps)){
00134     /// ...  It is OK only if it is an ETA.
00135     if (ps->stmt_class()==ASSIGNMENT_STMT){
00136       if (ps->rhs().op()==ETA_OP){
00137         continue;
00138       }
00139     }
00140 ///     cerr<<"\nDefined at stmt "<<*ps;
00141 ///     cerr<<"\n\tRET 2";
00142     return false;
00143       }
00144     }
00145   }
00146 
00147 /// 2. If the array is defined within the loop, make sure it is defined
00148 /// in an assignement statement, and that RHS is made only of scalars.
00149   RefList<Expression> primary_sources;
00150   Statement* begin;
00151   Statement* end;
00152   if (loop){
00153     begin=loop->next_ref();
00154     end=loop->follow_ref();
00155   } else {
00156     begin=pgm.stmts().first_ref();
00157     end=pgm.stmts().last_ref();
00158   }
00159   for (Statement* ps=begin; 
00160        ps!=end; ps=ps->next_ref()){
00161     if (is_defined(*sym, *ps)){
00162       if (ps->stmt_class()!=ASSIGNMENT_STMT){
00163 ///     cerr<<"\n\tRET 3";
00164     return false;
00165       }
00166       switch (ps->rhs().op()){
00167       case MU_OP:
00168       case GAMMA_OP:
00169       case THETA_OP:
00170       case ETA_OP:
00171     continue;
00172       }
00173 ///       cerr<<"\n\t\talpha = "<<ps->rhs();
00174       Expression& rhs=ps->rhs().parameters_guarded().arg_list()[1];
00175 ///       cerr<<"\n\t\tnoalpha = "<<ps->rhs();
00176 
00177       if (rhs.op()==FUNCTION_CALL_OP){
00178 ///     cerr<<"\n\tRET 4";
00179     return false;
00180       }
00181       RefList<Symbol> syms;
00182       referred_symbols(rhs, syms);
00183       for(Iterator<Symbol> sit=syms; sit.valid(); ++sit){
00184 ///     cerr<<"\n\t"<<sit.current().name_ref();
00185     if (!sit.current().is_scalar()){
00186       
00187 ///     cerr<<"\n\tRET 5";
00188       return false;
00189     }
00190       }
00191       /// ...  Add rhs to the preliminary list.
00192       primary_sources.ins_last(rhs);
00193     }
00194   }
00195 
00196 ///   cerr<<"\n\tps = "<<primary_sources;
00197 
00198 /// Go through all the sources and find their ranges at the level of the body
00199 /// of the given loop.
00200   List<Expression> per_iteration;
00201   EvolutionGraph* eg=_get_eg(&pgm, (DoStmt*)loop);
00202   for(Iterator<Expression> eit=primary_sources; eit.valid(); ++eit){
00203     Expression* epi=eit.current().clone();
00204     epi=eg->_global_range_per_iteration(epi, (DoStmt*)loop);
00205     per_iteration.ins_last(epi);
00206   }
00207 
00208 /// Now expand the per-iteration descriptors over interval [1:i].
00209 /// silvius: take a shortcut here.
00210   p_warning("Incomplete implementation.");
00211   sources=per_iteration;
00212   
00213   return true;
00214 }
00215 
00216 
00217 /// Will not return the range over the whole loop, but for iterations 1 to i.
00218 /// Will only return a range if input values are the only way to generate 'e'.
00219 Expression* eg_range_array_1_to_i(Expression& expr, 
00220                   ProgramUnit& pgm, Statement* loop){
00221 /// For now, this will only work if the array is a parasite of
00222 /// some scalars.
00223   p_assert(expr.op()==ARRAY_REF_OP, "Not an array.");
00224   Symbol& sym=expr.array().symbol();
00225 ///   cerr<<"\nLooking for ss for "<<sym.name_ref();
00226   List<Expression> sources;
00227   bool found=_find_scalar_sources(pgm, loop, expr, sources);
00228   if (!found){
00229 ///     cerr<<"\n\t_find_scalar_sources = false";
00230     return new RangeExpr(infinity(-1), infinity(+1));
00231   }
00232   Statement* rs=loop;
00233   if (rs==0){
00234     rs=pgm.stmts().last_ref();
00235   } else {
00236     rs=rs->follow_ref();
00237   }
00238   RangeAccessor ra(pgm.range_dict_guarded(), *rs);
00239   if (sources.entries()==0){
00240     /// ...  Not defined in this pgm.
00241     return new RangeExpr(infinity(-1), infinity(+1));
00242   }
00243   Expression* e=sources.grab(0);
00244   ra.set_range(sym, e);
00245   while(sources.entries()){
00246     e=sources.grab(0);
00247     ra.union_range(sym, *e);
00248     delete e;
00249   }
00250   return ra.get_range_ref(sym)->clone();
00251 }
00252 
00253 
00254 
00255 
00256 /// Return the range over the whole loop.
00257 Expression* eg_range(Expression& e, ProgramUnit& pgm, Statement* loop){
00258   Expression* toret=e.clone();
00259   if (loop==0){
00260     /// ...  Go back to the inputs if given.
00261     RefList<Symbol> syms;
00262     referred_symbols(*toret, syms);
00263     if (!pgm.range_dict_valid()){
00264       pgm.range_dict(new AIRangeDict(pgm));
00265     }
00266     
00267     RangeAccessor ra(pgm.range_dict_guarded(), *pgm.stmts().first_ref());
00268     RefSet<Symbol> vars_to_eliminate;
00269     for(Iterator<Symbol> sit=syms; sit.valid(); ++sit){
00270       Expression* r=_get_eg(&pgm, loop)->range_from_input(sit.current());
00271       if (r){
00272     ra.set_range(sit.current(), r);
00273     vars_to_eliminate.ins(sit.current());
00274       }
00275     }
00276     toret=ra.eliminate_vars(toret, &vars_to_eliminate);
00277     if (toret->op()==OMEGA_OP){
00278       delete toret;
00279       toret=new RangeExpr(infinity(-1), infinity());
00280     }
00281   }
00282 
00283   if (_is_useless(*toret)){
00284     /// ...  Use the original, we did not do better.
00285     delete toret;
00286     toret=e.clone();
00287   }
00288   
00289   EvolutionGraph* global=_get_eg(&pgm, loop);
00290   toret=global->_global_range(toret, (DoStmt*)loop);
00291   
00292   if (toret->op()==OMEGA_OP){
00293     delete toret;
00294 ///       cerr<<"\n2. eg_range Return INF: ";
00295     return new RangeExpr(infinity(-1), infinity());
00296   } else {
00297 ///     cerr<<"\n3. eg_range Return  "<<*toret;
00298     return toret;
00299   }
00300 }
00301 
00302 
00303 static RangeAccessor* _get_ra(ProgramUnit& pgm, Statement* domain,
00304                   Expression& e1, Expression& e2){
00305   RefList<Symbol> syms;
00306   referred_symbols(e1, syms);
00307   referred_symbols(e2, syms);
00308   RefList<Symbol> vars;
00309   for (Iterator<Symbol> sit=syms; sit.valid(); ++sit){
00310     if (sit.current().sym_class()==VARIABLE_CLASS){
00311       vars.ins_last(sit.current());
00312     }
00313   }
00314 ///   cerr<<"\n\n\tvars = "<<vars;
00315   RangeAccessor* ra=0;
00316   switch(vars.entries()){
00317   case 1:
00318     {
00319       DefLoc* defloc=pgm.gsa_deflocs_guarded().find_ref(vars[0]);
00320       /// ... p_assert(defloc, "Could not find definition for symbol.");
00321       if(defloc)
00322       {   
00323          if (defloc->stmt_valid()){
00324        Statement* rs=&defloc->stmt_guarded();
00325        ra=new RangeAccessor(pgm.range_dict_guarded(), *rs);
00326          }
00327       }
00328     }
00329     break;
00330   case 2:
00331     {
00332       Statement* rs1=0;
00333       Statement* rs2=0;
00334       DefLoc* defloc=pgm.gsa_deflocs_guarded().find_ref(vars[0]);
00335       /// ... p_assert(defloc, "Could not find definition for symbol.");
00336       if(defloc)
00337       {
00338          if (defloc->stmt_valid()){
00339        rs1=&defloc->stmt_guarded();
00340          }
00341          defloc=pgm.gsa_deflocs_guarded().find_ref(vars[1]);
00342      if(defloc)
00343      {
00344             p_assert(defloc, "Could not find definition for symbol.");
00345             if (defloc->stmt_valid()){
00346           rs2=&defloc->stmt_guarded();
00347             }
00348             if (rs1 && rs2){
00349 ///           cerr<<"\n\t\t\tcase 2";
00350           ra=new RangeAccessor(pgm.range_dict_guarded(), 
00351                  *rs1->next_ref(), *rs2->next_ref(), false);
00352             } else {
00353           if (rs1) {
00354 ///             cerr<<"\n\t\t\tcase 2.1";
00355             ra=new RangeAccessor(pgm.range_dict_guarded(), *rs1->next_ref());
00356           } else {
00357             if (rs2){
00358 ///               cerr<<"\n\t\t\tcase 2.2";
00359               ra=new RangeAccessor(pgm.range_dict_guarded(), *rs2->next_ref());
00360             }
00361           }
00362             }
00363      }
00364       }
00365     }
00366     break;
00367   case 0:
00368     break;
00369   default:
00370     break;
00371   }
00372 
00373   if (ra==0){
00374     Statement* rs;
00375     if (domain){
00376       /// ...  Matching ENDDO.
00377       rs=domain->follow_ref();
00378     } else {
00379       /// ...  FLOWEXIT.
00380       rs=pgm.stmts().last_ref();
00381     }
00382     ra=new RangeAccessor(pgm.range_dict_guarded(), *rs);
00383   }
00384   return ra;
00385 }
00386 
00387 static Relation _eg_compare(Expression* r1, Expression* r2, 
00388                 ProgramUnit& pgm, Statement* domain){
00389 /// Find out the best place to compare them.
00390 /// silvius: I think this is somewhere after all the definitions of the
00391 /// symbols contained in the two expressions.
00392 
00393 /// only do it if integer exprs.
00394   if (r1->type().data_type()!=INTEGER_TYPE ||
00395       r2->type().data_type()!=INTEGER_TYPE){
00396     return Relation(false, false, false);
00397   }
00398 
00399 /// Perform the comparison.
00400   Expression* l;
00401   if (r1->op()==RANGE_OP){
00402     l=&((RangeExpr*)r1)->lb();
00403   } else {
00404     l=r1;
00405   }
00406   Expression* u;
00407   if (r2->op()==RANGE_OP){
00408     u=&((RangeExpr*)r2)->ub();
00409   } else {
00410     u=r2;
00411   }
00412   
00413 ///   cerr<<"\n\t\tcomparing: "<<*l<<", "<<*u<<"\n";
00414   RangeAccessor* ra = _get_ra(pgm, domain, *l, *u);
00415   Relation toret=ra->compare(*l, *u);
00416   delete ra;
00417 ///   cerr<<"\n\t\ttresult = "<<toret;
00418 
00419   if (toret.is_greater_than()){
00420     /// ...  r1 > r2
00421 ///     cerr<<"\n\treturning "<<toret;
00422     return toret;
00423   }
00424 
00425   if (toret.is_greater_equal()){
00426 ///     cerr<<"\n\treturning "<<toret;
00427     return toret;
00428     
00429   }
00430 
00431 /// Try it the other way.
00432   if (r2->op()==RANGE_OP){
00433     l=&((RangeExpr*)r2)->lb();
00434   } else {
00435     l=r2;
00436   }
00437   if (r1->op()==RANGE_OP){
00438     u=&((RangeExpr*)r1)->ub();
00439   } else {
00440     u=r1;
00441   }  
00442   ra = _get_ra(pgm, domain, *l, *u);
00443   toret=ra->compare(*l, *u);
00444   delete ra;
00445 ///   cerr<<"\n\t\tcomparing: "<<*l<<", "<<*u;
00446 ///   cerr<<"\n\t\tresult = "<<toret;
00447   if (toret.is_greater_than()){
00448     /// ...  r2 > r1, so return r1 < r2
00449 ///     cerr<<"\n\t\treturning <";
00450     return Relation(true, false, false);
00451   }
00452   if (toret.is_greater_equal()){
00453     /// ...  r2 > r1, so return r1 < r2
00454 ///     cerr<<"\n\t\treturning <";
00455     return Relation(true, true, false);
00456   }
00457   
00458 /// Could not find any useful result.
00459 ///   cerr<<"\n\t\treturning UNKNOWN";
00460   return Relation(false, false, false);
00461 }
00462 
00463 
00464 Relation eg_compare(Expression& e1, Expression& e2, ProgramUnit& pgm){
00465 /// Find the innermost loop that contains all the definitions
00466 /// of all the variables in e1 and e2.
00467   RefList<Symbol> syms;
00468   referred_symbols(e1, syms);
00469 ///   cerr<<"\n\te1: "<<e1;
00470   referred_symbols(e2, syms);
00471 ///   cerr<<"\te2: "<<e2;
00472   set<DoStmt*> loops;
00473   for(Iterator<Symbol> sit=syms; sit.valid(); ++sit){
00474     loops.insert(def_loop(sit.current(), pgm));
00475   }
00476   DoStmt* domain=common_outer(loops);
00477 
00478   Expression* r1=e1.clone();
00479   Expression* r2=e2.clone();
00480 ///   cerr<<"\n\tr1: "<<*r1;
00481 ///   cerr<<"\tr2: "<<*r2;
00482 
00483   
00484 
00485   while (1){
00486 ///     cerr<<"\n\tdomain is ";
00487 ///     if (domain){
00488 ///       cerr<<domain->get_loop_name();
00489 ///     } else {
00490 ///       cerr<<pgm.routine_name_ref();
00491 ///     }
00492     /// ...  Now get ranges over the domain for the expressions.
00493     EvolutionGraph* eg=_get_eg(&pgm, domain);
00494     r1=eg_forward_substitute(pgm, domain, r1);
00495     r2=eg_forward_substitute(pgm, domain, r2);
00496 ///     cerr<<"\n\t\texprs are: "<<*r1<<", "<<*r2;
00497     r1=eg->_global_range(r1, domain);
00498     r2=eg->_global_range(r2, domain);
00499     if (r1==0 || r2==0){
00500       return Relation();
00501     }
00502 ///     cerr<<"\n\t\tranges are: "<<*r1<<", "<<*r2;
00503 
00504     Relation toret=_eg_compare(r1, r2, pgm, domain);
00505     if (!toret.is_unknown()){
00506       /// ...  Found a relation.
00507 ///       cerr<<"\nReturning 1 "<<toret;
00508       delete r1;
00509       delete r2;
00510       return toret;
00511     }
00512     if (domain==0){
00513       /// ...  Found no relation.
00514       delete r1;
00515       delete r2;
00516 ///       cerr<<"\nReturning 2 "<<toret;
00517       if (toret.is_unknown()){
00518     /// ...  Try comparison using regular ranges.
00519 ///     cerr<<"\ne1 = "<<e1<<", e2 = "<<e2;
00520     RangeAccessor* ra = _get_ra(pgm, domain, e1, e2);
00521     if (e1.type().data_type()==INTEGER_TYPE && 
00522         e1.type().data_type()==INTEGER_TYPE){
00523       toret=ra->compare(e1, e2);
00524       delete ra;
00525       return toret;
00526     } else {
00527       return Relation();
00528     }
00529       }
00530       return toret;
00531     } else {
00532       /// ...  Try outer domains.
00533       domain=(DoStmt*)domain->outer_ref();
00534     }
00535   }
00536 }
00537 
00538 
00539 
00540 
00541 Expression* eg_distance(ProgramUnit& pgm, DoStmt& loop, 
00542             Symbol& left, Symbol& right){
00543 /// Compute it.
00544   EvolutionGraph* eg_both=_get_eg(&pgm, &loop);
00545   Expression* toret=eg_both->min_distance(left, right);
00546   return toret;
00547 }
00548 
00549 
00550 
00551 /// Measures the distance between sets of expressions across an iteration,
00552 /// such as: {3+5*x, 2+5*y} to {6+5*z, 1+5*t}
00553 static Expression* 
00554 eg_distance_1_dim(ProgramUnit& pgm, DoStmt& loop, RangeAccessor& ra,
00555           vector<vector<Symbol*> >& args_left,
00556           vector<vector<Expression*> >& coeffs_left,
00557           vector<vector<Symbol*> >& args_right,
00558           vector<vector<Expression*> >& coeffs_right){
00559 /// First check that they all have the same coefficients.
00560   Expression& model=*coeffs_left[0][0];
00561   unsigned int i,j;
00562   for(i=1; i<args_left.size(); ++i){
00563     if (!(*coeffs_left[i][0]==model)){
00564       return constant(0);
00565     }
00566   }
00567   for(i=0; i<args_right.size(); ++i){
00568     if (!(*coeffs_right[i][0]==model)){
00569       return constant(0);
00570     }
00571   }
00572 
00573 /// Put together the result.
00574   Expression* toret=infinity(1);
00575   for(i=0; i<args_left.size(); ++i){
00576     for(j=0; j<args_right.size(); ++j){
00577       /// ...  May have different free terms.
00578       Expression* candidate=simplify(sub(coeffs_right[j][1]->clone(), 
00579                      coeffs_left[i][1]->clone()));
00580       /// ...  May have different variables.
00581       Expression* sym_dist=eg_distance(pgm, loop, 
00582                        *args_left[i][0], *args_right[j][0]);
00583       /// ...  Have the same coefficient.
00584       candidate=simplify(add(candidate, mul(sym_dist, model.clone())));
00585       if (*candidate==*toret){
00586     /// ...  Discard candidate.
00587     delete candidate;
00588       } else {
00589     if (p_less_than(*candidate, *toret, &ra)){
00590       // Keep candidate.
00591       delete toret;
00592       toret=candidate;
00593     } else {
00594       if (p_greater_than(*candidate, *toret, &ra)){
00595         /// ...  Discard candidate.
00596         delete candidate;
00597       } else {
00598         /// ...  Incomparable, keep MAX.
00599         Symbol* best_op_sym=pgm.symtab().find_ref("MIN");
00600         p_assert(best_op_sym, "MIN intrinsic not in symbol table");
00601         toret=intrinsic_call(id(*best_op_sym), 
00602                  comma(toret, candidate));
00603       }
00604     }
00605       }
00606     }
00607   }
00608 
00609   if (toret->op()==INFINITY_OP){
00610     /// ...  Report distance conservatively.
00611     delete toret;
00612     return constant(0);
00613   } else {
00614     return toret;
00615   }
00616 }
00617 
00618 
00619 
00620 static void _cleanup_coeffs(vector<vector<Expression*> >& coeffs_left,
00621                 vector<vector<Expression*> >& coeffs_right){
00622   unsigned int i,j;
00623   for(i=0; i<coeffs_left.size(); ++i){
00624     for(j=0; j<coeffs_left[i].size(); ++j){
00625       delete coeffs_left[i][j];
00626     }
00627   }
00628   for(i=0; i<coeffs_right.size(); ++i){
00629     for(j=0; j<coeffs_right[i].size(); ++j){
00630       delete coeffs_right[i][j];
00631     }
00632   }
00633 }
00634 
00635 
00636 /*!
00637   \brief Returns the minimum distance between two elements in left and right.
00638 
00639   Conservative result: constant(0).
00640   Will only compute it for affine functions with identical linear 
00641   coefficients.
00642 */
00643 Expression* eg_distance(ProgramUnit& pgm, DoStmt& loop,
00644             List<Expression>& left, List<Expression>& right,
00645             set<Symbol*>& variants){
00646 /// silvius: for now do it only if
00647 /// the linear coefficients of the affine expression correspond for a 
00648 /// one-to-one correspondence of the variants.
00649 /// Handle cases like: 3+5*y+x  and x+4+5*y.
00650 
00651 /// silvius: in the future, make some repository of symbol distances to 
00652 /// solve the general problem efficiently.
00653   
00654   if (left.entries()==0 || right.entries()==0){
00655     return constant(0);
00656   }
00657 
00658 ///   cerr<<"\nleft = "<<left;
00659 ///   cerr<<"\nright = "<<right;
00660 
00661 /// Check that all symbols are scalar integers and that 
00662 /// all expresssions are affine functions of loop variants.
00663   vector<vector<Symbol*> > args_left, args_right;
00664   vector<vector<Expression*> > coeffs_left, coeffs_right;
00665 
00666   if (!check_scalars_affine(left, pgm, loop, args_left, coeffs_left)){
00667     _cleanup_coeffs(coeffs_left, coeffs_right);
00668     return constant(0);
00669   }
00670   if (!check_scalars_affine(right, pgm, loop, args_right, coeffs_right)){
00671     _cleanup_coeffs(coeffs_left, coeffs_right);
00672     return constant(0);
00673   }
00674   RangeAccessor ra(pgm.range_dict_guarded(), *loop.follow_ref());
00675 
00676 /// silvius: consider first the case when they each have exactly one 
00677 /// variable (possibly not the same).
00678   unsigned int i,j;
00679   bool all_1_dim=true;
00680   for(i=0; i<args_left.size(); ++i){
00681     if (args_left[i].size()!=1){
00682       all_1_dim=false;
00683       break;
00684     }
00685   }
00686   if (all_1_dim){
00687     for(i=0; i<args_right.size(); ++i){
00688       if (args_right[i].size()!=1){
00689     all_1_dim=false;
00690     break;
00691       }
00692     }
00693   }
00694   if (all_1_dim){
00695     Expression* toret= eg_distance_1_dim(pgm, loop, ra, 
00696                      args_left, coeffs_left, 
00697                      args_right, coeffs_right);
00698     _cleanup_coeffs(coeffs_left, coeffs_right);
00699     return toret;
00700   }
00701 
00702   
00703 /// Check that they have the same vars and coeffs (except for the free term).
00704   map<Symbol*, Expression*> args_coeffs;
00705   vector<Symbol*> args_model=args_left[0];
00706   vector<Expression*> coeffs_model=coeffs_left[0];
00707   args_model=args_left[0];
00708   for(j=0; j<args_model.size(); ++j){
00709     variants.insert(args_model[j]);
00710     args_coeffs[args_model[j]]=coeffs_model[j];
00711   }
00712 
00713   for(i=0; i<args_left.size(); ++i){
00714     /// ...  First check the number of variables.
00715     if (args_left[i].size()!=args_model.size()){
00716       _cleanup_coeffs(coeffs_left, coeffs_right);
00717       return constant(0);
00718     } else {
00719       for(j=0; j<args_left[i].size(); ++j){
00720     map<Symbol*, Expression*>::iterator found=
00721       args_coeffs.find(args_left[i][j]);
00722     if (found==args_coeffs.end()){
00723       // Variable not found in model.
00724       _cleanup_coeffs(coeffs_left, coeffs_right);
00725       return constant(0);
00726     } else {
00727       if (!(*(*found).second==*coeffs_left[i][j])){
00728         _cleanup_coeffs(coeffs_left, coeffs_right);
00729         return constant(0);
00730       }
00731     }
00732       }
00733     }
00734   }
00735   for(i=0; i<args_right.size(); ++i){
00736     /// ...  First check the number of variables.
00737     if (args_right[i].size()!=args_model.size()){
00738       _cleanup_coeffs(coeffs_left, coeffs_right);
00739       return constant(0);
00740     } else {
00741       for(j=0; j<args_right[i].size(); ++j){
00742     map<Symbol*, Expression*>::iterator found=
00743       args_coeffs.find(args_right[i][j]);
00744     if (found==args_coeffs.end()){
00745       // Variable not found in model.
00746       _cleanup_coeffs(coeffs_left, coeffs_right);
00747       return constant(0);
00748     } else {
00749       if (!(*(*found).second==*coeffs_right[i][j])){
00750         _cleanup_coeffs(coeffs_left, coeffs_right);
00751         return constant(0);
00752       }
00753     }
00754       }
00755     }
00756   }
00757 
00758 
00759 /// Find largest free term in 'left'
00760   Expression* toret=infinity(-1);
00761   for(i=0; i<args_left.size(); ++i){
00762     Expression& candidate=*coeffs_left[i][coeffs_left[i].size()-1];
00763     if (candidate==*toret){
00764       /// ...  Discard candidate.
00765     } else {
00766       if (p_greater_than(candidate, *toret, &ra)){
00767     /// ...  Keep candidate.
00768     delete toret;
00769     toret=candidate.clone();
00770       } else {
00771     if (p_less_than(candidate, *toret, &ra)){
00772       // Discard candidate.
00773     } else {
00774       // Incomparable, keep MAX.
00775       Symbol* best_op_sym=pgm.symtab().find_ref("MAX");
00776       p_assert(best_op_sym, "MAX intrinsic not in symbol table");
00777       toret=intrinsic_call(id(*best_op_sym), 
00778                    comma(toret, candidate.clone()));
00779     }
00780       }
00781     }
00782   }
00783   Expression* max_ftl=toret;
00784 
00785 
00786 /// Find smallest free term in 'right'
00787   toret=infinity(1);
00788   for(i=0; i<args_right.size(); ++i){
00789     Expression& candidate=*coeffs_right[i][coeffs_right[i].size()-1];
00790     if (candidate==*toret){
00791       /// ...  Discard candidate.
00792     } else {
00793       if (p_less_than(candidate, *toret, &ra)){
00794     /// ...  Keep candidate.
00795     delete toret;
00796     toret=candidate.clone();
00797       } else {
00798     if (p_greater_than(candidate, *toret, &ra)){
00799       // Discard candidate.
00800     } else {
00801       // Incomparable, keep MAX.
00802       Symbol* best_op_sym=pgm.symtab().find_ref("MIN");
00803       p_assert(best_op_sym, "MIN intrinsic not in symbol table");
00804       toret=intrinsic_call(id(*best_op_sym), 
00805                    comma(toret, candidate.clone()));
00806     }
00807       }
00808     }
00809   }
00810   Expression* min_ftr=toret;
00811 
00812 /// Make up the total distance.
00813   toret=simplify(sub(min_ftr, max_ftl));
00814   for(unsigned int i=0; i<args_model.size(); ++i){
00815     Symbol& arg=*args_model[i];
00816     Expression& coeff=*coeffs_model[i];
00817     Expression* sym_dist=eg_distance(pgm, loop, arg, arg);
00818     toret=simplify(add(toret, mul(sym_dist, coeff.clone())));
00819   }
00820 
00821 /// Return.
00822   _cleanup_coeffs(coeffs_left, coeffs_right);
00823   if (toret->op()==INFINITY_OP){
00824     /// ...  Report distance conservatively.
00825     delete toret;
00826     return constant(0);
00827   } else {
00828 ///     cerr<<"\nRETURNING: "<<*toret;
00829     return toret;
00830   }
00831 }
00832 
00833 
00834 bool eg_contradictory_gate(Expression& gate, ProgramUnit& pgm){
00835 ///   cerr<<"\nEnter contradictory gate with "<<gate;
00836   if (gate.op()==AND_OP){
00837     for(Iterator<Expression> eit=gate.arg_list(); eit.valid(); ++eit){
00838       if (eg_contradictory_gate(eit.current(), pgm)){
00839     return true;
00840       }
00841     }
00842   } else {
00843     switch (gate.op()){
00844     case NE_OP:
00845     case EQ_OP:
00846     case LT_OP:
00847     case GT_OP:
00848     case LE_OP:
00849     case GE_OP:
00850       {
00851 ///     cerr<<"\n\tcomparing "<<gate.arg_list()[0]
00852 ///         <<" and "<<gate.arg_list()[1];
00853     Relation lr=eg_compare(gate.arg_list()[0], gate.arg_list()[1], pgm);
00854 ///     cerr<<"\n\t\tRelation = "<<lr;
00855     if (lr.is_less_than() && (gate.op()==GT_OP || 
00856                   gate.op()==GE_OP || 
00857                   gate.op()==EQ_OP )){
00858 ///       cerr<<"\n\tTRUE.";
00859       return true;
00860     }
00861     if (lr.is_greater_than() && (gate.op()==LT_OP || 
00862                      gate.op()==LE_OP || 
00863                      gate.op()==EQ_OP )){
00864 ///       cerr<<"\n\tTRUE.";
00865       return true;
00866     }
00867     if (lr.is_less_equal() && gate.op()==GT_OP){
00868 ///       cerr<<"\n\tTRUE.";
00869       return true;
00870     }
00871     if (lr.is_greater_equal() && gate.op()==LT_OP){
00872 ///       cerr<<"\n\tTRUE.";
00873       return true;
00874     }
00875     if (lr.is_equal() && (gate.op()==GT_OP || 
00876                   gate.op()==LT_OP || 
00877                   gate.op()==NE_OP )){
00878 ///       cerr<<"\n\tTRUE.";
00879       return true;
00880     }
00881     if (lr.is_not_equal() && gate.op()==EQ_OP){
00882 ///       cerr<<"\n\tTRUE.";
00883       return true;
00884     }
00885 ///     cerr<<"\n\t\tfailed";
00886       }
00887     }
00888   }
00889 ///   cerr<<"\n\tFAILED.";
00890   return false;
00891 }
00892 
00893 bool eg_redundant_gate(Expression& gate, ProgramUnit& pgm){
00894   Expression* g=simplify(not(gate.clone()));
00895   bool toret=eg_contradictory_gate(*g, pgm);
00896   delete g;
00897   return toret;
00898 }
00899 
00900 
00901 
00902 
00903 /*!
00904   \brief Get the evolution summaries for all evolutions from a MU to a BACK
00905    node that pass through sym in loop dostmt in pgm.  All evolutions that
00906    MAY be in the given range are reported.
00907 */
00908 void eg_get_ev_summary(ProgramUnit& pgm, 
00909                DoStmt* dostmt,
00910                Symbol& sym,
00911                pair<RangeExpr*, bool>& range,
00912                vector<pair<List<Expression>, 
00913                pair<RangeExpr*, Expression*> > >& evs,
00914                Symbol*& mu){
00915   EvolutionGraph* eg=_get_eg(&pgm, dostmt);
00916 
00917 /// silvius: for now only do it if the given sym is only reachable from
00918 /// one MU which has exactly one BACK.
00919 
00920   mu=0;
00921   Symbol* back=0;
00922   if (!eg->find_unique_mu(&sym, mu, back)){
00923 ///     cerr<<"\n\t\tfind_unique_mu = FALSE.";
00924     return;
00925   }
00926 ///   cerr<<"\nmu = "<<mu->name_ref();
00927 ///   cerr<<"\nback = "<<back->name_ref();
00928 
00929 
00930 /// Get traces.
00931   map<Symbol*, list<list<Symbol*> > > traces;
00932   eg->traces_from_mu(back, range, traces);
00933 
00934 /// Get details for every trace originating from MU.
00935   list<list<Symbol*> >& trace=traces[mu];
00936   list<list<Symbol*> >::iterator it;
00937   for(it=trace.begin(); it!=trace.end(); ++it){
00938     evs.push_back(make_pair(List<Expression>(), 
00939                 make_pair((RangeExpr*)0, (Expression*)0)));
00940     pair<List<Expression>, pair<RangeExpr*, Expression*> >& top=
00941       evs[evs.size()-1];
00942     Evolution<Expression> ev;
00943     eg->get_trace_details(*it, ev, top.second.second, top.first);
00944     top.second.first=new RangeExpr(ev.min_difference()->clone(),
00945                    ev.max_difference()->clone());
00946   }
00947 }
00948 
00949 
00950 /*!
00951   \brief Returns true if the given sym forms a nondecreasing sequence within
00952   the given loop.
00953 */
00954 bool eg_nondecreasing(ProgramUnit& pgm, 
00955               DoStmt& dostmt,
00956               Symbol& sym){
00957   EvolutionGraph* eg=_get_eg(&pgm, &dostmt);
00958   return eg->sequence_type(sym) == EvolutionGraph::ST_NONDECREASING;
00959 }
00960 
00961 static void
00962 _find_call_sites(ProgramUnit& callee, 
00963          vector<pair<ProgramUnit*, Statement*> >&call_sites){
00964   RefSet<ProgramUnit>& callers=callee.called_by();
00965   for(Iterator<ProgramUnit> pit=callers; pit.valid(); ++pit){
00966     ProgramUnit& pgm=pit.current();
00967     Iterator<Statement> stit=pgm.stmts().iterator();
00968     for( ; stit.valid(); ++stit){
00969       Statement& stmt=stit.current();
00970       if (called_pgm(stmt)==&callee){
00971         call_sites.push_back(make_pair(&pgm, &stmt));
00972       }
00973     }
00974   }
00975 }
00976 
00977 
00978 
00979 
00980 RangeExpr* program_wide_range(ProgramUnit& pgm, Expression& expr){
00981 ///   cerr<<"\nComputing local pgm range in pgm. "<<pgm.routine_name_ref()
00982 ///       <<"for "<<expr;
00983   Expression* local_pgm_range=eg_range(expr, pgm, 0);
00984 ///   cerr<<"\nLocal pgm range in pgm. "<<pgm.routine_name_ref()
00985 ///       <<"for "<<expr<<" is "<<*local_pgm_range;
00986 
00987 /// Express it using only translatable symbols (GSA number == 0)
00988   RefSet<Symbol> vars_to_eliminate;
00989   RangeAccessor ra(pgm.range_dict_guarded(), *pgm.stmts().last_ref());
00990   RefList<Symbol> syms;
00991   referred_symbols(*local_pgm_range, syms);
00992   for(Iterator<Symbol> sit=syms; sit.valid(); ++sit){
00993     Symbol& sym=sit.current();
00994     bool range_is_set= (ra.get_range_ref(sym)!=0);
00995     vars_to_eliminate.ins(sym);
00996     List<RangeExpr> sym_ranges;
00997 ///     cerr<<"\n\tFor symbol "<<sym.name_ref();
00998     map<const Symbol*, Evolution<Expression> > muevs;
00999     list<pair<const Symbol*, Evolution<Expression> > > ievs;
01000     _get_eg(&pgm, 0)->export_evolutions(&sym, muevs, ievs);
01001     map<const Symbol*, Evolution<Expression> >::iterator muit;
01002     list<pair<const Symbol*, Evolution<Expression> > >::iterator iit;
01003     for(muit=muevs.begin(); muit!=muevs.end(); ++muit){
01004 ///       cerr<<"\n\t\tMU: "<<(*muit).first->name_ref()<<" : "<<(*muit).second;
01005       /// ...  Must trace it within all callers.
01006       vector<pair<ProgramUnit*, Statement*> > call_sites;
01007       _find_call_sites(pgm, call_sites);
01008       vector<pair<ProgramUnit*, Statement*> >::iterator it;
01009       for(it=call_sites.begin(); it!=call_sites.end(); ++it){
01010     ProgramUnit& caller=*(*it).first;
01011     Statement& callsite=*(*it).second;
01012     Translator trans(caller, callsite);
01013     /// ...  Translate the MU.
01014     Expression* t=translate_and_reshape(trans, pgm, caller, callsite,
01015                         id(*(*muit).first));
01016 ///     cerr<<"\n\t\tt = "<<*t;
01017     /// ...  Find its global range recursively.
01018     RangeExpr* trange=program_wide_range(caller, *t);
01019 ///     cerr<<"\n\t\ttrange = "<<*trange;
01020     delete t;
01021     /// ...  Add the range from MU to the global range of MU.
01022     RangeExpr* total=
01023       new RangeExpr(simplify(add((*muit).second.min_difference()->clone(),
01024                      trange->lb().clone())),
01025             simplify(add((*muit).second.max_difference()->clone(),
01026                      trange->ub().clone())));
01027 ///     cerr<<"\n\t\ttotal = "<<*total;
01028     delete trange;
01029     /// ...  Save contribution of 'total'.
01030     if (range_is_set){
01031       ra.union_range(sym, *total);
01032       delete total;
01033     } else {
01034       ra.set_range(sym, total);
01035       range_is_set=true;
01036     }
01037       }
01038     }
01039     for(iit=ievs.begin(); iit!=ievs.end(); ++iit){
01040 ///       cerr<<"\n\t\tINPUT: "<<(*iit).first->name_ref()<<" : "<<(*iit).second;
01041       /// ...  Insert range.
01042       RangeExpr r((*iit).second.min_difference()->clone(),
01043           (*iit).second.max_difference()->clone());
01044       ra.union_range(sym, r);
01045     }
01046 ///     cerr<<"\n\tGlobal range: ";
01047     const Expression* r=ra.get_range_ref(sym);
01048 ///     if (r){
01049 ///       cerr<<*r;
01050 ///     }
01051   }
01052 ///   cerr<<"\nTo eliminate: "<<vars_to_eliminate;
01053 ///   cerr<<"\nra = "<<ra;
01054   Expression* toret=ra.eliminate_vars(local_pgm_range, &vars_to_eliminate);
01055 ///   cerr<<"\nReturning: "<<*toret;
01056 ///   cerr<<"\nProgram wide range in pgm. "<<pgm.routine_name_ref()
01057 ///       <<"for "<<expr<<" is "<<*toret;
01058   if(toret->op()!=RANGE_OP){
01059     return new RangeExpr(toret, toret->clone());
01060   }
01061   return (RangeExpr*)toret;
01062 }
01063 
01064 
 © 1995-2005 University of Illinois, Urbana-Champaign. All rights reserved.  Fri Mar 25 23:05:46 2005