Polaris: EvolutionGraph.cc Source File

EvolutionGraph.cc

Go to the documentation of this file.
00001 ///
00002 ///
00003 #include <queue>
00004 #include <algorithm>
00005 
00006 #include "EvolutionGraph.h"
00007 #include "eg_utils.h"
00008 #include "utilities/stmt_util.h"
00009 #include "ip_ssa/prog_info.h"
00010 #include "ip_ssa/trans_util.h"
00011 #include "ip_ssa/ip_ssa.h"
00012 #include "ip_ssa/optimize_ssa.h"
00013 #include "BackTrace.h"
00014 
00015 
00016 ////////////////////////////////////////////////////////////////////////////
00017 /// BEGIN local constants and simple defs.
00018 ////////////////////////////////////////////////////////////////////////////
00019 static Symbol* ZERO=0;
00020 
00021 inline const char* node_name(const Symbol* s){
00022   if (s){
00023     return s->name_ref();
00024   } else {
00025     return "ZERO";
00026   }
00027 }
00028 
00029 inline Expression* node_value(const Symbol* s){
00030   if (s){
00031     return id(*s);
00032   } else {
00033     return constant(0);
00034   }
00035 }
00036 
00037 inline String loop_name(Statement* loop){
00038   if (loop){
00039     String l=loop->get_loop_name();
00040     for(int i=0; i<l.len(); i++){
00041       if (l[i]=='#'){
00042     l[i]='_';
00043       }
00044     }
00045     return l;
00046   } else {
00047     return String("ROOT");
00048   }
00049 }
00050 
00051 /// Find the incoming value for given mu symbol.
00052 static void get_imu(const Symbol& mu, ProgramUnit& pgm, 
00053             Symbol*& imu, bool& is_defined){
00054   imu=0;
00055   is_defined=false;
00056   DefLoc* defloc=pgm.gsa_deflocs_guarded().find_ref(mu);
00057   if (!defloc->stmt_valid()) {
00058     cerr<<"\nFor MU sym. "<<mu.name_ref();
00059     p_abort("Cannot find MU definition site.");
00060   }
00061   Statement& def=defloc->stmt_guarded();
00062   if (def.stmt_class()==ASSIGNMENT_STMT){
00063     imu=&def.rhs().parameters_guarded().arg_list()[0].symbol();
00064     if (gsa_base(*imu)!=imu){
00065       is_defined=true;
00066     } else {
00067       /// ...  Formals and commons may be defined for subprograms other
00068       /// ...  than the main one.
00069       /// ...  silvius: We assume here that the 'remove_data_statements' filter
00070       /// ...  was run previously.
00071       if (find_main_pgm(program())!=&pgm){
00072     if (imu->formal() || imu->common_ref()){
00073       is_defined=true;
00074     }
00075       }
00076     }
00077   }
00078 }
00079 
00080 ////////////////////////////////////////////////////////////////////////////
00081 /// END local constants and simple defs.
00082 ////////////////////////////////////////////////////////////////////////////
00083 
00084 
00085 
00086 ////////////////////////////////////////////////////////////////////////////
00087 /// BEGIN EG repository management.
00088 ////////////////////////////////////////////////////////////////////////////
00089 static map<ProgramUnit*, 
00090        map<Statement*,
00091            EvolutionGraph*> > _egs;
00092 
00093 static void _add_eg(ProgramUnit* pgm, Statement* loop, EvolutionGraph* eg){
00094   EvolutionGraph*& current=_egs[pgm][loop];
00095   if (current){
00096     delete current;
00097   }
00098   current=eg;
00099 }
00100 
00101 static void _remove_eg(ProgramUnit* pgm, Statement* loop){
00102   map<ProgramUnit*, map<Statement*,EvolutionGraph*> >::iterator found_pgm=
00103     _egs.find(pgm);
00104   if (found_pgm!=_egs.end()){
00105     map<Statement*,EvolutionGraph*>::iterator found_loop=
00106       (*found_pgm).second.find(loop);
00107     if (found_loop!=(*found_pgm).second.end()){
00108       delete (*found_loop).second;
00109       (*found_pgm).second.erase(found_loop);
00110     }
00111   }
00112 }
00113 
00114 static void _remove_egs(ProgramUnit* pgm){
00115   if (pgm==0){
00116     /// ...  Remove all.
00117     map<ProgramUnit*, map<Statement*,EvolutionGraph*> >::iterator found_pgm=
00118       _egs.begin();
00119     for(; found_pgm!=_egs.end(); ++found_pgm){
00120       map<Statement*,EvolutionGraph*>::iterator found_loop=
00121     (*found_pgm).second.begin();
00122       for(; found_loop!=(*found_pgm).second.end(); ++found_loop){
00123     delete (*found_loop).second;
00124       }
00125     }
00126     _egs.clear();
00127   } else {
00128     map<ProgramUnit*, map<Statement*,EvolutionGraph*> >::iterator found_pgm=
00129       _egs.find(pgm);
00130     if (found_pgm!=_egs.end()){
00131       map<Statement*,EvolutionGraph*>::iterator found_loop=
00132     (*found_pgm).second.begin();      
00133       for(; found_loop!=(*found_pgm).second.end(); ++found_loop){
00134     delete (*found_loop).second;
00135       }
00136       _egs.erase(found_pgm);
00137     }
00138   }
00139 }
00140 
00141 void remove_egs(ProgramUnit& pgm){
00142   _remove_egs(&pgm);
00143 }
00144 
00145 EvolutionGraph* _get_eg(ProgramUnit* pgm, Statement* loop){
00146   map<ProgramUnit*, map<Statement*,EvolutionGraph*> >::iterator found_pgm=
00147     _egs.find(pgm);
00148   if (found_pgm!=_egs.end()){
00149     map<Statement*,EvolutionGraph*>::iterator found_loop=
00150       (*found_pgm).second.find(loop);
00151     if (found_loop!=(*found_pgm).second.end()){
00152       EvolutionGraph* toret=(*found_loop).second;
00153       p_assert(toret, "'_get_eg' failed.");
00154       return toret;
00155     } else {
00156       p_assert(pgm, "Null pgm pointer.");
00157       EvolutionGraph* veg=new EvolutionGraph(*pgm, loop);
00158       EvolutionGraph* toret=_egs[pgm][loop]=veg;
00159       p_assert(toret, "'_get_eg' failed.");
00160       return toret;
00161     }
00162   } else {
00163     p_assert(pgm, "Null pgm pointer.");
00164     EvolutionGraph* veg=new EvolutionGraph(*pgm, loop);
00165     EvolutionGraph* toret=_egs[pgm][loop]=veg;
00166     p_assert(toret, "'_get_eg' failed.");
00167     return toret;
00168   }
00169 }
00170 
00171 ////////////////////////////////////////////////////////////////////////////
00172 /// END EG repository management.
00173 ////////////////////////////////////////////////////////////////////////////
00174 
00175 
00176 
00177 
00178 
00179 
00180 
00181 
00182 
00183 
00184 //////////////////////////////////////////////////////////////////////////
00185 /// BEGIN Shortest path computation.
00186 //////////////////////////////////////////////////////////////////////////
00187 bool EvolutionGraph::_relax(unsigned int nleft, unsigned int nright, 
00188                 const EdgeType& ev, RELAX_OP op, 
00189                 vector<Expression*>& best_path){
00190 /// First check whether there is a path to nleft.  Otherwise we will not
00191 /// perform the relaxation in order to avoid operations like (-Inf + Inf).
00192   Expression* best_left=best_path[nleft];
00193   Expression* best_right=best_path[nright];
00194   if (best_left->op()==INFINITY_OP){
00195     if (op==MAX_OP && best_left->sign()==-1){
00196       return false;
00197     }
00198     if (op==MIN_OP && best_left->sign()==1){
00199       return false;
00200     }
00201   }
00202 
00203 
00204 /// Get range information.
00205   const Symbol& sym=*nodes()[nright];
00206   Statement* stmt=0;
00207   DefLoc* defloc=_pgm->gsa_deflocs_guarded().find_ref(sym);
00208   if (defloc){
00209     if (defloc->stmt_valid()){
00210       Statement& def=defloc->stmt_guarded();
00211       if (def.stmt_class()==DO_STMT){
00212     stmt=&def;
00213       }
00214     }
00215   }
00216   if (!stmt){
00217     stmt=_pgm->stmts().last_ref();
00218   }
00219   RangeAccessor ra(_pgm->range_dict_guarded(), *range_stmt(*stmt));
00220 
00221 /// At this time we have best_left, best_right, and weight.
00222   bool has_relaxed=false;     /// ...  Path through nleft is better.
00223   bool has_not_relaxed=false; /// ...  Previous path is better.
00224 /// has_relaxed==false && has_not_relaxed==false => cannot compare.
00225   Expression* path_with_edge=0;
00226   Expression* conservative_best=0;
00227   switch(op){
00228   case MIN_OP: 
00229     path_with_edge=simplify(add(best_left->clone(), 
00230                 ev.min_difference()->clone()));
00231     has_relaxed=::p_less_than(*path_with_edge, *best_right, &ra);
00232     if (!has_relaxed){
00233       has_not_relaxed=::p_less_equal(*best_right, *path_with_edge, &ra);
00234     }
00235     break;
00236   case MAX_OP: 
00237     path_with_edge=simplify(add(best_left->clone(), 
00238                 ev.max_difference()->clone()));
00239     has_relaxed=::p_greater_than(*path_with_edge, *best_right, &ra);
00240     if (!has_relaxed){
00241       has_not_relaxed=::p_greater_equal(*best_right, *path_with_edge, &ra);
00242     }
00243     break;
00244   default:
00245     p_abort("Unknown operator in relaxation.");
00246   }
00247   if (has_relaxed){
00248     /// ...  Did relax.
00249     delete best_path[nright];
00250     best_path[nright]=path_with_edge;
00251     return true;
00252   } else {
00253     if (has_not_relaxed){
00254       /// ...  Did not relax.
00255       delete path_with_edge;
00256       return false;
00257     } else {
00258       /// ...  We cannot tell which is shorter, will take the best.
00259       conservative_best=make_best(*best_right, *path_with_edge, op, *_pgm);
00260       delete path_with_edge;
00261       delete best_path[nright];
00262       best_path[nright]=conservative_best;
00263       return true;
00264     }
00265   }
00266 }
00267 
00268 void EvolutionGraph::_bellman_ford(unsigned int source,
00269                    vector<Evolution<Expression> >& best,
00270                    vector<unsigned int>& topsorted,
00271                    bool forward){
00272 /// Clear result list just in case.
00273   best.clear();
00274 
00275 /// Initialize shortest/longest path for every destination node.
00276   vector<Expression*> shortest_path(nodes().size(), 0);
00277   vector<Expression*> longest_path(nodes().size(), 0);
00278   for(unsigned int cn=0; cn!=nodes().size(); ++cn){
00279     if (cn==source){
00280       shortest_path[cn]=constant(0);
00281       longest_path[cn]=constant(0);
00282     } else {
00283       shortest_path[cn]=infinity();
00284       longest_path[cn]=infinity(-1);
00285     }
00286   }
00287 
00288 /// Now chew it up.
00289   for (unsigned int i=0; i<topsorted.size(); ++i){
00290     unsigned int ifirst=topsorted[i];
00291     const EdgeList* pedges;
00292     if (forward){
00293       pedges=&get_edges(ifirst);
00294     } else {
00295       pedges=&get_reversed_edges(ifirst);
00296     }
00297     /// ...  For each incident edge.
00298     for (EdgeList::const_iterator cit=pedges->begin(); 
00299      cit!=pedges->end(); ++cit){
00300       unsigned int isecond=(*cit).first;
00301       /// ...  Relaxation.
00302       _relax(ifirst, isecond, (*cit).second, MIN_OP, shortest_path);
00303       _relax(ifirst, isecond, (*cit).second, MAX_OP, longest_path);
00304     }
00305   }
00306 
00307 /// Save result.
00308   for (unsigned int i=0; i<topsorted.size(); ++i){
00309     best.push_back(evolution(shortest_path[i], longest_path[i]));
00310   }
00311 
00312 /// Sanity check.
00313   p_assert(best.size()==nodes().size(), "Wrong output from bellman_ford.");
00314 }
00315 //////////////////////////////////////////////////////////////////////////
00316 /// END Shortest path computation.
00317 //////////////////////////////////////////////////////////////////////////
00318 
00319 
00320 
00321 
00322 //////////////////////////////////////////////////////////////////////////
00323 /// BEGIN Topology Information and Transformation.
00324 //////////////////////////////////////////////////////////////////////////
00325 bool EvolutionGraph::_back_edge(const Symbol* left, const Symbol* right){
00326 /// Check for loop index.
00327   if (_loop){
00328     if (left==right){
00329       if (left==&_loop->index().symbol()){
00330     return true;
00331       }
00332     }
00333   }
00334 
00335 /// General.
00336   map<const Symbol*, const Symbol*>::iterator beit=_back_edges.find(left);
00337   if (beit!=_back_edges.end()){
00338     if ((*beit).second==right){
00339       return true;
00340     }
00341   }
00342   return false;
00343 }
00344 
00345 
00346 void EvolutionGraph::_topsort(vector<unsigned int>& topsorted, bool forward){
00347   topsorted.clear();
00348 /// First compute the in-degrees for every node.
00349   map<unsigned int, unsigned int> indegrees;
00350   for (unsigned int left=0; left<nodes().size(); ++left){
00351     indegrees.insert(make_pair(left, 0));
00352   }
00353   for (unsigned int left=0; left<nodes().size(); ++left){
00354     const EdgeList* pedges;
00355     if (forward){
00356       pedges=&get_edges(left);
00357     } else {
00358       pedges=&get_reversed_edges(left);      
00359     }
00360     /// ...  For each outgoing edge.
00361     for (EdgeList::const_iterator cit=pedges->begin(); 
00362      cit!=pedges->end(); ++cit){
00363       unsigned int right=(*cit).first;
00364       if (forward){
00365     if (_back_edge(nodes()[left], nodes()[right])){
00366       // Skip back edge.
00367       continue;
00368     }
00369       } else {
00370     if (_back_edge(nodes()[right], nodes()[left])){
00371       // Skip back edge.
00372       continue;
00373     }
00374       }
00375       indegrees[right]++;
00376     }
00377   }
00378   
00379 /// Now start at root nodes and add nodes to 'topsort' as they are available.
00380 /// Use indegrees as consumable dependency DAG.
00381   queue<unsigned int> ready;
00382   for (unsigned int left=0; left<nodes().size(); ++left){
00383     if(indegrees[left]==0){
00384       ready.push(left);
00385     }
00386   }
00387   while (ready.size()>0){
00388     unsigned int left=ready.front();
00389     topsorted.push_back(left);
00390     ready.pop();
00391     const EdgeList* pedges;
00392     if (forward){
00393       pedges=&get_edges(left);
00394     } else {
00395       pedges=&get_reversed_edges(left);      
00396     }
00397     /// ...  For each outgoing edge.
00398     for (EdgeList::const_iterator cit=pedges->begin(); 
00399      cit!=pedges->end(); ++cit){
00400       unsigned int right=(*cit).first;
00401       if (forward){
00402     if (_back_edge(nodes()[left], nodes()[right])){
00403       // Skip back edge.
00404       continue;
00405     }
00406       } else {
00407     if (_back_edge(nodes()[right], nodes()[left])){
00408       // Skip back edge.
00409       continue;
00410     }
00411       }
00412 
00413       (*indegrees.find(right)).second--;
00414       if ((*indegrees.find(right)).second==0){
00415     ready.push(right);
00416       }
00417     }
00418   }
00419 
00420 /// Sanity check.
00421   if(topsorted.size()!=nodes().size()){
00422     p_abort("Error in topsort.");
00423   }
00424 }
00425 
00426 
00427 static void print_evolutions(map<const Symbol*, 
00428                  map<const Symbol*, Evolution<Expression> > >& evs,
00429                  const char* type, ostream& o){
00430   o<<"\n\nEvolutions ("<<type<<"):";
00431   map<const Symbol*, map<const Symbol*, Evolution<Expression> > >::iterator
00432     allit;
00433   for(allit=evs.begin(); allit!=evs.end(); ++allit){
00434     o<<"\n\tDestination = "<<node_name((*allit).first);
00435     map<const Symbol*, Evolution<Expression> >::iterator it;
00436     for(it=(*allit).second.begin(); it!=(*allit).second.end(); ++it){
00437       o<<"\n\t\tSource = "<<node_name((*it).first)
00438        <<", Evolution =  "<<(*it).second;
00439     }
00440   }
00441 }
00442 
00443 static void print_input_values(map<const Symbol*, Evolution<Expression> >& ivs,
00444                    const char* type, ostream& o){
00445   o<<"\n\nInput values ("<<type<<"):";
00446   map<const Symbol*, Evolution<Expression> >::iterator allit;
00447   for(allit=ivs.begin(); allit!=ivs.end(); ++allit){
00448     o<<"\n\tDestination = "<<node_name((*allit).first)
00449      <<", Value =  "<<(*allit).second;
00450   }
00451 }
00452 
00453 
00454 Expression* _eg_forward_substitute(EvolutionGraph* eg, 
00455                    ProgramUnit& pgm, DoStmt* loop,
00456                    Expression* expr){
00457   RefList<Symbol> syms;
00458   referred_symbols(*expr, syms);
00459   for(Iterator<Symbol> sit=syms; sit.valid(); ++sit){
00460     Symbol& sym=sit.current();
00461     Expression* s=eg->substitute(&sym);
00462     if (s){
00463       expr=simplify(substitute_var(expr, sym, *s));
00464       delete s;
00465     }
00466   }
00467   return expr;
00468 }
00469 
00470 
00471 static void remove_source(EvolutionGraph::EvolutionMap& em, Symbol* source){
00472   EvolutionGraph::EvolutionMap::iterator it;
00473   vector<EvolutionGraph::EvolutionMap::iterator> todel;
00474   for(it=em.begin(); it!=em.end(); ++it){
00475     map<const Symbol*, Evolution<Expression> >::iterator found=
00476       (*it).second.find(source);
00477     if (found!=(*it).second.end()){
00478       (*it).second.erase(found);
00479     }
00480     if ((*it).second.size()==0){
00481       /// ...  Erased them all.
00482       todel.push_back(it);
00483     }
00484   }
00485   for(vector<EvolutionGraph::EvolutionMap::iterator>::iterator 
00486     vit=todel.begin(); vit!=todel.end(); ++vit){
00487     em.erase(*vit);
00488   }
00489 }
00490 
00491 /*!
00492   \brief Add approximations for evolutions of this type:
00493   var1 = var2 + var3
00494   
00495   At this point, we have set the value of var1 as [-Inf:Inf].
00496   In case we know the range for var3, add an evolution from
00497   var2 to var1 with value range(var3).
00498   Same goes for when we know the range of the expression (var2 + var3).
00499 */
00500 bool EvolutionGraph::_add_approximations(){
00501 ///   if (_loop){
00502 ///     cerr<<"\nEnter add_approx for "<<loop_name(_loop);
00503 ///   }
00504   bool toret=false;
00505   Statement* first=0;
00506   Statement* last=0;
00507   if (_loop){
00508     first=_loop->next_ref();
00509     last=_loop->follow_ref();
00510   } else {
00511     first=_pgm->stmts().first_ref();
00512     last=_pgm->stmts().last_ref();
00513   }
00514 
00515   for(Statement* stit=first; stit!=last; stit=stit->next_ref()){
00516     if (stit->stmt_class()!=ASSIGNMENT_STMT) {
00517       if (stit->stmt_class()==DO_STMT ||
00518       stit->stmt_class()==WHILE_STMT){
00519     stit=stit->follow_ref();
00520       } else {
00521     if (stit->stmt_class()==IF_STMT){
00522       stit=stit->matching_endif_ref();
00523     }
00524       }
00525       continue;
00526     }
00527     if (stit->lhs().op()!=ID_OP) continue;
00528     if (stit->lhs().type().data_type()!=INTEGER_TYPE) continue;
00529     if (stit->rhs().op()!=ADD_OP) continue;
00530     Symbol* to=&stit->lhs().symbol();
00531       List<Expression>& args=stit->rhs().arg_list();
00532     if (args.first_ref()->op()==ID_OP &&
00533     args.last_ref()->op()==ID_OP){
00534 ///       cerr<<"\n\nrhs: "<<stit->rhs();
00535 ///       cerr<<"\n\tto = "<<to->name_ref();
00536       /// ...  They are both loop variants.  Will pick one that we can get a 
00537       /// ...  range for and replace it with the range.
00538       const Symbol& first=args.first_ref()->symbol();
00539       const Symbol& second=args.last_ref()->symbol();
00540       /// ...  Since we have not built the VEG yet, the best chance is that
00541       /// ...  one of them is produced in a subroutine or inner loop.
00542 
00543       Expression* lr=0;
00544       if (contains((Symbol*)&first) &&
00545       contains((Symbol*)&second)){
00546 
00547     /// ...  They are both defined here.
00548     /// ...  Get range for 'second'.
00549     lr=_local_range(second);
00550 ///     cerr<<"\n\tlr = "<<*lr;
00551 
00552     /// ...  Make sure it is nontrivial.
00553     if (lr->op()==RANGE_OP){
00554       if (((RangeExpr*)lr)->lb().op()==INFINITY_OP &&
00555           ((RangeExpr*)lr)->ub().op()==INFINITY_OP){
00556         delete lr;
00557         continue;
00558       }
00559     }
00560 
00561 
00562     /// ...  Remove the input value of [-Inf:Inf] from 'to'.
00563     map<const Symbol*, Evolution<Expression> >::iterator found=
00564       _input_values.find(to);
00565     if (found!=_input_values.end()){
00566       Evolution<Expression> ev=(*found).second; 
00567       if (ev.min_difference()->op()!=INFINITY_OP ||
00568           ev.max_difference()->op()!=INFINITY_OP){
00569         p_abort("Bad logic.");
00570       } else {
00571         /// ...  OK, add it.
00572 ///         cerr<<"\n\tAdding evolution "<<*lr<<" from "<<first.name_ref()
00573 ///         <<" to "<<to->name_ref();
00574         _add_evolution(&first, to, evolution(lr));
00575 ///         cerr<<"\n\tErased iv.";
00576         _input_values.erase(found);
00577         input_this_loop.erase(index(to));
00578         toret=true;
00579       }
00580     } else {
00581       // We must have seen it in a previous iteration of 
00582       // compute_acyclic + add_approximations.
00583       
00584     }
00585       }
00586     } else {
00587       /// ...  Look for var1 = var2 + (-1)*var3
00588       if (args.first_ref()->op()==ID_OP &&
00589       args.last_ref()->op()==MULT_OP){
00590     List<Expression>& args3=args.last_ref()->arg_list();
00591     if (args3.entries()==2){
00592       if (args3.first_ref()->op()==INTEGER_CONSTANT_OP){
00593         if (args3.first_ref()->value()==-1){
00594           Expression* e1=_eg_forward_substitute(this, *_pgm, (DoStmt*)_loop,
00595                             args.first_ref()->clone());
00596           Expression* e2=_eg_forward_substitute(this, *_pgm, (DoStmt*)_loop,
00597                             args3.last_ref()->clone());
00598           if (e1->op()==ID_OP &&
00599           e2->op()==ID_OP){
00600         /// ...  See if we can find the minimum distance between them.
00601         unsigned int source=index(&e1->symbol());
00602         vector<Evolution<Expression> > evs;
00603         vector<unsigned int> topsorted;
00604         _topsort(topsorted, true);
00605         _bellman_ford(source, evs, topsorted, true);
00606         Evolution<Expression>& ev=evs[index(&e2->symbol())];
00607         delete e1;
00608         delete e2;
00609         EXPR_SIGN s=_ra->sign(*ev.min_difference());
00610         if (s==POS_EXPR){
00611 ///           cerr<<"\n\tBINGO.";
00612           map<const Symbol*, Evolution<Expression> >::iterator found=
00613             _input_values.find(to);
00614           if (found!=_input_values.end()){
00615             Evolution<Expression> ev=(*found).second; 
00616             if (ev.min_difference()->op()==INFINITY_OP ||
00617             ev.max_difference()->op()==INFINITY_OP){
00618               _input_values[to]=evolution(constant(0), infinity());
00619               toret=true;
00620             }
00621           }
00622         }
00623           }
00624         }
00625       }
00626     }
00627       }
00628     }
00629   }
00630   return toret;
00631 }
00632 
00633 
00634 
00635 void EvolutionGraph::_build(){
00636 ///   cerr<<"\nGenerating EG for "<<_pgm->routine_name_ref()
00637 ///       <<" and loop "<<loop_name(_loop);
00638 ///   _pgm->write(cerr);
00639 /// Mark domain.
00640   Statement* first=0;
00641   Statement* last=0;
00642   if (_loop){
00643     first=_loop->next_ref();
00644     last=_loop->follow_ref();
00645   } else {
00646     first=_pgm->stmts().first_ref();
00647     last=_pgm->stmts().last_ref();
00648   }
00649 
00650 /// Add nodes.
00651 /// Add integer scalars and arrays only.
00652   if (_loop){
00653     Symbol* ind=&_loop->index().symbol();
00654     add_node(ind);
00655   }
00656 
00657   Statement* stit=first;  
00658   while(stit!=0 && stit!=last){
00659     if (stit->stmt_class()==ASSIGNMENT_STMT){
00660       if (stit->rhs().op()==FUNCTION_CALL_OP){
00661     Symbol* sym=stit->lhs().base_variable_ref();
00662     if (sym->is_scalar()){
00663       if (sym->type().data_type()==INTEGER_TYPE){
00664         add_node(sym);
00665       }
00666     }
00667       }
00668     }
00669     if (stit->stmt_class()==DO_STMT){
00670       /// ...  Add only MU values for inner DO stmts.
00671       add_node(&stit->index().symbol());
00672       Statement* mudef=stit->next_ref();
00673       while (mudef){
00674     if (mudef->stmt_class()!=ASSIGNMENT_STMT){
00675       break;
00676     }
00677     if (mudef->rhs().op()!=MU_OP){
00678       break;
00679     }
00680     Symbol* sym=&mudef->lhs().symbol();
00681     if (sym->is_scalar()){
00682       if (sym->type().data_type()==INTEGER_TYPE){
00683         add_node(sym);
00684       }
00685     }
00686     mudef=mudef->next_ref();
00687       }
00688       stit=stit->follow_ref()->next_ref();
00689     } else {
00690 ///       cerr<<"\nAt statement: "<<*stit;
00691       for(Iterator<Expression> eit=stit->out_refs(); eit.valid(); ++eit){
00692     Symbol* sym=eit.current().base_variable_ref();
00693     if (sym){
00694       if (sym->is_scalar()){
00695         if (sym->type().data_type()==INTEGER_TYPE){
00696           /// ...  If this is a call site, do not add the ones that will not
00697           /// ...  be modified based on MAYMODs.
00698           if (has_maymod(*stit)){
00699         if (!is_var_in_maymod(*gsa_base(*sym), *stit)){
00700           /// ...  Not modified.
00701           continue;
00702         }
00703           }
00704 ///           cerr<<"\n\tAdding "<<node_name(sym);
00705           add_node(sym);
00706         }
00707       }
00708     }
00709       }
00710       stit=stit->next_ref();
00711     }
00712   }
00713 /// If it is the whole program unit, add base gsa symbols for all commons
00714 /// and formals that may be defined in this subprogram.
00715 /// silvius: actually, add them all even if they are not defined because
00716 /// they may carry values in.
00717   if (_loop==0){
00718     for(DictionaryIter<Symbol> sit=_pgm->symtab().iterator();
00719     sit.valid(); ++sit){
00720       Symbol* base=gsa_base(sit.current());
00721       if (base){
00722     if (base->formal() || base->common_ref()){
00723       if (base->is_scalar() && 
00724           base->type().data_type()==INTEGER_TYPE){
00725         add_node(base);
00726       }
00727     }
00728       }
00729     }
00730   }
00731 
00732 /// Set mu nodes.
00733   if (_loop){
00734     /// ...  Find MU nodes defined in this loop.
00735     for(vector<Symbol*>::const_iterator it=nodes().begin();
00736     it!=nodes().end(); ++it){
00737       if (loop(**it, *_pgm)==_loop){
00738     unsigned int imu=index((Symbol*)*it);
00739     mu_this_loop.insert(imu);
00740       }
00741     }
00742   } else {
00743 ///     cerr<<"\n\nIn routine "<<_pgm->routine_name_ref();
00744     /// ...  Set as MU all symbols that may carry a definition outside the routine.
00745     for(vector<Symbol*>::const_iterator it=nodes().begin();
00746     it!=nodes().end(); ++it){
00747       if ((*it)->formal() || (*it)->common_ref()){
00748     if (gsa_base(**it)==*it){
00749 ///       cerr<<"\n\tAdding mu node "<<(*it)->name_ref();
00750       unsigned int imu=index((Symbol*)gsa_base(**it));
00751 ///       cerr<<" with index value "<<imu;
00752       mu_this_loop.insert(imu);
00753     }
00754       }
00755     }
00756   }
00757 
00758 /// Add back edges.
00759   if (_loop){
00760     Symbol* ind=&_loop->index().symbol();
00761     _back_edges.insert(make_pair(ind, ind));
00762     _back_edges_reversed.insert(make_pair(ind, ind));
00763     back_this_loop.insert(index(ind));
00764     for(Statement* ps=first; ps && ps!=last; ps=ps->next_ref()){
00765       if (ps->stmt_class()!=ASSIGNMENT_STMT) break;
00766       if (ps->rhs().op()!=MU_OP) break;
00767       if (ps->lhs().type().data_type()!=INTEGER_TYPE) continue;
00768       if (!ps->lhs().symbol().is_scalar()) continue;
00769       Symbol* to=&ps->lhs().symbol();
00770       Symbol& besym=ps->rhs().parameters_guarded().arg_list()[1].symbol();
00771       _back_edges.insert(make_pair(&besym, to));
00772       _back_edges_reversed.insert(make_pair(to, &besym));
00773       unsigned int back=index(&besym);
00774       back_this_loop.insert(back);
00775     }
00776   } else {
00777     for(set<unsigned int>::iterator def_it=mu_this_loop.begin();
00778     def_it!=mu_this_loop.end(); ++def_it){
00779       unsigned int incoming=*def_it;
00780       Symbol* outgoing_sym=last_gsa_symbol(*_pgm, *nodes()[incoming]);
00781       if (outgoing_sym){
00782 ///     cerr<<"\n\tAdding back edge from ";
00783 ///     cerr<<node_name(outgoing_sym)<<" to ";
00784 ///     cerr<<node_name(nodes()[incoming])<<endl;
00785     unsigned int outgoing=index(outgoing_sym);
00786     _back_edges.insert(make_pair(outgoing_sym, nodes()[incoming]));
00787     _back_edges_reversed.insert(make_pair(nodes()[incoming], 
00788                           outgoing_sym));
00789     back_this_loop.insert(outgoing);
00790 ///       cerr<<"\n\tAdding back node "<<outgoing_sym->name_ref();
00791       }
00792     }
00793   }
00794 
00795 /// Add evolutions.
00796   _add_evolutions(*first, *last);
00797 
00798 /// Store indices of all nodes.
00799   for(vector<Symbol*>::const_iterator it=nodes().begin();
00800       it!=nodes().end(); ++it){
00801     unsigned int ind=index((Symbol*)*it);
00802     nodes_this_loop.insert(ind);
00803   }
00804 
00805 /// Set as input all nodes that have an input value AND are not MU.
00806   for(vector<Symbol*>::const_iterator it=nodes().begin();
00807       it!=nodes().end(); ++it){
00808     if (_input_values.find(*it)!=_input_values.end()){
00809       unsigned int iin=index((Symbol*)*it); 
00810       if (mu_this_loop.find(iin)==mu_this_loop.end()){
00811     input_this_loop.insert(iin);
00812       }
00813     }
00814   }
00815 
00816 
00817   do {
00818     /// ...  Compute evolutions.
00819     _compute_acyclic_evolutions();
00820     
00821     /// ...  Add approximations.
00822     if (!_add_approximations()){
00823       break;
00824     } else {
00825       /// ...  We have to recompute.
00826       _mu_evolutions.clear();
00827       _evolutions_from_mu.clear();
00828       _input2mu_evolutions.clear();
00829       _evolutions_from_input.clear();
00830       _evolutions_to_mu.clear();
00831     }
00832   } while(1);
00833 
00834 /// Draw the graph.
00835   String cmd="mkdir -p ./.polaris/pgm_sources/";
00836   system(cmd);
00837   String gname=".polaris/pgm_sources/";
00838   if (_loop){
00839     gname+=_loop->get_loop_name();
00840   } else {
00841     gname+=_pgm->routine_name_ref();
00842   }
00843   gname+=".dot";
00844   print_graph(gname);
00845 
00846 }
00847 
00848 
00849 void EvolutionGraph::_add_evolutions(const Expression& rhs, const Symbol* to){
00850 /// If rhs is loop invariant, then no evolution is added, but the node must
00851 /// be marked as input.
00852   if (_loop){
00853     if (_loop_invariant(rhs)){
00854 ///       cerr<<"\n1. in loop "<<loop_name(_loop)
00855 ///       <<", set input value for "<<to->name_ref()<<" to "<<rhs;
00856       _input_values[to]=evolution(rhs);
00857       return;
00858     }
00859   } else {
00860     if (rhs.op()==INTEGER_CONSTANT_OP){
00861       _input_values[to]=evolution(rhs);
00862       return;
00863     }
00864   }
00865   
00866 
00867 
00868 /// If rhs contains any loop variants that are not scalar integers, then
00869 /// this node is marked as input with an initial value of Infinity.
00870   if (rhs.op()!=MU_OP &&
00871       rhs.op()!=GAMMA_OP &&
00872       rhs.op()!=ETA_OP &&
00873       rhs.op()!=THETA_OP){
00874     if (_contains_unknown_variants(rhs)){
00875       _input_values[to]=evolution();
00876 ///       cerr<<"\n\tIS UNKNOWN";
00877       return;
00878     }
00879   }
00880 
00881 /// When it gets here:
00882 /// 1. All symbols in rhs are either loop invariant or evgraph nodes.
00883 /// 2. There is at least an evgraph node in rhs.
00884   const Symbol* from=ZERO;
00885   switch(rhs.op()){
00886   case ID_OP:
00887     /// ...  Check for special case: x = i
00888     if (_loop){
00889       if (&rhs.symbol()==&_loop->index().symbol()){
00890     /// ...  silvius: assume the loop has been normalized.
00891 ///     _input_values[to]=evolution(_loop->init(), _loop->limit());
00892     _add_evolution(&_loop->index().symbol(), to, evolution(0));
00893     break;
00894       }
00895     }
00896     /// ...  0 edge.
00897     from=&rhs.symbol();
00898 ///     cerr<<"\n to = "<<to->name_ref()<<", rhs = "<<rhs;
00899     _add_evolution(from, to, evolution(0));
00900     break;
00901   case MU_OP: 
00902     /// ...  Skip back edge.  Input value is considered only when we compute
00903     /// ...  the aggregated cyclic evolutions.
00904     break;
00905   case ETA_OP:
00906 ///     cerr<<"\neta gate: "<<rhs;
00907     if (is_true(rhs.gate())){
00908       _add_evolution(&rhs.parameters_guarded().arg_list()[0].symbol(), 
00909              to, evolution(0));
00910       break;
00911     } else {
00912       if (is_logical_false(rhs.gate())){
00913     _add_evolution(&rhs.parameters_guarded().arg_list()[1].symbol(), 
00914                to, evolution(0));
00915       } else {
00916     /// ...  Let it be treated as a regular PHI node.
00917       }
00918     }
00919   case GAMMA_OP:
00920   case THETA_OP:
00921     {
00922       /// ...  0 edges.
00923       RefList<Symbol> entries;
00924       get_phinode_entries(rhs, entries);
00925 ///       cerr<<"\n\tto = "<<node_name(to)
00926 ///       <<", rhs = "<<rhs
00927 ///       <<", phi entries = "<<entries;
00928       Iterator<Symbol> sit=entries;
00929       for( ; sit.valid(); ++sit){
00930 ///     if (gsa_base(sit.current())!=&sit.current()){
00931       _add_evolution(&sit.current(), to, evolution(0));
00932 ///     }
00933       }
00934       break;
00935     }
00936   case ADD_OP:
00937     {
00938       const List<Expression>& args=rhs.arg_list();
00939       if (args.entries()==2){
00940     if (args.first_ref()->op()==ID_OP &&
00941         args.last_ref()->op()==INTEGER_CONSTANT_OP){
00942       from=&args.first_ref()->symbol();
00943       int add_offset=args.last_ref()->value();
00944       _add_evolution(from, to, evolution(add_offset));
00945       break;
00946     }
00947     if (args.last_ref()->op()==ID_OP &&
00948         args.first_ref()->op()==INTEGER_CONSTANT_OP){
00949       from=&args.last_ref()->symbol();
00950       int add_offset=args.first_ref()->value();
00951       _add_evolution(from, to, evolution(add_offset));
00952       break;
00953     }
00954     /// ...  For x = y + exp, add y -> x.
00955     if (args.first_ref()->op()==ID_OP){
00956       from=&args.first_ref()->symbol();
00957       if (contains((Symbol*)from)){
00958         if (_loop){
00959           if (_loop_invariant(*args.last_ref())){
00960         _add_evolution(from, to, evolution(*args.last_ref()));
00961         break;
00962           }
00963         } else {
00964           if (args.last_ref()->op()==INTEGER_CONSTANT_OP){
00965         _add_evolution(from, to, evolution(*args.last_ref()));
00966         break;
00967           }
00968         }
00969       }
00970     }
00971     if (args.last_ref()->op()==ID_OP){
00972       from=&args.last_ref()->symbol();
00973       if (contains((Symbol*)from)){
00974         if (_loop){
00975           if (_loop_invariant(*args.first_ref())){
00976         _add_evolution(from, to, evolution(*args.first_ref()));
00977         break;
00978           }
00979         } else {
00980           if (args.last_ref()->op()==INTEGER_CONSTANT_OP){
00981         _add_evolution(from, to, evolution(*args.first_ref()));
00982         break;
00983           }
00984         }
00985       }
00986     }
00987       }
00988 
00989       /// ...  If it gets here, we could not analyze it well.
00990 ///       cerr<<"\n2. in loop "<<loop_name(_loop)
00991 ///       <<", set input value for "<<to->name_ref()<<" to "<<rhs;
00992       
00993       _input_values[to]=evolution();
00994       break;
00995     }
00996   case SUB_OP:
00997     {
00998       const List<Expression>& args=rhs.arg_list();
00999       if (args.first_ref()->op()==ID_OP &&
01000       args.last_ref()->op()==INTEGER_CONSTANT_OP){
01001     from=&args.first_ref()->symbol();
01002     int add_offset=-args.last_ref()->value();
01003     _add_evolution(from, to, evolution(add_offset));
01004     break;
01005       }
01006       /// ...  For x = y - exp, add y -> x.
01007       if (args.first_ref()->op()==ID_OP){
01008     from=&args.first_ref()->symbol();
01009     if (contains((Symbol*)from)){
01010       if (_loop_invariant(*args.last_ref())){
01011         Expression* neg=simplify(mul(constant(-1),
01012                      args.last_ref()->clone()));
01013         _add_evolution(from, to, evolution(neg));
01014         break;
01015       }
01016     }
01017       }
01018       /// ...  If it gets here, we could not analyze it well.
01019       _input_values[to]=evolution();
01020       break;
01021     }
01022   default:
01023     /// ...  Unknown.
01024     _input_values[to]=evolution();
01025   }
01026 }
01027 
01028 
01029 void EvolutionGraph::_add_evolution(const Symbol* from, 
01030                     const Symbol* to, 
01031                     const Evolution<Expression>& ev){
01032 ///   cerr<<"\nAdd evolution from "<<from->name_ref()
01033 ///       <<" to "<<to->name_ref();
01034   if (!contains((Symbol*)to)){
01035     p_abort("Destination node not in graph.");
01036   }
01037   if (!contains((Symbol*)from)){
01038 ///     cerr<<"\n\n\tBOO!";
01039     return;
01040   }
01041   add_edge((Symbol*)from, (Symbol*)to, ev);
01042 }
01043 
01044 
01045 
01046 bool EvolutionGraph::_loop_invariant(const Expression& expr){
01047   RefList<Symbol> syms;
01048   referred_symbols(expr, syms);
01049   for(Iterator<Symbol> sit=syms; sit.valid(); ++sit){
01050     Symbol& s=sit.current();
01051     if (loop_variant(s, _loop, *_pgm)){
01052       return false;
01053     }
01054   }
01055   return true;
01056 }
01057 
01058 
01059 /// Returns whether given expression contains at least one symbol
01060 /// that is loop variant and is not scalar or is not integer.
01061 bool EvolutionGraph::_contains_unknown_variants(const Expression& expr){
01062   RefList<Symbol> syms;
01063   referred_symbols(expr, syms);
01064   for(Iterator<Symbol> sit=syms; sit.valid(); ++sit){
01065     Symbol& s=sit.current();
01066     bool unknown=false;
01067     if (!s.is_scalar()){
01068       unknown=true;
01069     } else {
01070       if (s.type().data_type()!=INTEGER_TYPE) {
01071     unknown=true;
01072       }
01073     }
01074     if (unknown){
01075       if (_loop){
01076     if (loop_variant(s, _loop, *_pgm)){
01077       return true;
01078     }
01079       } else {
01080     return true;
01081       }
01082     }
01083   }
01084   return false;
01085 }
01086 
01087 
01088 /*!
01089   \brief Add evolutions from inner loop.
01090 */
01091 void EvolutionGraph::_add_evolutions(DoStmt& loop){
01092 /// Get graph for inner loop.
01093   EvolutionGraph* egloop=_get_eg(_pgm, &loop);
01094 
01095 /// Get overall evolutions for the inner loop.
01096   EvolutionMap inner_evs;
01097   map<const Symbol*, Evolution<Expression> > inner_ivs;
01098   egloop->_compute_cyclic_evolutions(inner_evs, inner_ivs);
01099 
01100 ///   cerr<<"\ninner_ivs: ";
01101 ///   print_input_values(inner_ivs, "", cerr);
01102 
01103 /// Copy evolutions to outer domain.
01104   for(EvolutionMap::iterator it=inner_evs.begin(); it!=inner_evs.end(); ++it){
01105     const Symbol* inner_mu_input=(*it).first;
01106     for(map<const Symbol*, Evolution<Expression> >::iterator it2=
01107       (*it).second.begin(); it2!=(*it).second.end(); ++it2){
01108       const Symbol* inner_mu=(*it2).first;
01109       _add_evolution(inner_mu_input, inner_mu, (*it2).second);
01110     }
01111   }
01112 /// Add input relations.
01113   for(map<const Symbol*, Evolution<Expression> >::iterator it=
01114     inner_ivs.begin(); it!=inner_ivs.end(); ++it){
01115     _input_values[(*it).first]=(*it).second;
01116   }
01117 }
01118 
01119 
01120 
01121 
01122 /*!
01123   \brief Add evolutions from given assignment.
01124 */
01125 void EvolutionGraph::_add_evolutions(AssignmentStmt& stmt){
01126   Expression& lhs=stmt.lhs();
01127   Expression& rhs=stmt.rhs();
01128 ///   cerr<<"\n\nlhs="<<lhs<<", rhs="<<rhs;
01129   Symbol* to=0;
01130   if (lhs.op()==ID_OP){
01131     if (lhs.symbol().type().data_type()==INTEGER_TYPE){     
01132       to=&lhs.symbol();
01133     }
01134   }
01135   if (to){
01136     if (to->is_scalar()){
01137       _add_evolutions(rhs, to);
01138     }
01139   }
01140 }
01141 
01142 inline Evolution<Expression> 
01143 get_translated_evolution(Translator& trans,
01144              ProgramUnit& caller,
01145              ProgramUnit& callee,
01146              Statement& callsite,
01147              Evolution<Expression>& original){
01148   Expression* mind=original.min_difference()->clone();
01149   Expression* maxd=original.max_difference()->clone();
01150   if (can_translate(*mind, trans, callee, caller, callsite)){
01151     mind=translate_and_reshape(trans, callee, caller, callsite, mind);
01152   } else {
01153     delete mind;
01154     mind=infinity(-1);
01155   }
01156   if (can_translate(*maxd, trans, callee, caller, callsite)){
01157     maxd=translate_and_reshape(trans, callee, caller, callsite, maxd);
01158   } else {
01159     delete maxd;
01160     maxd=infinity(1);
01161   }
01162   return evolution(mind, maxd);
01163 }
01164 
01165 
01166 /*!
01167   1. There is a path from MU to BACK.   (T/F)
01168   2. There is a path from INPUT to BACK (T/F)
01169 */
01170 void EvolutionGraph::_add_evolutions(Statement& callsite, ProgramUnit& callee){
01171 /// Get graph for called subprogram.
01172   EvolutionGraph* egloop=_get_eg(&callee, 0);
01173 
01174 /// For now, the return value is set to [-Inf:+Inf].
01175   if (callsite.stmt_class()==ASSIGNMENT_STMT){
01176     if (callsite.rhs().op()==FUNCTION_CALL_OP){
01177       Symbol* sym=callsite.lhs().base_variable_ref();
01178       if (sym->is_scalar()){
01179     if (sym->type().data_type()==INTEGER_TYPE){
01180       _input_values[sym]=evolution();
01181     }
01182       }
01183     }
01184   }
01185 
01186 /// silvius: must check here for a particular case: when a scalar integer
01187 /// is passed to a routine that sees it as something else.
01188 /// If so, we need to add unknown evolutions for them.
01189   
01190 /// Forall MU symbols in called routine.
01191   for(set<unsigned int>::iterator muit=egloop->mu_this_loop.begin();
01192       muit!=egloop->mu_this_loop.end(); ++muit){
01193     Symbol* mu=egloop->nodes()[*muit];    
01194 
01195 ///     cerr<<"\n\nMU = "<<node_name(mu);
01196 
01197     /// ...  Find corresponding symbol in caller.
01198     Expression* actual=translate_var((VariableSymbol&)*mu,
01199                      callee, *_pgm, callsite);
01200     Symbol* actualsym=0;
01201     if(actual->op()==ID_OP){
01202       actualsym=&actual->symbol();
01203       if (!actualsym->is_scalar() || 
01204       !actualsym->type().data_type()==INTEGER_TYPE){
01205     actualsym=0;
01206       }    
01207     }
01208     if (actualsym!=0){
01209 ///       cerr<<"\nActual = "<<actualsym->name_ref()
01210 ///       <<" at call site: "<<callsite;
01211     }
01212 ///     if (actualsym==0){
01213 ///       /// ...  This is just an IN argument, cannot carry an evolution.
01214 ///       cerr<<"\nStmt: "<<callsite
01215 ///       <<"\nactual: "<<*actual;
01216 ///     }
01217 
01218     EvolutionMap::iterator found_mu2mu=egloop->_mu_evolutions.find(mu);
01219     if (found_mu2mu!=egloop->_mu_evolutions.end()){
01220       EvolutionMap::data_type::iterator it=(*found_mu2mu).second.begin();
01221       for( ; it!=(*found_mu2mu).second.end(); ++it){
01222     
01223     /// ...  There is a path from incoming((*it).first) to outgoing(mu).
01224     Translator trans(*_pgm, callsite);
01225     Symbol* incoming;
01226     Symbol* outgoing;
01227     if (actualsym==0){
01228       p_abort("Cannot deal with this translation type yet.");
01229     }
01230 ///     cerr<<"\n\n\npgm = "<<_pgm->routine_name_ref();
01231 ///     cerr<<"\ncallsite = "<<callsite;
01232 ///     cerr<<"\nact = "<<*actualsym;
01233     get_out(*_pgm, callsite, *gsa_base(*actualsym), outgoing);
01234     Expression* actual_source=translate_var((VariableSymbol&)*(*it).first,
01235                         callee, *_pgm, callsite);
01236     Symbol* actualsym_source=0;
01237     if(actual_source->op()==ID_OP){
01238       actualsym_source=&actual_source->symbol();
01239       if (!actualsym_source->is_scalar() || 
01240           !actualsym_source->type().data_type()==INTEGER_TYPE){
01241         actualsym_source=0;
01242       }    
01243     }
01244     if (actualsym_source!=0){
01245 ///       cerr<<"\nActual = "<<actualsym->name_ref()
01246 ///           <<" at call site: "<<callsite;
01247     }   
01248     get_in(*_pgm, callsite, *gsa_base(*actualsym_source), incoming);
01249 
01250     _add_evolution(incoming, outgoing, 
01251                get_translated_evolution(trans, *_pgm, callee, callsite,
01252                         (*it).second));
01253       }
01254     }
01255 
01256     EvolutionMap::iterator found_input2mu=
01257       egloop->_input2mu_evolutions.find(mu);
01258     if (found_input2mu!=egloop->_input2mu_evolutions.end()){
01259 ///       print_evolutions(egloop->_input2mu_evolutions, "I2MU", cerr);
01260       /// ...  There is a path from an input node to an outgoing.
01261       Translator trans(*_pgm, callsite);
01262       Symbol* incoming;
01263       Symbol* outgoing;
01264       if (actualsym==0){
01265     p_abort("Cannot deal with this translation type yet.");
01266       }
01267       get_in_out(*_pgm, callsite, *gsa_base(*actualsym), incoming, outgoing);
01268       /// ...  Get first evolution from input.
01269       const Symbol* sym=(*egloop->_input2mu_evolutions[mu].begin()).first;
01270       Evolution<Expression> ivtotal=egloop->_input_values[sym];
01271       ivtotal+=(*egloop->_input2mu_evolutions[mu].begin()).second;
01272       /// ...  Merge it with any other evolutions from other input nodes.
01273       map<const Symbol*, Evolution<Expression> >::iterator iit;
01274       iit=egloop->_input2mu_evolutions[mu].begin();
01275       ++iit;
01276 
01277       for( ; iit!=egloop->_input2mu_evolutions[mu].end(); ++iit){
01278     const Symbol* sym=(*iit).first;
01279     Evolution<Expression> total=egloop->_input_values[sym];
01280     total+=(*iit).second;
01281     ivtotal=merge_unite(ivtotal, total, *_pgm, egloop->_ra);
01282       }
01283       _input_values[outgoing]=
01284     get_translated_evolution(trans, *_pgm, callee, callsite, ivtotal);
01285     }
01286   }
01287 }
01288 
01289 /*!
01290   \brief Add evolutions for this loop level.
01291 */
01292 void EvolutionGraph::_add_evolutions(Statement& first, Statement& last){
01293 /// Add evolutions.
01294   Statement* stit=&first;
01295   while(stit!=0 && stit!=&last){
01296     Statement& stmt=*stit;
01297     ProgramUnit* callee=called_pgm(stmt);
01298     if (callee){
01299       /// ...  Call site, must import evolutions from called subprogram.
01300       _add_evolutions(stmt, *callee);
01301       /// ...  Skip THETA assignments, they have been handled by now.
01302       stit=stit->next_ref();
01303       while (stit){
01304     if (stit->stmt_class()==ASSIGNMENT_STMT){
01305       if (stit->rhs().op()==THETA_OP){
01306         stit=stit->next_ref();
01307         continue;
01308       }
01309     }
01310     break;
01311       }
01312     } else {
01313       switch(stmt.stmt_class()){
01314       case DO_STMT:
01315     _add_evolutions((DoStmt&)stmt);
01316     stit=stit->follow_ref()->next_ref();
01317     break;
01318       case ASSIGNMENT_STMT: 
01319     _add_evolutions((AssignmentStmt&)stmt);
01320     stit=stit->next_ref();
01321     break;
01322       default:
01323     /// ...  Will add unknown input values for all definitions.
01324     for(Iterator<Expression> eit=stmt.out_refs(); eit.valid(); ++eit){
01325       Expression& e=eit.current();
01326       if (e.type().data_type()==INTEGER_TYPE){
01327         Symbol* to=e.base_variable_ref();
01328         if (to){
01329           if (to->is_scalar()){
01330         _input_values[to]=evolution();
01331           }
01332         }
01333       }
01334     }
01335     stit=stit->next_ref();
01336       }
01337     }
01338     /// ...  tmp results
01339 ///     cerr<<*stit<<flush;
01340 ///     print_graph("eg.dot");
01341 ///     system("dot -Tps -o t.ps eg.dot");
01342 ///     int tmp;
01343 ///     cin>>tmp;
01344   }
01345 }
01346 
01347 void EvolutionGraph::_verify_preconditions(){
01348 /// Our current preconditions are:
01349 /// 1. There is no path between any two different MUs.
01350 /// 2. There is at most one INPUT per MU other than its incoming value.
01351   for(EvolutionMap::iterator it=_mu_evolutions.begin(); 
01352       it!=_mu_evolutions.end(); ++it){
01353     const Symbol* mu1=(*it).first;
01354     for(map<const Symbol*, Evolution<Expression> >::iterator it2=
01355       (*it).second.begin(); it2!=(*it).second.end(); ++it2){
01356       const Symbol* mu2=(*it2).first;
01357       if(mu1!=mu2){
01358     /// ...  Cross-MU definitions are not supported yet.
01359     /// ...  Add an UNKNOWN input to this MU.
01360 
01361     /// ...  But first, let us see whether we are in a special case:
01362     /// ...  Check whether the only way to get values to this MU is
01363     /// ...  through the coupled recurrence.
01364     Symbol* imu;
01365     bool imu_is_defined;
01366     get_imu(*mu1, *_pgm, imu, imu_is_defined);
01367     if (imu==0 || !imu_is_defined){
01368       parasites.insert(index((Symbol*)mu1));
01369     } else {
01370       _input_values[mu1]=evolution();
01371     }
01372       }
01373     }
01374   }
01375 
01376 /// silvius: I don't think this is necessary anymore.
01377 ///   for(EvolutionMap::iterator it=_input2mu_evolutions.begin(); 
01378 ///       it!=_input2mu_evolutions.end(); ++it){
01379 ///     if((*it).second.size()>1){
01380 ///       /// ...  More than one INPUT may get to a MU.
01381 ///       cerr<<"\n3. in loop "<<loop_name(_loop)
01382 ///       <<", set input value for "<<(*it).first->name_ref()<<" to INF";
01383 ///       _input_values[(*it).first]=evolution();
01384 ///     }
01385 ///   }
01386 }
01387 
01388 
01389 void EvolutionGraph::_compact_zero_paths(){
01390 /// For now, only if they start at ZERO.
01391   bool change;
01392   do {
01393     change=false;
01394     unsigned int n=index(ZERO);
01395     const EdgeList& edges=get_edges(n);
01396     for(EdgeList::const_iterator eit=edges.begin(); eit!=edges.end(); ++eit){
01397       unsigned int t1=(*eit).first;
01398       if (loop(*nodes()[t1], *_pgm)==0){
01399     const EdgeList& edges2=get_edges(t1);
01400     vector<int> todel;
01401     for(EdgeList::const_iterator e2it=edges2.begin(); 
01402         e2it!=edges2.end(); ++e2it){
01403       unsigned int t2=(*e2it).first;
01404       EdgeType final=(*eit).second;
01405       final+=(*e2it).second;
01406       _add_evolution(nodes()[n], nodes()[t2], final);
01407       change=true;
01408     }
01409     remove_edges(t1);
01410       }
01411     }
01412   } while (change);
01413 }
01414 
01415 
01416 
01417 
01418 
01419 /*!
01420   \brief Computes all the evolutions for one trip of the given loop for
01421   all MU definitions at this loop level.
01422 
01423   Assumes that all inner loops have been processed.
01424   Reads/writes from/to _mu_step.
01425 */
01426 void EvolutionGraph::_compute_acyclic_evolutions(){
01427 
01428   Symbol* ind=0;
01429   if (_loop){
01430     ind=&_loop->index().symbol();
01431   }
01432 
01433 /// Topsort the nodes.
01434   vector<unsigned int> topsorted;
01435   _topsort(topsorted, true);
01436 
01437 /// Find root nodes.
01438   set<unsigned int> starters;
01439   set_union(mu_this_loop.begin(), mu_this_loop.end(),
01440         input_this_loop.begin(), input_this_loop.end(),
01441         inserter(starters, starters.begin()));
01442 ///   print_evolutions(_mu_evolutions, "MU", cerr);
01443 
01444 /// Chew them up.
01445   for(set<unsigned int>::iterator stit=starters.begin();
01446       stit!=starters.end(); ++stit){
01447     unsigned int source=*stit;
01448     bool is_mu_node=(mu_this_loop.find(source)!=mu_this_loop.end());
01449     vector<Evolution<Expression> > evs;
01450     _bellman_ford(source, evs, topsorted, true);
01451     for(set<unsigned int>::iterator it=nodes_this_loop.begin();
01452     it!=nodes_this_loop.end(); ++it){
01453       const Symbol* to=nodes()[*it];
01454       /// ...  Check whether 'to' is reachable from 'from'
01455       const Expression& md=*evs[*it].min_difference();
01456       if (md.op()==INFINITY_OP){
01457     if (md.sign()==1){
01458         /// ...  Unreachable.
01459       continue;
01460     }
01461       }
01462       if (is_mu_node){
01463     /// ...  MU Node.
01464     /// ...  Set evolutions from mu.
01465     const Symbol* mu_from=nodes()[source];
01466     _evolutions_from_mu[to][mu_from]=evs[*it];
01467     
01468     /// ...  Set mu evolutions.
01469     map<const Symbol*, const Symbol*>::iterator be=
01470       _back_edges.find(nodes()[*it]);
01471     if (be!=_back_edges.end()){
01472       // Save this evolution as from MU to MU.
01473       const Symbol* mu_to=(*be).second;
01474       const Symbol* mu_from=nodes()[source];
01475       _mu_evolutions[mu_to][mu_from]=evs[*it];
01476     }
01477       } else {
01478     /// ...  INPUT node.
01479     const Symbol* input_from=nodes()[source];
01480     _evolutions_from_input[to][input_from]=evs[*it];
01481     /// ...  Set INPUT-to-MU evolutions.
01482     map<const Symbol*, const Symbol*>::iterator be=
01483       _back_edges.find(nodes()[*it]);
01484     if (be!=_back_edges.end()){
01485       // Save this evolution as from INPUT to MU.
01486       const Symbol* mu_to=(*be).second;
01487       _input2mu_evolutions[mu_to][input_from]=evs[*it];
01488     }
01489       }
01490     }
01491   }
01492   
01493   if (_loop){
01494     /// ...  Manual reset for loop index.
01495     /// ...  This is needed because our logic would otherwise detect a zero-length
01496     /// ...  pass between 'ind' and 'ind' and overwrite the real step.
01497     _mu_evolutions[ind][ind]=evolution(_loop->step());
01498   }
01499   
01500 /// Now build _evolutions_to_mu.
01501   topsorted.clear();
01502   _topsort(topsorted, false);
01503   for(set<unsigned int>::iterator stit=back_this_loop.begin();
01504       stit!=back_this_loop.end(); ++stit){
01505     unsigned int source=*stit;
01506     vector<Evolution<Expression> > evs;
01507     _bellman_ford(source, evs, topsorted, false);
01508     for(set<unsigned int>::iterator it=nodes_this_loop.begin();
01509     it!=nodes_this_loop.end(); ++it){
01510       const Symbol* to=nodes()[*it];
01511       /// ...  Check whether 'to' is reachable from 'from'
01512       const Expression& md=*evs[*it].min_difference();
01513       if (md.op()==INFINITY_OP){
01514     if (md.sign()==1){
01515       // Unreachable.
01516       continue;
01517     }
01518       }
01519       const Symbol* mu=_back_edges[nodes()[source]];
01520       p_assert(mu, "Could not find MU symbol.");
01521       _evolutions_to_mu[to][mu]=evs[*it];
01522     }
01523   }
01524 
01525 
01526 ///   cerr<<"\nACYCLIC evs for loop "<<loop_name(_loop);
01527 ///   print_evolutions(_evolutions_from_mu, "MU", cerr);
01528 ///   print_evolutions(_mu_evolutions, "MU", cerr);
01529 ///   print_evolutions(_input2mu_evolutions, "INPUT2MU", cerr);
01530 ///   print_input_values(_input_values, "INPUT", cerr);
01531 }
01532 
01533 
01534 
01535 
01536 static bool has_known_iteration_space(DoStmt& dostmt){
01537   if (dostmt.limit().op()==INFINITY_OP){
01538     /// ...  Really a WHILE statement, the iteration space is unknown.
01539     return false;
01540   }
01541   Statement* ps=dostmt.prev_ref();
01542   while(ps){
01543     switch(ps->stmt_class()){
01544     case ASSIGNMENT_STMT:
01545       if (ps->lhs().op()==ID_OP){
01546     String name(ps->lhs().symbol().name_ref());
01547     if (name.index("SKIP_FLAG")==0){
01548       // DO statement with premature exit.
01549       return false;
01550     }
01551       }
01552       break;
01553     case LABEL_STMT:
01554       break;
01555     default:
01556       /// ...  Found no flag assignment before the loop.
01557       return true;
01558     }
01559     ps=ps->prev_ref();
01560   }
01561   return true;
01562 }
01563 
01564 /*!
01565   Consider the following:
01566   We have a MU that may have an incoming value, and may also be reached by 
01567   another loop-invariant definition from within the loop body through
01568   the loop-back arc (BACK, MU).
01569   Let us denote by IMU the incoming value for the MU node and by
01570   INPUT the other input value.
01571 
01572   Consider the following events:
01573   1. There is a path from MU to BACK.   (T/F)
01574   2. The loop has at least 1 iteration. (T/F)
01575   3. IMU is defined.                    (T/F)
01576   4. There is a path from INPUT to BACK (T/F)
01577 
01578   Here is a table describing the cyclic evolutions:
01579   ???F: MU = IMU   +         IC   *muev
01580   T?TT: MU = INPUT + i2mu + (IC-1)*muev
01581         MU = IMU   +         IC   *muev
01582   T?FT: MU = INPUT + i2mu + (IC-1)*muev
01583   FT?T: MU = INPUT + i2mu
01584   FFTT: MU = INPUT + i2mu
01585         MU = IMU 
01586   FFFT: MU = INPUT + i2mu
01587 */
01588 void EvolutionGraph::_compute_cyclic_evolutions(EvolutionMap& evs,
01589                         map<const Symbol*, 
01590                         Evolution<Expression> >& ivs){
01591 ///   if (_cyclic_evs_computed) {
01592 ///     return;
01593 ///   }
01594 ///   _cyclic_evs_computed=true;
01595 
01596   if (_loop==0) {
01597     evs=_mu_evolutions;
01598     return;
01599   }
01600 
01601 /// Check preconditions.
01602   _verify_preconditions();
01603 
01604   Expression* ic=iteration_count((DoStmt&)*_loop, *_pgm);
01605   bool the_loop_has_at_least_1_iteration;
01606   if (_ra->signz(*ic)==POS_EXPR){
01607     the_loop_has_at_least_1_iteration=true;
01608   } else {
01609     the_loop_has_at_least_1_iteration=false;
01610   }
01611 
01612 /// Forall MU symbols.
01613   for(set<unsigned int>::iterator muit=mu_this_loop.begin();
01614       muit!=mu_this_loop.end(); ++muit){
01615     Symbol* mu=nodes()[*muit];
01616     
01617     /// ...  Check for loop index.
01618     if (mu==&_loop->index().symbol()){
01619       /// ...  Check whether the loop has premature exits.
01620       if (has_known_iteration_space((DoStmt&)*_loop)){
01621     /// ...  Iteration space limit.
01622     ivs[mu]=evolution(last_value((DoStmt&)*_loop, *_pgm));
01623       } else {
01624     /// ...  Premature exit value.
01625     ivs[mu]=evolution(_loop->index());
01626       }
01627       continue;
01628     }
01629 
01630     /// ...  Check whether this is a parasite.
01631     if (parasites.find(index(mu))!=parasites.end()){
01632       continue;
01633     }
01634 
01635     /// ...  Check whether this MU was marked as not computable.
01636     if (_input_values.find(mu)!=_input_values.end()){
01637       ivs[mu]=evolution();
01638       continue;
01639     }
01640 
01641     bool there_is_a_path_from_mu_to_back;
01642     Evolution<Expression> muev;
01643     EvolutionMap::iterator found_mu2mu=_mu_evolutions.find(mu);
01644     if (found_mu2mu!=_mu_evolutions.end()){
01645       there_is_a_path_from_mu_to_back=true;
01646       muev=_mu_evolutions[mu][mu];
01647     } else {
01648       there_is_a_path_from_mu_to_back=false;
01649     }
01650 
01651     bool there_is_a_path_from_input_to_back;
01652     Evolution<Expression> i2mu, input;
01653     const Symbol* isym=0;
01654     EvolutionMap::iterator found_input2mu=_input2mu_evolutions.find(mu);
01655     if (found_input2mu!=_input2mu_evolutions.end()){
01656       there_is_a_path_from_input_to_back=true;
01657       i2mu=(*_input2mu_evolutions[mu].begin()).second;
01658       const Symbol* sym=(*_input2mu_evolutions[mu].begin()).first;
01659 ///       cerr<<"\nAt pgm "<<_pgm->routine_name_ref();
01660 ///       cerr<<"\nAt loop "<<loop_name(_loop);
01661 ///       cerr<<"\n\tFor MU symbol "<<node_name(mu)<<" : ";
01662 ///       cerr<<"\n\tInput symbol "<<node_name(sym);
01663       
01664 ///       print_evolutions(_input2mu_evolutions, "I2MUs", cerr);
01665       
01666       input=_input_values[sym];
01667 ///       if (input.min_difference()==0){
01668 ///     p_abort("ERROR");
01669 ///       }
01670       if (*input.min_difference()==*input.max_difference()){
01671     if (input.min_difference()->op()==ID_OP){
01672       isym=&input.min_difference()->symbol();
01673     }
01674       }
01675       if (isym){
01676     if (isym->type().data_type()!=INTEGER_TYPE){
01677       isym=0;
01678     } else {
01679       if (!isym->is_scalar()){
01680         isym=0;
01681       }
01682     }
01683       }
01684     } else {
01685       there_is_a_path_from_input_to_back=false;
01686     }
01687 
01688     Symbol* imu;
01689     bool imu_is_defined;
01690     get_imu(*mu, *_pgm, imu, imu_is_defined);
01691 
01692 ///     cerr<<"\nAt loop "<<loop_name(_loop);
01693 ///     cerr<<"\n\tFor MU symbol "<<node_name(mu)<<" : ";
01694 ///     if (there_is_a_path_from_mu_to_back)    cerr<<"T"; else cerr<<"F";
01695 ///     if (the_loop_has_at_least_1_iteration)  cerr<<"T"; else cerr<<"F";
01696 ///     if (imu_is_defined)                     cerr<<"T"; else cerr<<"F";
01697 ///     if (there_is_a_path_from_input_to_back) cerr<<"T"; else cerr<<"F";
01698 
01699     /// ...  Let's roll.
01700     /// ...  ???F
01701     if (!there_is_a_path_from_input_to_back){
01702       if (imu_is_defined){
01703     if (there_is_a_path_from_mu_to_back){
01704       // T?TF
01705       evs[imu][mu]=muev;
01706       evs[imu][mu]*=ic->clone();
01707     } else {
01708       // F?TF
01709       // There is no incoming value (input or mu).
01710       // Signal logic error.
01711       cerr<<"\nAt loop "<<loop_name(_loop);
01712       cerr<<"\n\tFor MU symbol "<<node_name(mu)<<" : ";
01713       if (there_is_a_path_from_mu_to_back)    cerr<<"T"; else cerr<<"F";
01714       if (the_loop_has_at_least_1_iteration)  cerr<<"T"; else cerr<<"F";
01715       if (imu_is_defined)                     cerr<<"T"; else cerr<<"F";
01716       if (there_is_a_path_from_input_to_back) cerr<<"T"; else cerr<<"F";
01717       p_abort("Cannot compute cyclic evolution, no incoming value.");
01718     }
01719       } else {
01720     /// ...  ??FF
01721     cerr<<endl<<node_name(mu);
01722     p_warning("Possibly undefined variable.");
01723       }
01724     }
01725     /// ...  T??T
01726     if (there_is_a_path_from_mu_to_back &&
01727     there_is_a_path_from_input_to_back){
01728       if(imu_is_defined){
01729     /// ...  T?TT
01730     evs[imu][mu]=muev;
01731     evs[imu][mu]*=ic->clone();
01732       } else {
01733     /// ...  T?FT
01734       }
01735       Evolution<Expression> ev=muev;
01736 ///       cerr<<"\n\t1 ev = "<<ev;
01737 ///       cerr<<"\n\t ic = "<<*ic;
01738       if (ev.max_difference()->op()==INFINITY_OP &&
01739       ev.min_difference()->op()!=INFINITY_OP){
01740     /// ...  silvius: there are problems multiplying Inf with possibly negative
01741     /// ...  numbers.
01742     ev=evolution(simplify(mul(ev.min_difference()->clone(),
01743                   simplify(sub(ic->clone(), constant(1))))),
01744              infinity());
01745       } else {
01746     ev*=simplify(sub(ic->clone(), constant(1)));
01747       }
01748 ///       cerr<<"\n\t2 ev = "<<ev;
01749       ev+=i2mu;
01750 ///       cerr<<"\n\t3 ev = "<<ev;
01751       if (isym){
01752     evs[isym][mu]=ev;
01753       } else {
01754 ///     cerr<<"\nev = "<<ev;
01755 ///     cerr<<"\ninput = "<<input;
01756     ev+=input;
01757 ///     cerr<<"\n1. setting "<<ev;
01758     ivs[mu]=ev;
01759       }
01760     }
01761     /// ...  FT?T
01762     if (!there_is_a_path_from_mu_to_back &&
01763     the_loop_has_at_least_1_iteration &&
01764     there_is_a_path_from_input_to_back){
01765       /// ...  Since the loop has an iteration and there is no way to get the BACK
01766       /// ...  value from IMU (no path from MU to BACK), the only value possible
01767       /// ...  is the INPUT one.
01768 ///     cerr<<"\n2. setting "<<input;
01769       ivs[mu]=input;
01770     }
01771     /// ...  FFTT
01772     if (!there_is_a_path_from_mu_to_back &&
01773     !the_loop_has_at_least_1_iteration &&
01774     imu_is_defined &&
01775     there_is_a_path_from_input_to_back){
01776       if (isym){
01777     evs[isym][mu]=i2mu;
01778       } else {
01779 ///     cerr<<"\n3. setting "<<input;
01780     ivs[mu]=input;
01781       }
01782       evs[imu][mu]=evolution(0);
01783     }
01784     /// ...  FFFT
01785     if (!there_is_a_path_from_mu_to_back &&
01786     !the_loop_has_at_least_1_iteration &&
01787     !imu_is_defined &&
01788     there_is_a_path_from_input_to_back){
01789       if (isym){
01790     evs[isym][mu]=i2mu;
01791       } else {
01792 ///     cerr<<"\n4. setting "<<input;
01793     ivs[mu]=input;
01794       }      
01795     }
01796   }
01797   delete ic;
01798 
01799 /// For the parasites.
01800   for(set<unsigned int>::iterator muit=mu_this_loop.begin();
01801       muit!=mu_this_loop.end(); ++muit){
01802     Symbol* mu=nodes()[*muit];
01803 
01804     if (parasites.find(index(mu))!=parasites.end()){
01805       /// ...  silvius: for now, do it for parasites only if the SCC that contains 
01806       /// ...  the parasite MU contains only 0-evolutions and has a single entry
01807       /// ...  which is a MU itself.
01808       const Symbol* host_mu=_verify_parasites_preconditions(mu);
01809       if(host_mu){
01810 ///     cerr<<"\nFound host_mu: "<<host_mu->name_ref();
01811     if (ivs.find(host_mu)!=ivs.end()){
01812       // Copy input from host MU.
01813 ///     cerr<<"\n5. setting "<<ivs[host_mu];
01814       ivs[mu]=ivs[host_mu];
01815     }
01816     for(EvolutionMap::iterator it=evs.begin(); it!=evs.end(); ++it){
01817       map<const Symbol*, Evolution<Expression> >::iterator 
01818         found=(*it).second.find(host_mu);
01819       if (found!=(*it).second.end()){
01820         /// ...  Copy evolution from host MU.
01821         evs[(*it).first][mu]=(*found).second;
01822       }
01823     }
01824       } else {
01825 ///     cerr<<"\nCould not find host_mu for parasite_mu "<<mu->name_ref();
01826     ivs[mu]=evolution();
01827       }
01828     }
01829   }
01830 
01831 ///   cerr<<"\nCYCLIC evs for loop "<<loop_name(_loop);
01832 ///   print_evolutions(evs, "MU", cerr);
01833 ///   print_input_values(ivs, "CYCLIC", cerr);
01834 }
01835 
01836 
01837 /*!
01838   \brief
01839   Checks whether the given parasite MU is in an SCC which consists of only
01840   0-evolutions and has a single entry which is a MU node.  This node is the
01841   return value, otherwise 0.
01842 */
01843 const Symbol* 
01844 EvolutionGraph::_verify_parasites_preconditions(Symbol* parasite_mu){
01845 ///   print_evolutions(_evolutions_from_mu, "PARASITE", cerr);
01846 /// First, find the SCC.
01847 /// Collect all nodes reachable from parasite_mu.
01848   set<const Symbol*> reachable;
01849   reachable.insert(parasite_mu);
01850   for(EvolutionMap::iterator emit=_evolutions_from_mu.begin();
01851       emit!=_evolutions_from_mu.end(); ++emit){
01852     map<const Symbol*, Evolution<Expression> >& evs=(*emit).second;
01853     map<const Symbol*, Evolution<Expression> >::iterator found=
01854       evs.find(parasite_mu);
01855     if (found!=evs.end()){
01856       reachable.insert((*emit).first);
01857     }
01858   }
01859 
01860 /// Go through all the reachable nodes and make sure all the links between 
01861 /// them are 0-valued.  Also, make sure the BACK nodes come back to 
01862 /// parasite_mu.
01863   for(set<const Symbol*>::iterator it=reachable.begin(); 
01864       it!=reachable.end(); ++it){
01865     if (back_this_loop.find(index((Symbol*)*it))!=back_this_loop.end()){
01866       /// ...  Back node.
01867       if (_back_edges[*it]!=parasite_mu){
01868     return 0;
01869       }
01870     }
01871     const EdgeList& edges=get_edges(index((Symbol*)*it));
01872     for(EdgeList::const_iterator elit=edges.begin(); 
01873     elit!=edges.end(); ++elit){
01874       if (reachable.find(nodes()[(*elit).first])!=reachable.end()){
01875     /// ...  Edge between two reachable nodes.
01876     if (!is_integer_zero(*(*elit).second.min_difference()) ||
01877         !is_integer_zero(*(*elit).second.max_difference())){
01878 ///       cerr<<"\nRET 1";
01879       return 0;
01880     }
01881       }
01882     }
01883   }
01884 
01885 /// Look for the entries in this SCC.
01886   const Symbol* entry=0;
01887   for(set<const Symbol*>::iterator it=reachable.begin(); 
01888       it!=reachable.end(); ++it){
01889 ///     cerr<<"\n\tREACHABLE: "<<(*it)->name_ref();
01890     const EdgeList& edges=get_reversed_edges(index((Symbol*)*it));
01891     for(EdgeList::const_iterator elit=edges.begin(); 
01892     elit!=edges.end(); ++elit){
01893       const Symbol* candidate=nodes()[(*elit).first];
01894       if (reachable.find(candidate)==reachable.end()){
01895 ///     cerr<<"\n\t\tCANDIDATE: "<<candidate->name_ref();
01896     /// ...  Entry.
01897     if (entry){
01898       if (entry!=candidate){
01899         /// ...  Multiple entries
01900 ///         cerr<<"\nRET 2";
01901         return 0;
01902       }
01903     } else {
01904       entry=candidate;
01905     }
01906       }
01907     }
01908   }
01909 
01910 /// Check whether this single entry is a MU node.
01911 /// Backtrack to a MU if possible.
01912   while(entry){
01913 ///     cerr<<"\n\tENTRY: "<<entry->name_ref();
01914     if (_loop){
01915       if (&_loop->index().symbol()==(Symbol*)entry){
01916     return entry;
01917       }
01918     }
01919     if (mu_this_loop.find(index((Symbol*)entry))!=mu_this_loop.end()){
01920       return entry;
01921     }
01922     const EdgeList& edges=get_reversed_edges(index((Symbol*)entry));
01923     if (edges.size()==1){
01924       if (!is_integer_zero(*(*edges.begin()).second.min_difference()) ||
01925       !is_integer_zero(*(*edges.begin()).second.max_difference())){
01926 ///       cerr<<"\nRET 3";
01927     return 0;
01928       }
01929       entry=nodes()[(*edges.begin()).first];
01930       continue;
01931     } else {
01932       break;
01933     }
01934   }
01935 ///       cerr<<"\nRET 4";
01936   return 0;
01937 }
01938 
01939 
01940 
01941 /* Dumps the graph in DOT format. */
01942 void EvolutionGraph::print_graph(const char* filename){
01943   ofstream f(filename);
01944   f<<"\n/* Automatically generated by Polaris */"
01945    <<"\n\ndigraph EvolutionGraph { ";
01946   vector<Symbol*>::const_iterator sit=nodes().begin();
01947   for( ; sit!=nodes().end(); ++sit){
01948     unsigned n=index((Symbol*)*sit);
01949     /// ...  Node info.
01950     /// ...  Is it an INPUT node?
01951     if (_input_values.find(*sit)!=_input_values.end()){
01952       f<<"\n\t\t\""<<n<<"\" [label=\""<<node_name(*sit)
01953        <<":"<<_input_values[*sit]<<"\", shape=\"box\", color=\"green\""
01954        <<"];";
01955     } else {
01956       /// ...  Is it a MU node?
01957       if (mu_this_loop.find(n)!=mu_this_loop.end()){
01958     f<<"\n\t\t\""<<n<<"\" [label=\""<<node_name(*sit)
01959      <<"\", shape=\"doublecircle\", color=\"red\""
01960      <<"];";
01961       } else {
01962     /// ...  Or is it a BACK node?
01963     if (back_this_loop.find(n)!=back_this_loop.end()){
01964       f<<"\n\t\t\""<<n<<"\" [label=\""<<node_name(*sit)
01965        <<"\", shape=\"hexagon\", color=\"brown\""
01966        <<"];";
01967     } else {
01968       // Regular node.
01969       f<<"\n\t\t\""<<n<<"\" [label=\""<<node_name(*sit)
01970        <<"\", shape=\"ellipse\", color=\"black\""
01971        <<"];";
01972     }
01973       }
01974     }
01975   }
01976 
01977 /// Edges.
01978   for(unsigned int n=0; n<nodes().size(); ++n){
01979     const EdgeList& edges=get_edges(n);
01980     for(EdgeList::const_iterator eit=edges.begin(); eit!=edges.end(); ++eit){
01981       unsigned int target=(*eit).first;
01982       if (*(*eit).second.min_difference()==*(*eit).second.max_difference()){
01983     f<<"\n\t\""<<n<<"\" -> \""<<target<<"\" [label=\""
01984      <<*(*eit).second.max_difference()<<"\"";
01985       } else {
01986     f<<"\n\t\""<<n<<"\" -> \""<<target<<"\" [label=\"["
01987      <<*(*eit).second.min_difference()<<", "
01988      <<*(*eit).second.max_difference()<<"]\"";
01989       }
01990       f<<"];";
01991     }
01992     /// ...  Look for back edges.
01993     map<const Symbol*, const Symbol*>::iterator beit=
01994       _back_edges.find(nodes()[n]);
01995     if (beit!=_back_edges.end()){
01996       f<<"\n\t\""<<n<<"\" -> \""<<index((Symbol*)(*beit).second)
01997        <<"\" [label=\"0\", style=dotted];";
01998     }
01999   }
02000   f<<"\n}\n/* End of file */";
02001 }
02002 
02003 
02004 static RangeExpr* _range(const Evolution<Expression>& ev){
02005   if (ev.min_difference() && ev.max_difference()){
02006     return new RangeExpr(ev.min_difference()->clone(),
02007              ev.max_difference()->clone());
02008   }
02009   return new RangeExpr(infinity(-1), infinity(+1));
02010 }
02011 
02012 /*!
02013   \brief There are three ways to compute the value:
02014   1. input + input_2_value
02015   2. mu_input + mu_acyclic*(ic-1) + mu_2_value
02016   3. input + input2mu + mu_acyclic*(ic-2) + mu_2_value
02017 
02018   If this VEG corresponds to a whole routine, just case 1 is considered.
02019 
02020   \warning Only works if given symbol is a node in this evolution graph.
02021 */
02022 void EvolutionGraph::_possible_ranges(const Symbol& sym, 
02023                       list<pair<list<Symbol*>,
02024                       RangeExpr*> >& result){
02025 /// Only do it if &sym is a node in *this.
02026   if (!contains((Symbol*)&sym)){
02027     return;
02028   }
02029   Symbol* nsym=(Symbol*)&sym;
02030 
02031   if (sym.is_array()){
02032     cerr<<"\nNode not scalar: "<<sym.name_ref();
02033     p_warning("");
02034     return;
02035   }
02036 
02037   if (_loop){
02038     if (&sym==&_loop->index().symbol()){
02039       /// ... silvius: check for negative step!
02040       list<Symbol*> path;
02041       path.push_back(nsym);
02042       result.push_back(make_pair(path, new RangeExpr(_loop->init().clone(), 
02043                              _loop->limit().clone())));
02044       return;
02045     }
02046   }
02047 
02048 /// Find total values in first class.
02049 /// First check whether it is an input itself.
02050   map<const Symbol*, Evolution<Expression> >::iterator found=
02051     _input_values.find(&sym);
02052   if (found!=_input_values.end()){
02053     Evolution<Expression> ev=(*found).second;    
02054     list<Symbol*> path;
02055     path.push_back((Symbol*)&sym);
02056     result.push_back(make_pair(path, _range(ev)));
02057   }
02058   EvolutionMap::iterator it=_evolutions_from_input.find(&sym);
02059   if (it!=_evolutions_from_input.end()){
02060     for(map<const Symbol*, Evolution<Expression> >::iterator it2=
02061       (*it).second.begin(); it2!=(*it).second.end(); ++it2){
02062       const Symbol* isym=(*it2).first;
02063       list<Symbol*> path;
02064       path.push_back((Symbol*)isym);
02065       Evolution<Expression> ev=_input_values[isym];
02066       ev+=(*it2).second;
02067       result.push_back(make_pair(path, _range(ev)));
02068     }
02069   }
02070 
02071   if (_loop){
02072     /// ...  Find total values in second and third class.
02073     it=_evolutions_from_mu.find(&sym);
02074     if (it!=_evolutions_from_mu.end()){
02075       for(map<const Symbol*, Evolution<Expression> >::iterator it2=
02076         (*it).second.begin(); it2!=(*it).second.end(); ++it2){
02077     const Symbol* mu=(*it2).first;
02078       
02079     if (parasites.find(index((Symbol*)mu))!=parasites.end()){
02080       Evolution<Expression> ev=evolution();
02081       list<Symbol*> path;
02082       path.push_back((Symbol*)mu);
02083       result.push_back(make_pair(path, _range(ev)));
02084       continue;
02085     }
02086 
02087     /// ...  Second class.
02088     Symbol* imu;
02089     bool imu_is_defined;
02090     get_imu((Symbol&)*mu, *_pgm, imu, imu_is_defined);
02091       
02092     if (imu==0){
02093       // This better be the loop index.
02094       if (_loop){
02095         if (mu==&_loop->index().symbol()){
02096           /// ... silvius: check for negative step!
02097           Evolution<Expression> ev=(*it2).second;
02098           ev+=evolution(_loop->init().clone(),
02099                 _loop->limit().clone());
02100           list<Symbol*> path;
02101           path.push_back((Symbol*)mu);
02102           result.push_back(make_pair(path, _range(ev)));
02103         }
02104       }
02105       cerr<<"\nFor MU node: "<<mu->name_ref();
02106       p_abort("No input to MU node.");
02107     }
02108 
02109     if (imu_is_defined){
02110       // Second class.
02111       Evolution<Expression> current=evolution(id(*imu));
02112       Evolution<Expression> cyclic;
02113       if (_mu_evolutions.find(mu)!=_mu_evolutions.end()){
02114         /// ...  There is a cycle from mu to itself.
02115         cyclic=_mu_evolutions[mu][mu];
02116       } else {
02117         cyclic=evolution(constant(0));
02118       }
02119       cyclic*=simplify(sub(iteration_count((DoStmt&)*_loop, *_pgm), 
02120                    constant(1)));
02121       current+=cyclic;
02122       current+=(*it2).second;
02123       list<Symbol*> path;
02124       path.push_back((Symbol*)mu);
02125       result.push_back(make_pair(path, _range(current)));
02126     }
02127       
02128     /// ...  Third class.
02129     /// ...  This only makes sense if there are inputs reaching mu.
02130     EvolutionMap::iterator iit=_input2mu_evolutions.find(mu);
02131     if (iit!=_input2mu_evolutions.end()){
02132       for(map<const Symbol*, Evolution<Expression> >::iterator iit2=
02133         (*iit).second.begin(); iit2!=(*iit).second.end(); ++iit2){
02134         const Symbol* isym=(*iit2).first;
02135         Evolution<Expression> current=_input_values[isym];
02136         current+=(*iit2).second;
02137         Evolution<Expression> cyclic;
02138         if (_mu_evolutions.find(mu)!=_mu_evolutions.end()){
02139           /// ...  There is a cycle from mu to itself.
02140           cyclic=_mu_evolutions[mu][mu];
02141         } else {
02142           cyclic=evolution(constant(0));
02143         }
02144         cyclic*=simplify(sub(iteration_count((DoStmt&)*_loop, *_pgm), 
02145                  constant(2)));
02146         current+=cyclic;
02147         current+=(*it2).second;
02148         list<Symbol*> path;
02149         path.push_back((Symbol*)isym);
02150         path.push_back((Symbol*)mu);
02151         result.
02152           push_back(make_pair(path, _range(current)));
02153       }
02154     }
02155       }
02156     }  
02157   }
02158 }
02159 
02160 
02161 
02162 /*!
02163   There are three ways to compute the value:
02164   1. input + input_2_value
02165   2. mu_input + mu_acyclic*(ic-1) + mu_2_value
02166   3. input + input2mu + mu_acyclic*(ic-2) + mu_2_value
02167 
02168   If this VEG corresponds to a whole routine, just case 1 is considered.
02169 
02170   \warning Only works if given symbol is a node in this evolution graph.
02171 */
02172 Expression* EvolutionGraph::_local_range(const Symbol& sym){
02173 
02174 ///   cerr<<"\n\nEnter local_range in loop "<<loop_name(_loop)
02175 ///       <<", for symbol "<<sym.name_ref();
02176 /// For now, only do it if &sym is a node in *this.
02177   if (!contains((Symbol*)&sym)){
02178     cerr<<"\nNode not in graph: "<<sym.name_ref();
02179     p_warning("");
02180     return new RangeExpr(infinity(-1), infinity(1));
02181   }
02182 
02183   if (sym.is_array()){
02184     cerr<<"\nNode not scalar: "<<sym.name_ref();
02185     p_warning("");
02186     return new RangeExpr(infinity(-1), infinity(1));
02187   }
02188 
02189   if (_loop){
02190     if (&sym==&_loop->index().symbol()){
02191       /// ... silvius: check for negative step!
02192       return new RangeExpr(_loop->init().clone(), _loop->limit().clone());
02193     }
02194   }
02195 
02196   Evolution<Expression> ev;
02197   bool ev_is_initialized=false;
02198 
02199 /// Find total values in first class.
02200 /// First check whether it is an input itself.
02201   map<const Symbol*, Evolution<Expression> >::iterator found=
02202     _input_values.find(&sym);
02203   if (found!=_input_values.end()){
02204     ev=(*found).second;
02205     ev_is_initialized=true;
02206     /// ...  Return now, all other reaching values will be overwritten.
02207 ///     cerr<<"\n\tearly return.";
02208 ///     print_input_values(_input_values, "INPUT", cerr);
02209 
02210     return new RangeExpr(ev.min_difference()->clone(),
02211              ev.max_difference()->clone());
02212   }
02213   EvolutionMap::iterator it=_evolutions_from_input.find(&sym);
02214   if (it!=_evolutions_from_input.end()){
02215     for(map<const Symbol*, Evolution<Expression> >::iterator it2=
02216       (*it).second.begin(); it2!=(*it).second.end(); ++it2){
02217       const Symbol* isym=(*it2).first;
02218       Evolution<Expression> this_ev=_input_values[isym];
02219       this_ev+=(*it2).second;
02220       if (ev_is_initialized){
02221     ev=merge_unite(ev, this_ev, *_pgm, _ra);
02222       } else {
02223     ev=this_ev;
02224     ev_is_initialized=true;
02225       }
02226     }
02227   }
02228 
02229   if (_loop){
02230     /// ...  Find total values in second and third class.
02231     it=_evolutions_from_mu.find(&sym);
02232     if (it!=_evolutions_from_mu.end()){
02233       for(map<const Symbol*, Evolution<Expression> >::iterator it2=
02234         (*it).second.begin(); it2!=(*it).second.end(); ++it2){
02235     const Symbol* mu=(*it2).first;
02236       
02237     if (parasites.find(index((Symbol*)mu))!=parasites.end()){
02238       // silvius: for now, don't do anything about parasites.
02239 ///       cerr<<"\n\tparasite.";
02240       ev=evolution();
02241       return new RangeExpr(ev.min_difference()->clone(),
02242                    ev.max_difference()->clone());
02243     }
02244 
02245 
02246 ///     cerr<<"\n\t mu = "<<mu->name_ref();
02247     /// ...  Second class.
02248     Symbol* imu;
02249     bool imu_is_defined;
02250     get_imu((Symbol&)*mu, *_pgm, imu, imu_is_defined);
02251       
02252     if (imu==0){
02253       // This better be the loop index.
02254       if (_loop){
02255         if (mu==&_loop->index().symbol()){
02256           /// ... silvius: check for negative step!
02257           Evolution<Expression> from_mu=(*it2).second;
02258           from_mu+=evolution(_loop->init().clone(),
02259                  _loop->limit().clone());
02260           return new RangeExpr(from_mu.min_difference()->clone(),
02261                    from_mu.max_difference()->clone());
02262         }
02263       }
02264       cerr<<"\nFor MU node: "<<mu->name_ref();
02265       p_abort("No input to MU node.");
02266     }
02267 
02268     if (imu_is_defined){
02269       // Second class.
02270       Evolution<Expression> current=evolution(id(*imu));
02271       Evolution<Expression> cyclic;
02272       if (_mu_evolutions.find(mu)!=_mu_evolutions.end()){
02273         /// ...  There is a cycle from mu to itself.
02274         cyclic=_mu_evolutions[mu][mu];
02275       } else {
02276         cyclic=evolution(constant(0));
02277       }
02278       cyclic*=simplify(sub(iteration_count((DoStmt&)*_loop, *_pgm), 
02279                    constant(1)));
02280       current+=cyclic;
02281       current+=(*it2).second;
02282       if (ev_is_initialized){
02283         ev=merge_unite(ev, current, *_pgm, _ra);
02284 ///         cerr<<"\n\t2. ev = "<<ev;
02285       } else {
02286         ev=current;
02287 ///         cerr<<"\n\t3. ev = "<<ev;
02288         ev_is_initialized=true;
02289       }
02290     }
02291       
02292     /// ...  Third class.
02293     /// ...  This only makes sense if there are inputs reaching mu.
02294     EvolutionMap::iterator iit=_input2mu_evolutions.find(mu);
02295     if (iit!=_input2mu_evolutions.end()){
02296       for(map<const Symbol*, Evolution<Expression> >::iterator iit2=
02297         (*iit).second.begin(); iit2!=(*iit).second.end(); ++iit2){
02298         const Symbol* isym=(*iit2).first;
02299         Evolution<Expression> current=_input_values[isym];
02300         current+=(*iit2).second;
02301         Evolution<Expression> cyclic;
02302         if (_mu_evolutions.find(mu)!=_mu_evolutions.end()){
02303           /// ...  There is a cycle from mu to itself.
02304           cyclic=_mu_evolutions[mu][mu];
02305         } else {
02306           cyclic=evolution(constant(0));
02307         }
02308         cyclic*=simplify(sub(iteration_count((DoStmt&)*_loop, *_pgm), 
02309                  constant(2)));
02310         current+=cyclic;
02311         current+=(*it2).second;
02312         if (ev_is_initialized){
02313           ev=merge_unite(ev, current, *_pgm, _ra);
02314 ///           cerr<<"\n\t4. ev = "<<ev;
02315         } else {
02316           ev=current;
02317 ///           cerr<<"\n\t5. ev = "<<ev;
02318           ev_is_initialized=true;
02319         }
02320       }
02321     }
02322       }
02323     }  
02324   }
02325 
02326   if (ev_is_initialized){
02327 ///     cerr<<"\n\t6. ev = "<<ev;
02328     return new RangeExpr(ev.min_difference()->clone(),
02329              ev.max_difference()->clone());
02330   } else {
02331 ///     cerr<<"\n\t7. ev = OMEGA";
02332     return new RangeExpr(infinity(-1), infinity());
02333   }
02334 }
02335 
02336 
02337 
02338 /*!
02339   \brief Computes the range of the given expression over _loop.
02340   
02341   \warning All symbols referenced by the given expression must be defined
02342   in _loop.
02343   \warning We will take ownership over expr.
02344  */
02345 Expression* 
02346 EvolutionGraph::_eliminate_vars(Expression* expr, 
02347                 set<Symbol*>& syms){
02348 /// Eliminate all symbols defined here.
02349   RangeAccessor ra(*_ra);
02350   RefSet<Symbol> vars_to_eliminate;
02351   for(set<Symbol*>::iterator sit=syms.begin(); sit!=syms.end(); ++sit){
02352     Expression* lr=_local_range(**sit);
02353 ///     cerr<<"\n\t\tSetting local range for "<<(*sit)->name_ref()
02354 ///     <<" to "<<*lr;
02355     /// ...  Optimization.  Try to detect (-Inf:+Inf) early.
02356     if (lr->op()==RANGE_OP){
02357       if (((RangeExpr*)lr)->lb().op()==INFINITY_OP){
02358     if ((((RangeExpr*)lr)->lb().sign()==-1)){
02359       if (((RangeExpr*)lr)->ub().op()==INFINITY_OP){
02360         if ((((RangeExpr*)lr)->ub().sign()==1)){
02361           return lr;
02362         }
02363       }
02364     }
02365       }
02366     }
02367     
02368     ra.set_range(**sit, lr);    
02369     vars_to_eliminate.ins(**sit);
02370   }
02371   return ra.eliminate_vars(expr, &vars_to_eliminate);
02372 }
02373 
02374 
02375 
02376 static Expression* _embed_symbolic_range(Expression* range, 
02377                      ProgramUnit& pgm,
02378                      RangeAccessor* ra,
02379                      set<Symbol*>& dummies){
02380   Symbol& dummy=
02381     pgm.symtab().rename_and_ins(new VariableSymbol("DUMMY", 
02382                            make_type(INTEGER_TYPE),
02383                            NOT_FORMAL, NOT_SAVED));
02384   dummies.insert(&dummy);
02385   ra->set_range(dummy, range);
02386   return id(dummy);
02387 }
02388                    
02389 
02390 /// Embeds the tightest known range for array references. 
02391 static Expression* _filter_arrays(Expression* expr, 
02392                   ProgramUnit& pgm, 
02393                   Statement* loop,
02394                   set<Symbol*>& dummies,
02395                   RangeAccessor* ra){
02396   if (expr==0){
02397     return 0;
02398   }
02399   if (expr->op()==ARRAY_REF_OP){
02400     if (gsa_base(expr->array().symbol())->formal() ||
02401     gsa_base(expr->array().symbol())->common_ref()){
02402       Expression* toret=new RangeExpr(infinity(-1), infinity());
02403       delete expr;
02404 ///       cerr<<"\nReturn 1";
02405       return _embed_symbolic_range(toret, pgm, ra, dummies);
02406     }
02407     Expression* eg_range_array_1_to_i(Expression& e, 
02408                       ProgramUnit& pgm, Statement* loop);
02409     Statement* last=loop;
02410     while(loop){
02411       last=loop;
02412       loop=loop->outer_ref();
02413     }
02414     if (last==0){
02415       Expression* toret=new RangeExpr(infinity(-1), infinity());
02416       delete expr;
02417 ///       cerr<<"\nReturn 2";
02418       return _embed_symbolic_range(toret, pgm, ra, dummies);
02419     }
02420     Expression* toret=eg_range_array_1_to_i(*expr, pgm, last);
02421     delete expr;
02422     if (toret->op()==RANGE_OP){
02423 ///       cerr<<"\nReturn 3: "<<*toret;
02424       return _embed_symbolic_range(toret, pgm, ra, dummies);
02425     } else {
02426 ///       cerr<<"\nReturn 4";
02427       return toret;
02428     }
02429   }
02430   for(Mutator<Expression> expit=expr->arg_list(); expit.valid(); ++expit) {
02431     Assign<Expression> a = expit.assign();
02432     a=_filter_arrays(expit.pull(), pgm, loop, dummies, ra);
02433   }
02434 ///   cerr<<"\nReturn 5";
02435   return expr;
02436 }
02437 
02438 static Expression* _filter_arrays(Expression* expr, 
02439                   ProgramUnit& pgm, 
02440                   Statement* loop){
02441   Statement* rs=&quick_pgm_entry(pgm);
02442   if (loop){
02443     rs=loop->next_ref();
02444   }
02445 ///   cerr<<"\nEnter filter_arrays: "<<*expr;
02446   RangeAccessor* ra=new RangeAccessor(pgm.range_dict_guarded(), *rs);
02447   set<Symbol*> dummies;
02448   Expression* toret=_filter_arrays(expr, pgm, loop, dummies, ra);
02449 ///   cerr<<"\n\tLevel 1 before subst:"<<*toret;
02450 ///   cerr<<"\nra = "<<*ra;
02451 
02452   set<Symbol*>::iterator sit;
02453   RefSet<Symbol> vars_to_eliminate;
02454   bool found_infinity=false;
02455   for(sit=dummies.begin(); sit!=dummies.end(); ++sit){
02456     const Expression* r=ra->get_range_ref(**sit);
02457     if (r->op()==RANGE_OP){
02458       if (((const RangeExpr*)r)->lb().op()==INFINITY_OP ||
02459       ((const RangeExpr*)r)->ub().op()==INFINITY_OP){
02460     found_infinity=true;
02461     break;
02462       }
02463     }
02464     vars_to_eliminate.ins(**sit);
02465   }
02466   if (found_infinity){
02467     delete ra;
02468     for(sit=dummies.begin(); sit!=dummies.end(); ++sit){
02469       pgm.symtab().del((*sit)->name_ref());
02470     }
02471     delete toret;
02472     toret=new RangeExpr(infinity(-1), infinity());
02473   } else {
02474     toret=ra->eliminate_vars(toret, &vars_to_eliminate);
02475     delete ra;
02476     for(sit=dummies.begin(); sit!=dummies.end(); ++sit){
02477       pgm.symtab().del((*sit)->name_ref());
02478     }
02479   }
02480 
02481   if (toret->op()==OMEGA_OP){
02482     /// ...  Probably some undefined operation such as ( -Inf + Inf ).
02483     delete toret;
02484     toret=new RangeExpr(infinity(-1), infinity());    
02485   }
02486 ///   cerr<<"\nExit filter_arrays: "<<*toret;
02487   return toret;
02488 }
02489 
02490 
02491 /// Finds the range of expr across the given domain.
02492 /// If the given domain is 0, the range across the whole program unit 
02493 /// is returned.
02494 Expression* EvolutionGraph::_global_range_per_iteration(Expression* expr,
02495                             DoStmt* domain){
02496 
02497 ///   cerr<<"\n\n\nEntering EvolutionGraph::_global_range "
02498 ///       <<"\n\texpr = "<<*expr
02499 ///       <<"\n\tdomain = "<<loop_name(domain);
02500 
02501   expr=_filter_arrays(expr, *_pgm, domain);
02502   
02503 /// Iterate until we have no symbols defined in a loop within domain.
02504   do {
02505     DoStmt* ci=0;
02506     set<Symbol*> syms_in_innermost;
02507     RefList<Symbol> syms;
02508     referred_symbols(*expr, syms);
02509 
02510     if (syms.entries()==0){
02511       /// ...  No variables in expr.
02512       return expr;
02513     }
02514 
02515     for(Iterator<Symbol> sit=syms; sit.valid(); ++sit){
02516       DoStmt* current=def_loop(sit.current(), *_pgm);
02517       if (inner(current, ci)){
02518     /// ...  current <= ci
02519     if (current==ci){
02520       // At this point we think we are in the innermost.
02521       syms_in_innermost.insert(&sit.current());
02522     } else {
02523       // This is a new innermost.
02524       ci=current;
02525       syms_in_innermost.clear();
02526       syms_in_innermost.insert(&sit.current());
02527     }
02528       }
02529     }
02530 ///     cerr<<"\n\tin loop "<<loop_name(ci);
02531 ///     cerr<<"\n\tEG::rs: "<<syms;
02532     /// ...  This test is a valid termination condition because we are going outer.
02533     if (inner(domain, ci)){
02534       break;
02535     } else {
02536 ///       cerr<<"\n\tbefore elimination in loop "<<loop_name(ci)<<": "<<*expr;
02537       expr=_get_eg(_pgm, ci)->_eliminate_vars(expr, syms_in_innermost);
02538 ///       cerr<<"\n\t result = "<<*expr;
02539     }
02540   } while (1);
02541 
02542 ///   if (expr){
02543 ///     cerr<<"\n\tfrom EvolutionGraph::_global_range: "<<*expr;
02544 ///   }
02545 
02546 /// silvius: optimization
02547   if (expr->op()==ID_OP){
02548     Symbol* value=&expr->symbol();
02549     if (contains(value)){
02550       map<const Symbol*, Evolution<Expression> >::iterator found=
02551     _input_values.find(value);
02552       if (found!=_input_values.end()){
02553     /// ...  Does have an input value.
02554     delete expr;
02555     return new RangeExpr((*found).second.min_difference()->clone(),
02556                  (*found).second.max_difference()->clone());
02557       }
02558     }
02559   }
02560 
02561 
02562   expr=_filter_arrays(expr, *_pgm, domain);
02563 ///   if (expr){
02564 ///     cerr<<"\n\tfrom EvolutionGraph::_global_range: "<<*expr;
02565 ///   }
02566   return expr;
02567 }
02568 
02569 
02570 /// Finds the range of expr across the given domain.
02571 /// If the given domain is 0, the range across the whole program unit 
02572 /// is returned.
02573 Expression* EvolutionGraph::_global_range(Expression* expr,
02574                       DoStmt* domain){
02575 
02576 ///   if (domain){
02577 ///     if (domain->outer_ref()){
02578 ///       cerr<<"\n\n\nEntering EvolutionGraph::_global_range "
02579 ///       <<"\n\texpr = "<<*expr
02580 ///       <<"\n\tdomain = "<<loop_name(domain);
02581 ///     }
02582 ///   }
02583 
02584 
02585   expr=_filter_arrays(expr, *_pgm, domain);
02586 ///   cerr<<"\nAfter _filter_arrays : "<<*expr;
02587 ///   cerr<<"\nDomain = "<<loop_name(domain);
02588   
02589 /// Iterate until we have no symbols defined in a loop within domain.
02590   do {
02591     DoStmt* ci=0;
02592     set<Symbol*> syms_in_innermost;
02593     RefList<Symbol> syms;
02594     referred_symbols(*expr, syms);
02595 
02596     if (syms.entries()==0){
02597       /// ...  No variables in expr.
02598       return expr;
02599     }
02600 
02601     for(Iterator<Symbol> sit=syms; sit.valid(); ++sit){
02602       DoStmt* current=def_loop(sit.current(), *_pgm);
02603       if (inner(current, ci)){
02604     /// ...  current <= ci
02605     if (current==ci){
02606       // At this point we think we are in the innermost.
02607       syms_in_innermost.insert(&sit.current());
02608     } else {
02609       // This is a new innermost.
02610       ci=current;
02611       syms_in_innermost.clear();
02612       syms_in_innermost.insert(&sit.current());
02613     }
02614       }
02615     }
02616 ///     cerr<<"\n\tin loop "<<loop_name(ci);
02617 ///     cerr<<"\n\tEG::rs: "<<syms;
02618     /// ...  This test is a valid termination condition because we are going outer.
02619     if (inner(domain, ci)){
02620       break;
02621     } else {
02622 ///       cerr<<"\n\tbefore elimination in loop "<<loop_name(ci)<<": "<<*expr;
02623       expr=_get_eg(_pgm, ci)->_eliminate_vars(expr, syms_in_innermost);
02624 ///       cerr<<"\n\t result = "<<*expr;
02625     }
02626   } while (1);
02627 
02628 ///   if (expr){
02629 ///     cerr<<"\n\tfrom EvolutionGraph::_global_range: "<<*expr;
02630 ///   }
02631 
02632 /// silvius: optimization
02633   if (expr->op()==ID_OP){
02634     Symbol* value=&expr->symbol();
02635     if (contains(value)){
02636       map<const Symbol*, Evolution<Expression> >::iterator found=
02637     _input_values.find(value);
02638       if (found!=_input_values.end()){
02639     /// ...  Does have an input value.
02640     delete expr;
02641     return new RangeExpr((*found).second.min_difference()->clone(),
02642                  (*found).second.max_difference()->clone());
02643       }
02644     }
02645   }
02646 
02647 /// We are at the outermost level within domain.
02648   if (domain==0){
02649 
02650   } else {
02651     set<Symbol*> syms_in_domain;
02652     RefList<Symbol> syms;
02653     referred_symbols(*expr, syms);
02654     for(Iterator<Symbol> sit=syms; sit.valid(); ++sit){
02655       DoStmt* current=def_loop(sit.current(), *_pgm);
02656       if (current==domain){
02657     syms_in_domain.insert(&sit.current());
02658       }
02659     }
02660     expr= _get_eg(_pgm, domain)->_eliminate_vars(expr, 
02661                          syms_in_domain);
02662   }
02663 
02664   if (domain){
02665     expr=_filter_arrays(expr, *_pgm, domain->outer_ref());
02666   } else {
02667     expr=_filter_arrays(expr, *_pgm, domain);
02668   }
02669 ///   if (expr){
02670 ///     if (domain){
02671 ///       if (domain->outer_ref()){
02672 ///     cerr<<"\n\tfrom EvolutionGraph::_global_range: "<<*expr;
02673 ///       }
02674 ///     }
02675 ///   }
02676   return expr;
02677 }
02678 
02679 
02680 Expression* EvolutionGraph::_global_range(Expression* expr){
02681 /// Find the outermost loop.
02682   DoStmt* co=0;
02683   RefList<Symbol> syms;
02684   referred_symbols(*expr, syms);
02685   Iterator<Symbol> sit=syms;
02686   if (!sit.valid()){
02687     /// ...  No variables.
02688     return expr;
02689   } else {
02690     co=def_loop(sit.current(), *_pgm);
02691     ++sit;
02692   }
02693   for(; sit.valid(); ++sit){
02694     DoStmt* current=def_loop(sit.current(), *_pgm);
02695     if (outer(current, co)){
02696       co=current;
02697     }
02698   }
02699 
02700   return _global_range(expr, co);
02701 }
02702 
02703 
02704 
02705 
02706 /*!
02707   We try to prove that:
02708   value_2_mu + mu_2_value > 0
02709 */
02710 bool EvolutionGraph::increasing(const Symbol& value){
02711 /// For now, only do it if &sym is a node in *this.
02712   Expression* dist=min_distance(value, value);
02713   cerr<<"\nEnd of implementation: TODO: compare "<<*dist<<" to 0.";
02714   p_abort("");
02715 }
02716 
02717 
02718 /*!
02719   We look at:
02720   value_2_mu + mu_2_value > 0
02721   Also, we make sure that there are no input values.
02722 */
02723 EvolutionGraph::SequenceType 
02724 EvolutionGraph::sequence_type(const Symbol& value){
02725   if (_loop==0){
02726     return ST_UNKNOWN;
02727   }
02728 /// Let us bring the problem into our own domain.
02729   Symbol* node=(Symbol*)&value;
02730   if (!contains(node)){
02731     /// ...  Let us get its range for the outermost domain within this loop.
02732     DoStmt* loop=def_loop(*node, *_pgm);
02733     if (!inner(loop, (DoStmt*)_loop)){
02734       /// ...  Defined within outer loop, it is invariant here.
02735       return ST_UNKNOWN;
02736     }
02737     /// ...  silvius: for now, return ST_UNKNOWN at this point.
02738     return ST_UNKNOWN;
02739   }
02740 
02741 /// If it gets here, 'node' was defined at this level.
02742 /// Make sure there are no reaching input values.
02743   if (_evolutions_from_input.find(node)!=_evolutions_from_input.end()){
02744     return ST_UNKNOWN;
02745   }
02746 
02747 /// Find value_2_mu and mu_2_value.
02748   EvolutionMap::iterator v2mit=_evolutions_to_mu.find(node);
02749   if (v2mit==_evolutions_to_mu.end()){
02750     return ST_UNKNOWN;
02751   }
02752   EvolutionMap::iterator m2vit=_evolutions_from_mu.find(node);
02753   if (m2vit==_evolutions_from_mu.end()){
02754     return ST_UNKNOWN;
02755   }
02756   
02757 /// For now, do it only if they have exactly one fromMU and exactly one
02758 /// toMU, and it is the same.
02759   if ((*m2vit).second.size()!=1){
02760     return ST_UNKNOWN;
02761   }
02762   const Symbol* mu=(*(*m2vit).second.begin()).first;
02763   EvolutionMap::data_type::iterator v2mitit=(*v2mit).second.find(mu);
02764   if (v2mitit==(*v2mit).second.end()){
02765     return ST_UNKNOWN;
02766   }
02767 
02768 /// Let us compute the aggregated evolution from 'node' to itself.
02769   Evolution<Expression> value2mu=(*v2mitit).second;
02770   Evolution<Expression> mu2value=(*(*m2vit).second.begin()).second;
02771   Evolution<Expression> total=value2mu;
02772   total+=mu2value;
02773 
02774 /// Let us see where this evolution goes.
02775   Expression* zero=constant(0);
02776   List<Expression> automatic_destructor;
02777   automatic_destructor.ins_last(zero);
02778   if (p_greater_than(*total.min_difference(), *zero, _ra)){
02779     return ST_INCREASING;
02780   }
02781   if (p_greater_equal(*total.min_difference(), *zero, _ra)){
02782     return ST_NONDECREASING;
02783   }
02784   if (p_less_than(*total.max_difference(), *zero, _ra)){
02785     return ST_DECREASING;
02786   }
02787   if (p_less_equal(*total.max_difference(), *zero, _ra)){
02788     return ST_NONINCREASING;
02789   }
02790 
02791 /// Just could not figure it out.
02792   return ST_UNKNOWN;
02793 }
02794 
02795 
02796 static void _cleanup_map(map<Symbol*, Expression*>& m){  
02797 /// Cleanup.
02798   map<Symbol*, Expression*>::iterator mit;
02799   for(mit=m.begin(); mit!=m.end(); ++mit){
02800     delete (*mit).second;
02801   }
02802 }
02803 
02804 
02805 Expression* EvolutionGraph::min_distance(const Symbol& left, 
02806                      const Symbol& right){
02807 /// Sanity checks.
02808   p_assert(_loop, "Cannot compute distance for contexts other than loops.");
02809   DoStmt* loop_left=def_loop(left, *_pgm);
02810   DoStmt* loop_right=def_loop(left, *_pgm);
02811   p_assert(outer((DoStmt*)_loop, loop_left), "Symbol not defined in loop.");
02812   p_assert(outer((DoStmt*)_loop, loop_right), "Symbol not defined in loop.");
02813 
02814 
02815 ///   cerr<<"\n\n\n_loop = "<<_loop->get_loop_name();
02816 ///   cerr<<"\n\tSyms = "<<left.name_ref()<<", "<<right.name_ref();
02817 
02818 /// First compute the minimum distance from 'left' to all the MU(_loop) that
02819 /// it reaches.
02820   map<Symbol*, Expression*> min_dist_from_left;
02821   min_dist_from_left.insert(make_pair((Symbol*)&left, constant(0)));
02822 /// Add the distances from all the MUs that may be reached by left.
02823 /// Do it for all the EGs from loop_left to _loop inclussively.
02824   DoStmt* loop=loop_left;
02825   do {
02826     EvolutionGraph* eg=_get_eg(_pgm, loop);
02827 ///     cerr<<"\n\nLEFT loop = "<<loop->get_loop_name();
02828     map<Symbol*, Expression*> new_dists;
02829     map<Symbol*, Expression*>::iterator mit;
02830 ///     for(mit=min_dist_from_left.begin(); mit!=min_dist_from_left.end(); ++mit){
02831 ///       Symbol* sym=(*mit).first;
02832 ///       Expression* dist=(*mit).second;
02833 ///       cerr<<"\n\tsym = "<<sym->name_ref()<<" : "<<*dist;
02834 ///     }    
02835     for(mit=min_dist_from_left.begin(); mit!=min_dist_from_left.end(); ++mit){
02836       Symbol* sym=(*mit).first;
02837       Expression* dist=(*mit).second;
02838       EvolutionMap::iterator found=eg->_evolutions_to_mu.find(sym);
02839       if (found!=eg->_evolutions_to_mu.end()){
02840     /// ...  Found a MU that sym goes into.
02841     for(map<const Symbol*, Evolution<Expression> >::iterator it2=
02842       (*found).second.begin(); it2!=(*found).second.end(); ++it2){
02843       Expression* newdist=
02844         simplify(add(dist->clone(), 
02845              (*it2).second.min_difference()->clone()));
02846       new_dists.insert(make_pair((Symbol*)(*it2).first, newdist));
02847     }
02848       }
02849     }
02850     loop=(DoStmt*)loop->outer_ref();
02851     min_dist_from_left.swap(new_dists);
02852     _cleanup_map(new_dists);
02853   } while (loop!=_loop->outer_ref());
02854 
02855 /// Now compute the minimum distance from all the MU(_loop) that reach 'right'
02856 /// to 'right'.
02857   map<Symbol*, Expression*> min_dist_to_right;
02858   min_dist_to_right.insert(make_pair((Symbol*)&right, constant(0)));
02859   loop=loop_right;
02860   do {
02861     EvolutionGraph* eg=_get_eg(_pgm, loop);
02862 ///     cerr<<"\n\nRIGHT loop = "<<loop->get_loop_name();
02863     map<Symbol*, Expression*> new_dists;
02864     map<Symbol*, Expression*>::iterator mit;
02865 ///     for(mit=min_dist_to_right.begin(); mit!=min_dist_to_right.end(); ++mit){
02866 ///       Symbol* sym=(*mit).first;
02867 ///       Expression* dist=(*mit).second;
02868 ///       cerr<<"\n\tsym = "<<sym->name_ref()<<" : "<<*dist;
02869 ///     }    
02870     for(mit=min_dist_to_right.begin(); mit!=min_dist_to_right.end(); ++mit){
02871       Symbol* sym=(*mit).first;
02872       Expression* dist=(*mit).second;
02873       EvolutionMap::iterator found=eg->_evolutions_from_input.find(sym);
02874       if (found!=eg->_evolutions_from_input.end()){
02875     /// ...  Found an INPUT that goes into sym.
02876     /// ...  silvius: we could do a little better.
02877     _cleanup_map(min_dist_from_left);
02878     _cleanup_map(min_dist_to_right);
02879     _cleanup_map(new_dists);
02880     return constant(0);
02881       }
02882       found=eg->_evolutions_from_mu.find(sym);
02883       if (found!=eg->_evolutions_from_mu.end()){
02884     /// ...  Found a MU that goes into sym.
02885     for(map<const Symbol*, Evolution<Expression> >::iterator it2=
02886       (*found).second.begin(); it2!=(*found).second.end(); ++it2){
02887       Expression* newdist=
02888         simplify(add(dist->clone(), 
02889              (*it2).second.min_difference()->clone()));
02890       new_dists.insert(make_pair((Symbol*)(*it2).first, newdist));
02891     }
02892       }    
02893     }
02894     loop=(DoStmt*)loop->outer_ref();
02895     min_dist_to_right.swap(new_dists);
02896     _cleanup_map(new_dists);
02897   } while (loop!=_loop->outer_ref());
02898 
02899 
02900 /// By default set the distance to Infinity since we do not know whether 
02901 /// they are connected.
02902   Expression* toret=infinity();
02903 /// Now add the distances for all the common MU(_loop).
02904   map<Symbol*, Expression*>::iterator mit, found;
02905   for(mit=min_dist_to_right.begin(); mit!=min_dist_to_right.end(); ++mit){
02906     Symbol* mu=(*mit).first;
02907     Expression* dright=(*mit).second;
02908     found=min_dist_from_left.find(mu);
02909     if (found!=min_dist_from_left.end()){
02910       Expression* dleft=(*found).second;
02911       Expression* candidate=simplify(add(dleft->clone(), dright->clone()));
02912       if (*candidate==*toret){
02913     /// ...  Discard candidate.
02914     delete candidate;
02915       } else {
02916     if (p_less_than(*candidate, *toret, _ra)){
02917       // Keep candidate.
02918       delete toret;
02919       toret=candidate;
02920     } else {
02921       if (p_greater_than(*candidate, *toret, _ra)){
02922         /// ...  Discard candidate.
02923         delete candidate;    
02924       } else {
02925         /// ...  Incomparable, keep MIN.
02926         Symbol* best_op_sym=_pgm->symtab().find_ref("MIN");
02927         p_assert(best_op_sym, "MIN intrinsic not in symbol table");
02928         toret=intrinsic_call(id(*best_op_sym), comma(toret, candidate));
02929       }
02930     }
02931       }
02932     } else {
02933       /// ...  There is a MU that can reach right but there is no path from 
02934       /// ...  left to it.
02935       delete toret;
02936       _cleanup_map(min_dist_from_left);
02937       _cleanup_map(min_dist_to_right);
02938       return constant(0);
02939     }
02940   }
02941 
02942 /// Return.
02943   if (toret->op()==INFINITY_OP){
02944     /// ...  The values are not related, report distance conservatively.
02945     delete toret;
02946     return constant(0);
02947   } else {
02948     return toret;
02949   }
02950 }
02951 
02952 
02953 /// Returns true if ev1 is included in ev2*complementary.
02954 static bool included(Evolution<Expression>& ev1,
02955              Evolution<Expression>& ev2,
02956              bool complementary,
02957              ProgramUnit& pgm,
02958              RangeAccessor* ra){
02959 ///   cerr<<"\nenter included with "<<ev1<<", "<<ev2<<", and "<<complementary;
02960   if (complementary==false){
02961     if (included(ev1, ev2, pgm, ra)){
02962 ///       cerr<<"\n\treturn true 1";
02963       return true;
02964     }
02965   } else {
02966     /// ...  Complementary range.
02967     Evolution<Expression> below=
02968       evolution(infinity(-1), 
02969         simplify(sub(ev2.min_difference()->clone(), constant(1))));
02970     if (included(ev1, below, pgm, ra)){
02971 ///       cerr<<"\n\treturn true 2";
02972       return true;
02973     }
02974     Evolution<Expression> above=
02975       evolution(simplify(add(ev2.max_difference()->clone(), constant(1))), 
02976         infinity(1));
02977     if (included(ev1, above, pgm, ra)){
02978 ///       cerr<<"\n\treturn true 3";
02979       return true;
02980     }
02981   }
02982 ///   cerr<<"\n\treturn false";
02983   return false;
02984 }
02985 
02986 /// Returns true if ev1 may be disjoint from ev2*complementary.
02987 static bool disjoint(Evolution<Expression>& ev1,
02988              Evolution<Expression>& ev2,
02989              bool complementary,
02990              ProgramUnit& pgm,
02991              RangeAccessor* ra){
02992   return included(ev1, ev2, !complementary, pgm, ra);
02993 }
02994 
02995 static void print_trace(pair<list<Symbol*>, Evolution<Expression> >& trace){
02996   for(list<Symbol*>::iterator it=trace.first.begin();
02997       it!=trace.first.end(); ++it){
02998     cerr<<(*it)->name_ref()<<",";
02999   }
03000   cerr<<": "<<trace.second;
03001 }
03002 
03003 void 
03004 EvolutionGraph::traces_from_mu(Symbol* node, 
03005                    pair<RangeExpr*, bool>& range, 
03006                    map<Symbol*, list<list<Symbol*> > >& trace){
03007   Evolution<Expression> given=evolution(*range.first);
03008   EvolutionMap::iterator it=_evolutions_from_mu.find(node);
03009   if (it!=_evolutions_from_mu.end()){
03010     for(map<const Symbol*, Evolution<Expression> >::iterator itmu=
03011       (*it).second.begin(); itmu!=(*it).second.end(); ++itmu){
03012       const Symbol* mu=(*itmu).first;
03013       /// ...  Initialize the traces.
03014       list<pair<list<Symbol*>, Evolution<Expression> > > tlist;
03015       list<Symbol*> initial_trace;
03016       initial_trace.push_back(node);
03017       tlist.push_back(make_pair(initial_trace, evolution(constant(0))));
03018       while(tlist.size()>0){
03019     list<pair<list<Symbol*>, Evolution<Expression> > > new_tlist;
03020 
03021     /// ...  For all old partial traces.
03022     for(list<pair<list<Symbol*>, Evolution<Expression> > >::iterator
03023           llit=tlist.begin(); llit!=tlist.end(); ++llit){
03024 ///       cerr<<"\n\tPartial trace: ";
03025 ///       print_trace(*llit);
03026       list<Symbol*>& clist=(*llit).first;
03027       // Get the last element in the trace.
03028       list<Symbol*>::iterator lit=clist.end();
03029       --lit;
03030       
03031       // Check whether it is a complete trace.
03032       if (*lit==mu){
03033         if (!disjoint((*llit).second, given, range.second, *_pgm, _ra)){
03034           /// ...  BINGO, got a valid trace.
03035 ///           cerr<<"\n\t\tCOMPLETE.";
03036           trace[(Symbol*)mu].push_back((*llit).first);
03037         }
03038       }
03039 
03040       // Check whether it is a valid trace.
03041       EvolutionMap::iterator it1=_evolutions_from_mu.find(*lit);
03042       if (it1==_evolutions_from_mu.end()){
03043         /// ...  No path to any MU.  Discard partial trace, leads nowhere.
03044 ///         cerr<<"\n\t\tNo path to any MU.  Discard.";
03045         continue;
03046       }
03047       map<const Symbol*, Evolution<Expression> >::iterator it2=
03048         (*it1).second.find(mu);
03049       if (it2==(*it1).second.end()){
03050 ///         cerr<<"\n\t\tNo path to current MU.  Discard.";
03051         /// ...  No path to current MU.  Discard partial trace.
03052         continue;
03053       }
03054       Evolution<Expression> total=(*it2).second;
03055       total+=(*llit).second;
03056       if (disjoint(total, given, range.second, *_pgm, _ra)){
03057         /// ...  Cannot extend trace, it cannot be within the given range.
03058 ///         cerr<<"\n\t\ttotal = "<<total;
03059 ///         cerr<<"\n\t\tgiven = "<<given;
03060 ///         cerr<<"\n\t\tOutside given range.  Discard.";
03061         continue;
03062       }
03063       
03064       // Extend traces to all predecessors.
03065       set<Symbol*> candidates;
03066       const EdgeList& edges=get_reversed_edges(index(*lit));
03067       for (EdgeList::const_iterator cit=edges.begin(); 
03068            cit!=edges.end(); ++cit){
03069         /// ...  Pick up a predecessor.
03070         Symbol* cand=(Symbol*)nodes()[(*cit).first];
03071 ///         cerr<<"\n\t\t\tExtend trace to "<<cand->name_ref();
03072         /// ...  Make up new trace by cloning the old one.
03073         pair<list<Symbol*>, Evolution<Expression> > newtrace;
03074         newtrace.first=(*llit).first;
03075         /// ...  Extend new trace.
03076         newtrace.first.push_back(cand);
03077         newtrace.second=(*llit).second;
03078         newtrace.second+=(*cit).second;
03079         /// ...  Add new trace to candidates.
03080         new_tlist.push_back(newtrace);
03081       }
03082     }
03083 
03084     // Swap old/new lists.
03085     tlist.swap(new_tlist);
03086       }
03087     }
03088   }  
03089 }
03090 
03091 
03092 /// Get the bacwards trace from 'node' towards 'mu' assuming that
03093 /// the length of the path must be exactly 'given_length'.
03094 void EvolutionGraph::perfect_trace_from_mu(Symbol* mu, Symbol* node, 
03095                        const Expression& given_length,
03096                        list<Symbol*>& trace){
03097   if (node==mu){
03098     trace.push_back(mu);
03099     return;
03100   }
03101   Statement* stmt=_loop;
03102   if (!stmt){
03103     stmt=&quick_pgm_entry(*_pgm);
03104   }
03105   RangeAccessor ra(_pgm->range_dict_guarded(), *range_stmt(*stmt));
03106   const EdgeList& edges=get_reversed_edges(index(node));
03107 ///   cerr<<"\nnode = "<<node->name_ref();
03108 ///   cerr<<"\nmu = "<<mu->name_ref();
03109   
03110   Symbol* prev=0;
03111   Expression* newlength=0;
03112   for (EdgeList::const_iterator cit=edges.begin(); 
03113        cit!=edges.end(); ++cit){
03114     Symbol* cand=(Symbol*)nodes()[(*cit).first];
03115 ///     cerr<<"\ncand = "<<cand->name_ref();
03116     Evolution<Expression> edge=(*cit).second;
03117     
03118     EvolutionMap::iterator muevit=_evolutions_from_mu.find(cand);
03119     if (muevit==_evolutions_from_mu.end()){
03120       /// ...  No MU evs for this node.
03121       continue;
03122     }
03123     EvolutionMap::data_type::iterator it=(*muevit).second.find(mu);
03124     if (it==(*muevit).second.end()){
03125       /// ...  No path from 'mu'.
03126       continue;
03127     }
03128     if (!(*edge.min_difference()==*edge.max_difference())){
03129       /// ...  Cannot go on edges with nontrivial range.
03130       continue;
03131     }
03132 
03133     Evolution<Expression> muev=(*it).second;
03134     Evolution<Expression> total=muev;
03135     total+=edge;
03136 ///     cerr<<"\ntotal = "<<total;
03137 ///     cerr<<"\ngiven = "<<given_length;
03138     /// ...  Let us see whether 'total' may contain 'given_length'
03139     if ( (! ::p_less_than(given_length, *total.min_difference(), _ra)) &&
03140      (! ::p_greater_than(given_length, *total.max_difference(), _ra)) ){
03141       if (prev){
03142     /// ...  Ambiguous.
03143     delete newlength;
03144     return;
03145 ///     p_abort("Ambiguous trace from MU.");
03146       } else {
03147     prev=cand;
03148     newlength=simplify(sub(given_length.clone(), 
03149                    edge.min_difference()->clone()));
03150       }
03151     }
03152   }
03153   trace.push_back(node);
03154   perfect_trace_from_mu(mu, prev, *newlength, trace);
03155 }
03156 
03157 
03158 void EvolutionGraph::perfect_trace_from_mu(Symbol* node, 
03159                        pair<RangeExpr*, bool>& range, 
03160                        list<Symbol*>& trace){
03161   if (back_this_loop.find(index(node))==back_this_loop.end()){
03162     p_abort("Perfect traces only start at BACK nodes.");
03163   }
03164 ///   cerr<<"\nEnter perfect_trace_from_mu : "<<node->name_ref();
03165 /// First, let us find whether there is a unique MU node that can reach
03166 /// 'node' such that the range of 'node' through that MU is within 'range'.
03167   EvolutionMap::iterator musit=_evolutions_from_mu.find(node);
03168   p_assert(musit!=_evolutions_from_mu.end(), "No reaching MU for given node.");
03169   EvolutionMap::data_type& mus=(*musit).second;
03170 
03171 /// silvius: for now, only do it if it is reachable by exactly one MU.
03172   if (mus.size()!=1){
03173     return;
03174   }
03175   const Symbol* mu=(*mus.begin()).first;
03176   Symbol* imu;
03177   bool imu_is_defined;
03178   get_imu(*mu, *_pgm, imu, imu_is_defined);
03179   if (!imu_is_defined){
03180     /// ...  Unknown definition.  No INPUT, no IMU, something is wrong.
03181     cerr<<*mu;
03182     p_warning("Undefined imu value.");
03183     return;
03184   }
03185 /// For now, only do it if this MU is reachable by itself, and not by 
03186 /// any other MU.
03187   EvolutionMap::iterator mu_mus_it=_mu_evolutions.find(mu);
03188   if (mu_mus_it==_mu_evolutions.end()){
03189     return;
03190   }
03191   EvolutionMap::data_type& mu_mus=(*mu_mus_it).second;
03192   if (mu_mus.size()!=1){
03193     return;
03194   }
03195   if ((*mu_mus.begin()).first!=mu){
03196     return;
03197   }
03198   
03199 /// For now, the only thing we do is check the given range (less the mu input)
03200 /// against the extremes of the possible range.  For instance, if the possible
03201 /// range for an iteration (muev) is [0:1], the iteration count is 10,
03202 /// and the given range is [0:0], then the range for each iteration is 
03203 /// actually [0:0], so only paths made entirely of 0-edges are possible.
03204   Evolution<Expression> muev=(*mu_mus.begin()).second;
03205   Evolution<Expression> allev=muev;
03206   if (_loop){
03207     allev*=iteration_count((DoStmt&)*_loop, *_pgm);
03208   }
03209   allev+=evolution(id(*imu));
03210   Evolution<Expression> r1,r2;
03211   if (range.second){
03212     r1=evolution(infinity(-1), 
03213          simplify(sub(range.first->lb().clone(), constant(1))));
03214     r2=evolution(simplify(add(range.first->ub().clone(), constant(1))),
03215          infinity(+1));
03216     p_warning("Incomplete implementation.");
03217   } else {
03218     Statement* rs;
03219     if (_loop){
03220       rs=_loop;
03221     } else {
03222       rs=_pgm->stmts().last_ref();
03223     }
03224     RangeAccessor ra(_pgm->range_dict_guarded(), *rs);
03225     r1=evolution(range.first->lb().clone(), range.first->ub().clone());
03226 ///     cerr<<"\nallev = "<<allev
03227 ///     <<", r1 = "<<r1;
03228     Relation r=ra.compare(*r1.min_difference(),*allev.max_difference());
03229 ///     cerr<<"\n\tr = "<<r;
03230     if (r.is_equal()){
03231       /// ...  Got it.
03232       perfect_trace_from_mu((Symbol*)mu, node, *muev.max_difference(), 
03233                 trace);
03234     } else {
03235       r=ra.compare(*r1.max_difference(), *allev.min_difference());
03236 ///       cerr<<"\n\tr = "<<r;
03237       if (r.is_equal()){
03238     /// ...  Got it.
03239     perfect_trace_from_mu((Symbol*)mu, node, 
03240                   *muev.min_difference(), trace);
03241       }
03242     }
03243   }
03244 }
03245 
03246 
03247 /// Return true only if sure.
03248 /// Return false when either compatible or unsure.
03249 static bool _incompatible_ranges(const pair<RangeExpr*, bool>& range1,
03250                  const pair<RangeExpr*, bool>& range2,
03251                  RangeAccessor& ra){
03252 
03253   if (range1.second==false && range2.second==false){
03254     /// ...  [.......]
03255     /// ...             [.......]
03256     return (p_less_than(range2.first->ub(), 
03257             range1.first->lb(), &ra) ||
03258         p_less_than(range1.first->ub(), 
03259             range2.first->lb(), &ra));
03260   }
03261   if (range1.second==true && range2.second==false){
03262     /// ...  .......]               [...............
03263     /// ...             [.......]
03264     return (p_greater_equal(range2.first->lb(), 
03265                 range1.first->lb(), &ra) &&
03266         p_less_equal(range2.first->ub(), 
03267              range1.first->ub(), &ra));
03268   }
03269   if (range1.second==false && range2.second==true){
03270     /// ...             [.......]
03271     /// ...  .......]               [...............
03272     return (p_greater_equal(range1.first->lb(), 
03273                 range2.first->lb(), &ra) &&
03274         p_less_equal(range1.first->ub(), 
03275              range2.first->ub(), &ra));
03276   }
03277   if (range1.second==true && range2.second==true){
03278     return false;
03279   }
03280 
03281   p_abort("Sanity check failed: control should have not gotten here.");
03282 }
03283 
03284 /// Execute the program backwards and remember the trace.
03285 /// The final value of 'node' must stay within 'range'.
03286 /// Stop at the first ambiguity.
03287 /// Stop at this loop level (either MU or INPUT site).
03288 /// Skip called subprograms and inner loops.
03289 void EvolutionGraph::backtrack(Symbol* node, 
03290                    pair<RangeExpr*, bool>& range,
03291                    list<Symbol*>& trace){
03292   bool from_mu=false;
03293   bool from_input=false;
03294 /// First, let us find all the possible values for the given node,
03295 /// together with their sources (INPUT and MU).
03296   list<pair<
03297     list<Symbol*>, /// ...  E.g. INPUT1, MU1, MU2, ..., MUn, [node]
03298     RangeExpr* > > basic_sources, valid_sources;
03299   _possible_ranges(*node, basic_sources);
03300   list<pair<list<Symbol*>, RangeExpr* > >::iterator it;
03301 ///   cerr<<"\n\n\nSOURCES for "<<node->name_ref()<<" in "<<
03302 ///       loop_name(_loop)<<": ";
03303   for(it=basic_sources.begin(); it!=basic_sources.end(); ++it){
03304 ///     cerr<<"\n\t";
03305     list<Symbol*>::iterator sit;
03306     for(sit=(*it).first.begin(); sit!=(*it).first.end(); ++sit){
03307       cerr<<(*sit)->name_ref()<<" ";
03308     }
03309 ///     cerr<<"\t:\t"<<*(*it).second;
03310     if (_incompatible_ranges(make_pair((*it).second, false), range, *_ra)){
03311 ///       cerr<<"\n\t\tINCOMPATIBLE";
03312       delete (*it).second;
03313     } else {
03314 ///       cerr<<"\n\t\tCOMPATIBLE";
03315       valid_sources.push_back(*it);
03316       if (mu_this_loop.find(index(*(*it).first.begin()))!=mu_this_loop.end()){
03317     from_mu=true;
03318       } else {
03319     from_input=true;
03320       }
03321     }
03322   }
03323 
03324 /// silvius: for now, do nothing if the loop contains both MU and INPUT 
03325 /// sources for the given node.
03326   if (from_mu && from_input){
03327 ///     cerr<<"\nBoth from_mu && from_input.";
03328     return;
03329   }
03330   if (from_mu){
03331     /// ...  Trace from MU.
03332     /// ...  First look for perfect traces.
03333     if (back_this_loop.find(index(node))!=back_this_loop.end()){
03334       perfect_trace_from_mu(node, range, trace);
03335       if (trace.size()>0){
03336     return;
03337       }
03338     }
03339     /// ...  Now look for other traces.
03340     map<Symbol*, list<list<Symbol*> > > all_traces;
03341     traces_from_mu(node, range, all_traces);
03342     if (all_traces.size()!=1){
03343       /// ...  Traces from more than one MU.
03344 ///       cerr<<"\nTraces from more than one MU.";
03345       return;
03346     }
03347     list<list<Symbol*> >& traces=(*all_traces.begin()).second;
03348     if (traces.size()!=1){
03349       /// ...  Multiple paths from this MU.
03350 ///       cerr<<"\nMultiple paths from this MU.";
03351       return;
03352     }
03353     trace=*(traces.begin());
03354   }
03355   if (from_input){
03356     /// ...  Trace from INPUT.
03357     trace_from_input(node, range, trace);
03358     if (trace.size()>0){
03359       trace.push_front(node);
03360     }
03361   }
03362 }
03363 
03364 void _print_range(const char* sname, const pair<RangeExpr*, bool>& r);
03365 
03366 
03367 void EvolutionGraph::trace_from_input(Symbol* node, 
03368                       pair<RangeExpr*, bool>& range, 
03369                       list<Symbol*>& trace){
03370 ///   cerr<<"\n\n\tEnter trace_from_input (";
03371 ///   _print_range(node->name_ref(), range);
03372 ///   cerr<<") in loop "<<loop_name(_loop);
03373 ///   print_evolutions(_evolutions_from_input, "from input", cerr);
03374   Evolution<Expression> given=evolution(*range.first);
03375   set<const Symbol*> solutions;
03376   EvolutionMap::iterator it=_evolutions_from_input.find(node);
03377   if (it!=_evolutions_from_input.end()){
03378     for(map<const Symbol*, Evolution<Expression> >::iterator it2=
03379       (*it).second.begin(); it2!=(*it).second.end(); ++it2){
03380       const Symbol* isym=(*it2).first;
03381       Evolution<Expression> ev=_input_values[isym];
03382       ev+=(*it2).second;
03383 ///       cerr<<"\n\t\t\tLooking at input: "<<isym->name_ref()
03384 ///       <<" with total range "<<ev;
03385       RangeExpr* rev=_range(ev);
03386       if (!_incompatible_ranges(range, make_pair(rev, false), *_ra)){
03387     solutions.insert(isym);
03388       }
03389       delete rev;
03390     }
03391 ///     cerr<<"\nsolution count: "<<solutions.size();
03392     if (solutions.size()==0){
03393       /// ...  Could not find any trace for sure.
03394       return;
03395     }
03396 ///     cerr<<"\n\t"<<(*solutions.begin())->name_ref();
03397     /// ...  Find all edges on all the paths from 'solutions' to 'node' then 
03398     /// ...  go backwards until the first fork.
03399     /// ...  silvius: will take a shortcut.  This hopes that all the edges are 0
03400     /// ...  (but is conservative as it may only report more paths).
03401     Symbol* current=node;
03402     while (1) {
03403 ///       cerr<<"\n\t\tNow at current "<<current->name_ref();
03404       const EdgeList& edges=get_reversed_edges(index(current));
03405       Symbol* pred=0;
03406       for (EdgeList::const_iterator cit=edges.begin(); 
03407        cit!=edges.end(); ++cit){
03408     /// ...  Pick up a parent.
03409     Symbol* cand=(Symbol*)nodes()[(*cit).first];
03410 ///     cerr<<"\n\t\t\tcand= "<<cand->name_ref();
03411     EvolutionMap::iterator found_ivs=_evolutions_from_input.find(cand);
03412     if (found_ivs!=_evolutions_from_input.end()){
03413       // There is a path from an input node to it.
03414       for(map<const Symbol*, Evolution<Expression> >::iterator it2=
03415         (*found_ivs).second.begin(); 
03416           it2!=(*found_ivs).second.end(); ++it2){
03417         const Symbol* icand=(*it2).first;
03418 ///         cerr<<"\n\t\t\t\ticand = "<<icand->name_ref();
03419         /// ...  Check whether any of its reaching ivs is in 'solutions'
03420         if (solutions.find(icand)!=solutions.end()){
03421 ///           cerr<<"\n\t\t\t\thas reaching input with valid path.";
03422           /// ...  It is on the path to an ivs.
03423           if (pred){
03424         /// ...  Dichotomy.
03425         return;
03426           } else {
03427         pred=(Symbol*)cand;
03428         break;
03429           }
03430         }
03431       }
03432     }
03433       }
03434       if (pred){
03435     /// ...  Found a predecessor towards the ivs.
03436 ///     cerr<<"\n\t\t\t\tadd to trace: "<<pred->name_ref();
03437     trace.push_back(pred);
03438     current=pred;
03439       } else {
03440     /// ...  Nowhere to go.
03441     return;
03442       }
03443     }
03444   }
03445 }
03446 
03447 void EvolutionGraph::get_trace_details(list<Symbol*>& trace,
03448                        Evolution<Expression>& ev,
03449                        Expression*& length,
03450                        List<Expression>& preds){
03451 /// Initialize results.
03452   ev=evolution(constant(0));
03453   length=constant(0);
03454   preds.clear();
03455 
03456 /// Applicability check.
03457   if (trace.size()<2){
03458     return;
03459   }
03460 
03461 /// Chew it up.
03462   list<Symbol*>::iterator it1=trace.begin();
03463   list<Symbol*>::iterator it2=it1;
03464   ++it2;
03465   do {
03466     const Evolution<Expression>* edge=get_reversed_edge(*it1, *it2);
03467     p_assert(edge, 
03468          "The given trace contains an edge that is not in the graph.");
03469 
03470     /// ...  Update evolution.
03471     ev+=*edge;
03472 ///     cerr<<"\n\tAt edge: "<<*edge;
03473 
03474     /// ...  Update length.
03475     if (*edge->min_difference()==*edge->max_difference()){
03476       length=simplify(add(length, edge->min_difference()->clone()));
03477     } else {
03478       length=simplify(add(length, sub(id(**it1),id(**it2))));
03479     }
03480 
03481     /// ...  Update predicate list.
03482     DefLoc* defloc=_pgm->gsa_deflocs_guarded().find_ref(**it1);
03483     if (defloc->stmt_valid()) {
03484       Statement& def=defloc->stmt_guarded();
03485       if (def.stmt_class()==ASSIGNMENT_STMT){
03486     if (def.rhs().op()==GAMMA_OP){
03487       List<Expression>& args=def.rhs().parameters_guarded().arg_list();
03488       if (&args[0].symbol()==*it2){
03489         preds.ins_last(def.rhs().gate().clone());
03490       } else {
03491         if (&args[1].symbol()==*it1){
03492           preds.ins_last(simplify(not(def.rhs().gate().clone())));
03493         }
03494       }
03495     }
03496       }
03497     }
03498     
03499     /// ...  Next, please.
03500     it1=it2;
03501     ++it2;
03502   } while (it2!=trace.end());
03503 }
03504 
03505 
03506 
03507 /// Performs forward substitution on demand such as:
03508 /// x -> y, ev=[1,1] ==> y = x+1
03509 Expression* EvolutionGraph::substitute(Symbol* given){
03510 /// If it is not here, return.
03511   if (!contains(given)){
03512     return 0;
03513   }
03514 /// If it is a MU, return.
03515   if (mu_this_loop.find(index(given))!=mu_this_loop.end()){
03516     return 0;
03517   }
03518 
03519   const EdgeList& edges=get_reversed_edges(index(given));
03520   if (edges.size()!=1){
03521     return 0;
03522   }
03523   Symbol* pred=nodes()[(*edges.begin()).first];
03524   const Evolution<Expression>& edge=(*edges.begin()).second;
03525   if (*edge.min_difference()==*edge.max_difference()){
03526     Expression* predvalue=substitute(pred);
03527     if (predvalue==0){
03528       predvalue=id(*pred);
03529     }
03530     return simplify(add(predvalue,
03531             edge.min_difference()->clone()));
03532   }
03533   return 0;
03534 }
03535 
03536 
03537 
03538 /*!
03539   \brief Return the reaching MU and BACK for this intermediate symbol
03540   and return TRUE if they are unique.  Also, only return TRUE if MU cannot be
03541   reached from any other MU.  Also, only return TRUE if MU cannot be reached 
03542   from any input.
03543 */
03544 bool EvolutionGraph::find_unique_mu(Symbol* node, Symbol*& mu, Symbol*& back){
03545   mu=back=0;
03546   EvolutionMap::iterator it=_evolutions_from_mu.find(node);
03547   
03548 /// Find the unique reaching MU.
03549   if (it!=_evolutions_from_mu.end()){
03550     /// ...  Reaching MUs.
03551     if ((*it).second.size()==1){
03552       /// ...  GOOD.
03553       mu=(Symbol*)(*(*it).second.begin()).first;
03554     } else {
03555 ///       cerr<<"\nRET 1";
03556       return false;
03557     }
03558   } else {
03559     /// ...  Cannot be reached by any MU
03560 ///       cerr<<"\nRET 2";
03561     return false;
03562   }
03563 
03564 /// Make sure that MU can be reached by itself, but no other MUs.
03565   it=_mu_evolutions.find(mu);
03566   if (it!=_mu_evolutions.end()){
03567     if ((*it).second.size()==1){
03568       if (mu==(*(*it).second.begin()).first){
03569     /// ...  GOOD.
03570     back=(Symbol*)_back_edges_reversed[mu];
03571       } else {
03572     /// ...  MU can be reached by another MU.
03573 ///     cerr<<"\nRET 3";
03574     return false;
03575       }
03576     } else {
03577 ///     cerr<<"\nRET 4";
03578       return false;
03579     }
03580   } else {
03581     /// ...  MU cannot be reached by any other MU.
03582 ///     cerr<<"\nRET 5";
03583     return false;
03584   }
03585 
03586 /// Make sure that MU cannot be reached by any INPUT.
03587   it=_input2mu_evolutions.find(mu);
03588   if (it==_input2mu_evolutions.end()){
03589     /// ...  BINGO.
03590     return true;
03591   } else {
03592     /// ...  MU can be reached by an INPUT.
03593 ///     cerr<<"\nRET 6";
03594     return false;
03595   }
03596 }
03597 
03598 
03599 
03600 void EvolutionGraph::enhance(map<Symbol*, Symbol*>& imposed_edges){
03601   p_abort("Not implemented.");
03602 }
03603 
03604 void EvolutionGraph::undo_enhancement(){
03605   p_abort("Not implemented.");
03606 }
03607 
03608 
03609 void EvolutionGraph::_p_abort(const char *file, 
03610                   int line, const char *str){
03611   cerr<<"\nEvolutionGraph fatal message follows (see files 'error.veg.f' "
03612       <<"and 'error.veg.dot'):"
03613       <<"\nIn pgm. "<<_pgm->routine_name_ref()
03614       <<", at loop "<<loop_name(_loop);
03615   ofstream err("error.veg.f");
03616   program().write(err);
03617   err.close();
03618   print_graph("error.veg.dot");
03619   ::_p_abort(file, line, str);
03620 }
03621 
03622 
03623 /*!
03624   \brief Compute the range of the given expression if it can be inferred
03625   from input values only.  If so, do not express the input values using
03626   RangeDictionary.  Otherwise, return 0.
03627 */
03628 Expression* EvolutionGraph::range_from_input(Symbol& s){
03629 
03630 /// Quick check.  If there are any MU nodes reaching this symbol, return 0.
03631   if (_evolutions_from_mu.find(&s)!=_evolutions_from_mu.end()){
03632     return 0;
03633   }
03634 
03635   map<const Symbol*, Evolution<Expression> > todo, result;
03636   if (!contains(&s)){
03637     /// ...  Symbol not in this VEG.
03638     return 0;
03639   }
03640   todo[(const Symbol*)&s]=evolution(0);
03641 
03642   while(todo.size()>0){
03643     const Symbol* n=(*todo.begin()).first;
03644     Evolution<Expression> sofar=(*todo.begin()).second;
03645     todo.erase(todo.begin());
03646 
03647     if (input_this_loop.find(index((Symbol*)n))!=input_this_loop.end()){
03648       /// ...  Made it to the input.
03649       sofar+=_input_values[n];
03650       result[n]=sofar;
03651       continue;
03652     }
03653 
03654     if (mu_this_loop.find(index((Symbol*)n))!=mu_this_loop.end()){
03655       /// ...  Got to a MU, get out.
03656       return 0;
03657     }    
03658 
03659     /// ...  Go on.
03660     const EdgeList& edges=get_reversed_edges(index((Symbol*)n));
03661     for (EdgeList::const_iterator cit=edges.begin(); 
03662      cit!=edges.end(); ++cit){
03663       /// ...  Pick up a parent.
03664       Symbol* cand=(Symbol*)nodes()[(*cit).first];
03665       Evolution<Expression> ev=sofar;
03666       ev+=(*cit).second;
03667       todo.insert(make_pair(cand, ev));
03668     }
03669   }
03670 
03671 /// Merge results.
03672   p_assert(result.size()>0, 
03673        "Logic error in EvolutionGraph::range_from_input.");
03674   map<const Symbol*, Evolution<Expression> >::iterator it=result.begin();
03675   Evolution<Expression> toret=(*it).second;
03676   ++it;
03677   for(; it!=result.end(); ++it){
03678     Evolution<Expression> ev=(*it).second;
03679     toret=merge_unite(toret, ev, *_pgm, _ra);
03680   }
03681   return new RangeExpr(toret.min_difference()->clone(),
03682                toret.max_difference()->clone());
03683 }
03684 
03685 
03686 /// Export evolution knowledge for a node.
03687 void EvolutionGraph::
03688 export_evolutions(Symbol* node, 
03689           map<const Symbol*, Evolution<Expression> >& muevs,
03690           list<pair<const Symbol*, Evolution<Expression> > >& ievs){
03691   if (!contains(node)){
03692     return;
03693   }
03694   
03695 /// MU evs.
03696   EvolutionMap::iterator it=_evolutions_from_mu.find(node);
03697   if (it!=_evolutions_from_mu.end()){
03698     muevs=(*it).second;
03699   }
03700 
03701 /// INPUT evs.
03702   it=_evolutions_from_input.find(node);
03703   if (it!=_evolutions_from_input.end()){
03704     for(map<const Symbol*, Evolution<Expression> >::iterator it2=
03705       (*it).second.begin(); it2!=(*it).second.end(); ++it2){
03706       const Symbol* isym=(*it2).first;
03707       Evolution<Expression> ev=_input_values[isym];
03708       ev+=(*it2).second;
03709       ievs.push_back(make_pair(isym, ev));
03710     }
03711   }
03712 }
 © 1995-2005 University of Illinois, Urbana-Champaign. All rights reserved.  Fri Mar 25 23:05:47 2005