Polaris: optimize_ssa.cc Source File

optimize_ssa.cc

Go to the documentation of this file.
00001 ///
00002 #include <set>
00003 #include <map>
00004 
00005 #include "Expression/FunctionCallExpr.h"
00006 #include "Expression/IDExpr.h"
00007 #include "Evolution/eg_utils.h"
00008 #include "Program.h"
00009 
00010 #include "trans_util.h"
00011 #include "optimize_ssa.h"
00012 #include "ip_ssa.h"
00013 
00014 /*!
00015   \brief Returns 1 iff 'ex' is a BETA function call.
00016  */
00017 int is_beta(Expression& ex){
00018   if (ex.op()!=FUNCTION_CALL_OP) return 0;
00019   String fname=ex.function().symbol().name_ref();
00020   if (fname=="<BETA>") return 1;
00021   return 0;
00022 }
00023 
00024 
00025 ///
00026 /// has_maymod
00027 ///   Return true if the given statement has a maymod assertion.
00028 
00029 int has_maymod(const Statement &stmt){
00030   Iterator<Assertion> asrt_iter = stmt.assertions();
00031   
00032   for ( ; asrt_iter.valid(); ++asrt_iter)
00033     if (asrt_iter.current().type() == AS_MAYMOD)
00034       return 1;
00035   
00036   return 0;
00037 }
00038 
00039 /// is_var_in_maymod
00040 ///   Return true if the given 
00041 
00042 int is_var_in_maymod(const Symbol &var, const Statement &stmt){
00043   Iterator<Assertion> asrt_iter = stmt.assertions();
00044   
00045   for ( ; asrt_iter.valid(); ++asrt_iter)
00046     if (asrt_iter.current().type() == AS_MAYMOD) {
00047       Iterator<Expression> aexpr_iter = asrt_iter.current().arg_list_guarded();
00048       
00049       for ( ; aexpr_iter.valid(); ++aexpr_iter)
00050     if (aexpr_iter.current().base_variable_ref() == &var)
00051       return 1;
00052     }
00053   
00054   return 0;
00055 }
00056 
00057 
00058 void gsa_details(const char* gsaname, String& basename, int& rank){
00059   rank=0;
00060   basename="";
00061   String gsa=gsaname;
00062   int at_sign=gsa.index("@");
00063   if (at_sign!=-1) {
00064     new (&basename) String(gsa, 0, at_sign-1);
00065     String srank(gsa, at_sign+1, gsa.len()-1);
00066     if (srank.len()>0){
00067       istrstream str(srank);
00068       str>>rank;
00069     }
00070   } else {
00071     basename=gsaname;
00072     rank=0;
00073   }
00074 }
00075 
00076 inline void gsa_details(Symbol& sym, String& basename, int& rank){
00077   gsa_details(sym.name_ref(), basename, rank);
00078 }
00079 
00080 /// Returns the name of the gsa symbol with same base name but rank-=1 as 'gsasym'
00081 void prev_gsa_rank_name(Symbol& gsasym, String& name){
00082   String base_name;
00083   int rank;
00084   gsa_details(gsasym.name_ref(), base_name, rank);
00085   ostrstream str;
00086   str<<rank-1<<'\0';
00087   name=base_name+"@"+str.str();
00088   str.freeze(0);
00089 }
00090 
00091 static void fix_substituted(Expression& expr, Symbol& n, Symbol& s){
00092   if (expr.op()==ID_OP){
00093     IDExpr& idexpr=(IDExpr&)expr;
00094     if (idexpr.substituted_valid()){
00095       substitute_var(idexpr.substituted_guarded(), n, s);
00096     }
00097   } else {
00098     Iterator<Expression> expit=expr.arg_list();
00099     for ( expit.reset() ; expit.valid(); ++expit){
00100       fix_substituted(expit.current(), n, s);
00101     }
00102   }  
00103 }
00104 
00105 
00106 
00107 /// Adjusts gmap to reflect symbol remapping as given by 'final'
00108 static void adjust_gmap(ProgramUnit& pgm, 
00109             Database<String, StringElem>& final_table,
00110             bool remove_from_symtab=false){
00111   Database<Statement*, RefDatabase<Symbol*, Symbol> >* lmap=
00112     ip_ssa_gmap().find_ref(&pgm);
00113   if (!lmap) return;
00114   for (KeyIterator<Statement*, RefDatabase<Symbol*, Symbol> > stit=*lmap;
00115        stit.valid(); ++stit){
00116     for (KeyIterator<String, StringElem> sit=final_table;
00117      sit.valid(); ++sit){
00118       VariableSymbol* vs=
00119     (VariableSymbol*)pgm.symtab().find_ref(sit.current_key());
00120       Symbol* base=vs;
00121       if (vs->is_gsa_symbol()){
00122     base=&vs->gsa_base_symbol();
00123       }
00124       Symbol* mapped=stit.current_data().find_ref(base);
00125       /// ...  Checked whether old mapped gsa symbol was renamed, and replace it 
00126       /// ...  in case it was.
00127       if (mapped==vs){
00128     Symbol* newsym=pgm.symtab().find_ref(sit.current_data());
00129     Symbol* key=&vs->gsa_base_symbol();
00130     if (key!=0){
00131       stit.current_data().del(key);
00132       stit.current_data().ins(key, *newsym);
00133     }
00134       }
00135     }
00136   }
00137 
00138 /// Also remove final symbols from symbol table.
00139   for (KeyIterator<String, StringElem> sit=final_table;
00140        sit.valid(); ++sit){
00141     if (sit.current_key()!=sit.current_data()){
00142       Symbol* found=pgm.symtab().find_ref(sit.current_key());
00143       if (found){
00144     if (found->is_scalar() || found->is_array()){
00145       // Remove from deflocmap.
00146       pgm.gsa_deflocs_guarded().remove_invalid_defloc(*found);
00147       // Remove from symbol table.
00148       if (remove_from_symtab){
00149         pgm.symtab().del(sit.current_key());
00150       }
00151     }
00152       }
00153     }
00154   }
00155 }
00156 
00157 /*!
00158   \brief Reduces the SSA name count by replacing a@0 with a.
00159 */
00160 static bool optimize_ssa_zero(ProgramUnit& pgm){
00161 /// First go through all statements and find all unnecessary MU's.
00162   map<String, String> final;
00163   Database<String, StringElem> old_style_final;
00164   for (DictionaryIter<Symbol> symit=pgm.symtab().iterator();
00165        symit.valid(); ++symit){
00166     Symbol& sym=symit.current();
00167     int rank;
00168     String base;
00169     gsa_details(sym, base, rank);
00170     if (rank==0){
00171       final.insert(make_pair(sym.name_ref(), base));
00172       old_style_final.ins(sym.name_ref(), new StringElem(base));
00173     }
00174   }
00175 
00176 /// For all statements
00177   Iterator<Statement> stit;
00178   for (stit=pgm.stmts().iterator(); stit.valid(); ++stit){
00179     Statement& stmt=stit.current();
00180     stmt.build_refs();
00181     /// ...  For all symbols accessed in this statement.
00182     Mutator<Expression> allrefs=stmt.in_refs();
00183     for ( ; allrefs.valid(); ++allrefs){
00184       Symbol* sym=0;
00185       switch(allrefs.current().op()){
00186       case ID_OP:
00187     sym=&allrefs.current().symbol();
00188     break;
00189       case ARRAY_REF_OP:
00190     sym=&allrefs.current().array().symbol();
00191     break;
00192       default: 
00193     continue;
00194       }
00195       map<String, String>::iterator found=final.find(sym->name_ref());
00196       if (found!=final.end()) {
00197     Symbol* first=pgm.symtab().find_ref((*found).second);
00198     Mutator<Expression> expmut=stmt.iterate_expressions();
00199     for ( ; expmut.valid(); ++expmut ){
00200         substitute_var(expmut.current(), *sym, *first);
00201     }
00202       }
00203     }
00204     allrefs=stmt.out_refs();
00205     for ( ; allrefs.valid(); ++allrefs){
00206       if (allrefs.current().op()!=ID_OP) continue;
00207       map<String, String>::iterator found=
00208     final.find(allrefs.current().symbol().name_ref());
00209       if (found!=final.end()) {
00210     Symbol* first=pgm.symtab().find_ref((*found).second);
00211     Iterator<Expression> expmut=stmt.iterate_expressions();
00212     for ( ; expmut.valid(); ++expmut ){
00213       substitute_var(expmut.current(), allrefs.current().symbol(), *first);
00214     }
00215       }
00216     }
00217     /// ...  Need to update 'substituted' fields
00218     map<String, String>::iterator kit=final.begin();
00219     for ( ; kit!=final.end(); ++kit){
00220       const String& key=(*kit).first;
00221       String& value=(*kit).second;
00222       Symbol* sk=pgm.symtab().find_ref(key);
00223       p_assert(sk, "Could not find gsa symbol to replace.");
00224       Symbol* sv=pgm.symtab().find_ref(value);
00225       p_assert(sv, "Could not find gsa symbol to replace with.");
00226       Iterator<Expression> expit=stmt.iterate_expressions();
00227       for (expit=stmt.iterate_expressions(); expit.valid(); ++expit){
00228     fix_substituted(expit.current(), *sk, *sv);
00229       }
00230     }
00231     /// ...  Re-build references.
00232     stmt.build_refs();
00233   }
00234 
00235 /// Adjust gmap.
00236 /// silvius: do not remove them from symtab, otherwise DeGSA will crash.
00237   adjust_gmap(pgm, old_style_final, false);
00238 
00239   return true;
00240 }
00241 
00242 
00243 
00244 /*!
00245   \brief Reduces the SSA name count by removing MU functions
00246   where unnecessary.
00247 
00248   MU functions are unnecessary when of this form:
00249   x@5 = MU(x@4, x@5)
00250 */
00251 static bool optimize_ssa_mu(ProgramUnit& pgm){
00252 /// First go through all CALL statements and find all unnecessary MU's.
00253   bool global_change=false;
00254   RefList<Symbol> unnecessary_syms;
00255   RefSet<Statement> unnecessary_mu;
00256   Iterator<Statement> stit;
00257   Database<String, StringElem> final;
00258   for (stit=pgm.stmts().iterator(); stit.valid(); ++stit){
00259     /// ...  Skip all statements except for CALL and x = func()
00260     Statement& stmt=stit.current();
00261     if (stmt.stmt_class()!=ASSIGNMENT_STMT) continue;
00262     Expression& rhs=stmt.rhs();
00263     if (rhs.op()!=MU_OP) continue;
00264     /// ...  It is a MU statement
00265     Expression& lhs=stmt.lhs();
00266     Expression& first=rhs.parameters_guarded().arg_list()[0];
00267     Expression& second=rhs.parameters_guarded().arg_list()[1];
00268     if (first.op()!=ID_OP || second.op()!=ID_OP) continue;
00269     int rank1, rank2, rank;
00270     String base1, base2, base;
00271     gsa_details(lhs.symbol(), base, rank);
00272     gsa_details(first.symbol(), base1, rank1);
00273     gsa_details(second.symbol(), base2, rank2);
00274     if (rank==rank2){
00275       final.ins(lhs.symbol().name_ref(), 
00276         new StringElem(first.symbol().name_ref()));
00277       unnecessary_mu.ins(stmt);
00278       unnecessary_syms.ins_last(lhs.symbol());
00279       global_change=true;
00280     }
00281   }
00282   
00283 /// Remove unnecessary statements.
00284   pgm.stmts().del(unnecessary_mu);
00285   
00286 /// Replace the symbols that have been removed.
00287 /// It may happen that a@6 is to be replaced with a@5, but a@5 is to
00288 /// be replaced with a@4.  We must first find for every symbol which is
00289 /// the final symbol to be replaced with (thus we avoid iterating over the
00290 /// whole replacing procedure, and do it beforehand).
00291 
00292   if (final.entries()==0) return false; /// ...  made no change.
00293 /// Iterate until no change.
00294   int change;
00295   do {
00296     change=0;
00297     KeyIterator<String, StringElem> kit=final;
00298     for ( ; kit.valid(); ++kit){
00299       StringElem& value=kit.current_data();
00300       /// ...  Look for transitivity.
00301       StringElem* found=final.find_ref(value);
00302       if (found){
00303     change=1;
00304     value=*found;
00305       }
00306     }
00307   } while (change);
00308 /// At this time, the map should have converged.
00309 /// For all statements
00310   for (stit=pgm.stmts().iterator(); stit.valid(); ++stit){
00311     Statement& stmt=stit.current();
00312     stmt.build_refs();
00313     /// ...  For all symbols accessed in this statement.
00314     Mutator<Expression> allrefs=stmt.in_refs();
00315     for ( ; allrefs.valid(); ++allrefs){
00316       if (allrefs.current().op()!=ID_OP &&
00317       allrefs.current().op()!=ARRAY_REF_OP) continue;
00318       StringElem* found;
00319       if (allrefs.current().op()==ID_OP){
00320     found=final.find_ref(allrefs.current().symbol().name_ref());
00321       } else {
00322     found=final.find_ref(allrefs.current().array().symbol().name_ref());
00323       }
00324       if (found) {
00325     Symbol* first=pgm.symtab().find_ref(*found);
00326     Mutator<Expression> expmut=stmt.iterate_expressions();
00327     for ( ; expmut.valid(); ++expmut ){
00328       if (allrefs.current().op()==ID_OP){
00329         substitute_var(expmut.current(), allrefs.current().symbol(), *first);
00330       } else {
00331         substitute_var(expmut.current(), allrefs.current().array().symbol(), *first);
00332       }
00333     }
00334       }
00335     }
00336     allrefs=stmt.out_refs();
00337     for ( ; allrefs.valid(); ++allrefs){
00338       if (allrefs.current().op()!=ID_OP) continue;
00339       StringElem* found=final.find_ref(allrefs.current().symbol().name_ref());
00340       if (found) {
00341     Symbol* first=pgm.symtab().find_ref(*found);
00342     Iterator<Expression> expmut=stmt.iterate_expressions();
00343     for ( ; expmut.valid(); ++expmut ){
00344       substitute_var(expmut.current(), allrefs.current().symbol(), *first);
00345     }
00346       }
00347     }
00348     /// ...  Need to update 'substituted' fields
00349     KeyIterator<String, StringElem> kit=final;
00350     for ( ; kit.valid(); ++kit){
00351       String& key=kit.current_key();
00352       StringElem& value=kit.current_data();
00353       Symbol* sk=pgm.symtab().find_ref(key);
00354       p_assert(sk, "Could not find gsa symbol to replace.");
00355       Symbol* sv=pgm.symtab().find_ref(value);
00356       p_assert(sv, "Could not find gsa symbol to replace with.");
00357       Iterator<Expression> expit=stmt.iterate_expressions();
00358       for (expit=stmt.iterate_expressions(); expit.valid(); ++expit){
00359     fix_substituted(expit.current(), *sk, *sv);
00360       }
00361     }
00362     /// ...  Re-build references.
00363     stmt.build_refs();
00364   }
00365 
00366 /// Adjust gmap.
00367   adjust_gmap(pgm, final);
00368   return true;
00369 }
00370 
00371 
00372 
00373 
00374 
00375 /*!
00376   \brief Reduces the SSA name count by removing GAMMA functions
00377   where unnecessary.
00378 
00379   GAMMA functions are unnecessary when of this form:
00380   x@5 = GAMMA(condition, x@8, x@8)
00381 */
00382 static bool optimize_ssa_gamma(ProgramUnit& pgm){
00383 /// First go through all statements and find all unnecessary GAMMA's.
00384   bool global_change=false;
00385   RefList<Symbol> unnecessary_syms;
00386   RefSet<Statement> unnecessary_gamma;
00387   Iterator<Statement> stit;
00388   Database<String, StringElem> final;
00389   for (stit=pgm.stmts().iterator(); stit.valid(); ++stit){
00390     /// ...  Skip all statements except for CALL and x = func()
00391     Statement& stmt=stit.current();
00392     if (stmt.stmt_class()!=ASSIGNMENT_STMT) continue;
00393     Expression& rhs=stmt.rhs();
00394     if (rhs.op()!=GAMMA_OP) continue;
00395     /// ...  It is a GAMMA statement
00396     RefList<Symbol> entries;
00397     get_phinode_entries(rhs, entries);
00398     p_assert(entries.entries()>0, "Wrong output from 'get_phinode_entries'.");
00399     Symbol* usym=&entries[0];
00400     for(Iterator<Symbol> sit=entries; sit.valid(); ++sit){
00401       if (usym!=&sit.current()){
00402     usym=0;
00403     break;
00404       }
00405     }
00406     if (usym==0) continue;
00407     /// ...  It is unnecessary.
00408     Expression& lhs=stmt.lhs();
00409     final.ins(lhs.symbol().name_ref(), 
00410           new StringElem(usym->name_ref()));
00411     unnecessary_gamma.ins(stmt);
00412     unnecessary_syms.ins_last(lhs.symbol());
00413     global_change=true;
00414   }
00415   
00416 /// Remove unnecessary statements.
00417   pgm.stmts().del(unnecessary_gamma);
00418   
00419 /// Replace the symbols that have been removed.
00420 /// It may happen that a@6 is to be replaced with a@5, but a@5 is to
00421 /// be replaced with a@4.  We must first find for every symbol which is
00422 /// the final symbol to be replaced with (thus we avoid iterating over the
00423 /// whole replacing procedure, and do it beforehand).
00424 
00425   if (final.entries()==0) return false; /// ...  made no change.
00426 /// Iterate until no change.
00427   int change;
00428   do {
00429     change=0;
00430     KeyIterator<String, StringElem> kit=final;
00431     for ( ; kit.valid(); ++kit){
00432       StringElem& value=kit.current_data();
00433       /// ...  Look for transitivity.
00434       StringElem* found=final.find_ref(value);
00435       if (found){
00436     change=1;
00437     value=*found;
00438       }
00439     }
00440   } while (change);
00441 /// At this time, the map should have converged.
00442 /// For all statements
00443   for (stit=pgm.stmts().iterator(); stit.valid(); ++stit){
00444     Statement& stmt=stit.current();
00445     stmt.build_refs();
00446     /// ...  For all symbols accessed in this statement.
00447     Mutator<Expression> allrefs=stmt.in_refs();
00448     for ( ; allrefs.valid(); ++allrefs){
00449       if (allrefs.current().op()!=ID_OP &&
00450       allrefs.current().op()!=ARRAY_REF_OP) continue;
00451       StringElem* found;
00452       if (allrefs.current().op()==ID_OP){
00453     found=final.find_ref(allrefs.current().symbol().name_ref());
00454       } else {
00455     found=final.find_ref(allrefs.current().array().symbol().name_ref());
00456       }
00457       if (found) {
00458     Symbol* first=pgm.symtab().find_ref(*found);
00459     Mutator<Expression> expmut=stmt.iterate_expressions();
00460     for ( ; expmut.valid(); ++expmut ){
00461       if (allrefs.current().op()==ID_OP){
00462         substitute_var(expmut.current(), allrefs.current().symbol(), *first);
00463       } else {
00464         substitute_var(expmut.current(), allrefs.current().array().symbol(), *first);
00465       }
00466     }
00467       }
00468     }
00469     allrefs=stmt.out_refs();
00470     for ( ; allrefs.valid(); ++allrefs){
00471       if (allrefs.current().op()!=ID_OP) continue;
00472       StringElem* found=final.find_ref(allrefs.current().symbol().name_ref());
00473       if (found) {
00474     Symbol* first=pgm.symtab().find_ref(*found);
00475     Iterator<Expression> expmut=stmt.iterate_expressions();
00476     for ( ; expmut.valid(); ++expmut ){
00477       substitute_var(expmut.current(), allrefs.current().symbol(), *first);
00478     }
00479       }
00480     }
00481     /// ...  Need to update 'substituted' fields
00482     KeyIterator<String, StringElem> kit=final;
00483     for ( ; kit.valid(); ++kit){
00484       String& key=kit.current_key();
00485       StringElem& value=kit.current_data();
00486       Symbol* sk=pgm.symtab().find_ref(key);
00487       p_assert(sk, "Could not find gsa symbol to replace.");
00488       Symbol* sv=pgm.symtab().find_ref(value);
00489       p_assert(sv, "Could not find gsa symbol to replace with.");
00490       Iterator<Expression> expit=stmt.iterate_expressions();
00491       for (expit=stmt.iterate_expressions(); expit.valid(); ++expit){
00492     fix_substituted(expit.current(), *sk, *sv);
00493       }
00494     }
00495     /// ...  Re-build references.
00496     stmt.build_refs();
00497   }
00498 
00499 /// Adjust gmap.
00500   adjust_gmap(pgm, final);
00501   return true;
00502 }
00503 
00504 
00505 
00506 
00507 /*!
00508   \brief Reduces the SSA name count by removing ETA functions
00509   where unnecessary.
00510 
00511   ETA functions are unnecessary when of this form:
00512   x@5 = ETA(condition, x@8, x@8)
00513 */
00514 static bool optimize_ssa_eta(ProgramUnit& pgm){
00515 /// First go through all statements and find all unnecessary ETA's.
00516   bool global_change=false;
00517   RefList<Symbol> unnecessary_syms;
00518   RefSet<Statement> unnecessary_eta;
00519   Iterator<Statement> stit;
00520   Database<String, StringElem> final;
00521   for (stit=pgm.stmts().iterator(); stit.valid(); ++stit){
00522     /// ...  Skip all statements except for CALL and x = func()
00523     Statement& stmt=stit.current();
00524     if (stmt.stmt_class()!=ASSIGNMENT_STMT) continue;
00525     Expression& rhs=stmt.rhs();
00526     if (rhs.op()!=ETA_OP) continue;
00527     /// ...  It is a ETA statement
00528     Expression& lhs=stmt.lhs();
00529     Expression& first=rhs.parameters_guarded().arg_list()[0];
00530     Expression& second=rhs.parameters_guarded().arg_list()[1];
00531     if (first.op()!=ID_OP || second.op()!=ID_OP) continue;
00532     int rank1, rank2, rank;
00533     String base1, base2, base;
00534     gsa_details(lhs.symbol(), base, rank);
00535     gsa_details(first.symbol(), base1, rank1);
00536     gsa_details(second.symbol(), base2, rank2);
00537     if (rank1==rank2){
00538       final.ins(lhs.symbol().name_ref(), 
00539         new StringElem(first.symbol().name_ref()));
00540       unnecessary_eta.ins(stmt);
00541       unnecessary_syms.ins_last(lhs.symbol());
00542       global_change=true;
00543     }
00544   }
00545   
00546 /// Remove unnecessary statements.
00547   pgm.stmts().del(unnecessary_eta);
00548   
00549 /// Replace the symbols that have been removed.
00550 /// It may happen that a@6 is to be replaced with a@5, but a@5 is to
00551 /// be replaced with a@4.  We must first find for every symbol which is
00552 /// the final symbol to be replaced with (thus we avoid iterating over the
00553 /// whole replacing procedure, and do it beforehand).
00554 
00555   if (final.entries()==0) return false; /// ...  made no change.
00556 /// Iterate until no change.
00557   int change;
00558   do {
00559     change=0;
00560     KeyIterator<String, StringElem> kit=final;
00561     for ( ; kit.valid(); ++kit){
00562       StringElem& value=kit.current_data();
00563       /// ...  Look for transitivity.
00564       StringElem* found=final.find_ref(value);
00565       if (found){
00566     change=1;
00567     value=*found;
00568       }
00569     }
00570   } while (change);
00571 /// At this time, the map should have converged.
00572 /// For all statements
00573   for (stit=pgm.stmts().iterator(); stit.valid(); ++stit){
00574     Statement& stmt=stit.current();
00575     stmt.build_refs();
00576     /// ...  For all symbols accessed in this statement.
00577     Mutator<Expression> allrefs=stmt.in_refs();
00578     for ( ; allrefs.valid(); ++allrefs){
00579       if (allrefs.current().op()!=ID_OP &&
00580       allrefs.current().op()!=ARRAY_REF_OP) continue;
00581       StringElem* found;
00582       if (allrefs.current().op()==ID_OP){
00583     found=final.find_ref(allrefs.current().symbol().name_ref());
00584       } else {
00585     found=final.find_ref(allrefs.current().array().symbol().name_ref());
00586       }
00587       if (found) {
00588     Symbol* first=pgm.symtab().find_ref(*found);
00589     Mutator<Expression> expmut=stmt.iterate_expressions();
00590     for ( ; expmut.valid(); ++expmut ){
00591       if (allrefs.current().op()==ID_OP){
00592         substitute_var(expmut.current(), allrefs.current().symbol(), *first);
00593       } else {
00594         substitute_var(expmut.current(), allrefs.current().array().symbol(), *first);
00595       }
00596     }
00597       }
00598     }
00599     allrefs=stmt.out_refs();
00600     for ( ; allrefs.valid(); ++allrefs){
00601       if (allrefs.current().op()!=ID_OP) continue;
00602       StringElem* found=final.find_ref(allrefs.current().symbol().name_ref());
00603       if (found) {
00604     Symbol* first=pgm.symtab().find_ref(*found);
00605     Iterator<Expression> expmut=stmt.iterate_expressions();
00606     for ( ; expmut.valid(); ++expmut ){
00607       substitute_var(expmut.current(), allrefs.current().symbol(), *first);
00608     }
00609       }
00610     }
00611     /// ...  Need to update 'substituted' fields
00612     KeyIterator<String, StringElem> kit=final;
00613     for ( ; kit.valid(); ++kit){
00614       String& key=kit.current_key();
00615       StringElem& value=kit.current_data();
00616       Symbol* sk=pgm.symtab().find_ref(key);
00617       p_assert(sk, "Could not find gsa symbol to replace.");
00618       Symbol* sv=pgm.symtab().find_ref(value);
00619       p_assert(sv, "Could not find gsa symbol to replace with.");
00620       Iterator<Expression> expit=stmt.iterate_expressions();
00621       for (expit=stmt.iterate_expressions(); expit.valid(); ++expit){
00622     fix_substituted(expit.current(), *sk, *sv);
00623       }
00624     }
00625     /// ...  Re-build references.
00626     stmt.build_refs();
00627   }
00628 
00629 /// Adjust gmap.
00630   adjust_gmap(pgm, final);
00631   return true;
00632 }
00633 
00634 
00635 
00636 /*!
00637   \brief Reduces the SSA name count by removing BETA functions
00638   where unnecessary.
00639 
00640   BETA functions are unnecessary when a routine argument is of type IN,
00641   i.e. not modified inside the called routine.
00642 
00643   It uses the IPCP MAYMOD assertions to check for parameter type.
00644 */
00645 static void optimize_ssa_beta(ProgramUnit& pgm){
00646 /// First go through all CALL statements and find all BETA calls.
00647 /// For every BETA call, find whether its pre-SSA argument has a MAYMOD
00648 /// assertion.  If not, put it in 'unnecessary_syms'.
00649 
00650   RefList<Symbol> unnecessary_syms;
00651   RefList<Expression> unnecessary_betas;
00652   RefList<Expression> unnecessary_beta_sites;
00653   Iterator<Statement> stit;
00654   Database<String, StringElem> final;
00655   for (stit=pgm.stmts().iterator(); stit.valid(); ++stit){
00656     /// ...  Skip all statements except for CALL and x = func()
00657     Statement& stmt=stit.current();
00658     Expression* params=0;
00659     if (stmt.stmt_class()==CALL_STMT) {
00660       params=&stmt.parameters_guarded();
00661     } else {
00662       if (stmt.stmt_class()==ASSIGNMENT_STMT){
00663     if (stmt.rhs().op()==FUNCTION_CALL_OP) {
00664       if (!is_pseudo_function(stmt.rhs())){
00665         params=&stmt.rhs().parameters_guarded();
00666       } else continue;
00667     } else continue;
00668       } else continue;
00669     }
00670 
00671     /// ...  Check if it has a MAYMOD assertion associated with it.
00672     /// ...  If not, we cannot do anything about it.
00673     if (!has_maymod(stmt)) continue;
00674 
00675     /// ...  If we got here, 'params' points to the list of arguments.
00676     if (params->op()==OMEGA_OP) continue;
00677     for (Iterator<Expression> expit=params->arg_list(); 
00678      expit.valid(); ++expit){
00679       Expression& arg=expit.current();
00680       if (!is_beta(arg)) continue;
00681 
00682       /// ...  Get its base symbol.
00683       Symbol* oldvalue;
00684       Expression* last_arg=arg.parameters_guarded().arg_list().last_ref();
00685       Expression* first_arg=arg.parameters_guarded().arg_list().first_ref();
00686       Expression* alpha_arg=
00687     first_arg->parameters_guarded().arg_list().first_ref();
00688 ///       cerr<<"\nlast_arg= "<<*last_arg<<" = "<<*first_arg
00689 ///       <<" = "<<*alpha_arg;
00690       Symbol* basesym;
00691       VariableSymbol* varsym;
00692       if (last_arg->op()==ARRAY_REF_OP){
00693     varsym=(VariableSymbol*)&last_arg->array().symbol();
00694     basesym=varsym;
00695     if (varsym->is_gsa_symbol()) basesym=&varsym->gsa_base_symbol();
00696     oldvalue=&alpha_arg->array().symbol();
00697       } else {
00698     varsym=(VariableSymbol*)&last_arg->symbol();
00699     basesym=varsym;
00700     if (varsym->is_gsa_symbol()) basesym=&varsym->gsa_base_symbol();
00701     oldvalue=&alpha_arg->symbol();
00702       }
00703       
00704       /// ...  Check if it has a MAYMOD assertion associated with this particular sym.
00705       if (!is_var_in_maymod(*basesym, stmt)){
00706     unnecessary_syms.ins_last(*varsym);
00707     unnecessary_betas.ins_last(arg);
00708     unnecessary_beta_sites.ins_last(*params);
00709     final.ins(varsym->name_ref(), new StringElem(oldvalue->name_ref()));
00710       }
00711     }
00712   }
00713 
00714 /// The second step consists of replacing all symbols in 'unnecessary'
00715 /// with their ssa-base-equivalent symbol of previous rank:
00716 /// (such as a@7 will be replaced by a@6).
00717 /// Also, the BETA call where this happens will be replaced by a simple
00718 /// variable expression.
00719 ///       cerr<<"\n final: "<<final;
00720 
00721 /// Start removing BETA calls.
00722   Iterator<Expression> beta_site=unnecessary_beta_sites;
00723   Iterator<Expression> beta=unnecessary_betas;
00724   Iterator<Symbol> sym=unnecessary_syms;
00725   for ( ; beta_site.valid() && beta.valid() && sym.valid(); 
00726     ++beta_site, ++beta, ++sym){
00727     List<Expression>& exlist=beta_site.current().arg_list();
00728     Expression& ex=beta.current();
00729     Symbol* newsym=0;
00730     String bname;
00731     int rank;
00732     gsa_details(sym.current(), bname, rank);
00733     if (rank==0){
00734       /// ...  Do nothing, this is a CALL p(1) type of statement.
00735       /// ...  Gets transformed into arg=1; CALL p(BETA(ALPHA(arg), arg))
00736       newsym=&sym.current();
00737     } else {
00738       String prevgsa;
00739       prev_gsa_rank_name(sym.current(), prevgsa);
00740       newsym=pgm.symtab().find_ref(prevgsa);
00741       if (newsym==0){
00742     cerr<<"\nCould not find previous GSA rank for this symbol: "
00743         <<sym.current();
00744     cerr<<"\nBeta: "<<ex; 
00745     cerr<<"\nBeta site: "<<beta_site.current();
00746     p_abort("");
00747       }
00748     }
00749     FunctionCallExpr& func=(FunctionCallExpr&)ex;
00750     Expression* first_arg=func.parameters_guarded().arg_list().first_ref();
00751     /// ...  first_arg points now to ALPHA.
00752     first_arg=first_arg->parameters_guarded().arg_list().first_ref();
00753     Expression* newex=first_arg->clone();
00754     Expression* grabbed=0;
00755     if (newex->op()==ID_OP){
00756       if (newex->substituted_valid()){
00757     grabbed=first_arg->grab_substituted();
00758       }
00759     }
00760     substitute_var(*newex, sym.current(), *newsym);
00761     if (newex->op()==ID_OP){
00762       if (newex->substituted_valid()){
00763     newex->substituted(grabbed);
00764       }
00765     }    
00766     exlist.modify(ex, newex);
00767   }
00768   
00769 /// Replace the symbols that have been removed.
00770 /// It may happen that a@6 is to be replaced with a@5, but a@5 is to
00771 /// be replaced with a@4.  We must first find for every symbol which is
00772 /// the final symbol to be replaced with (thus we avoid iterating over the
00773 /// whole replacing procedure, and do it beforehand).
00774 ///     cerr<<"\n final: "<<final;
00775 
00776 /// Iterate until no change.
00777   int change;
00778   do {
00779     change=0;
00780     KeyIterator<String, StringElem> kit=final;
00781     for ( ; kit.valid(); ++kit){
00782       StringElem& value=kit.current_data();
00783       /// ...  Look for transitivity.
00784       StringElem* found=final.find_ref(value);
00785       if (found==&value) continue;
00786       if (found){
00787     change=1;
00788     value=*found;
00789       }
00790     }
00791   } while (change);
00792 ///     cerr<<"\n final: "<<final;
00793 
00794 /// At this time, the map should have converged.
00795 /// For all statements
00796   for (stit=pgm.stmts().iterator(); stit.valid(); ++stit){
00797     Statement& stmt=stit.current();
00798     stmt.build_refs();
00799     /// ...  For all symbols accessed in this statement.
00800     Mutator<Expression> allrefs=stmt.in_refs();
00801     for ( ; allrefs.valid(); ++allrefs){
00802       if (allrefs.current().op()!=ID_OP &&
00803       allrefs.current().op()!=ARRAY_REF_OP) continue;
00804       StringElem* found;
00805       if (allrefs.current().op()==ID_OP){
00806     found=final.find_ref(allrefs.current().symbol().name_ref());
00807       } else {
00808     found=final.find_ref(allrefs.current().array().symbol().name_ref());
00809       }
00810       if (found) {
00811     Symbol* first=pgm.symtab().find_ref(*found);
00812     Mutator<Expression> expmut=stmt.iterate_expressions();
00813     for ( ; expmut.valid(); ++expmut ){
00814       if (allrefs.current().op()==ID_OP){
00815         substitute_var(expmut.current(), allrefs.current().symbol(), *first);
00816       } else {
00817         substitute_var(expmut.current(), allrefs.current().array().symbol(), *first);
00818       }
00819     }
00820       }
00821     }
00822     allrefs=stmt.out_refs();
00823     for ( ; allrefs.valid(); ++allrefs){
00824       if (allrefs.current().op()!=ID_OP) continue;
00825       StringElem* found=final.find_ref(allrefs.current().symbol().name_ref());
00826       if (found) {
00827     Symbol* first=pgm.symtab().find_ref(*found);
00828     Iterator<Expression> expmut=stmt.iterate_expressions();
00829     for ( ; expmut.valid(); ++expmut ){
00830       substitute_var(expmut.current(), allrefs.current().symbol(), *first);
00831     }
00832       }
00833     }
00834     /// ...  Need to update 'substituted' fields
00835 ///     cerr<<"\n final: "<<final;
00836     KeyIterator<String, StringElem> kit=final;
00837     for ( ; kit.valid(); ++kit){
00838       String& key=kit.current_key();
00839       StringElem& value=kit.current_data();
00840       Symbol* sk=pgm.symtab().find_ref(key);
00841       p_assert(sk, "Could not find gsa symbol to replace.");
00842       Symbol* sv=pgm.symtab().find_ref(value);
00843       p_assert(sv, "Could not find gsa symbol to replace with.");
00844       Iterator<Expression> expit=stmt.iterate_expressions();
00845       for (expit=stmt.iterate_expressions(); expit.valid(); ++expit){
00846     fix_substituted(expit.current(), *sk, *sv);
00847       }
00848     }
00849     /// ...  Re-build references.
00850     stmt.build_refs();
00851   }
00852 
00853 /// Adjust gmap.
00854   adjust_gmap(pgm, final);
00855 }
00856 
00857 void optimize_ssa(ProgramUnit& pgm, SSA_OptFlags flags){
00858   if ( flags & SSA_OPT_BETA) {
00859     optimize_ssa_beta(pgm);
00860   }
00861 /// Iterate until convergence.
00862   bool change;
00863   int iter_count=0;
00864   do {
00865     change=false;
00866     if ( flags & SSA_OPT_MU) {
00867       change=change || optimize_ssa_mu(pgm);
00868     }
00869     if ( flags & SSA_OPT_GAMMA) {
00870       change=change || optimize_ssa_gamma(pgm);
00871     }
00872     if ( flags & SSA_OPT_ETA) {
00873       change=change || optimize_ssa_eta(pgm);
00874     }
00875     ++iter_count;
00876   } while (change);
00877 
00878   if (flags & SSA_OPT_ZERO){
00879 ///     cerr<<"\nOptimize_ssa_zero: "<<pgm.routine_name_ref();
00880     optimize_ssa_zero(pgm);
00881   }
00882   cout<<"\n\tOptimize_ssa "<<pgm.routine_name_ref()
00883       <<" converged after "<<iter_count<<" iterations.";
00884 ///   if (iter_count>1){
00885 ///     cout<<"\n\t\tSSA prune converged after "<<iter_count<<
00886 ///       " iterations for pgm "<<pgm.routine_name_ref();
00887 ///   } else {
00888 ///     cout<<"\n\t\tSSA prune converged after an iteration for pgm "
00889 ///     <<pgm.routine_name_ref();
00890 ///   }
00891   
00892 /// Re-build refs.
00893   pgm.stmts().build_all_refs();
00894 }
00895 
00896 
 © 1995-2005 University of Illinois, Urbana-Champaign. All rights reserved.  Fri Mar 25 23:05:59 2005