Polaris: eg_traces.cc Source File

eg_traces.cc

Go to the documentation of this file.
00001 ///
00002 ///
00003 ///
00004 ///
00005 ///
00006 #include "EvolutionGraph.h"
00007 #include "eg_utils.h"
00008 #include "affine.h"
00009 #include "BackTrace.h"
00010 
00011 #include "ip_ssa/trans_util.h"
00012 #include "ip_ssa/optimize_ssa.h"
00013 
00014 #include "guarded_values.h"
00015 
00016 EvolutionGraph* _get_eg(ProgramUnit* pgm, Statement* loop);
00017 
00018 
00019 /*!
00020   \brief Find all possible traces from input values to given node so that
00021   the input value + evolutions on the road are within the given range.
00022 */
00023 void eg_trace_from_input(ProgramUnit& pgm, 
00024              DoStmt* loop,
00025              pair<RangeExpr*, bool>& range, 
00026              Symbol* node,
00027              DefTrace::DTrace& dt){
00028   list<Symbol*> trace;
00029   _get_eg(&pgm, loop)->trace_from_input(node, range, trace);
00030   for(list<Symbol*>::iterator it=trace.begin(); it!=trace.end(); ++it){
00031     dt.push_back(make_pair(&pgm, *it));
00032   }
00033 }
00034 
00035 /*!
00036   \brief Performs forward substitution on demand.
00037   
00038   x -> y, ev=[1,1] ==> y = x+1
00039   \warning Returns 0 if no proper substitution can be found
00040   (rather than returning id(*given) as would seem fit).
00041 */
00042 Expression* eg_forward_substitute(ProgramUnit& pgm, Symbol& sym){
00043   EvolutionGraph* eg=_get_eg(&pgm, def_loop(sym, pgm));
00044   return eg->substitute(&sym);
00045 }
00046 
00047 /*!
00048   \brief Performs forward substitution on demand.
00049 */
00050 Expression* eg_forward_substitute(ProgramUnit& pgm, DoStmt* loop,
00051                   Expression* expr){
00052   EvolutionGraph* eg=_get_eg(&pgm, loop);
00053   RefList<Symbol> syms;
00054   referred_symbols(*expr, syms);
00055   for(Iterator<Symbol> sit=syms; sit.valid(); ++sit){
00056     Symbol& sym=sit.current();
00057     Expression* s=eg->substitute(&sym);
00058     if (s){
00059       expr=simplify(substitute_var(expr, sym, *s));
00060       delete s;
00061     }
00062   }
00063   return expr;
00064 }
00065 
00066 
00067 static Statement* is_mu_sym(Symbol& sym, ProgramUnit& pgm){
00068   DefLoc* defloc=pgm.gsa_deflocs_guarded().find_ref(sym);
00069   if (defloc->stmt_valid()) {
00070     Statement& def=defloc->stmt_guarded();
00071     if (def.stmt_class()==ASSIGNMENT_STMT){
00072       if(def.rhs().op()==MU_OP){
00073     if (&def.lhs().symbol()==&sym){
00074       return def.outer_ref();
00075     }
00076       }
00077     }
00078   }
00079   return 0;
00080 }
00081 
00082 static Symbol& get_back_sym(Symbol& sym, ProgramUnit& pgm){
00083 /// 'sym' must be MU symbol.
00084   DefLoc* defloc=pgm.gsa_deflocs_guarded().find_ref(sym);
00085   if (defloc->stmt_valid()) {
00086     Statement& def=defloc->stmt_guarded();
00087     if (def.stmt_class()==ASSIGNMENT_STMT){
00088       if(def.rhs().op()==MU_OP){
00089     if (&def.lhs().symbol()==&sym){
00090       return def.rhs().parameters_guarded().arg_list()[1].symbol();
00091     }
00092       }
00093     }
00094   }
00095   p_abort("Could not find BACK for given MU.");
00096 }
00097 
00098 static Evolution<Expression> get_evolution(EvolutionGraph& veg, 
00099                        Symbol* source, Symbol* dest){
00100 ///   cerr<<"\ns = "<<source->name_ref()
00101 ///       <<", d = "<<dest->name_ref();
00102   const Evolution<Expression>* found=veg.get_edge(source, dest);
00103   if (found!=0){
00104     return *found;
00105   } else {
00106     p_abort("Edge not in graph.");
00107   }
00108 }
00109 
00110 static pair<RangeExpr*, bool> 
00111 subtract_evolution(pair<RangeExpr*, bool>& range,
00112            const Evolution<Expression>& ev){
00113   pair<RangeExpr*, bool> toret;
00114   if (*ev.min_difference()==*ev.max_difference()){
00115     toret=make_pair(new RangeExpr(simplify(sub(range.first->lb().clone(), 
00116                            ev.min_difference()->clone())),
00117                   simplify(sub(range.first->ub().clone(), 
00118                            ev.min_difference()->clone()))),
00119             range.second);
00120     delete range.first;
00121   } else {
00122     if (range.second==false){
00123       toret=
00124     make_pair(new RangeExpr(simplify(sub(range.first->lb().clone(), 
00125                          ev.max_difference()->clone())),
00126                 simplify(sub(range.first->ub().clone(), 
00127                          ev.min_difference()->clone()))),
00128           false);
00129       delete range.first;
00130     } else {
00131       p_abort("Not implemented");
00132     }
00133   }
00134   return toret;
00135 }
00136 
00137 
00138 static Statement* callsite(ProgramUnit& pgm, Symbol& sym){
00139   DefLoc* defloc=pgm.gsa_deflocs_guarded().find_ref(sym);
00140   p_assert(defloc, "Could not find definition for symbol.");
00141   if (defloc->stmt_valid()){
00142     ProgramUnit* callee=called_pgm(defloc->stmt_guarded());
00143     if (callee){
00144       return &defloc->stmt_guarded();
00145     }
00146     if (defloc->stmt_guarded().stmt_class()==ASSIGNMENT_STMT){
00147       if (defloc->stmt_guarded().rhs().op()==THETA_OP){
00148     Statement* ps=&defloc->stmt_guarded();
00149     while(ps->stmt_class()==ASSIGNMENT_STMT){
00150       if (ps->rhs().op()!=THETA_OP){
00151         return ps;
00152       }
00153       ps=ps->prev_ref();
00154     }
00155     return ps;
00156       }
00157     }
00158   }
00159   return 0;
00160 }
00161 
00162 void _print_range(const char* sname, const pair<RangeExpr*, bool>& r);
00163 
00164 
00165 
00166 static pair<RangeExpr*, bool> 
00167 _translate_range(const pair<RangeExpr*, bool>& range,
00168          ProgramUnit& callee,
00169          ProgramUnit& caller,
00170          Statement& callsite){
00171   Expression* range_callee=range.first->clone();
00172   RefList<Symbol> syms;
00173   referred_symbols(*range.first, syms);
00174   for(Iterator<Symbol> sit=syms; sit.valid(); ++sit){
00175     Symbol& s=sit.current();
00176     
00177     RefList<Symbol> outs=untranslate_var(s, callee, caller, callsite);
00178     if (outs.entries()!=1){
00179       delete range_callee;
00180       return make_pair((RangeExpr*)0, false);
00181     }
00182     Symbol& s_callee=outs[0];
00183     Symbol* sgsa_callee=last_gsa_symbol(callee, s_callee);
00184     substitute_var(*range_callee, s, *sgsa_callee);
00185   }
00186   return make_pair((RangeExpr*)range_callee, range.second);
00187 }
00188 
00189 static Symbol* symgsa_callee(Symbol& sym,
00190                  ProgramUnit& callee,
00191                  ProgramUnit& caller,
00192                  Statement& callsite){
00193   RefList<Symbol> outs=untranslate_var((VariableSymbol&)sym, 
00194                        callee, caller, callsite);
00195   if (outs.entries()!=1){
00196     return 0;
00197   }
00198   Symbol& sym_callee=outs[0];
00199   return last_gsa_symbol(callee, sym_callee);  
00200 }
00201 
00202 
00203 /*!
00204   \brief Finds the full backwards trace.
00205 
00206   \warning Will consume 'range.first'.
00207 */
00208 void eg_backtrack(ProgramUnit& pgm, Symbol& sym, pair<RangeExpr*, bool> range,
00209           BackTrace& trace){
00210 /// First find the VEG where 'sym' is defined.
00211   Statement* loop=0;
00212   DefLoc* defloc=pgm.gsa_deflocs_guarded().find_ref(sym);
00213   if (defloc->stmt_valid()) {
00214     Statement& def=defloc->stmt_guarded();
00215     if (def.stmt_class()==DO_STMT){
00216       return;
00217     }
00218     loop=def.outer_ref();
00219   }
00220   EvolutionGraph* veg=_get_eg(&pgm, loop);
00221 
00222 /// Find the trace at this level.
00223   list<Symbol*> basic_trace;
00224   cerr<<"\nCalling veg::backtrack: ";
00225   _print_range(sym.name_ref(), range);
00226   veg->backtrack(&sym, range, basic_trace);
00227   if (basic_trace.size()==0){
00228     basic_trace.push_back(&sym);
00229   }
00230 
00231   cerr<<"\nBasic trace: ";
00232 /// Copy the trace information in multi-level format.
00233   for(list<Symbol*>::iterator it=basic_trace.begin(); 
00234       it!=basic_trace.end(); ++it){
00235     TraceSite ts;
00236     cerr<<"\t"<<(*it)->name_ref();
00237     ts.sym=*it;
00238     ts.inner=0;
00239     trace.push_back(ts);
00240   }
00241 
00242 /// Extend the trace to inner levels.
00243   if (trace.size()==1){
00244     /// ...  This can only be useful if we are at a callsite.
00245     /// ...  Check for call sites;
00246     Statement* cs=callsite(pgm, *(*trace.begin()).sym);
00247     if (cs){
00248       BackTrace::iterator btit=trace.begin();
00249       ProgramUnit* callee=called_pgm(*cs);
00250       Symbol* csym=symgsa_callee(*(*btit).sym, *callee, pgm, *cs);
00251       pair<RangeExpr*, bool> range_callee=
00252     _translate_range(range, *callee, pgm, *cs);
00253       if (csym==0 || range_callee.first==0){
00254     delete range.first;
00255     return;
00256       }
00257       InnerTrace* inner=new InnerTrace;
00258       eg_backtrack(*callee, *csym, range_callee, inner->trace);
00259       delete range.first;
00260       if (inner->trace.size()>0){
00261     (*btit).inner=inner;
00262     (*btit).inner->context=make_pair(&pgm, cs);
00263     (*btit).inner->type=LTT_UNKNOWN;
00264       } else {
00265     delete inner;
00266     trace.clear();
00267       }
00268       return;
00269     } else {
00270       trace.clear();
00271       delete range.first;
00272       return;
00273     }
00274   }
00275 
00276   BackTrace::iterator btit=trace.begin();
00277   Symbol* current=(*btit).sym;
00278   ++btit;
00279   Statement* inner_loop=is_mu_sym(*current, pgm);
00280   if (inner_loop){
00281     if (inner_loop==loop){
00282       p_abort("'backtrack' on a MU symbol is undefined.");
00283     }
00284   }
00285   Symbol* last=current;
00286   do {
00287     current=(*btit).sym;
00288 ///     cerr<<"\nCurrent = "<<current->name_ref();
00289 ///     cerr<<", last = "<<last->name_ref();
00290     range=subtract_evolution(range, get_evolution(*veg, current, last));
00291     /// ...  Check for MU symbol.
00292     inner_loop=is_mu_sym(*current, pgm);
00293     if (inner_loop){
00294       if (inner_loop!=loop){
00295 ///     cerr<<"\n\tInner loop: "<<inner_loop->get_loop_name();
00296     InnerTrace* inner=new InnerTrace;
00297     pair<RangeExpr*, bool> copy=range;
00298     copy.first=(RangeExpr*)copy.first->clone();
00299     eg_backtrack(pgm, get_back_sym(*current, pgm), copy, inner->trace);
00300     if (inner->trace.size()>0){
00301       (*btit).inner=inner;
00302       (*btit).inner->context=make_pair(&pgm, inner_loop);
00303       (*btit).inner->type=LTT_UNKNOWN;
00304     } else {
00305       delete inner;
00306     }
00307       } else {
00308     /// ...  Got to the MU in this loop.
00309     /// ...  Extend the trace to the outer level.
00310     p_warning("Outer loops not implemented.");
00311       }
00312     } else {
00313       /// ...  Check for call sites;
00314       Statement* cs=callsite(pgm, *current);
00315       if (cs){
00316     cerr<<"\nAt callsite: "<<*cs;
00317     p_warning("Call sites not implemented.");
00318       }
00319     }
00320     last=current;
00321     ++btit;
00322   } while(btit!=trace.end());
00323   if (range.first){
00324     delete range.first;
00325   }
00326 }
00327 
00328 
 © 1995-2005 University of Illinois, Urbana-Champaign. All rights reserved.  Fri Mar 25 23:05:45 2005