Polaris: ip_ssa.cc Source File

ip_ssa.cc

Go to the documentation of this file.
00001 ///
00002 #include <set>
00003 
00004 #include "Statement/AssignmentStmt.h"
00005 #include "Statement/DoStmt.h"
00006 #include "utilities/gsa_util.h"
00007 #include "utilities/program_util.h"
00008 #include "Deadcode/deadcode.h"
00009 
00010 #include "simple_maymods.h"
00011 #include "ip_ssa.h"
00012 #include "trans_util.h" 
00013 #include "optimize_ssa.h"
00014 #include "Expression/BinaryExpr.h"
00015 #include "Expression/UnaryExpr.h"
00016 #include "Expression/expr_funcs.h"
00017 
00018 
00019 static Database<ProgramUnit*, Database<Symbol*, RefList<Symbol> > > iomap;
00020 
00021 /*!
00022   \brief Global mapping per pgm, per base symbol, of subprogram calls into SSA
00023   names.
00024 */
00025 static Database<ProgramUnit*, /// ...  Every program unit.
00026         Database<Statement*, /// ...  Every call site.
00027              RefDatabase<Symbol*, /// ...  Every base symbol.
00028                      Symbol> > > _gmap; /// ...  SSA name.
00029 
00030 /*!
00031   \brief The reaching definitions list per pgm, per base symbol (for 
00032   commons only).
00033 */
00034 static Database<ProgramUnit*, /// ...  Every program unit.
00035         Database<Symbol*, /// ...  Every base common variable.
00036              List<GlobalDefSite> > > _dmap; /// ...  Reaching defs.
00037 
00038 Database<ProgramUnit*, 
00039         Database<Statement*, 
00040              RefDatabase<Symbol*, 
00041                      Symbol> > >& ip_ssa_gmap(){
00042   return _gmap;
00043 }
00044 
00045 Database<ProgramUnit*, 
00046      Database<Symbol*, 
00047           List<GlobalDefSite> > >& ip_ssa_dmap(){
00048   return _dmap;
00049 }
00050 
00051 
00052 
00053 static void print_dmap(){
00054   cerr<<"\n\n\nBEGIN DMAP: \n\n";
00055   KeyIterator<ProgramUnit*, Database<Symbol*, List<GlobalDefSite> > > it1=
00056     _dmap;
00057   for (; it1.valid(); ++it1){
00058     cerr<<"\nFor pgm. "<<it1.current_key()->routine_name_ref();
00059     KeyIterator<Symbol*, List<GlobalDefSite> > it2=it1.current_data();
00060     for(; it2.valid(); ++it2){
00061       cerr<<"\n\tFor Sym. "<<it2.current_key()->name_ref()<<
00062     " "<<it2.current_data();
00063     }
00064   }
00065   cerr<<"\n\n\nEND DMAP\n\n\n ";
00066 }
00067 
00068 
00069 static void print_gmap(ProgramUnit& pgm){
00070   cerr<<"\n\n\nBEGIN GMAP: \n\n";
00071   cerr<<"\nFor pgm. "<<pgm.routine_name_ref();
00072   if (_gmap.find_ref(&pgm)!=0) {
00073     KeyIterator<Statement*, RefDatabase<Symbol*, Symbol> > it2=
00074       *_gmap.find_ref(&pgm);
00075     for(; it2.valid(); ++it2){
00076       cerr<<"\nFor stmt: ";
00077       int w=1;
00078       it2.current_key()->write(cerr, w);
00079       KeyIterator<Symbol*, Symbol> it3=it2.current_data();
00080       for(; it3.valid(); ++it3){
00081     cerr<<"\n"<<it3.current_key();
00082     cerr<<"\n\tFor Sym. "<<it3.current_key()->name_ref()<<
00083       ", mapped is: "<<it3.current_data().name_ref();
00084       }
00085     }
00086   }
00087   cerr<<"\n\n\nEND GMAP\n\n\n ";
00088 }
00089 
00090 
00091 
00092 
00093 static void print_in_out_sets(Program& prog){
00094   for (KeyIterator<ProgramUnit*, Database<Symbol*, RefList<Symbol> > > pssit=
00095      iomap; pssit.valid(); ++pssit){
00096     cerr<<"\nIn pgm. "<<pssit.current_key()->routine_name_ref();
00097     for (KeyIterator<Symbol*, RefList<Symbol> > ssit=
00098      pssit.current_data(); ssit.valid(); ++ssit){
00099       cerr<<"\n\tFor output value "<<ssit.current_key()->name_ref()<<"\t:";
00100       for (Iterator<Symbol> sit=
00101      ssit.current_data(); sit.valid(); ++sit){
00102     cerr<<" "<<sit.current().name_ref();
00103       }
00104     }
00105   }
00106 }
00107 
00108 void build_in_out_set(Symbol& out, IntraPCodeDomain& domain,
00109               RefList<Symbol>& in,
00110               ProgramUnit& pgm, Program& prog){
00111 /// Go back on the use-def chains for all variables input to this one.
00112   RefList<Symbol> q;
00113   q.ins_last(out);
00114   Database<Symbol*, IntElem> seen;
00115 ///   cerr<<"\n\n\nFor symbol: "<<out.name_ref();
00116   while (q.entries()){
00117     VariableSymbol& current=(VariableSymbol&)q.grab(0);
00118 ///     cerr<<"\nDequeuing "<<current.name_ref();
00119     VariableSymbol* base_current=&current;
00120     if (base_current->is_gsa_symbol()){
00121       base_current=(VariableSymbol*)&base_current->gsa_base_symbol();
00122     }
00123     if (seen.find_ref(&current)){
00124       continue;
00125     } else {
00126       seen.ins(&current, new IntElem(0));
00127     }
00128 
00129     if (current.intrinsic()){
00130       continue;
00131     }
00132 
00133     String basename;
00134     int rank;
00135     gsa_details(current.name_ref(), basename, rank);
00136     if (rank==0){
00137       bool is_data=false;
00138       /// ...  It is an input to the whole routine or given in a DATA statement.
00139       for (Iterator<Data> dit=pgm.data(); dit.valid(); ++dit){
00140     for(Iterator<Expression> eit=dit.current().variable_list().arg_list();
00141         eit.valid(); ++eit){
00142       if (eit.current().base_variable_ref()==base_current){
00143         /// ...  In a DATA.
00144         is_data=true;
00145         break;
00146       }
00147     }
00148     if (is_data) break;
00149       }
00150       if (is_data){
00151     /// ...  Do nothing, its value depends only on constants.
00152       } else {
00153     /// ...  It is an input to the whole routine, it'd better be translatable.
00154     if (!in.member(current)){
00155       in.ins_last(current);
00156     }
00157       }
00158       continue;
00159     }
00160     
00161     /// ...  Not an input, proper GSA name (rank>=1).
00162     DefLoc* defloc=pgm.gsa_deflocs_guarded().find_ref(current);
00163     if (!defloc) {
00164       p_abort("Bad DefLoc map.");
00165     }
00166     if (!defloc->stmt_valid()) {
00167       p_abort("Bad DefLoc map.");
00168     }
00169     Statement& def=defloc->stmt_guarded();
00170     
00171     /// ...  Check whether definition site is within domain.
00172     if (!domain.contains(def)){
00173       if (!in.member(current)){
00174     in.ins_last(current);
00175       }
00176       continue;
00177     }
00178     
00179     Statement* call=0;
00180     ProgramUnit* callee=0;
00181     /// ...  If this is a call site, then current value is either:
00182     /// ...  1. in a common modified inside.
00183     /// ...  2. passed as a formal parameter
00184     /// ...  3. returned by a function
00185 
00186     /// ...  Find corresponding symbol in called routine.
00187     /// ...  1. THETA
00188     RefList<Symbol> corresponding_base_syms;
00189     if (def.stmt_class()==ASSIGNMENT_STMT){
00190       if (def.rhs().op()==THETA_OP){
00191     call=&def;
00192     while (call!=0){
00193       if (called_pgm(*call)){
00194         break;
00195       }
00196       call=call->prev_ref();
00197     }
00198     p_assert(call, "Bad THETA placement.");
00199     callee=called_pgm(*call);
00200     Symbol* cbs=0;
00201     cbs=callee->symtab().find_ref(basename);
00202     p_assert(cbs, "Could not map common vars.");
00203     corresponding_base_syms.ins_last(*cbs);
00204       }
00205     }
00206 
00207     /// ...  2. Subroutine or function.
00208     if (!call){
00209       callee=called_pgm(def);
00210       if (callee){
00211     /// ...  Subprogram call.
00212     call=&def;
00213     Translator translator(pgm, def);
00214     corresponding_base_syms=untranslate_var(current,
00215                         *callee, pgm, *call);
00216     p_assert(corresponding_base_syms.entries(),
00217          "No suitable un-translation found.");
00218     /// ...  Must also add corresponding symbol if it is also a common.
00219     if (current.common_ref()){
00220     corresponding_base_syms.ins_last(*callee->symtab().find_ref(basename));
00221     }
00222       }
00223     }
00224 
00225     /// ...  Either THETA, function or subroutine.
00226     if (call){
00227       Translator translator(pgm, *call);
00228       /// ...  Find all inputs for this output.
00229       for(Iterator<Symbol> sit=corresponding_base_syms; sit.valid(); ++sit){
00230     Symbol* corresponding_base_sym=&sit.current();
00231     Database<Symbol*, RefList<Symbol> >* local_iomap=iomap.find_ref(callee);
00232     if (local_iomap==0){ 
00233       cerr<<"\nFor routine: "<<callee->routine_name_ref();
00234       p_abort("Could not find local in-out map.");
00235     }
00236     RefList<Symbol>* callee_iomap=
00237       local_iomap->find_ref(corresponding_base_sym);
00238     if (!callee_iomap){
00239       cerr<<"\nFor routine: "<<callee->routine_name_ref()
00240           <<" and symbol "<<corresponding_base_sym->name_ref();
00241       p_abort( "Could not find in-out map.");
00242     }
00243     for(Iterator<Symbol> csit=*callee_iomap; csit.valid(); ++csit){
00244 ///       cerr<<"\n\t\tcsit.current()="<<csit.current().name_ref()
00245 ///           <<"\n iomap = "<<*callee_iomap;
00246       // Translate every input back to the caller.
00247       Expression* te=translate_var((VariableSymbol&)csit.current(),
00248                        *callee, pgm, *call);
00249 ///       cerr<<"\n\t\tactuals:"<<parameters(*call);
00250       if(te==0){
00251 ///         cerr<<"\nUse of possibly undefined variable "
00252 ///         <<csit.current().name_ref()
00253 ///         <<" in subprogram "<<callee->routine_name_ref();
00254 ///         p_warning("");
00255         /// ...  Do nothing else, it was probably an undefined local
00256         /// ...  that will never need definition due to application logic.
00257       } else {
00258         te=simplify(te);
00259         if (te->op()==INTEGER_CONSTANT_OP ||
00260         te->op()==REAL_CONSTANT_OP ||
00261         te->op()==STRING_CONSTANT_OP ||
00262         te->op()==LOGICAL_CONSTANT_OP ||
00263         te->op()==HOLLERITH_CONSTANT_OP){
00264           /// ...  Do nothing
00265         } else {
00266           RefList<Symbol> referred;
00267           referred_symbols(*te, referred);
00268 ///           cerr<<"\n\t\tte: "<<*te;
00269           for (Iterator<Symbol> ssit=referred; ssit.valid(); ++ssit){
00270 ///             cerr<<"\nQueuing "<<ts->name_ref();
00271         q.ins_last(ssit.current());
00272           }
00273         }
00274         delete te;
00275       }
00276     }
00277       }
00278       continue;
00279     }
00280     
00281     /// ...  Regular definition site.  Add input values.
00282     Iterator<Expression> sit=def.in_refs();
00283     for( ; sit.valid(); ++sit){
00284       switch(sit.current().op()){
00285       case ID_OP:
00286 ///     cerr<<"\nQueuing "<<sit.current().symbol().name_ref();
00287     q.ins_last(sit.current().symbol());
00288     break;
00289       case ARRAY_REF_OP:
00290 ///     cerr<<"\nQueuing "<<sit.current().array().symbol().name_ref();
00291     q.ins_last(sit.current().array().symbol());
00292       }
00293     }
00294   }
00295 }
00296 
00297 
00298 Symbol* last_gsa_symbol(ProgramUnit& pgm, Symbol& sym){
00299 /// Sanity check (make sure the symbol is in the symbol table.
00300 ///   if (pgm.symtab().find_ref(sym.name_ref())!=&sym){
00301 ///     cerr<<"\nIn pgm. "<<pgm.routine_name_ref()
00302 ///     <<" base symbol "<<sym.name_ref()<<" is not in the symbol table.";
00303 ///     p_abort("Sanity check failure.");
00304 ///   }
00305 /// silvius: this should be done on the CDG, for now assume restructured.
00306   Symbol* last_def_sym=0;
00307   for(Statement* stit=pgm.stmts().last_ref(); stit!=0; stit=stit->prev_ref()){
00308 ///     int dummy=1;
00309 ///     stit->write(cerr, dummy);
00310     if (stit->stmt_class()==ENDDO_STMT){
00311       /// ...  If there is a MU for 'sym', return it.
00312       Statement* dostmt=stit->follow_ref();
00313       Statement* ps=dostmt->next_ref();
00314       while (ps){
00315     if (ps->stmt_class()!=ASSIGNMENT_STMT){
00316       break;
00317     }
00318     if (ps->rhs().op()!=MU_OP){
00319       break;
00320     }
00321     if (gsa_base(ps->lhs().symbol())==&sym){
00322       last_def_sym=&ps->lhs().symbol();
00323       break;
00324     }
00325     ps=ps->next_ref();
00326       }
00327     }
00328     if (last_def_sym) break;
00329 
00330     for(Iterator<Expression> sit=stit->out_refs(); sit.valid(); ++sit){
00331       Expression& ce=sit.current();
00332       VariableSymbol* candidate=0;
00333       switch (ce.op()){
00334       case ID_OP:
00335     candidate=(VariableSymbol*)&ce.symbol();
00336     break;
00337       case ARRAY_REF_OP:
00338     candidate=(VariableSymbol*)&ce.array().symbol();
00339     break;
00340       default:
00341         cerr<<"\nIn statement: "<<*stit;
00342     cerr<<"\n "<<sit.current();
00343     p_abort("Out ref. is not variable.");
00344       }
00345 ///       cerr<<"\n\tCandidate: "<<candidate->name_ref()
00346 ///       <<"\t sym: "<<sym;
00347       
00348       if (candidate->sym_class()==FUNCTION_CLASS){
00349     /// ...  There seems to be a bug with function names.
00350     /// ...  better make sure.
00351     String basename;
00352     int rank;
00353     gsa_details(candidate->name_ref(), basename, rank);
00354     if (basename==sym.name_ref()){
00355       last_def_sym=candidate;
00356       break;
00357     }
00358       } else {
00359     if (!candidate->is_gsa_symbol()){
00360       if (has_maymod(*stit)){
00361         if (is_var_in_maymod(*candidate, *stit)){
00362           cerr<<"\n "<<candidate->name_ref()
00363           <<"\n in stmt "<<*stit;
00364           p_abort("Definition must refer to nontrivial GSA name.");
00365         } else {
00366           /// ...  Do nothing, it is actually wrongly placed in out_refs().
00367           continue;     
00368         }
00369       } else {
00370         if (called_pgm(*stit)){
00371           /// ...  This one should be ok, even though it is missing its
00372           /// ...  MAYMOD assertion.
00373           p_warning("Subprogram call statement has no MAYMOD assertions.");
00374           last_def_sym=candidate;
00375           break;
00376         } else {
00377           cerr<<"\n "<<candidate->name_ref()
00378           <<"\n in stmt "<<*stit;
00379 ///           pgm.write(cerr);
00380           p_abort("Definition must refer to nontrivial GSA name.");
00381         }
00382       }
00383     }
00384 
00385     if (&candidate->gsa_base_symbol()==&sym){
00386       last_def_sym=candidate;
00387       break;
00388     }
00389       }
00390     }
00391     if (last_def_sym) {
00392       break;
00393     }
00394   }
00395   return last_def_sym;
00396 }
00397 
00398 void build_in_out_sets(Program& prog, ProgramUnit& pgm, Symbol& sym, 
00399                Database<Symbol*, RefList<Symbol> >& pgm_iomap){
00400   RefList<Symbol>* in=new RefList<Symbol>;
00401   pgm_iomap.ins(&sym, in);
00402 
00403 /// Find gsa name corresponding to latest definition of this symbol.
00404   Symbol* last_def_sym=last_gsa_symbol(pgm, sym);
00405   
00406   if (last_def_sym==0){
00407     /// ...  Not defined in this routine.
00408     in->ins_last(sym);
00409     return;
00410   }
00411   
00412   
00413   IntraPCodeDomain domain(pgm);
00414 ///   cerr<<"\n Running build_in_out_set 1 on "<<last_def_sym->name_ref();
00415   build_in_out_set(*last_def_sym, domain, *in, pgm, prog);
00416 }
00417 
00418 
00419 
00420 void build_in_out_sets(Program& prog, ProgramUnit& pgm){
00421   if (!is_code_pu(pgm)){
00422     /// ...  Data subprogram.
00423     return;
00424   }
00425   if (iomap.find_ref(&pgm)){
00426     /// ...  Already built.
00427     return; 
00428   }
00429   Database<Symbol*, RefList<Symbol> >* pgm_iomap=
00430     new Database<Symbol*, RefList<Symbol> >;
00431   iomap.ins(&pgm, pgm_iomap);
00432   
00433 
00434 /// Make sure all children are already done.
00435   for(Iterator<ProgramUnit> pgmit=pgm.calls(); pgmit.valid(); ++pgmit){
00436 ///     cerr<<"\n "<<pgm.routine_name_ref()
00437 ///     <<" CALLS "<<pgmit.current().routine_name_ref();
00438     build_in_out_sets(prog, pgmit.current());
00439   }
00440 
00441 ///   ofstream before("before_bios");
00442 ///   prog.write(before);
00443 ///   before.close();
00444 
00445 
00446 /// Initialize OUT to all formals + commons + return value.
00447 /// First add formals.
00448   RefList<Symbol> out;
00449   Statement* entry=pgm.stmts().first_ref();
00450   while (entry->stmt_class()!=ENTRY_STMT) {
00451     entry=entry->next_ref();
00452     if(entry==0) break;
00453   }
00454   if(entry==0){
00455     cerr<<"\nProgram without entry: "<<pgm.routine_name_ref();
00456     p_abort("");
00457   }
00458   List<Expression>& formals=parameters(*entry);
00459   for(Iterator<Expression> eit=formals; eit.valid(); ++eit){
00460     if (eit.current().op()!=ID_OP){
00461       cerr<<"Formal not ID_OP: "<<eit.current();
00462       p_abort("");
00463     }
00464     Symbol& sym=eit.current().symbol();
00465     out.ins_last(sym);
00466   }
00467 /// Now add common vars.
00468   for(DictionaryIter<CommonBlock> cbit=pgm.common_blocks(); 
00469       cbit.valid(); ++cbit){
00470     for(Iterator<Symbol> sit=cbit.current().iterator(); sit.valid(); ++sit){
00471       if (!out.member(sit.current())){
00472     out.ins_last(sit.current());
00473       }
00474     }
00475   }
00476 /// Now add return value.
00477   if (pgm.pu_class()==FUNCTION_PU_TYPE){
00478     Symbol* fret=pgm.symtab().find_ref(pgm.routine_name_ref());
00479     p_assert(fret, "Function did not declare return value.");
00480     out.ins_last(*fret);
00481   }
00482   
00483 
00484 
00485 /// For every symbol, execute the program unit in reverse symbolically 
00486 /// following use-def chains of output variables.
00487   for(Iterator<Symbol> sit=out; sit.valid(); ++sit){
00488     Symbol& sym=sit.current();
00489 ///     cerr<<"\n Running  build_in_out_sets 0 on "<<sym.name_ref();
00490     build_in_out_sets(prog, pgm, sym, *pgm_iomap);
00491   }
00492 }
00493 
00494 /// Builds, for every subprogram, the set of input values for every output.
00495 /// The output values are considered right before exiting the routine,
00496 /// and the input ones right after entry.
00497 void build_in_out_sets(Program& prog){
00498 
00499 ///   prog.write(cerr);
00500   prog.compute_call_lists();
00501 
00502 
00503 /// Find top level routines.
00504   RefList<ProgramUnit> tops;
00505   for (KeyIterator<String, ProgramUnit> pgmit=prog; pgmit.valid(); ++pgmit){
00506     ProgramUnit& pgm=pgmit.current_data();
00507     if (pgm.called_by().entries()==0){
00508       tops.ins_last(pgm);
00509     }
00510   }
00511 /// Iterate over top level routines.
00512   for(Iterator<ProgramUnit> pit=tops; pit.valid(); ++pit){
00513     ProgramUnit& pgm=pit.current();
00514     build_in_out_sets(prog, pgm);
00515   }
00516   
00517 /// Print them.
00518 ///   print_in_out_sets(prog);
00519 }
00520 
00521 
00522 Expression* theta(Expression *parameters); /// ...  from Expression.cc
00523 Expression* eta(Expression* gate, Expression* parameters); /// ... from Expression.cc
00524 
00525 static bool actual_out_param(Symbol& sym, Statement& stmt){
00526 ///   cerr<<"\n actual_out_param: "<<&sym;
00527   for(Iterator<Expression> eit=parameters(stmt); eit.valid(); ++eit){
00528 ///     cerr<<"\n\t eit: "<<eit.current();
00529     if(eit.current().base_variable_ref()==&sym) return true;
00530   }
00531   return false;
00532 }
00533 
00534 static void remove_dummy_assignments(Program& prog){
00535 /// Remove stmts like 'x = x'.
00536   KeyIterator<String,ProgramUnit> progiter = prog;
00537   for (progiter.reset();
00538        progiter.valid();
00539        ++progiter) {
00540     ProgramUnit& pgm=progiter.current_data();
00541     Statement* ps=pgm.stmts().first_ref();
00542     Statement* next=0;
00543     while (ps){
00544       next=ps->next_ref();
00545       if (ps->stmt_class()==ASSIGNMENT_STMT){
00546     if (ps->lhs()==ps->rhs()){
00547       pgm.stmts().del(*ps);
00548     }
00549       }
00550       ps=next;
00551     }
00552   }
00553 }
00554 
00555 static void add_dummy_global_assignments_at_calls(Program& prog){
00556 /// The second major step is to insert dummy assignments after routine calls
00557 /// modifying commons.
00558   KeyIterator<String,ProgramUnit> progiter = prog;
00559   for (progiter.reset();
00560        progiter.valid();
00561        ++progiter) {
00562     ProgramUnit& pgm=progiter.current_data();
00563     Statement* ps=pgm.stmts().first_ref();
00564     Statement* next;
00565     while (ps){
00566       next=ps->next_ref();
00567       ProgramUnit* callee=called_pgm(*ps);
00568       if (callee) {
00569     Symbol* callee_sym;
00570     if (ps->stmt_class()==CALL_STMT){
00571       callee_sym=&ps->routine_guarded().symbol();
00572     } else {
00573       callee_sym=&ps->rhs().function().symbol();
00574     }
00575     Iterator<Assertion> asrt_iter = ps->assertions();
00576     for ( ; asrt_iter.valid(); ++asrt_iter) {
00577       if (asrt_iter.current().type() == AS_MAYMOD) {
00578         Iterator<Expression> aexpr_iter = 
00579           asrt_iter.current().arg_list_guarded();
00580         for ( ; aexpr_iter.valid(); ++aexpr_iter){
00581           Symbol* sym=aexpr_iter.current().base_variable_ref();
00582           if (sym) {
00583         if (sym->common_ref() && 
00584             /// ...  Do not insert theta if it is also passed as parameter.
00585             !actual_out_param(*sym, *ps)){
00586           if (sym->is_scalar()){
00587             /// ...  Insert dummy assignment to make GSA give it a distinctive name.
00588             AssignmentStmt* newstmt=
00589               new AssignmentStmt(pgm.stmts().new_tag(),
00590                      id(*sym),
00591                      theta(comma(id(*sym))));
00592             pgm.stmts().ins_before(newstmt, next);
00593           } else {
00594             /// ...  Insert dummy assignment to make GSA give it a distinctive name.
00595             AssignmentStmt* newstmt=
00596               new AssignmentStmt(pgm.stmts().new_tag(),
00597                      id(*sym),
00598                      theta(comma(id(*sym))));
00599             pgm.stmts().ins_before(newstmt, next);
00600             
00601           }
00602         }
00603           }
00604         }
00605       }
00606     }
00607       }
00608       ps=next;
00609     }
00610   }
00611 }
00612 
00613 
00614 
00615 
00616 static void add_dummy_eta_assignments_after_loops(Program& prog){
00617 /// The third major step is to insert dummy assignments after loops
00618   KeyIterator<String,ProgramUnit> progiter = prog;
00619   for(progiter.reset();progiter.valid();++progiter)
00620   {
00621      ProgramUnit& pgm=progiter.current_data();
00622      Iterator<Statement> stmt_iter=
00623        pgm.stmts().stmts_of_type(DO_STMT,WHILE_STMT);
00624      for(stmt_iter.reset();stmt_iter.valid();++stmt_iter)
00625      {
00626         Statement& stmt=stmt_iter.current();
00627     Expression * _condition;
00628     Type type(VOID_TYPE);
00629     RefList<Symbol> sym_list;
00630     Iterator<Statement> loop_body_iter;
00631     if(stmt.stmt_class()==DO_STMT)
00632     {
00633        Expression& lmt=stmt.limit();
00634        if(lmt.op()!=INFINITY_OP)
00635        {
00636               _condition=at_least_one_iteration(pgm, (DoStmt&)stmt, false);
00637        }
00638        else
00639        {
00640           Statement * _if_stmt=stmt.next_ref();
00641           if (_if_stmt->stmt_class()==ENDDO_STMT){
00642         /// ...  Empty DO i=1,Inf
00643         _condition=constant(".TRUE.");
00644           } else {
00645         p_assert(_if_stmt->stmt_class()==IF_STMT,
00646              "The next statement to the do statement"
00647              " should be IF statement\n");
00648         Expression& if_condition=_if_stmt->expr();
00649         _condition=simplify(not(if_condition.clone()));
00650           }
00651        };
00652 
00653        loop_body_iter=
00654          pgm.stmts().iterate_loop_body(CASTAWAY(Statement *)&stmt);
00655     }
00656     else
00657     {
00658        Expression& while_condition=stmt.expr();
00659        _condition=simplify(not(while_condition.clone()));
00660        /// ...  guobin & silvius: this is not really right, change it if you
00661        /// ...  have to deal with while loops.
00662        p_warning("Incomplete implementation.");
00663        loop_body_iter=
00664          pgm.stmts().iterator((Statement&)stmt,*stmt.follow_ref());
00665     };
00666 
00667     for(loop_body_iter.reset();loop_body_iter.valid();++loop_body_iter)
00668     {
00669        Statement& loop_body_stmt=loop_body_iter.current();
00670        if(loop_body_stmt.stmt_class()==DO_STMT)
00671           continue;
00672        RefSet<Expression> out_exprs=loop_body_stmt.out_refs();
00673        while(out_exprs.entries()>0)
00674        {
00675           Expression& out_expr=out_exprs.grab();
00676           if(out_expr.op()==ARRAY_REF_OP||out_expr.op()==ID_OP)
00677           {
00678              Symbol * _out_sym=out_expr.base_variable_ref(); 
00679          if(!sym_list.member(*_out_sym))
00680          {
00681             sym_list.ins_last(*_out_sym);
00682          }
00683           }
00684        }
00685     };
00686 
00687     Iterator<Symbol> sym_iter=sym_list;
00688     Statement * _stmt_ref=stmt.follow_ref();
00689     for(sym_iter.reset();sym_iter.valid();++sym_iter)
00690     {
00691        Symbol& sym=sym_iter.current();
00692        AssignmentStmt* newstmt=
00693           new AssignmentStmt(pgm.stmts().new_tag(), id(sym),
00694                                   eta(_condition->clone(),
00695                       comma(id(sym),id(sym))));
00696            pgm.stmts().ins_after(newstmt,_stmt_ref);
00697     }
00698     delete _condition;
00699      }
00700   }
00701 }
00702 
00703 static void modify_dummy_eta_assignments_after_loops(Program& prog){
00704 /// The forth major step is to modify dummy assignments after loops
00705   KeyIterator<String,ProgramUnit> progiter = prog;
00706   for(progiter.reset();progiter.valid();++progiter)
00707   {
00708      ProgramUnit& pgm=progiter.current_data();
00709      Iterator<Statement> stmt_iter=pgm.stmts().stmts_of_type(DO_STMT,WHILE_STMT);
00710      for(stmt_iter.reset();stmt_iter.valid();++stmt_iter)
00711      {
00712         Statement& stmt=stmt_iter.current();
00713     RefMap<Symbol,Statement> mu_assignment;
00714     RefList<Statement> eta_assignment;
00715     bool keep_searching=true;
00716     Statement * _stmt_ptr=stmt.next_ref();
00717     while(keep_searching)
00718     {
00719        if(_stmt_ptr->stmt_class()==ASSIGNMENT_STMT)
00720        {
00721           Expression& mu_expr=_stmt_ptr->rhs();
00722           if(mu_expr.op()==MU_OP)
00723           {
00724              p_assert(_stmt_ptr->lhs().op()==ID_OP,
00725                           "The left expression in mu" 
00726                   " statement should be an id expression\n");
00727              Symbol& mu_sym=_stmt_ptr->lhs().symbol();
00728              mu_assignment.ins(mu_sym,*_stmt_ptr);
00729           }
00730           else
00731              keep_searching=false;
00732        }
00733        else
00734           keep_searching=false;
00735        _stmt_ptr=_stmt_ptr->next_ref();
00736     };
00737 
00738     _stmt_ptr=stmt.follow_ref()->next_ref();
00739     keep_searching=true;
00740     while(keep_searching)
00741     {
00742        if(_stmt_ptr->stmt_class()==ASSIGNMENT_STMT)
00743        {
00744           Expression& eta_expr=_stmt_ptr->rhs();
00745           if(eta_expr.op()==ETA_OP)
00746           {
00747              eta_assignment.ins_last(*_stmt_ptr);
00748           }
00749           else
00750           {
00751              keep_searching=false;
00752           }
00753        }
00754        else
00755        {
00756           keep_searching=false;
00757        }
00758        _stmt_ptr=_stmt_ptr->next_ref();
00759     };
00760 
00761     Iterator<Statement> eta_iter=eta_assignment;
00762     for(eta_iter.reset();eta_iter.valid();++eta_iter)
00763     {
00764        Statement& eta_stmt=eta_iter.current();
00765        Expression& eta_expr=eta_stmt.rhs();
00766        p_assert(eta_expr.op()==ETA_OP,
00767            "The right expression in eta statement should be an eta expression\n");
00768            Expression& first_eta_expr=eta_expr.parameters_guarded().arg_list()[1]; 
00769            Symbol& first_sym=first_eta_expr.symbol();
00770        /// ... p_assert(mu_assignment.member(first_sym),
00771        /// ...     "The first symbol in an eta statement should be in a mu statement\n");
00772        if(mu_assignment.member(first_sym))
00773        {
00774               Statement& mu_stmt=mu_assignment[first_sym];
00775           Expression& mu_expr=mu_stmt.rhs();
00776           Expression& second_mu_expr=mu_expr.parameters_guarded().arg_list()[0];
00777           Symbol& new_sym=second_mu_expr.symbol();
00778           substitute_var(first_eta_expr,first_sym,new_sym);
00779            }
00780     }
00781      }
00782   }
00783 }
00784 
00785 /// Return the gsa name of the actual common var at a callsite.
00786 /// It only returns the value if the variable is modified during the call.
00787 static Symbol* def_call_gsa_name(Statement& callsite, Symbol& base){
00788   if (!base.is_scalar() && !base.is_array()){
00789     return 0;
00790   }
00791   p_assert(base.common_ref(), "Argument must be in a common.");
00792   p_assert(!((VariableSymbol&)base).is_gsa_symbol(),
00793        "Argument must NOT be a GSA symbol.");
00794   for (Statement* ps=callsite.next_ref(); ps; ps=ps->next_ref()){
00795     if (ps->stmt_class()!=ASSIGNMENT_STMT) {
00796       break;
00797     }
00798     if (ps->rhs().op()!=THETA_OP){
00799       break;
00800     }
00801     /// ...  This is a THETA stmt.
00802     Expression& id=ps->rhs().parameters_guarded().arg_list()[0];
00803     if (id.op()!=ARRAY_REF_OP && id.op()!=ID_OP){
00804       continue;
00805     }
00806     VariableSymbol& sym=(VariableSymbol&)id.symbol();
00807     Symbol* base_sym=&sym;
00808     if (sym.is_gsa_symbol()){
00809       base_sym=&sym.gsa_base_symbol();
00810     }
00811     if (base_sym==&base){
00812       return &sym;
00813     }
00814   }
00815 /// No match, return given arg.
00816   return 0;
00817 }
00818 
00819 static Symbol* use_call_gsa_name(ProgramUnit& pgm, 
00820                  Statement& callsite, 
00821                  Symbol& base){
00822   Database<Statement*, RefDatabase<Symbol*, Symbol> >* pgmap=
00823     _gmap.find_ref(&pgm);
00824   p_assert(pgmap, "Cannot find gmap for program unit.");
00825   RefDatabase<Symbol*, Symbol>* spgmap=pgmap->find_ref(&callsite);
00826   p_assert(spgmap, "Cannot find gmap for statement.");
00827   return spgmap->find_ref(&base);
00828 }
00829 
00830 /// Builds dmap given gmap for one pgm only.
00831 /// 'gmap' is a global mapping per pgm, per base symbol, of subprogram calls into SSA
00832 /// names.
00833 /// 'dmap' is the reaching definitions list per pgm, per base symbol (for 
00834 /// commons only).
00835 void build_def_map(Program& prog, EntryPoints& ep,
00836            ProgramUnit& pgm){
00837   static set<ProgramUnit*> processed;
00838   if (processed.find(&pgm)!=processed.end()){
00839     return;
00840   } else {
00841     processed.insert(&pgm);
00842   }
00843 
00844   for (Iterator<Statement> stit=pgm.stmts().iterator(); 
00845        stit.valid(); ++stit){
00846     Statement& stmt=stit.current();
00847     ProgramUnit* pcallee=called_pgm(stmt);
00848     if (pcallee) {
00849 ///       int w=16;
00850 ///       cerr<<"\nIn pgm. "<<pgm.routine_name_ref();
00851 ///       cerr<<"\n\tAt call site:";
00852 ///       stmt.write(cerr,w);
00853       ProgramUnit& callee=*pcallee;
00854       Statement& call_site=stmt;
00855       /// ...  This is a call site.
00856       Database<Symbol*, List<GlobalDefSite> >* pdmap=_dmap.find_ref(&callee);
00857       if (!pdmap){
00858     pdmap=new Database<Symbol*, List<GlobalDefSite> >;
00859 ///     cerr<<"\nInserting DMAP for "<<callee.routine_name_ref();
00860     _dmap.ins(&callee, pdmap);
00861       }
00862       /// ...  Now go over all common base vars in pgm.
00863       for(DictionaryIter<Symbol> sit=pgm.symtab().iterator();
00864       sit.valid(); ++sit){
00865     Symbol& sym=sit.current();
00866     if (sym.common_ref()){
00867       if (!((VariableSymbol&)sym).is_gsa_symbol()){
00868         Symbol* base=&sym;
00869 ///         cerr<<"\n\t\tLooking at symbol "<<base->name_ref();
00870         /// ...  Find it in dmap, or create if not existent.
00871         Symbol* corresponding_sym=
00872           callee.symtab().find_ref(base->name_ref());
00873         if (corresponding_sym==0){
00874           prog.write(cerr);
00875           cerr<<"\nIn pgm. "<<callee.routine_name_ref();
00876           cerr<<"\nIn common "<<base->common_ref()->name_ref();
00877           cerr<<"\nSymbol "<<base->name_ref();
00878           p_abort("Could not find corresponding symbol in symbol table.");
00879         }
00880         List<GlobalDefSite>* sdmap=pdmap->find_ref(corresponding_sym);
00881         if (!sdmap){
00882           sdmap=new List<GlobalDefSite>;
00883           pdmap->ins(corresponding_sym, sdmap);
00884         }
00885 
00886         /// ...  Find value, aka real SSA name while at this call site.
00887         Symbol* usedname=use_call_gsa_name(pgm, call_site, *base);
00888         p_assert(usedname, "Could not figure out name used at call site.");
00889 ///         cerr<<"\n\t\tName used at callsite "<<usedname->name_ref();
00890         /// ...  Store this symbol's definition into the callee's dmap.
00891         DefLoc* defloc=pgm.gsa_deflocs_guarded().find_ref(*usedname);
00892         bool found_def=true;
00893         if (!defloc) {
00894           found_def=false;
00895         } else {
00896           if (!defloc->stmt_valid()) {
00897         found_def=false;
00898           }
00899         }
00900         if (found_def){
00901           sdmap->ins_last(new GlobalDefSite(pgm, defloc->stmt_guarded()));
00902         } else {
00903 ///           cerr<<"\n\t\tNot defined in "<<pgm.routine_name_ref();
00904           /// ...  Could not find def.  Try to add the last known defs.
00905           Database<Symbol*, List<GlobalDefSite> >* own_pdmap=
00906         _dmap.find_ref(&pgm);
00907           if (own_pdmap==0){
00908         cerr<<"\nFor program unit: "<<pgm.routine_name_ref();
00909         p_abort("Nonexisting dmap object for this pgm.");
00910           }
00911           List<GlobalDefSite>* own_sdmap=
00912         own_pdmap->find_ref(base);
00913           /// ...   cerr<<"\nOwn pdmap = "<<*own_pdmap;
00914           if (own_sdmap){
00915         for(Iterator<GlobalDefSite> gdsit=*own_sdmap; 
00916             gdsit.valid(); ++gdsit){
00917           sdmap->ins_last(new GlobalDefSite(gdsit.current()));
00918         }
00919           } else {
00920         /// ...  This symbol is not initialized yet.  Hopefully this call
00921         /// ...  is to a routine that will do it.
00922         /// ...  Do nothing, there is nothing to insert.
00923           }
00924         }
00925       }
00926     }
00927       }
00928       /// ...  Go recursively into the callee.
00929       build_def_map(prog, ep, callee);
00930     }
00931   }
00932 }
00933 
00934 
00935 
00936 /// Builds dmap given gmap.
00937 /// 'gmap' is a global mapping per pgm, per base symbol, of subprogram 
00938 /// calls into SSA names.
00939 /// 'dmap' is the reaching definitions list per pgm, per base symbol (for 
00940 /// commons only).
00941 /// silvius: do a DFS on the call graph in program order.
00942 void build_def_map(Program& prog){
00943 
00944 
00945 /// Walk down the call dag adding defs to 'dmap'.
00946   EntryPoints* ep=prog.entry_points();
00947   for(KeyIterator<String, ProgramUnit> kit=prog; kit.valid(); ++kit){
00948     ProgramUnit& pgm=kit.current_data();
00949     if (pgm.pu_class()==PROGRAM_PU_TYPE){
00950       /// ...  Must insert an empty list of defs for every common scalar.
00951       Database<Symbol*, List<GlobalDefSite> >* pdmap=
00952     new Database<Symbol*, List<GlobalDefSite> >;
00953       _dmap.ins(&pgm, pdmap);
00954       for (DictionaryIter<Symbol> sit=pgm.symtab().iterator();
00955        sit.valid(); ++sit){
00956     if (sit.current().common_ref()){
00957       if (sit.current().is_array()){
00958         continue;
00959       }
00960       pdmap->ins(&sit.current(), new List<GlobalDefSite>);
00961       build_def_map(prog, *ep, pgm);
00962     }
00963       }      
00964     }
00965   }
00966   delete ep;
00967 ///   print_dmap();
00968 ///   prog.write(cerr);
00969 ///   exit(1);
00970 }
00971               
00972 
00973 /// Finds out whether the program is in SSA form.
00974 /// It does it by checking whether there are any symbols in 
00975 /// the main subprogram that are SSA names.
00976 static bool already_ip_ssa(Program& prog){
00977   ProgramUnit* main_pgm=find_main_pgm(prog);
00978   p_assert(main_pgm, "Could not find main pgm.");
00979   KeyIterator<String,ProgramUnit> myprogiter = prog;
00980   for(myprogiter.reset();myprogiter.valid();++myprogiter){
00981     ProgramUnit& pgm=myprogiter.current_data();
00982     for(DictionaryIter<Symbol> sit=pgm.symtab().iterator();
00983         sit.valid();++sit){
00984       String name=sit.current().name_ref();
00985       if (name.index("@")!=-1){
00986         return true;
00987       }
00988     }
00989   }
00990   return false;
00991 }
00992 
00993 void make_ip_ssa(Program& prog){
00994 
00995   if (already_ip_ssa(prog)){
00996     return;
00997   }
00998 
00999 /// Generate MAYMOD assertions.
01000   generate_maymods(prog, true, false);
01001 
01002 /// Insert dummy assignments for thetas.
01003   add_dummy_global_assignments_at_calls(prog);
01004 
01005 /// Insert dummy assignments for etas.
01006   add_dummy_eta_assignments_after_loops(prog);
01007 
01008 /// Translate to GSA.
01009   KeyIterator<String,ProgramUnit> progiter = prog;
01010   for (progiter.reset();
01011        progiter.valid();
01012        ++progiter) {
01013     ProgramUnit& pgm=progiter.current_data();
01014     if (!is_code_pu(pgm)) continue;
01015     MakeGSA(pgm);
01016   }
01017 
01018   //Modify ETA statements to make them correct
01019   modify_dummy_eta_assignments_after_loops(prog);
01020 
01021   for (progiter.reset();
01022        progiter.valid();
01023        ++progiter) {
01024     ProgramUnit& pgm=progiter.current_data();
01025     if (!is_code_pu(pgm)) continue;
01026     optimize_ssa(pgm, 
01027          SSA_OPT_BETA | SSA_OPT_MU | 
01028          SSA_OPT_GAMMA | SSA_OPT_ETA | SSA_OPT_ZERO );
01029   }
01030 
01031 /// Build dmap given the gmap computed during MakeGSA.
01032   build_def_map(prog);
01033 
01034 /// Build global in-out structures.
01035   build_in_out_sets(prog);
01036 }
01037 
01038 
01039 void undo_ip_ssa(Program& prog){
01040   if (!already_ip_ssa(prog)){
01041     return;
01042   }
01043 
01044   KeyIterator<String,ProgramUnit> progiter = prog;
01045   for (progiter.reset();
01046        progiter.valid();
01047        ++progiter) {
01048     ProgramUnit& pgm=progiter.current_data();
01049     if (!is_code_pu(pgm)) continue;
01050     DeGSA(pgm);
01051     /// ...     eliminate_dead_code(pgm, DONT_DEADCODE_ARRAYS, 0);
01052   }
01053   remove_dummy_assignments(prog);
01054   _dmap.clear();
01055   _gmap.clear();
01056 }
 © 1995-2005 University of Illinois, Urbana-Champaign. All rights reserved.  Fri Mar 25 23:05:56 2005