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
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
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
00068
00069
00070
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
00082
00083
00084
00085
00086
00087
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
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
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187 bool EvolutionGraph::_relax(unsigned int nleft, unsigned int nright,
00188 const EdgeType& ev, RELAX_OP op,
00189 vector<Expression*>& best_path){
00190
00191
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
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
00222 bool has_relaxed=false;
00223 bool has_not_relaxed=false;
00224
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
00249 delete best_path[nright];
00250 best_path[nright]=path_with_edge;
00251 return true;
00252 } else {
00253 if (has_not_relaxed){
00254
00255 delete path_with_edge;
00256 return false;
00257 } else {
00258
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
00273 best.clear();
00274
00275
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
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
00298 for (EdgeList::const_iterator cit=pedges->begin();
00299 cit!=pedges->end(); ++cit){
00300 unsigned int isecond=(*cit).first;
00301
00302 _relax(ifirst, isecond, (*cit).second, MIN_OP, shortest_path);
00303 _relax(ifirst, isecond, (*cit).second, MAX_OP, longest_path);
00304 }
00305 }
00306
00307
00308 for (unsigned int i=0; i<topsorted.size(); ++i){
00309 best.push_back(evolution(shortest_path[i], longest_path[i]));
00310 }
00311
00312
00313 p_assert(best.size()==nodes().size(), "Wrong output from bellman_ford.");
00314 }
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325 bool EvolutionGraph::_back_edge(const Symbol* left, const Symbol* right){
00326
00327 if (_loop){
00328 if (left==right){
00329 if (left==&_loop->index().symbol()){
00330 return true;
00331 }
00332 }
00333 }
00334
00335
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
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
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
00367 continue;
00368 }
00369 } else {
00370 if (_back_edge(nodes()[right], nodes()[left])){
00371
00372 continue;
00373 }
00374 }
00375 indegrees[right]++;
00376 }
00377 }
00378
00379
00380
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
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
00404 continue;
00405 }
00406 } else {
00407 if (_back_edge(nodes()[right], nodes()[left])){
00408
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
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
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
00493
00494
00495
00496
00497
00498
00499
00500 bool EvolutionGraph::_add_approximations(){
00501
00502
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
00535
00536
00537
00538 const Symbol& first=args.first_ref()->symbol();
00539 const Symbol& second=args.last_ref()->symbol();
00540
00541
00542
00543 Expression* lr=0;
00544 if (contains((Symbol*)&first) &&
00545 contains((Symbol*)&second)){
00546
00547
00548
00549 lr=_local_range(second);
00550
00551
00552
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
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
00572
00573
00574 _add_evolution(&first, to, evolution(lr));
00575
00576 _input_values.erase(found);
00577 input_this_loop.erase(index(to));
00578 toret=true;
00579 }
00580 } else {
00581
00582
00583
00584 }
00585 }
00586 } else {
00587
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
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
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
00637
00638
00639
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
00651
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
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
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
00697
00698 if (has_maymod(*stit)){
00699 if (!is_var_in_maymod(*gsa_base(*sym), *stit)){
00700
00701 continue;
00702 }
00703 }
00704
00705 add_node(sym);
00706 }
00707 }
00708 }
00709 }
00710 stit=stit->next_ref();
00711 }
00712 }
00713
00714
00715
00716
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
00733 if (_loop){
00734
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
00744
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
00750 unsigned int imu=index((Symbol*)gsa_base(**it));
00751
00752 mu_this_loop.insert(imu);
00753 }
00754 }
00755 }
00756 }
00757
00758
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
00783
00784
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
00791 }
00792 }
00793 }
00794
00795
00796 _add_evolutions(*first, *last);
00797
00798
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
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
00819 _compute_acyclic_evolutions();
00820
00821
00822 if (!_add_approximations()){
00823 break;
00824 } else {
00825
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
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
00851
00852 if (_loop){
00853 if (_loop_invariant(rhs)){
00854
00855
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
00869
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
00877 return;
00878 }
00879 }
00880
00881
00882
00883
00884 const Symbol* from=ZERO;
00885 switch(rhs.op()){
00886 case ID_OP:
00887
00888 if (_loop){
00889 if (&rhs.symbol()==&_loop->index().symbol()){
00890
00891
00892 _add_evolution(&_loop->index().symbol(), to, evolution(0));
00893 break;
00894 }
00895 }
00896
00897 from=&rhs.symbol();
00898
00899 _add_evolution(from, to, evolution(0));
00900 break;
00901 case MU_OP:
00902
00903
00904 break;
00905 case ETA_OP:
00906
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
00917 }
00918 }
00919 case GAMMA_OP:
00920 case THETA_OP:
00921 {
00922
00923 RefList<Symbol> entries;
00924 get_phinode_entries(rhs, entries);
00925
00926
00927
00928 Iterator<Symbol> sit=entries;
00929 for( ; sit.valid(); ++sit){
00930
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
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
00990
00991
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
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
01019 _input_values[to]=evolution();
01020 break;
01021 }
01022 default:
01023
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
01033
01034 if (!contains((Symbol*)to)){
01035 p_abort("Destination node not in graph.");
01036 }
01037 if (!contains((Symbol*)from)){
01038
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
01060
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
01090
01091 void EvolutionGraph::_add_evolutions(DoStmt& loop){
01092
01093 EvolutionGraph* egloop=_get_eg(_pgm, &loop);
01094
01095
01096 EvolutionMap inner_evs;
01097 map<const Symbol*, Evolution<Expression> > inner_ivs;
01098 egloop->_compute_cyclic_evolutions(inner_evs, inner_ivs);
01099
01100
01101
01102
01103
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
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
01124
01125 void EvolutionGraph::_add_evolutions(AssignmentStmt& stmt){
01126 Expression& lhs=stmt.lhs();
01127 Expression& rhs=stmt.rhs();
01128
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
01168
01169
01170 void EvolutionGraph::_add_evolutions(Statement& callsite, ProgramUnit& callee){
01171
01172 EvolutionGraph* egloop=_get_eg(&callee, 0);
01173
01174
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
01187
01188
01189
01190
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
01196
01197
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
01210
01211 }
01212
01213
01214
01215
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
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
01231
01232
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
01246
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
01260
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
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
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
01291
01292 void EvolutionGraph::_add_evolutions(Statement& first, Statement& last){
01293
01294 Statement* stit=&first;
01295 while(stit!=0 && stit!=&last){
01296 Statement& stmt=*stit;
01297 ProgramUnit* callee=called_pgm(stmt);
01298 if (callee){
01299
01300 _add_evolutions(stmt, *callee);
01301
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
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
01339
01340
01341
01342
01343
01344 }
01345 }
01346
01347 void EvolutionGraph::_verify_preconditions(){
01348
01349
01350
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
01359
01360
01361
01362
01363
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
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386 }
01387
01388
01389 void EvolutionGraph::_compact_zero_paths(){
01390
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
01421
01422
01423
01424
01425
01426 void EvolutionGraph::_compute_acyclic_evolutions(){
01427
01428 Symbol* ind=0;
01429 if (_loop){
01430 ind=&_loop->index().symbol();
01431 }
01432
01433
01434 vector<unsigned int> topsorted;
01435 _topsort(topsorted, true);
01436
01437
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
01443
01444
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
01455 const Expression& md=*evs[*it].min_difference();
01456 if (md.op()==INFINITY_OP){
01457 if (md.sign()==1){
01458
01459 continue;
01460 }
01461 }
01462 if (is_mu_node){
01463
01464
01465 const Symbol* mu_from=nodes()[source];
01466 _evolutions_from_mu[to][mu_from]=evs[*it];
01467
01468
01469 map<const Symbol*, const Symbol*>::iterator be=
01470 _back_edges.find(nodes()[*it]);
01471 if (be!=_back_edges.end()){
01472
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
01479 const Symbol* input_from=nodes()[source];
01480 _evolutions_from_input[to][input_from]=evs[*it];
01481
01482 map<const Symbol*, const Symbol*>::iterator be=
01483 _back_edges.find(nodes()[*it]);
01484 if (be!=_back_edges.end()){
01485
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
01495
01496
01497 _mu_evolutions[ind][ind]=evolution(_loop->step());
01498 }
01499
01500
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
01512 const Expression& md=*evs[*it].min_difference();
01513 if (md.op()==INFINITY_OP){
01514 if (md.sign()==1){
01515
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
01527
01528
01529
01530
01531 }
01532
01533
01534
01535
01536 static bool has_known_iteration_space(DoStmt& dostmt){
01537 if (dostmt.limit().op()==INFINITY_OP){
01538
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
01549 return false;
01550 }
01551 }
01552 break;
01553 case LABEL_STMT:
01554 break;
01555 default:
01556
01557 return true;
01558 }
01559 ps=ps->prev_ref();
01560 }
01561 return true;
01562 }
01563
01564
01565
01566
01567
01568
01569
01570
01571
01572
01573
01574
01575
01576
01577
01578
01579
01580
01581
01582
01583
01584
01585
01586
01587
01588 void EvolutionGraph::_compute_cyclic_evolutions(EvolutionMap& evs,
01589 map<const Symbol*,
01590 Evolution<Expression> >& ivs){
01591
01592
01593
01594
01595
01596 if (_loop==0) {
01597 evs=_mu_evolutions;
01598 return;
01599 }
01600
01601
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
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
01618 if (mu==&_loop->index().symbol()){
01619
01620 if (has_known_iteration_space((DoStmt&)*_loop)){
01621
01622 ivs[mu]=evolution(last_value((DoStmt&)*_loop, *_pgm));
01623 } else {
01624
01625 ivs[mu]=evolution(_loop->index());
01626 }
01627 continue;
01628 }
01629
01630
01631 if (parasites.find(index(mu))!=parasites.end()){
01632 continue;
01633 }
01634
01635
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
01660
01661
01662
01663
01664
01665
01666 input=_input_values[sym];
01667
01668
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
01693
01694
01695
01696
01697
01698
01699
01700
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
01705 evs[imu][mu]=muev;
01706 evs[imu][mu]*=ic->clone();
01707 } else {
01708
01709
01710
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
01721 cerr<<endl<<node_name(mu);
01722 p_warning("Possibly undefined variable.");
01723 }
01724 }
01725
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
01730 evs[imu][mu]=muev;
01731 evs[imu][mu]*=ic->clone();
01732 } else {
01733
01734 }
01735 Evolution<Expression> ev=muev;
01736
01737
01738 if (ev.max_difference()->op()==INFINITY_OP &&
01739 ev.min_difference()->op()!=INFINITY_OP){
01740
01741
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
01749 ev+=i2mu;
01750
01751 if (isym){
01752 evs[isym][mu]=ev;
01753 } else {
01754
01755
01756 ev+=input;
01757
01758 ivs[mu]=ev;
01759 }
01760 }
01761
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
01766
01767
01768
01769 ivs[mu]=input;
01770 }
01771
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
01780 ivs[mu]=input;
01781 }
01782 evs[imu][mu]=evolution(0);
01783 }
01784
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
01793 ivs[mu]=input;
01794 }
01795 }
01796 }
01797 delete ic;
01798
01799
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
01806
01807
01808 const Symbol* host_mu=_verify_parasites_preconditions(mu);
01809 if(host_mu){
01810
01811 if (ivs.find(host_mu)!=ivs.end()){
01812
01813
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
01821 evs[(*it).first][mu]=(*found).second;
01822 }
01823 }
01824 } else {
01825
01826 ivs[mu]=evolution();
01827 }
01828 }
01829 }
01830
01831
01832
01833
01834 }
01835
01836
01837
01838
01839
01840
01841
01842
01843 const Symbol*
01844 EvolutionGraph::_verify_parasites_preconditions(Symbol* parasite_mu){
01845
01846
01847
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
01861
01862
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
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
01876 if (!is_integer_zero(*(*elit).second.min_difference()) ||
01877 !is_integer_zero(*(*elit).second.max_difference())){
01878
01879 return 0;
01880 }
01881 }
01882 }
01883 }
01884
01885
01886 const Symbol* entry=0;
01887 for(set<const Symbol*>::iterator it=reachable.begin();
01888 it!=reachable.end(); ++it){
01889
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
01896
01897 if (entry){
01898 if (entry!=candidate){
01899
01900
01901 return 0;
01902 }
01903 } else {
01904 entry=candidate;
01905 }
01906 }
01907 }
01908 }
01909
01910
01911
01912 while(entry){
01913
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
01927 return 0;
01928 }
01929 entry=nodes()[(*edges.begin()).first];
01930 continue;
01931 } else {
01932 break;
01933 }
01934 }
01935
01936 return 0;
01937 }
01938
01939
01940
01941
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
01950
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
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
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
01969 f<<"\n\t\t\""<<n<<"\" [label=\""<<node_name(*sit)
01970 <<"\", shape=\"ellipse\", color=\"black\""
01971 <<"];";
01972 }
01973 }
01974 }
01975 }
01976
01977
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
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
02014
02015
02016
02017
02018
02019
02020
02021
02022 void EvolutionGraph::_possible_ranges(const Symbol& sym,
02023 list<pair<list<Symbol*>,
02024 RangeExpr*> >& result){
02025
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
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
02049
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
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
02088 Symbol* imu;
02089 bool imu_is_defined;
02090 get_imu((Symbol&)*mu, *_pgm, imu, imu_is_defined);
02091
02092 if (imu==0){
02093
02094 if (_loop){
02095 if (mu==&_loop->index().symbol()){
02096
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
02111 Evolution<Expression> current=evolution(id(*imu));
02112 Evolution<Expression> cyclic;
02113 if (_mu_evolutions.find(mu)!=_mu_evolutions.end()){
02114
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
02129
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
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
02164
02165
02166
02167
02168
02169
02170
02171
02172 Expression* EvolutionGraph::_local_range(const Symbol& sym){
02173
02174
02175
02176
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
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
02200
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
02207
02208
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
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
02239
02240 ev=evolution();
02241 return new RangeExpr(ev.min_difference()->clone(),
02242 ev.max_difference()->clone());
02243 }
02244
02245
02246
02247
02248 Symbol* imu;
02249 bool imu_is_defined;
02250 get_imu((Symbol&)*mu, *_pgm, imu, imu_is_defined);
02251
02252 if (imu==0){
02253
02254 if (_loop){
02255 if (mu==&_loop->index().symbol()){
02256
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
02270 Evolution<Expression> current=evolution(id(*imu));
02271 Evolution<Expression> cyclic;
02272 if (_mu_evolutions.find(mu)!=_mu_evolutions.end()){
02273
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
02285 } else {
02286 ev=current;
02287
02288 ev_is_initialized=true;
02289 }
02290 }
02291
02292
02293
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
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
02315 } else {
02316 ev=current;
02317
02318 ev_is_initialized=true;
02319 }
02320 }
02321 }
02322 }
02323 }
02324 }
02325
02326 if (ev_is_initialized){
02327
02328 return new RangeExpr(ev.min_difference()->clone(),
02329 ev.max_difference()->clone());
02330 } else {
02331
02332 return new RangeExpr(infinity(-1), infinity());
02333 }
02334 }
02335
02336
02337
02338
02339
02340
02341
02342
02343
02344
02345 Expression*
02346 EvolutionGraph::_eliminate_vars(Expression* expr,
02347 set<Symbol*>& syms){
02348
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
02354
02355
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
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
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
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
02424 return _embed_symbolic_range(toret, pgm, ra, dummies);
02425 } else {
02426
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
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
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
02450
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
02483 delete toret;
02484 toret=new RangeExpr(infinity(-1), infinity());
02485 }
02486
02487 return toret;
02488 }
02489
02490
02491
02492
02493
02494 Expression* EvolutionGraph::_global_range_per_iteration(Expression* expr,
02495 DoStmt* domain){
02496
02497
02498
02499
02500
02501 expr=_filter_arrays(expr, *_pgm, domain);
02502
02503
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
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
02519 if (current==ci){
02520
02521 syms_in_innermost.insert(&sit.current());
02522 } else {
02523
02524 ci=current;
02525 syms_in_innermost.clear();
02526 syms_in_innermost.insert(&sit.current());
02527 }
02528 }
02529 }
02530
02531
02532
02533 if (inner(domain, ci)){
02534 break;
02535 } else {
02536
02537 expr=_get_eg(_pgm, ci)->_eliminate_vars(expr, syms_in_innermost);
02538
02539 }
02540 } while (1);
02541
02542
02543
02544
02545
02546
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
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
02564
02565
02566 return expr;
02567 }
02568
02569
02570
02571
02572
02573 Expression* EvolutionGraph::_global_range(Expression* expr,
02574 DoStmt* domain){
02575
02576
02577
02578
02579
02580
02581
02582
02583
02584
02585 expr=_filter_arrays(expr, *_pgm, domain);
02586
02587
02588
02589
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
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
02605 if (current==ci){
02606
02607 syms_in_innermost.insert(&sit.current());
02608 } else {
02609
02610 ci=current;
02611 syms_in_innermost.clear();
02612 syms_in_innermost.insert(&sit.current());
02613 }
02614 }
02615 }
02616
02617
02618
02619 if (inner(domain, ci)){
02620 break;
02621 } else {
02622
02623 expr=_get_eg(_pgm, ci)->_eliminate_vars(expr, syms_in_innermost);
02624
02625 }
02626 } while (1);
02627
02628
02629
02630
02631
02632
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
02640 delete expr;
02641 return new RangeExpr((*found).second.min_difference()->clone(),
02642 (*found).second.max_difference()->clone());
02643 }
02644 }
02645 }
02646
02647
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
02670
02671
02672
02673
02674
02675
02676 return expr;
02677 }
02678
02679
02680 Expression* EvolutionGraph::_global_range(Expression* expr){
02681
02682 DoStmt* co=0;
02683 RefList<Symbol> syms;
02684 referred_symbols(*expr, syms);
02685 Iterator<Symbol> sit=syms;
02686 if (!sit.valid()){
02687
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
02708
02709
02710 bool EvolutionGraph::increasing(const Symbol& value){
02711
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
02720
02721
02722
02723 EvolutionGraph::SequenceType
02724 EvolutionGraph::sequence_type(const Symbol& value){
02725 if (_loop==0){
02726 return ST_UNKNOWN;
02727 }
02728
02729 Symbol* node=(Symbol*)&value;
02730 if (!contains(node)){
02731
02732 DoStmt* loop=def_loop(*node, *_pgm);
02733 if (!inner(loop, (DoStmt*)_loop)){
02734
02735 return ST_UNKNOWN;
02736 }
02737
02738 return ST_UNKNOWN;
02739 }
02740
02741
02742
02743 if (_evolutions_from_input.find(node)!=_evolutions_from_input.end()){
02744 return ST_UNKNOWN;
02745 }
02746
02747
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
02758
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
02769 Evolution<Expression> value2mu=(*v2mitit).second;
02770 Evolution<Expression> mu2value=(*(*m2vit).second.begin()).second;
02771 Evolution<Expression> total=value2mu;
02772 total+=mu2value;
02773
02774
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
02792 return ST_UNKNOWN;
02793 }
02794
02795
02796 static void _cleanup_map(map<Symbol*, Expression*>& m){
02797
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
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
02816
02817
02818
02819
02820 map<Symbol*, Expression*> min_dist_from_left;
02821 min_dist_from_left.insert(make_pair((Symbol*)&left, constant(0)));
02822
02823
02824 DoStmt* loop=loop_left;
02825 do {
02826 EvolutionGraph* eg=_get_eg(_pgm, loop);
02827
02828 map<Symbol*, Expression*> new_dists;
02829 map<Symbol*, Expression*>::iterator mit;
02830
02831
02832
02833
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
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
02856
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
02863 map<Symbol*, Expression*> new_dists;
02864 map<Symbol*, Expression*>::iterator mit;
02865
02866
02867
02868
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
02876
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
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
02901
02902 Expression* toret=infinity();
02903
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
02914 delete candidate;
02915 } else {
02916 if (p_less_than(*candidate, *toret, _ra)){
02917
02918 delete toret;
02919 toret=candidate;
02920 } else {
02921 if (p_greater_than(*candidate, *toret, _ra)){
02922
02923 delete candidate;
02924 } else {
02925
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
02934
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
02943 if (toret->op()==INFINITY_OP){
02944
02945 delete toret;
02946 return constant(0);
02947 } else {
02948 return toret;
02949 }
02950 }
02951
02952
02953
02954 static bool included(Evolution<Expression>& ev1,
02955 Evolution<Expression>& ev2,
02956 bool complementary,
02957 ProgramUnit& pgm,
02958 RangeAccessor* ra){
02959
02960 if (complementary==false){
02961 if (included(ev1, ev2, pgm, ra)){
02962
02963 return true;
02964 }
02965 } else {
02966
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
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
02979 return true;
02980 }
02981 }
02982
02983 return false;
02984 }
02985
02986
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
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
03022 for(list<pair<list<Symbol*>, Evolution<Expression> > >::iterator
03023 llit=tlist.begin(); llit!=tlist.end(); ++llit){
03024
03025
03026 list<Symbol*>& clist=(*llit).first;
03027
03028 list<Symbol*>::iterator lit=clist.end();
03029 --lit;
03030
03031
03032 if (*lit==mu){
03033 if (!disjoint((*llit).second, given, range.second, *_pgm, _ra)){
03034
03035
03036 trace[(Symbol*)mu].push_back((*llit).first);
03037 }
03038 }
03039
03040
03041 EvolutionMap::iterator it1=_evolutions_from_mu.find(*lit);
03042 if (it1==_evolutions_from_mu.end()){
03043
03044
03045 continue;
03046 }
03047 map<const Symbol*, Evolution<Expression> >::iterator it2=
03048 (*it1).second.find(mu);
03049 if (it2==(*it1).second.end()){
03050
03051
03052 continue;
03053 }
03054 Evolution<Expression> total=(*it2).second;
03055 total+=(*llit).second;
03056 if (disjoint(total, given, range.second, *_pgm, _ra)){
03057
03058
03059
03060
03061 continue;
03062 }
03063
03064
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
03070 Symbol* cand=(Symbol*)nodes()[(*cit).first];
03071
03072
03073 pair<list<Symbol*>, Evolution<Expression> > newtrace;
03074 newtrace.first=(*llit).first;
03075
03076 newtrace.first.push_back(cand);
03077 newtrace.second=(*llit).second;
03078 newtrace.second+=(*cit).second;
03079
03080 new_tlist.push_back(newtrace);
03081 }
03082 }
03083
03084
03085 tlist.swap(new_tlist);
03086 }
03087 }
03088 }
03089 }
03090
03091
03092
03093
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
03108
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
03116 Evolution<Expression> edge=(*cit).second;
03117
03118 EvolutionMap::iterator muevit=_evolutions_from_mu.find(cand);
03119 if (muevit==_evolutions_from_mu.end()){
03120
03121 continue;
03122 }
03123 EvolutionMap::data_type::iterator it=(*muevit).second.find(mu);
03124 if (it==(*muevit).second.end()){
03125
03126 continue;
03127 }
03128 if (!(*edge.min_difference()==*edge.max_difference())){
03129
03130 continue;
03131 }
03132
03133 Evolution<Expression> muev=(*it).second;
03134 Evolution<Expression> total=muev;
03135 total+=edge;
03136
03137
03138
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
03143 delete newlength;
03144 return;
03145
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
03165
03166
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
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
03181 cerr<<*mu;
03182 p_warning("Undefined imu value.");
03183 return;
03184 }
03185
03186
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
03200
03201
03202
03203
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
03227
03228 Relation r=ra.compare(*r1.min_difference(),*allev.max_difference());
03229
03230 if (r.is_equal()){
03231
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
03237 if (r.is_equal()){
03238
03239 perfect_trace_from_mu((Symbol*)mu, node,
03240 *muev.min_difference(), trace);
03241 }
03242 }
03243 }
03244 }
03245
03246
03247
03248
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
03285
03286
03287
03288
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
03295
03296 list<pair<
03297 list<Symbol*>,
03298 RangeExpr* > > basic_sources, valid_sources;
03299 _possible_ranges(*node, basic_sources);
03300 list<pair<list<Symbol*>, RangeExpr* > >::iterator it;
03301
03302
03303 for(it=basic_sources.begin(); it!=basic_sources.end(); ++it){
03304
03305 list<Symbol*>::iterator sit;
03306 for(sit=(*it).first.begin(); sit!=(*it).first.end(); ++sit){
03307 cerr<<(*sit)->name_ref()<<" ";
03308 }
03309
03310 if (_incompatible_ranges(make_pair((*it).second, false), range, *_ra)){
03311
03312 delete (*it).second;
03313 } else {
03314
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
03325
03326 if (from_mu && from_input){
03327
03328 return;
03329 }
03330 if (from_mu){
03331
03332
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
03340 map<Symbol*, list<list<Symbol*> > > all_traces;
03341 traces_from_mu(node, range, all_traces);
03342 if (all_traces.size()!=1){
03343
03344
03345 return;
03346 }
03347 list<list<Symbol*> >& traces=(*all_traces.begin()).second;
03348 if (traces.size()!=1){
03349
03350
03351 return;
03352 }
03353 trace=*(traces.begin());
03354 }
03355 if (from_input){
03356
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
03371
03372
03373
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
03384
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
03392 if (solutions.size()==0){
03393
03394 return;
03395 }
03396
03397
03398
03399
03400
03401 Symbol* current=node;
03402 while (1) {
03403
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
03409 Symbol* cand=(Symbol*)nodes()[(*cit).first];
03410
03411 EvolutionMap::iterator found_ivs=_evolutions_from_input.find(cand);
03412 if (found_ivs!=_evolutions_from_input.end()){
03413
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
03419
03420 if (solutions.find(icand)!=solutions.end()){
03421
03422
03423 if (pred){
03424
03425 return;
03426 } else {
03427 pred=(Symbol*)cand;
03428 break;
03429 }
03430 }
03431 }
03432 }
03433 }
03434 if (pred){
03435
03436
03437 trace.push_back(pred);
03438 current=pred;
03439 } else {
03440
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
03452 ev=evolution(constant(0));
03453 length=constant(0);
03454 preds.clear();
03455
03456
03457 if (trace.size()<2){
03458 return;
03459 }
03460
03461
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
03471 ev+=*edge;
03472
03473
03474
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
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
03500 it1=it2;
03501 ++it2;
03502 } while (it2!=trace.end());
03503 }
03504
03505
03506
03507
03508
03509 Expression* EvolutionGraph::substitute(Symbol* given){
03510
03511 if (!contains(given)){
03512 return 0;
03513 }
03514
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
03540
03541
03542
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
03549 if (it!=_evolutions_from_mu.end()){
03550
03551 if ((*it).second.size()==1){
03552
03553 mu=(Symbol*)(*(*it).second.begin()).first;
03554 } else {
03555
03556 return false;
03557 }
03558 } else {
03559
03560
03561 return false;
03562 }
03563
03564
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
03570 back=(Symbol*)_back_edges_reversed[mu];
03571 } else {
03572
03573
03574 return false;
03575 }
03576 } else {
03577
03578 return false;
03579 }
03580 } else {
03581
03582
03583 return false;
03584 }
03585
03586
03587 it=_input2mu_evolutions.find(mu);
03588 if (it==_input2mu_evolutions.end()){
03589
03590 return true;
03591 } else {
03592
03593
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
03625
03626
03627
03628 Expression* EvolutionGraph::range_from_input(Symbol& s){
03629
03630
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
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
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
03656 return 0;
03657 }
03658
03659
03660 const EdgeList& edges=get_reversed_edges(index((Symbol*)n));
03661 for (EdgeList::const_iterator cit=edges.begin();
03662 cit!=edges.end(); ++cit){
03663
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
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
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
03696 EvolutionMap::iterator it=_evolutions_from_mu.find(node);
03697 if (it!=_evolutions_from_mu.end()){
03698 muevs=(*it).second;
03699 }
03700
03701
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 }