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
00021
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
00037
00038
00039
00040
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
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
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
00101
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
00205
00206
00207
00208 void eg_backtrack(ProgramUnit& pgm, Symbol& sym, pair<RangeExpr*, bool> range,
00209 BackTrace& trace){
00210
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
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
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
00243 if (trace.size()==1){
00244
00245
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
00289
00290 range=subtract_evolution(range, get_evolution(*veg, current, last));
00291
00292 inner_loop=is_mu_sym(*current, pgm);
00293 if (inner_loop){
00294 if (inner_loop!=loop){
00295
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
00309
00310 p_warning("Outer loops not implemented.");
00311 }
00312 } else {
00313
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