Polaris: trans_util.cc Source File

trans_util.cc

Go to the documentation of this file.
00001 ///
00002 ///
00003 /*!
00004   \brief Translates variables in commons across subroutine boundaries.
00005   \author Silvius Rus
00006 */
00007 ///
00008 #include "Traverser.h"
00009 #include <set>
00010 #include <map>
00011 #include <queue>
00012 #include <algorithm>
00013 
00014 #include "Symbol/FunctionSymbol.h"
00015 #include "Expression/ArrayRefExpr.h"
00016 #include "Expression/FunctionCallExpr.h"
00017 #include "Range/AIRangeDict.h"
00018 #include "utilities/lambda_util.h"
00019 #include "utilities/stmt_util.h"
00020 
00021 #include "prog_info.h"
00022 #include "trans_util.h"
00023 #include "optimize_ssa.h"
00024 
00025 
00026 
00027 Translator::Translator(ProgramUnit& caller, Statement& callsite){
00028   _caller=&caller;
00029   _callsite=&callsite;
00030   _callee=called_pgm(callsite);
00031   p_assert(_callee, 
00032        "Cannot build translator for statements that are not call sites.");
00033 }
00034 
00035 Translator::~Translator(){
00036 }
00037 
00038 Expression* Translator::translate(Symbol& sym){
00039   if (sym.sym_class()==VARIABLE_CLASS) {
00040     return translate_var((VariableSymbol&)sym, 
00041              *_callee, *_caller, *_callsite);
00042   } else {
00043     p_abort("Cannot translate symbols that are not variables.");
00044     return 0;
00045   }
00046 }
00047 
00048 Expression* Translator::actual(Symbol& sym){
00049   if (sym.sym_class()!=VARIABLE_CLASS){
00050     cerr<<"\n sym: "<<sym.name_ref()
00051     <<" in routine "<<_callee->routine_name_ref();
00052     p_warning("Non-variable symbol cannot be formal.");
00053     return 0;
00054   }
00055   String sbase;
00056   int rank;
00057   gsa_details(sym.name_ref(), sbase, rank);
00058 /// No translation if this is a non-zero gsa rank.
00059   if (rank!=0) {
00060     cerr<<"\n sym: "<<sym.name_ref()
00061     <<" in routine "<<_callee->routine_name_ref();
00062     p_warning("Can not translate non-entry value.");
00063     return 0;
00064   }
00065   VariableSymbol* base=(VariableSymbol*)&sym;
00066   if (base->is_gsa_symbol()){
00067     base=(VariableSymbol*)&base->gsa_base_symbol();
00068   }
00069   if (sym.formal()){
00070     Statement* entry=_callee->stmts().first_ref();
00071     while (entry->stmt_class()!=ENTRY_STMT) {
00072       entry=entry->next_ref();
00073       p_assert(entry, "Could not find entry to program unit.");
00074     }
00075   
00076     List<Expression>& actuals=parameters(*_callsite);
00077     List<Expression>& formals=parameters(*entry);  
00078   
00079     Iterator<Expression> ait=actuals;
00080     Iterator<Expression> fit=formals;
00081     for ( ; ait.valid() && fit.valid(); ++ait, ++fit){
00082       if (&fit.current().symbol()==base){
00083     if (is_beta(ait.current())){
00084       return ait.current().parameters_guarded().arg_list().last_ref();
00085     } else {
00086       return &ait.current();
00087     }
00088       }
00089     }   
00090   } else {
00091 ///     cerr<<"\n sym: "<<sym.name_ref()
00092 ///     <<" in routine "<<_callee->routine_name_ref();
00093 ///     p_warning("Cannot find mapping for a non-formal symbol.");
00094     return 0;
00095   }
00096   return 0;
00097 }
00098 
00099 
00100 
00101 
00102 
00103 void display_translation_error(VariableSymbol& sym, 
00104                    ProgramUnit& from,
00105                    ProgramUnit& to,
00106                    Statement& callsite){
00107   cerr<<"\nVariable "<<&sym<<":"<<sym.name_ref()
00108     <<" upon entry to program unit "<<from.routine_name_ref()
00109     <<" when called from program unit "<<to.routine_name_ref()
00110     <<" at the callsite at line "<<callsite.line();
00111   static int dummy=1;
00112   callsite.write(cerr,dummy);
00113 }
00114 
00115 void display_translation_error(Expression& e, 
00116                    ProgramUnit& from,
00117                    ProgramUnit& to,
00118                    Statement& callsite){
00119   cerr<<"Variable "<<e
00120       <<" upon entry to program unit "<<from.routine_name_ref()
00121       <<" when called from program unit "<<to.routine_name_ref()
00122       <<" at the callsite at line "<<callsite.line();
00123   int dummy=1;
00124   callsite.write(cerr,dummy);
00125 }
00126 
00127 
00128 ProgramUnit* called_pgm(Statement& stmt){
00129   const char* callee_tag=0;
00130   if (stmt.stmt_class()==CALL_STMT){
00131     callee_tag=stmt.routine_guarded().symbol().tag_ref(); 
00132   } else {
00133     if (stmt.stmt_class()==ASSIGNMENT_STMT){
00134       if (stmt.rhs().op()==FUNCTION_CALL_OP) {
00135     callee_tag=stmt.rhs().function().symbol().tag_ref();
00136       }
00137     }
00138   }
00139   if (!callee_tag) return 0;
00140   return entry_points().find_ref(callee_tag);
00141 }
00142 
00143 
00144 
00145 /*!
00146   \brief This function just checks for:
00147   - same common block
00148   - same position
00149   
00150   It gives a warning if the resulting name is different.
00151 
00152   \warning It does not check for the real offset inside the common.
00153 */
00154 VariableSymbol* translate_common_var(VariableSymbol& sym, 
00155                      ProgramUnit& from,
00156                      ProgramUnit& to,
00157                      Statement& callsite){
00158   if (!sym.common_ref()) return 0;
00159   Database<ProgramUnit*, Database<Statement*, RefDatabase<Symbol*, Symbol> > >*
00160     gmap=&ip_ssa_gmap();
00161   Database<Statement*, RefDatabase<Symbol*, Symbol> >* lmap=
00162     gmap->find_ref(&to);
00163   if (!lmap){
00164     display_translation_error(sym, from, to, callsite);
00165     p_abort("gmap not set.");
00166   }
00167   RefDatabase<Symbol*, Symbol>* smap=lmap->find_ref(&callsite);
00168   if (!smap){
00169     display_translation_error(sym, from, to, callsite);
00170     p_abort("gmap not set.");
00171   }
00172   
00173   VariableSymbol* base=&sym;
00174   if (base->is_gsa_symbol()) base=(VariableSymbol*)&base->gsa_base_symbol();
00175   Symbol* trans=to.symtab().find_ref(base->name_ref());
00176   if (trans==0){
00177     display_translation_error(sym, from, to, callsite);
00178     p_abort("Commons must be unified before attempting translations.");
00179   }
00180   VariableSymbol* toret=(VariableSymbol*)smap->find_ref(trans);
00181   if (toret==0){
00182     display_translation_error(sym, from, to, callsite);
00183     p_abort("Could not translate common name properly.");
00184   }
00185   return toret;
00186 }
00187 
00188 
00189 
00190 static Expression* reshape_array(Expression& formal, 
00191                  VariableSymbol& actual_array_sym,
00192                  Translator& translator,
00193                  ProgramUnit& from,
00194                  ProgramUnit& to, 
00195                  Statement& callsite){
00196 /// Use each other.
00197   if (formal.op()!=ARRAY_REF_OP) {
00198     p_abort("Wrong argument to reshape_array");
00199   }
00200 
00201   VariableSymbol *formal_symbol=(VariableSymbol *) formal.base_variable_ref();
00202   Expression& subscript_formal=formal.subscript();
00203   Expression* subscript_actual=constant(0);
00204   Expression* stride=constant(1);
00205   for (int i=0; i<formal_symbol->dim().entries(); i++) {
00206     /// ...  Compute contribution by dimension (i)
00207     Expression* this_dim=
00208       translate_and_reshape(translator, from, to, callsite, 
00209                 subscript_formal.arg_list()[i].clone());
00210     this_dim=mul(stride->clone(), this_dim);
00211                  ;
00212     subscript_actual=simplify(add(subscript_actual, this_dim));
00213     
00214     /// ...   If this is the highest dimension we are done
00215     if (i==formal_symbol->dim().entries()-1) {
00216       break;
00217     }
00218 
00219     /// ...  Compute stride for next dimension.
00220     ArrayBounds & formal_bounds = formal_symbol->dim()[i];
00221     Expression * lower;
00222     Expression * upper;
00223     if (!(formal_bounds.lower_exists())) {
00224       lower = constant(1);
00225     } else {
00226       lower = translate_and_reshape(translator, from, to, callsite, 
00227                     formal_bounds.lower_guarded().clone());
00228     }
00229     if (!formal_bounds.upper_exists()) {
00230       p_abort("Cannot reshape array because dimensions are not given.");
00231     }
00232     upper=translate_and_reshape(translator, from, to, callsite, 
00233                 formal_bounds.upper_guarded().clone());
00234     Expression* diff=add(sub(upper, lower), constant(1));
00235     stride=simplify(mul(stride, diff));
00236   }
00237   delete stride;
00238   List<Expression>* new_sub=new List<Expression>;
00239   new_sub->ins_first(subscript_actual);
00240   VariableSymbol& actual_symbol=actual_array_sym;
00241   for (int i=1; i<actual_symbol.dim().entries(); i++) {
00242     new_sub->ins_last(constant(1));
00243   }
00244   CommaExpr* new_subscript=new CommaExpr(new_sub);
00245   return new ArrayRefExpr(formal.array().symbol().type(),
00246               id(actual_array_sym),
00247               new_subscript);
00248 }
00249 
00250 
00251 /// Checks whether actual parameter is an integer.
00252 bool is_actual_integer_constant(VariableSymbol& sym,
00253                 Translator& translator){
00254   Expression* new_const=0;
00255   VariableSymbol* base=0;
00256   if (sym.is_gsa_symbol()){
00257     base=(VariableSymbol*)&sym.gsa_base_symbol();
00258   } else {
00259     base=&sym;
00260   }    
00261   new_const=translator.actual(*base);
00262   if (new_const) {
00263     if (new_const->op()==INTEGER_CONSTANT_OP){
00264       return true;
00265     }
00266   }
00267   return false;
00268 }
00269 
00270 Symbol* symbol(Expression* e){
00271   if (!e) return 0;
00272   if (e->op()==ID_OP) return &e->symbol();
00273   if (e->op()==ARRAY_REF_OP) return &e->array().symbol();
00274   return 0;
00275 }
00276 
00277 /// Translate from actuals to formals.
00278 RefList<Symbol> untranslate_var(Symbol& sym,
00279                 ProgramUnit& callee,
00280                 ProgramUnit& caller,
00281                 Statement& callsite){  
00282   RefList<Symbol> toret;
00283   switch (sym.sym_class()){
00284   case UNDEFINED_CLASS:
00285     p_abort("Cannot translate symbol of undefined type.");
00286   case PROGRAM_CLASS:
00287     p_abort("Cannot have more than one main subprogram in a program.");
00288   case BLOCK_DATA_CLASS:
00289     p_abort("Cannot have more than one block data subprogram in a program.");
00290   case FUNCTION_CLASS:
00291   case SUBROUTINE_CLASS:
00292   case SYMBOLIC_CONSTANT_CLASS:
00293     {
00294       Symbol* found=callee.symtab().find_ref(sym.name_ref());
00295       if (found){
00296     /// ...  silvius: should make sure they are the same.
00297     toret.ins_last(*found);
00298     return toret;
00299       } else {
00300     Symbol* callee_sym=sym.clone();
00301     callee.symtab().rename_and_ins(callee_sym);
00302       }
00303     }
00304   case VARIABLE_CLASS:
00305     break; /// ...  See code after this switch statement.
00306   case NAMELIST_CLASS:
00307   default:
00308     p_abort("Unhandled case in untranslate_var.");
00309   }
00310 
00311 /// First check whether this is a function and sym is the return value.
00312   if (callsite.stmt_class()==ASSIGNMENT_STMT){
00313     if (callsite.lhs().base_variable_ref()==&sym){
00314       Symbol* fret=callee.symtab().find_ref(callee.routine_name_ref());
00315       p_assert(fret, "Function did not declare return value.");
00316       toret.ins_last(*fret);
00317       return toret;
00318     }
00319   }
00320 
00321   Statement& entry=quick_pgm_entry(callee);
00322   List<Expression>& actuals=parameters(callsite);
00323   List<Expression>& formals=parameters(entry);
00324   Iterator<Expression> ait=actuals;
00325   Iterator<Expression> fit=formals;
00326 
00327   for ( ; ait.valid() && fit.valid(); ++ait, ++fit){
00328     Expression& expr=ait.current();
00329     Symbol* actual=0;
00330     if (is_beta(ait.current())){
00331       /// ...  Get its base symbol.
00332       Expression* last_arg=expr.parameters_guarded().arg_list().last_ref();
00333       if (last_arg->op()==ARRAY_REF_OP){
00334     actual=(VariableSymbol*)&last_arg->array().symbol();
00335       } else {
00336     if (last_arg->op()==ID_OP){
00337       actual=(VariableSymbol*)&last_arg->symbol();
00338     } else {
00339       p_abort("Expression not supported as actual.");
00340     }
00341       }
00342     } else {
00343       actual=symbol(&ait.current());
00344     }
00345 ///     cerr<<"\nactual = "<<actual->name_ref();
00346     if (actual!=&sym) continue;
00347     Symbol* formal=symbol(&fit.current());
00348     p_assert(formal, "Expression not supported as formal.");
00349     toret.ins_last(*formal);
00350   }
00351 
00352 /// Check for commons.
00353   if (sym.common_ref()){
00354     Symbol* trans=callee.symtab().find_ref(sym.name_ref());
00355     p_assert(trans, "Commons not unified.");
00356     p_assert(trans->common_ref(), "Commons not unified.");
00357     if (!toret.member(*trans)){
00358       toret.ins_last(*trans);
00359     }
00360   }
00361   
00362   return toret;
00363 }
00364 
00365 /// Translate from formals to actuals.
00366 Expression* translate_var(VariableSymbol& sym,
00367               ProgramUnit& from,
00368               ProgramUnit& to,
00369               Statement& callsite){  
00370   if (!sym.formal() && !sym.common_ref() && sym.sym_class()!=FUNCTION_CLASS){
00371 ///     display_translation_error(sym, from, to, callsite);
00372 ///     p_warning("Cannot translate local.");
00373     return 0;
00374   }
00375 
00376 
00377 /// Check whether it is an intrinsic.
00378   if (sym.intrinsic()){
00379     Symbol* trans=to.symtab().find_ref(sym.name_ref());
00380     if (!trans) {
00381       /// ...  This intrinsic not in the other symbol table.
00382       /// ...  Create it.
00383       trans=&to.symtab().ins(new FunctionSymbol(sym.name_ref(),
00384                         sym.type(),
00385                         NOT_EXTERNAL,
00386                         IS_INTRINSIC,
00387                         NOT_FORMAL));
00388     } else {
00389       /// ...  Check whether it is an intrinsic function.
00390       if (!trans->intrinsic()){
00391     display_translation_error(sym, from, to, callsite);
00392     p_abort("This variable has an intrinsic name.");
00393       }
00394     }
00395     /// ...  If it gets here, trans is the corresponding symbol.
00396     return id(*trans);
00397   }
00398 
00399   String sbase;
00400   int rank;
00401   gsa_details(sym.name_ref(), sbase, rank);
00402 /// No translation if this is a non-zero gsa rank.
00403   if (rank!=0) {
00404     display_translation_error(sym, from, to, callsite);
00405     p_warning("Can not translate non-entry value.");
00406     return 0;
00407   }
00408   VariableSymbol* base=0;
00409   if (sym.is_gsa_symbol()){
00410     base=(VariableSymbol*)&sym.gsa_base_symbol();
00411   } else {
00412     base=&sym;
00413   }
00414 
00415   
00416   if (sym.formal()){
00417     /// ...  If it gets here it must be formal.
00418     Statement* entry=from.stmts().first_ref();
00419     while (entry->stmt_class()!=ENTRY_STMT) {
00420       entry=entry->next_ref();
00421       if(entry==0) break;
00422     }
00423     p_assert(entry, "Could not find program unit entry.");
00424 
00425     List<Expression>& actuals=parameters(callsite);
00426     List<Expression>& formals=parameters(*entry);  
00427   
00428     Iterator<Expression> ait=actuals;
00429     Iterator<Expression> fit=formals;
00430     for ( ; ait.valid() && fit.valid(); ++ait, ++fit){      
00431       KeyIterator<String,ProgramUnit> progiter = program();
00432       if (&fit.current().symbol()==base){
00433     Expression* a=0;
00434     if (is_beta(ait.current())){
00435       a=ait.current().parameters_guarded().arg_list().first_ref();
00436     } else {
00437       a=ait.current().clone();
00438     }
00439     if (a->op()==ALPHA_OP){
00440       return a->parameters_guarded().arg_list()[0].clone();
00441     } else {
00442       return a->clone();
00443     }
00444       }
00445     }
00446     display_translation_error(sym, from, to, callsite);
00447     p_abort("Formal could not be matched to an actual.");
00448   }
00449 
00450   if (sym.common_ref()){
00451     /// ...  Hope this is in a common.
00452     VariableSymbol* ct=translate_common_var(sym, from, to, callsite);
00453     if (ct) {
00454       return id(*ct);
00455     } else {
00456       p_abort("Failed to translate common ref.");
00457     }
00458   }
00459 
00460   display_translation_error(sym, from, to, callsite);
00461   p_abort("Translation failed: cause unknown.");
00462   return 0;
00463 }
00464 
00465 
00466 /// Returns the dimension of this array as number of elements.
00467 /// It assumes that the last dimension is defined (not an assumed size array).
00468 Expression* array_element_count(Symbol& sym){
00469   Expression* stride=constant(1);
00470   for (Iterator<ArrayBounds> abit=sym.dim(); abit.valid(); ++abit){
00471     /// ...  Compute new stride.
00472     ArrayBounds& ab=abit.current();
00473     Expression* diff=0;
00474     if (ab.lower_exists()){
00475       if (ab.upper_exists()){
00476     diff=add(constant(1),
00477          sub(ab.upper_guarded().clone(), 
00478              ab.lower_guarded().clone()));
00479       } else {
00480     diff=ab.lower_guarded().clone();
00481       }
00482     } else {
00483       if (ab.upper_exists()){
00484     diff=ab.upper_guarded().clone();
00485       } else {
00486     p_abort("Cannot understand array declaration.");
00487       }
00488     }
00489     if (diff==0){
00490       p_abort("'array_element_count' called on assumed size array.");
00491     }
00492     stride=simplify(mul(stride, diff));
00493   }
00494   return stride;
00495 }
00496 
00497 /// Returns the linearized offset of an array expression.
00498 /// DIMENSION a(M,N)
00499 /// For a(j, i)
00500 /// It returns j + i*N
00501 Expression* base_offset(Expression* expr){
00502   if (!expr) return 0;
00503   if (expr->op()!=ARRAY_REF_OP) return 0;
00504   VariableSymbol * newsym = (VariableSymbol *) &expr->array().symbol();
00505   Expression* start_offset=constant(0);
00506   int dims=newsym->dim().entries();
00507   int dim=0;
00508   Expression* stride=constant(1);
00509   Iterator<Expression> actit=expr->subscript().arg_list();
00510   for (Iterator<ArrayBounds> abit=newsym->dim(); 
00511        abit.valid() && dim<dims;
00512        ++abit, ++actit, ++dim){
00513     /// ...  Compute offset
00514     start_offset=add(start_offset,
00515              mul(sub(actit.current().clone(), constant(1)), 
00516              stride->clone()));
00517     if (dim==dims-1) {
00518       delete stride;
00519       break; /// ...  Don't need stride anymore.
00520     }
00521     /// ...  Compute new stride.
00522     ArrayBounds& ab=abit.current();
00523     Expression* diff=0;
00524     if (ab.lower_exists()){
00525       if (ab.upper_exists()){
00526     diff=add(constant(1),
00527          sub(ab.upper_guarded().clone(), 
00528              ab.lower_guarded().clone()));
00529       } else {
00530     diff=ab.lower_guarded().clone();
00531       }
00532     } else {
00533       if (ab.upper_exists()){
00534     diff=ab.upper_guarded().clone();
00535       } else {
00536     p_abort("Cannot understand array declaration.");
00537       }
00538     }
00539     stride=simplify(mul(stride, diff));
00540   }
00541   start_offset=simplify(start_offset);
00542   return start_offset;
00543 }
00544 
00545 Expression* trans_update_expr(Translator& translator, Expression* expr){
00546   if (is_leaf(*expr)) {
00547     Symbol * oldsym = expr->base_variable_ref();
00548     if (oldsym == 0) {
00549       return expr;
00550     } else {
00551       return translator.translate(*oldsym);
00552     }
00553   } else {
00554     Traverser tr(*expr, is_leaf);
00555     for ( ; tr.valid(); ++tr) {
00556       if (tr.current().op() != ID_OP) continue;
00557       Assign<Expression> eas = tr.assign();
00558       Expression * epull = tr.pull();
00559       static LambdaInfo lambda(0, 0, INLINE_CALL);
00560       /// ...  remap_expr
00561       while (1) {
00562     /// ...  Nothing replaced so far
00563     Expression* changed = trans_update_expr(translator, epull);
00564     
00565     if (changed!=epull) {
00566       // If this expression was replaced, remove lambda
00567       // calls and check the expression again.
00568       epull = remove_lambda_calls(changed, lambda);
00569     } else {
00570       break;
00571     }      
00572       }
00573       eas = epull;
00574     }
00575     return expr;
00576   }
00577 }
00578 
00579 Expression* translate_and_reshape( Translator& translator, 
00580                    ProgramUnit& from,
00581                    ProgramUnit& to,
00582                    Statement& callsite,
00583                    Expression* expr){
00584   if (!expr) return 0;
00585   if (is_leaf(*expr)){
00586     Expression* new_leaf=0;
00587     if (expr->op()==ID_OP){
00588       /// ...  If it is an intrinsic, get corresponding one.
00589       if (expr->symbol().intrinsic()){
00590     Symbol* tosym=to.symtab().find_ref(expr->symbol().name_ref());
00591     if(tosym==0){
00592       tosym=&to.symtab().ins_intrinsic(expr->symbol().name_ref());
00593     }
00594     return id(*tosym);
00595       }
00596       VariableSymbol& vs=(VariableSymbol&)expr->symbol();
00597       /// ...  The symbol must have the GSA rank 0, or no rank at all.
00598       /// ...  Otherwise, it should not be translated, as it represents a 
00599       /// ...  different value.
00600       VariableSymbol* base=(VariableSymbol*)gsa_base(vs);
00601       if (base!=&vs){
00602     cerr<<"\n in routine "<<from.routine_name_ref();
00603     cerr<<"\n expr."<<*expr;
00604     p_abort("Could not translate name in translate_and_reshape.");
00605       }
00606       const Expression* new_const=0;
00607       VariableSymbol* tovar=0;
00608       new_const=translator.actual(*base);
00609       if (!new_const) {
00610     /// ...  Hope this is in a common
00611     tovar=translate_common_var(*base, from, to, callsite);
00612     if (!tovar){
00613       p_abort("Could not translate name in translate_and_reshape.");
00614       return 0;
00615     } else {
00616       new_leaf=id(*tovar);
00617     }
00618       } else {
00619     new_leaf=new_const->clone();
00620       }
00621     } else {
00622       /// ...  Don't know how to do it, use Jay's version.
00623       new_leaf=trans_update_expr(translator, expr);
00624     }
00625     return new_leaf;
00626   }
00627   if (expr->op() == ARRAY_REF_OP) {
00628     Expression& array=expr->array();
00629     /// ...  The symbol must have the GSA rank 0, or no rank at all.
00630     /// ...  Otherwise, it should not be translated, as it represents a 
00631     /// ...  different value.
00632     VariableSymbol& vs=(VariableSymbol&)array.symbol();
00633     VariableSymbol* base=(VariableSymbol*)gsa_base(vs);
00634     if (base!=&array.symbol()){
00635       cerr<<"\n in routine "<<from.routine_name_ref();
00636       cerr<<"\n expr."<<*expr;
00637       p_abort("Could not translate name in translate_and_reshape.");
00638     }
00639 
00640     Expression* new_array=0;
00641     const Expression* new_array_const=0;
00642     new_array_const=translator.actual(*base);
00643     if (!new_array_const) {
00644       /// ...  Hope this is in a common
00645       VariableSymbol* tovar=translate_common_var(*base, from, to, callsite);
00646       if (!tovar){
00647     p_abort("Could not translate name in translate_and_reshape.");
00648     return 0;
00649       }
00650       new_array=id(*tovar);
00651     } else {
00652       new_array=new_array_const->clone();
00653     }
00654     Expression* new_expr=0;
00655     if (new_array->op()==ARRAY_REF_OP){
00656       new_expr=reshape_array(*expr, 
00657                  (VariableSymbol&)new_array->array().symbol(),
00658                  translator, from, to, callsite);
00659       /// ...  Add actual base offset.
00660       Expression* start_offset=base_offset(new_array);
00661       Mutator<Expression> mut=new_expr->subscript().arg_list();
00662       Assign<Expression> a = mut.assign();
00663       a=simplify(add(start_offset, mut.pull()));
00664     } else {
00665       if (new_array->op()==ID_OP){
00666     new_expr=reshape_array(*expr, 
00667                    (VariableSymbol&)new_array->symbol(),
00668                    translator, from, to, callsite);
00669       } else {
00670     p_abort("Could not translate array in translate_and_reshape.");
00671       }
00672     }
00673     return new_expr;
00674   } else {
00675     Mutator<Expression> expit = expr->arg_list();
00676     for ( ; expit.valid(); ++expit) {
00677       Assign<Expression> a = expit.assign();
00678       a=translate_and_reshape(translator, from, to, callsite, expit.pull());
00679     }
00680   }
00681   return expr;
00682 }
00683 
00684 
00685 static bool same_base_name(VariableSymbol& sym1, VariableSymbol& sym2){
00686   Symbol* s1=&sym1;
00687   Symbol* s2=&sym2;
00688   if (sym1.is_gsa_symbol()){
00689     s1=&sym1.gsa_base_symbol();
00690   }
00691   if (sym2.is_gsa_symbol()){
00692     s2=&sym2.gsa_base_symbol();
00693   }
00694   if (s1==s2) {
00695     return true;
00696   }
00697   return false;
00698 }
00699 
00700 Symbol* syms_in_expr(RefSet<Symbol>& syms, Expression& expr){
00701   if (expr.op() == ID_OP) {
00702     Iterator<Symbol> sit=syms;
00703     for  (sit.reset(); sit.valid(); ++sit){
00704       Symbol& sym=sit.current();
00705       if (same_base_name((VariableSymbol&)expr.symbol(), 
00706              (VariableSymbol&)sym)) {
00707     return &sym;
00708       }
00709     }
00710   } else {
00711     Iterator<Expression> expit = expr.arg_list();
00712     for ( ; expit.valid(); ++expit) {
00713       Symbol* variant=syms_in_expr(syms, expit.current());
00714       if (variant) return variant; 
00715     }
00716   }
00717   return (Symbol*)0;
00718 }
00719 
00720 void referred_symbols(const Expression& expr,
00721               RefList<Symbol>& syms){
00722   if (expr.op() == ID_OP) {
00723     if (expr.symbol().name_ref()!=String("<BETA>")) {
00724       if (expr.symbol().name_ref()!=String("INF")){
00725     if (!syms.member(expr.symbol())){
00726       syms.ins_last(expr.symbol());
00727     }
00728       }
00729     }
00730   } else {
00731     Iterator<Expression> expit = expr.arg_list();
00732     for ( ; expit.valid(); ++expit) {
00733       referred_symbols(expit.current(), syms);
00734     }
00735   }
00736 }
00737 
00738 void referred_symbols(const List<AbstractAccess>& lmads, 
00739               RefList<Symbol>& syms){
00740   for (Iterator<AbstractAccess> aait=lmads; aait.valid(); ++aait){
00741     AbstractAccess& aa=aait.current();
00742     if ( aa.start_exists() ){
00743       referred_symbols(aa.start_guarded(), syms);
00744     }
00745     Iterator<AccessDimension> adit=aa.iter_dims();
00746     for (adit.reset(); adit.valid(); ++adit){
00747       AccessDimension& ad=adit.current();
00748       if (ad.stride_exists()){
00749     referred_symbols(ad.stride_guarded(), syms);
00750       }
00751       if (ad.span_exists()){
00752     referred_symbols(ad.span_guarded(), syms);
00753       }
00754     }
00755   }
00756 }
00757 
00758 void referred_symbols(AbstractAccess& aa, 
00759               RefList<Symbol>& syms){
00760   if ( aa.start_exists() ){
00761     referred_symbols(aa.start_guarded(), syms);
00762   }
00763   Iterator<AccessDimension> adit=aa.iter_dims();
00764   for (adit.reset(); adit.valid(); ++adit){
00765     AccessDimension& ad=adit.current();
00766     if (ad.stride_exists()){
00767       referred_symbols(ad.stride_guarded(), syms);
00768     }
00769     if (ad.span_exists()){
00770       referred_symbols(ad.span_guarded(), syms);
00771     }
00772   }
00773 }
00774 
00775  
00776 
00777 
00778 /*!
00779   \brief  Separates the given symbol list into two: the ones that can be, ant the ones
00780   that cannot be translated between the two given contexts.
00781 
00782   If there is at least a symbol that cannot be translated, it returns right when it
00783   finds it if 'return_asap' is 1 (default).
00784 */
00785 bool can_translate(const RefList<Symbol>& given,
00786            RefList<Symbol>& can, RefList<Symbol>& cannot,
00787            Translator& translator, 
00788            ProgramUnit& callee, ProgramUnit& caller,
00789            Statement& callsite,
00790            int return_asap){
00791   for (Iterator<Symbol> sit=given; sit.valid(); ++sit){
00792 
00793     /// ...  First check whether GSA rank is 0.
00794     String name;
00795     int rank;
00796     gsa_details(sit.current().name_ref(), name, rank);
00797     if (rank!=0){
00798       cannot.ins_last(sit.current());
00799       if (return_asap) return false;
00800     }
00801     
00802     /// ...  If it gets here, the rank is 0.
00803 
00804 
00805     /// ...  Let it go if it is an intrinsic.
00806     if (sit.current().intrinsic()){
00807       can.ins_last(sit.current());
00808       continue;
00809     }
00810 
00811     /// ...  Let it go if it is an integer constant.
00812     bool actual_is_const=
00813       is_actual_integer_constant((VariableSymbol&)sit.current(), translator);
00814     if (actual_is_const){
00815       can.ins_last(sit.current());
00816       continue;
00817     }
00818 
00819     /// ...  Do not even attempt to translate if it is a dummy index.
00820     String sname=sit.current().name_ref();
00821     if (sname.index_case("DUMMY_J")!=-1){
00822       cannot.ins_last(sit.current());
00823       if (return_asap) {
00824     return false;
00825       } else {
00826     continue;
00827       }
00828     }
00829     
00830     /// ...  Try to translate it.
00831     Expression* t=translate_var((VariableSymbol&)sit.current(), 
00832                 callee, caller, callsite);
00833     if (t){
00834       delete t;
00835       can.ins_last(sit.current());
00836     } else {
00837       /// ...  Cannot translate this symbol, it must be an uninitialized local.
00838       display_translation_error((VariableSymbol&)sit.current(), 
00839                 callee, caller, callsite);
00840       p_warning("Uninitialized variable may define memory access.");
00841       cannot.ins_last(sit.current());
00842       if (return_asap) return false;
00843     }
00844   }
00845   if (cannot.entries()==0) {
00846     return true;
00847   } else {
00848     return false;
00849   }
00850 }
00851 
00852 
00853 
00854 
00855 
00856 
00857 List<Expression>& parameters(Statement& stmt){
00858   if (stmt.stmt_class()==CALL_STMT) return stmt.parameters_guarded().arg_list();
00859   if (stmt.stmt_class()==ASSIGNMENT_STMT)
00860     if (stmt.rhs().op()==FUNCTION_CALL_OP)
00861       return stmt.rhs().parameters_guarded().arg_list();
00862   if (stmt.stmt_class()==ENTRY_STMT) return stmt.parameters_guarded().arg_list();
00863   p_abort("Statement has no parameters.");
00864 }
00865 
00866 
00867 
00868 static map<VariableSymbol*, GlobalDefSite> _explicitly_declared_defs;
00869 void add_new_definition(VariableSymbol& sym, 
00870             ProgramUnit& pgm, 
00871             Statement& stmt){
00872   _explicitly_declared_defs.insert(make_pair(&sym, GlobalDefSite(pgm, stmt)));
00873 }
00874 
00875 
00876 void find_defs(VariableSymbol& sym,
00877            ProgramUnit& pgm,
00878            List<GlobalDefSite>& defs){
00879 /// First loog for a match in the directory of explicitly declared 
00880 /// definitions.
00881   map<VariableSymbol*, GlobalDefSite>::iterator found_def=
00882     _explicitly_declared_defs.find(&sym);
00883   if (found_def!=_explicitly_declared_defs.end()){
00884     defs.ins_last(new GlobalDefSite((*found_def).second));
00885     return;
00886   }
00887 
00888 
00889   Database<ProgramUnit*, Database<Symbol*, List<GlobalDefSite> > >* dmap=
00890     &ip_ssa_dmap();
00891 /// silvius: for now treat arrays as scalars.
00892 /// Scalar, definition site is known.
00893   if (sym.is_scalar() 
00894       || sym.is_array()){
00895     VariableSymbol* base=&sym;
00896     if (sym.is_gsa_symbol()) {
00897       base=(VariableSymbol*)&sym.gsa_base_symbol();
00898       String sbase;
00899       int rank;
00900       gsa_details(sym.name_ref(), sbase, rank);
00901       if (rank>0) {
00902     DefLoc* defloc=pgm.gsa_deflocs_guarded().find_ref(sym);
00903     if (!defloc) {
00904       p_abort("Unknown definition site for GSA symbol.");
00905     }
00906     if (!defloc->stmt_valid()) {
00907       p_abort("Invalid definition site for GSA symbol.");
00908     }
00909     defs.ins_last(new GlobalDefSite(pgm, defloc->stmt_guarded()));
00910     return;
00911       }
00912     }
00913     /// ...  If it gets here it is either GSA rank 0 or not GSA.
00914     /// ...  It must be either in a common or formal.
00915     if (base->common_ref()){
00916       Database<Symbol*, List<GlobalDefSite> >* lmap=dmap->find_ref(&pgm);
00917       if (!lmap) {
00918     cerr<<"\nUndefined global variable "<<sym.name_ref()
00919         <<" in pgm "<<pgm.routine_name_ref();
00920     p_warning("");
00921     return;
00922       }
00923       List<GlobalDefSite>* gdsl=lmap->find_ref(base);
00924       if (!gdsl) {
00925     cerr<<"\nUndefined global variable "<<sym.name_ref()
00926         <<" in pgm "<<pgm.routine_name_ref();
00927     p_warning("");
00928     return;
00929       }
00930       defs=*gdsl;
00931     } else {
00932       if (base->formal()){
00933     /// ...  Return empty set.
00934     return;
00935       } else {
00936     if (base->is_array()){
00937 ///       cerr<<"\nPossibly undefined local variable "<<sym.name_ref()
00938 ///           <<" in pgm "<<pgm.routine_name_ref();
00939 ///       p_warning("");
00940     } else {
00941       cerr<<"\nUndefined local variable "<<sym.name_ref()
00942           <<" in pgm "<<pgm.routine_name_ref();
00943       p_abort("");
00944     }
00945       }
00946     }
00947   }
00948 }
00949 
00950 
00951 
00952 
00953 
00954 
00955 
00956 /// Computes the maximum range for memory accesses based on the DIMENSION
00957 /// declaration
00958 AbstractAccess* compute_top(Symbol& sym){
00959   AbstractAccess* toret=0;
00960   if (sym.is_scalar()) {
00961     List<AccessDimension> dims;
00962     toret=new AbstractAccess(sym, dims, constant(0));
00963   } else {
00964     if (sym.is_array()){
00965       List<AccessDimension> dims;
00966       List<Expression>* factors=new List<Expression>;
00967       Iterator<ArrayBounds> abit=sym.dim();
00968       bool found_all_bounds=true;
00969       for ( ; abit.valid(); ++abit){
00970     ArrayBounds& ab=abit.current();
00971     if (ab.lower_exists()){
00972       if (ab.upper_exists()){
00973         Expression* abup=0;
00974         if (ab.upper_guarded().substituted_valid()){
00975           abup=ab.upper_guarded().substituted_guarded().clone();
00976         } else {
00977           abup=ab.upper_guarded().clone();
00978         }
00979         factors->ins_last(simplify(add(constant(1),
00980                        sub(abup,
00981                            ab.lower_guarded().clone()))));
00982       } else {
00983         factors->ins_last(ab.lower_guarded().clone());
00984       }
00985     } else {
00986       if (ab.upper_exists()){
00987         Expression* abup=0;
00988         if (ab.upper_guarded().substituted_valid()){
00989           abup=ab.upper_guarded().substituted_guarded().clone();
00990         } else {
00991           abup=ab.upper_guarded().clone();
00992         }
00993         factors->ins_last(abup);
00994       } else {
00995         found_all_bounds=false;
00996         break;
00997       }
00998     }
00999       }
01000       if (found_all_bounds){
01001     AccessDimension* ad=new AccessDimension(constant(1), 
01002                         simplify(sub(mul(factors),
01003                                  constant(1))));
01004     dims.ins_first(ad);
01005     toret=new AbstractAccess(sym, dims, constant(0), ACCU_EXACT, AR_READ);
01006       } else {
01007     delete factors;
01008       }
01009     }
01010   }
01011   return toret;
01012 }
01013 
01014 
01015 
01016 
01017 /// Computes TOP range based on the Fortran 77 Standard assumption:
01018 /// call p(a(i1), a(i2))
01019 /// If p modifies its arguments and i1<i2, then write access in 
01020 /// subroutine p(b1, b2)
01021 /// is upper bounded for b1 by b1(i1:i2-1).
01022 /// Otherwise, two formals would be aliased and written (against the standard).
01023 void 
01024 compute_top_range_from_actuals(Program& prog,
01025                    ProgramUnit& pgm,
01026                    Statement& callsite,
01027                    Database<Symbol*, List<Expression> >& arrays){
01028   ProgramUnit* callee=called_pgm(callsite);
01029   if (!callee) return; /// ...  Not a call site.
01030   List<Expression>& actuals=parameters(callsite);
01031   Iterator<Expression> ait=actuals;
01032 /// First find arrays that are passed to the routine.
01033   for (ait=actuals; ait.valid(); ++ait){
01034     VariableSymbol* basesym=0;
01035     Expression* index=0;
01036     Expression& expr=ait.current();
01037     /// ...  Array expr, i.e. call p(a(i))
01038     if (expr.op()==ARRAY_REF_OP){
01039       basesym=(VariableSymbol*)&expr.array().symbol();
01040       index=base_offset(&expr);
01041     }
01042     /// ...  Array symbol, i.e. call p(a)
01043     if (expr.op()==ID_OP){
01044       if (expr.symbol().is_array()){
01045     basesym=(VariableSymbol*)&expr.symbol();
01046     index=constant(0);
01047       }
01048     }
01049     /// ...  Beta
01050     if (is_beta(expr)){
01051       /// ...  Get its base symbol.
01052       Expression* last_arg=expr.parameters_guarded().arg_list().last_ref();
01053       if (last_arg->op()==ARRAY_REF_OP){
01054     basesym=(VariableSymbol*)&last_arg->array().symbol();
01055     index=base_offset(last_arg);
01056       }
01057       if (last_arg->op()==ID_OP){
01058     if (last_arg->symbol().is_array()){
01059       basesym=(VariableSymbol*)&last_arg->symbol();
01060       index=constant(0);
01061     }
01062       }      
01063     }
01064     if (!basesym){
01065       /// ...  This is not an array or an array referrence.
01066       continue;
01067     }
01068     if (basesym->is_gsa_symbol()) {
01069       basesym=(VariableSymbol*)&basesym->gsa_base_symbol();
01070     }
01071     List<Expression>* this_array=arrays.find_ref(basesym);
01072     if (!this_array){
01073       this_array=new List<Expression>;
01074       arrays.ins(basesym, this_array);
01075     }
01076     /// ...  Find position to insert them sorted.
01077     if (!pgm.range_dict_valid()){
01078       cerr<<"\nFor program unit: "<<pgm.routine_name_ref();
01079       p_warning("Range Dictionary is missing or invalid.");
01080       pgm.range_dict(new AIRangeDict(pgm));
01081     }
01082     RangeAccessor range_acc(pgm.range_dict_guarded(), 
01083                 *(range_stmt(callsite)));
01084     int pos=0; /// ...  Assume it is the first.
01085     bool found_pos=false;
01086     if (this_array->entries()==0){
01087       this_array->ins_last(index);
01088     } else {
01089       for (Iterator<Expression> expit=*this_array;
01090        expit.valid(); ++expit, ++pos){
01091     Expression* simple=simplify(expit.current().clone());   
01092     Relation comp = range_acc.compare(*index, *simple);
01093     if (comp.is_less_than()){
01094       this_array->ins_before(index, &expit.current());
01095       found_pos=true;
01096       break;
01097     }
01098       }
01099       if (!found_pos){
01100     Expression* simple=simplify(this_array->last_ref()->clone());
01101     Relation comp = range_acc.compare(*index, 
01102                       *simple);
01103     delete simple;
01104     if (comp.is_greater_equal()){
01105       this_array->ins_last(index);
01106     } else {
01107       this_array->ins_last(index);
01108 ///       cerr<<"\nSubscript "<<*index;
01109 ///       cerr<<"\nCallsite "<<callsite;
01110 ///       cerr<<"\nThis array "<<*this_array;
01111 ///       p_warning("Could not find sorted subscript position at callsite.");
01112     }
01113       }
01114     }
01115   }
01116 }
01117 
01118 /// Builds the diamond-shaped structure that contains the call DAG between
01119 /// 'to' and 'from'.
01120 static void _build_call_diamond(ProgramUnit& from, ProgramUnit& to,
01121                 set<ProgramUnit*>& pgms){
01122 /// Build upward cone starting from 'from'
01123   set<ProgramUnit*> upwards;
01124   RefList<ProgramUnit> q;
01125   q.ins_first(from);
01126   while (q.entries()){
01127     ProgramUnit& pgm=q.grab(0);
01128     upwards.insert(&pgm);
01129     RefSet<ProgramUnit>& callers=pgm.called_by();
01130     for(Iterator<ProgramUnit> pit=callers; pit.valid(); ++pit){
01131       if (upwards.find(&pit.current())!=upwards.end()){
01132     /// ...  Already seen.
01133     continue;
01134       } else {
01135     q.ins_last(pit.current());
01136       }
01137     }
01138   }
01139 
01140 /// Build downward cone starting from 'to'
01141   set<ProgramUnit*> downward;
01142   q.ins_first(to);
01143   while (q.entries()){
01144     ProgramUnit& pgm=q.grab(0);
01145     downward.insert(&pgm);
01146     RefSet<ProgramUnit>& callees=pgm.calls();
01147     for(Iterator<ProgramUnit> pit=callees; pit.valid(); ++pit){
01148       if (downward.find(&pit.current())!=downward.end()){
01149     /// ...  Already seen.
01150     continue;
01151       } else {
01152     q.ins_last(pit.current());
01153       }
01154     }
01155   }
01156 
01157 /// Get intersection.
01158   set_intersection(upwards.begin(), upwards.end(),
01159            downward.begin(), downward.end(),
01160            inserter(pgms, pgms.begin()));
01161 }
01162 
01163 
01164 static void 
01165 _find_call_sites(ProgramUnit& callee, set<ProgramUnit*>& all_pgms,
01166          vector<pair<ProgramUnit*, Statement*> >&call_sites){
01167   RefSet<ProgramUnit>& callers=callee.called_by();
01168   for(Iterator<ProgramUnit> pit=callers; pit.valid(); ++pit){
01169     ProgramUnit& pgm=pit.current();
01170     if (all_pgms.find(&pgm)==all_pgms.end()){
01171       /// ...  Skip subprograms not in the given set.
01172       continue;
01173     }
01174     Iterator<Statement> stit=pgm.stmts().iterator();
01175     for( ; stit.valid(); ++stit){
01176       Statement& stmt=stit.current();
01177       if (called_pgm(stmt)==&callee){
01178     call_sites.push_back(make_pair(&pgm, &stmt));
01179       }
01180     }
01181   }
01182 }
01183 
01184 
01185 
01186 /// Translate the given list of symbols.
01187 /// This translation may span multiple subprograms but it must
01188 /// be unique.  For instance, 'from' may be called at different call sites
01189 /// on the way to 'to', but all of them must finally correspond to the same
01190 /// value in 'to'.
01191 const Symbol* translate_sym(ProgramUnit& from, ProgramUnit& to, 
01192                 const Symbol& sym){
01193   set<ProgramUnit*> all_pgms;
01194   _build_call_diamond(from, to, all_pgms);
01195   queue<pair<const Symbol*, ProgramUnit*> > q;
01196   q.push(make_pair(&sym, &from));
01197   const Symbol* target=0;
01198   while (q.size()>0){
01199     pair<const Symbol*, ProgramUnit*> current=q.front();
01200     q.pop();
01201     ProgramUnit& pgm=*current.second;
01202     const Symbol* s=current.first;
01203     if (&pgm==&to){
01204       /// ...  This is the final value.
01205       if (target){
01206     /// ...  Make sure all values are actually the same.
01207     /// ...  This makes it slower, but could be helpful for debugging.
01208     if (target!=s){
01209       p_warning("Two translations found for same symbol.");
01210       return 0;
01211     }
01212       } else {
01213     target=s;
01214       }
01215     } else {
01216       /// ...  This is just an intermediate value.
01217       /// ...  Find call sites within the diamond and translate the symbol
01218       /// ...  upwards.
01219       vector<pair<ProgramUnit*, Statement*> > call_sites;
01220       _find_call_sites(pgm, all_pgms, call_sites);
01221       /// ...  Translate upwards.
01222       vector<pair<ProgramUnit*, Statement*> >::iterator csit;
01223       for (csit=call_sites.begin(); csit!=call_sites.end(); ++csit){
01224     ProgramUnit& current_to=*(*csit).first;
01225     Statement& call_site=*(*csit).second;
01226     ProgramUnit& current_from=pgm;
01227     Expression* t=translate_var((VariableSymbol&)*s, 
01228                     current_from, current_to, call_site);
01229     p_assert(t, "Cannot translate input value.");
01230     if (t->op()!=ID_OP){
01231       p_warning("Translation of input values - only simple values for now.");
01232       // silvius: for now, just return 0
01233       return 0;
01234     }
01235     /// ...  Put translation in queue.
01236     q.push(make_pair(&t->symbol(), &current_to));
01237       }
01238     }
01239   }
01240   p_assert(target, "Could not find a suitable translation.");
01241   return target;
01242 }
01243 
01244 
01245 ProgramUnit* find_main_pgm(Program& prog){
01246   for(KeyIterator<String, ProgramUnit> pit=prog; pit.valid(); ++pit){
01247     ProgramUnit& pgm=pit.current_data();
01248     if (pgm.pu_class()==PROGRAM_PU_TYPE){
01249       return &pgm;
01250     }
01251   }
01252   return 0;
01253 }
01254 
01255 
01256 ProgramUnit* find_pgm(Program& prog,const char * routine_name){
01257   for(KeyIterator<String, ProgramUnit> pit=prog; pit.valid(); ++pit){
01258     ProgramUnit& pgm=pit.current_data();
01259     if (strcmp(pgm.routine_name_ref(),routine_name)==0){
01260       return &pgm;
01261     }
01262   }
01263   return 0;
01264 }
01265 
01266 
01267 /*!
01268   \brief Traverse the callgraph in postorder to produce a
01269   reverse topsort ordering of the nodes.
01270 */
01271 static void postorder(ProgramUnit& source, 
01272               vector<ProgramUnit*>& ordered,
01273               set<ProgramUnit*>& processed){
01274 /// Check whether already processed.
01275   if (processed.find(&source)!=processed.end()){
01276     return;
01277   } else {
01278     for (Iterator<ProgramUnit> pit=source.calls(); pit.valid(); ++pit){
01279       ProgramUnit& pgm=pit.current();
01280       postorder(pgm, ordered, processed);
01281     }
01282     processed.insert(&source);
01283     ordered.push_back(&source);
01284   }
01285 }
01286 
01287 /*!
01288   \brief Produce a reverse topsort ordering of the subprograms.
01289 */
01290 void topsort_call_dag(Program& prog, vector<ProgramUnit*>& ordered){
01291   prog.compute_call_lists();
01292   set<ProgramUnit*> processed;
01293   ProgramUnit* main=find_main_pgm(prog);
01294   if (!main){
01295     p_abort("IPA Bottom-up could not find main program.");
01296   }
01297   postorder(*main, ordered, processed);
01298 }
01299 
01300 
01301 Statement* matching_else(Statement* if_stmt){
01302   Statement* stit;
01303   for (stit=if_stmt; stit!=0 && stit !=if_stmt->matching_endif_ref(); 
01304        stit=stit->next_ref()){
01305     if (stit->stmt_class()==ELSE_STMT){
01306       if (stit->lead_ref()==if_stmt){
01307     return stit;
01308       }
01309     }
01310   }
01311   return 0;
01312 }
01313 
01314 
01315 void get_in_out(ProgramUnit& caller, Statement& callsite, Symbol& sym,
01316         Symbol*& incoming, Symbol*& outgoing){
01317   incoming=outgoing=0;
01318 /// First check whether it was passed as an actual parameter.
01319   for(Iterator<Expression> eit=callsite.act_refs(); eit.valid(); ++eit){
01320     if (eit.current().op()==ID_OP){
01321       if (gsa_base(eit.current().symbol())==&sym){
01322     outgoing=&eit.current().symbol();
01323       }
01324     }
01325   }
01326   if (outgoing){
01327     for(Iterator<Expression> eit=callsite.in_refs(); eit.valid(); ++eit){
01328       if (eit.current().op()==ID_OP){
01329     if (gsa_base(eit.current().symbol())==&sym){
01330       if (&eit.current().symbol()!=outgoing){
01331         incoming=&eit.current().symbol();
01332       }
01333     }
01334       }
01335     }
01336     if (incoming==0){
01337       display_translation_error((VariableSymbol&)sym, 
01338                 *called_pgm(callsite), caller, callsite);
01339       p_abort("Could not find IN parameter for a given OUT.");
01340     }
01341   } else {
01342     p_assert(sym.common_ref(), 
01343          "Symbol is neither passed as parameter nor in a common.");
01344     Statement* ps=callsite.next_ref();
01345     while (ps){
01346       if (ps->stmt_class()!=ASSIGNMENT_STMT){
01347     break;
01348       }
01349       if (ps->rhs().op()!=THETA_OP){
01350     break;
01351       }
01352       if (gsa_base(ps->lhs().symbol())==&sym){
01353     outgoing=&ps->lhs().symbol();
01354     incoming=&ps->rhs().parameters_guarded().arg_list()[0].symbol();
01355     return;
01356       } else {
01357     ps=ps->next_ref();
01358       }
01359     }
01360   }
01361 }
01362 
01363 void get_out(ProgramUnit& caller, Statement& callsite, Symbol& sym,
01364          Symbol*& outgoing){
01365   outgoing=0;
01366 /// First check whether it was passed as an actual parameter.
01367   for(Iterator<Expression> eit=callsite.act_refs(); eit.valid(); ++eit){
01368     if (eit.current().op()==ID_OP){
01369       if (gsa_base(eit.current().symbol())==&sym){
01370     outgoing=&eit.current().symbol();
01371       }
01372     }
01373   }
01374   if (outgoing==0){
01375     p_assert(sym.common_ref(), 
01376          "Symbol is neither passed as parameter nor in a common.");
01377     Statement* ps=callsite.next_ref();
01378     while (ps){
01379       if (ps->stmt_class()!=ASSIGNMENT_STMT){
01380     break;
01381       }
01382       if (ps->rhs().op()!=THETA_OP){
01383     break;
01384       }
01385       if (gsa_base(ps->lhs().symbol())==&sym){
01386     outgoing=&ps->lhs().symbol();
01387     return;
01388       } else {
01389     ps=ps->next_ref();
01390       }
01391     }
01392   }
01393 }
01394 
01395 
01396 void get_in(ProgramUnit& caller, Statement& callsite, Symbol& sym,
01397         Symbol*& incoming){
01398   ProgramUnit& callee=*called_pgm(callsite);
01399   incoming=0;
01400 /// First check whether it was passed as an actual parameter.
01401   for(Iterator<Expression> eit=callsite.act_refs(); eit.valid(); ++eit){
01402     if (eit.current().op()==ID_OP){
01403       if (gsa_base(eit.current().symbol())==&sym){
01404     incoming=&eit.current().symbol();
01405       }
01406     }
01407   }
01408   if (incoming){
01409     for(Iterator<Expression> eit=callsite.in_refs(); eit.valid(); ++eit){
01410       if (eit.current().op()==ID_OP){
01411     if (gsa_base(eit.current().symbol())==&sym){
01412       if (&eit.current().symbol()!=incoming){
01413         incoming=&eit.current().symbol();
01414         break;
01415       }
01416     }
01417       }
01418     }
01419     if (incoming==0){
01420       display_translation_error((VariableSymbol&)sym, 
01421                 *called_pgm(callsite), caller, callsite);
01422       p_abort("Could not find IN parameter.");
01423     }
01424   } else {
01425     p_assert(sym.common_ref(), 
01426          "Symbol is neither passed as parameter nor in a common.");
01427     Statement* ps=callsite.next_ref();
01428     while (ps){
01429       if (ps->stmt_class()!=ASSIGNMENT_STMT){
01430     break;
01431       }
01432       if (ps->rhs().op()!=THETA_OP){
01433     break;
01434       }
01435       if (gsa_base(ps->lhs().symbol())==&sym){
01436     incoming=&ps->rhs().parameters_guarded().arg_list()[0].symbol();
01437     return;
01438       } else {
01439     ps=ps->next_ref();
01440       }
01441     }
01442     /// ...  Maybe it is just passed in via a common.
01443     incoming=translate_common_var((VariableSymbol&)sym,
01444                   callee, caller, callsite);
01445   }
01446 }
01447 
01448 
01449 /// Replaces first with second everywhere in given.
01450 Expression* replace_expression(Expression* given,
01451                    Expression& first,  /// ...  Must be ARRAY_REF or ID
01452                    Expression& second){
01453   if (first.op()!=ID_OP && first.op()!=ARRAY_REF_OP){
01454     p_abort("First expression must be ID or ARRAY_REF to perform substitution.");
01455   }
01456   if (!given) return 0;
01457   if (given->op()==ID_OP || given->op()==ARRAY_REF_OP){
01458     if (*given==first){
01459       return second.clone();
01460     } else {
01461       return given;
01462     }
01463   }
01464   Mutator<Expression> expit = given->arg_list();
01465   for ( ; expit.valid(); ++expit) {
01466     Assign<Expression> a = expit.assign();
01467     a=replace_expression(expit.pull(), first, second);
01468   }
01469   return given;
01470 }
01471 
01472 void replace_expression(AbstractAccess& aa, 
01473             Expression& first, Expression& second){
01474   if ( aa.start_exists() ){
01475     Expression* tmp=simplify(aa.start_guarded().clone());
01476     tmp=replace_expression(tmp, first, second);
01477     aa.start(simplify(tmp));
01478   }
01479   Iterator<AccessDimension> adit=aa.iter_dims();
01480   for (adit.reset(); adit.valid(); ++adit){
01481     AccessDimension& ad=adit.current();
01482     if (ad.stride_exists()){
01483       Expression* tmp=simplify(ad.stride_guarded().clone());
01484       tmp=replace_expression(tmp, first, second);
01485       ad.stride(simplify(tmp));
01486     }
01487     if (ad.span_exists()){
01488       Expression* tmp=simplify(ad.span_guarded().clone());
01489       tmp=replace_expression(tmp, first, second);
01490       ad.span(simplify(tmp));
01491     }
01492   }
01493 }
01494 
01495 void replace_expression(List<AbstractAccess>& aalist, 
01496             Expression& first, Expression& second){
01497   for (Iterator<AbstractAccess> aait=aalist; aait.valid(); ++aait){
01498     AbstractAccess& aa=aait.current();
01499     replace_expression(aa, first, second); 
01500   }  
01501 }
01502 
01503 
01504 void replace_symbol(AbstractAccess& aa,
01505             Symbol& first, Symbol& second){
01506   if ( aa.start_exists() ){
01507     substitute_var(aa.start_guarded(), first, second);
01508   }
01509   Iterator<AccessDimension> adit=aa.iter_dims();
01510   for (adit.reset(); adit.valid(); ++adit){
01511     AccessDimension& ad=adit.current();
01512     if (ad.stride_exists()){
01513       substitute_var(ad.span_guarded(), first, second);
01514     }
01515     if (ad.span_exists()){
01516       substitute_var(ad.stride_guarded(), first, second);
01517     }
01518   }
01519 }
01520 
01521 void replace_symbol(AbstractAccess& aa, 
01522             Symbol& first, Expression& second){
01523   if ( aa.start_exists() ){
01524     Expression* tmp=aa.start_guarded().clone();
01525     aa.start(simplify(substitute_var(tmp, first, second)));
01526   }
01527   Iterator<AccessDimension> adit=aa.iter_dims();
01528   for (adit.reset(); adit.valid(); ++adit){
01529     AccessDimension& ad=adit.current();
01530     if (ad.stride_exists()){
01531       Expression* tmp=ad.stride_guarded().clone();
01532       ad.stride(simplify(substitute_var(tmp, first, second)));
01533     }
01534     if (ad.span_exists()){
01535       Expression* tmp=ad.span_guarded().clone();
01536       ad.span(simplify(substitute_var(tmp, first, second)));
01537     }
01538   }
01539 }
01540 
01541 
01542 void simplify_expressions(AbstractAccess& aa){
01543   if ( aa.start_exists() ){
01544     Expression* tmp=aa.start_guarded().clone();
01545     aa.start(simplify(tmp));
01546   }
01547   Iterator<AccessDimension> adit=aa.iter_dims();
01548   for (adit.reset(); adit.valid(); ++adit){
01549     AccessDimension& ad=adit.current();
01550     if (ad.stride_exists()){
01551       Expression* tmp=ad.stride_guarded().clone();
01552       ad.stride(simplify(tmp));
01553     }
01554     if (ad.span_exists()){
01555       Expression* tmp=ad.span_guarded().clone();
01556       ad.span(simplify(tmp));
01557     }
01558   }
01559 }
01560 
01561 void replace_symbol(List<AbstractAccess>& aalist, 
01562             Symbol& first, Expression& second){
01563   for (Iterator<AbstractAccess> aait=aalist; aait.valid(); ++aait){
01564     AbstractAccess& aa=aait.current();
01565     if ( aa.start_exists() ){
01566       Expression* tmp=aa.start_guarded().clone();
01567       aa.start(simplify(substitute_var(tmp, first, second)));
01568     }
01569     Iterator<AccessDimension> adit=aa.iter_dims();
01570     for (adit.reset(); adit.valid(); ++adit){
01571       AccessDimension& ad=adit.current();
01572       if (ad.stride_exists()){
01573     Expression* tmp=ad.stride_guarded().clone();
01574     ad.stride(simplify(substitute_var(tmp, first, second)));
01575       }
01576       if (ad.span_exists()){
01577     Expression* tmp=ad.span_guarded().clone();
01578     ad.span(simplify(substitute_var(tmp, first, second)));
01579       }
01580     }
01581   }
01582 }
01583 
01584 void replace_symbol(List<AbstractAccess>& aalist, 
01585             Symbol& first, Symbol& second){
01586   if (&first==&second) return;
01587   for (Iterator<AbstractAccess> aait=aalist; aait.valid(); ++aait){
01588     AbstractAccess& aa=aait.current();
01589     replace_symbol(aa, first, second);
01590   }
01591 }
01592 
01593 
01594 /// Returns whether the given loop executes at least one iteration.
01595 Expression* at_least_one_iteration(ProgramUnit& pgm, DoStmt& loop, 
01596                    bool use_range_dict){
01597 
01598   if (!use_range_dict){
01599     Expression* toret=or(and(gt(loop.step().clone(),
01600                 constant(0)),
01601                  ge(loop.limit().clone(),
01602                 loop.init().clone())),
01603              and(lt(loop.step().clone(),
01604                 constant(0)),
01605                  lt(loop.limit().clone(),
01606                 loop.init().clone())));
01607     return simplify(toret);
01608   }
01609 
01610   if (!pgm.range_dict_valid()){
01611     pgm.range_dict(new AIRangeDict(pgm));
01612   }
01613   RangeAccessor ra(pgm.range_dict_guarded(), loop);
01614   Relation r=ra.compare(loop.limit(), loop.init());
01615   if (ra.signz(loop.step())==POS_EXPR){
01616     if (r.is_greater_equal()){
01617       return constant(".TRUE.");
01618     } else {
01619       if (r.is_less_than()){
01620     return constant(".FALSE.");
01621       } else {
01622     return simplify(ge(loop.limit().clone(),
01623                loop.init().clone()));
01624       }
01625     }
01626   } else {
01627     if (ra.signz(loop.step())==NEG_EXPR){
01628       if (r.is_less_equal()){
01629     return constant(".TRUE.");
01630       } else {
01631     if (r.is_greater_than()){
01632       return constant(".FALSE.");
01633     } else {
01634       return simplify(le(loop.limit().clone(),
01635                  loop.init().clone()));
01636     }
01637       }
01638     } else {
01639       if (r.is_greater_equal()){
01640     return simplify(gt(loop.step().clone(), constant(0)));
01641       } else {
01642     if (r.is_less_equal()){
01643       return simplify(lt(loop.step().clone(), constant(0)));
01644     } else {
01645       Expression* toret=or(and(gt(loop.step().clone(),
01646                       constant(0)),
01647                    ge(loop.limit().clone(),
01648                       loop.init().clone())),
01649                    and(lt(loop.step().clone(),
01650                       constant(0)),
01651                    lt(loop.limit().clone(),
01652                       loop.init().clone())));
01653       return simplify(toret);
01654     }
01655       }
01656     }
01657   }
01658 }
01659 
01660 
01661 //Guobin: Find out the sub-expressions in expr whose OP_TYPE is the same as
01662 //the specified.
01663 RefSet<Expression> search_expression(Expression& expr,OP_TYPE o)
01664 {
01665    RefSet<Expression> results;
01666 
01667    if(expr.op() == ID_OP)
01668    {
01669       if(o==ID_OP)
01670       {
01671          results.ins(expr);
01672          return results;      
01673       }
01674    }
01675    else
01676    {
01677       if(expr.op()==o)
01678          results.ins(expr);
01679 
01680       for(Iterator<Expression> iter=expr.arg_list();iter.valid();++iter)
01681       {
01682          Expression& sub_expr=iter.current();
01683      if(o!=BETA_OP)
01684      {
01685         if(sub_expr.op()==o)
01686            results.ins(sub_expr);
01687          }
01688      else
01689         if(is_beta(sub_expr))
01690            results.ins(sub_expr);
01691      RefSet<Expression> sub_results;
01692          sub_results=search_expression(sub_expr,o);
01693      results+=sub_results; 
01694       }
01695    }
01696 
01697    return results;
01698 }
01699 
01700 //Guobin: Find out the sub-expressions in stmt whose OP_TYPE is the same as
01701 //the specified.
01702 RefSet<Expression> search_expression(Statement& stmt,OP_TYPE o)
01703 {
01704    RefSet<Expression> results;
01705 
01706    Iterator<Expression> iter=stmt.iterate_expressions();
01707    for(;iter.valid();++iter)
01708    {
01709       RefSet<Expression> sub_results;
01710       Expression& sub_expr=iter.current();
01711       sub_results=search_expression(sub_expr,o);
01712       results+=sub_results;
01713    }
01714 
01715    return results;
01716 }
 © 1995-2005 University of Illinois, Urbana-Champaign. All rights reserved.  Fri Mar 25 23:06:15 2005