Polaris: range_dict_util.cc Source File

range_dict_util.cc

Go to the documentation of this file.
00001 ///
00002 ///
00003 /// \file range_dict_util.cc
00004 ///
00005 #include <map>
00006 
00007 #include "ProgramUnit.h"
00008 #include "../Collection/Iterator.h"
00009 #include "../Symbol/FunctionSymbol.h"
00010 #include "../Statement/Statement.h"
00011 #include "../Directive/AssertMayMod.h"
00012 #include "../Symtab.h"
00013 
00014 #include "range_dict_util.h"
00015 
00016 
00017 /// sort_sym_list
00018 ///   Sort the given list of symbols.
00019 
00020 void
00021 sort_sym_list(RefList<Symbol> &sym_list)
00022 {
00023     RefList<Symbol> sym_queue = sym_list;
00024     sym_list.clear();
00025 
00026     while (sym_queue.entries()) {
00027     Symbol &sym = sym_queue.grab(0);
00028     const char *sym_name = sym.name_ref();
00029     Symbol *prev = 0;
00030     Iterator<Symbol> sorted_iter = sym_list;
00031         
00032     for ( ; sorted_iter.valid(); ++sorted_iter) {
00033         int name_cmp = strcmp(sym_name, sorted_iter.current().name_ref());
00034 
00035         if (name_cmp < 0)
00036         break;
00037         else
00038         prev = &sorted_iter.current();
00039     }
00040         
00041     sym_list.ins_after(sym, *prev);
00042     }
00043 }
00044 
00045 
00046 ///  remove_min_max_var_conflicts
00047 ///    Rename any variables named MIN or MAX in the given program so that
00048 ///    they will not conflict with the symbols for the intrinsics MIN and MAX.
00049 
00050 static void 
00051 _fix_intr_var_conflicts(Symtab &symtab, Symbol &var)
00052 {
00053     if (var.sym_class() != FUNCTION_CLASS || ! var.intrinsic()) {
00054     Symbol *var_ptr = symtab.grab(var.name_ref());
00055 
00056     Symbol *intr = new FunctionSymbol(var.name_ref(),
00057                       make_type(INTEGER_TYPE),
00058                       NOT_EXTERNAL, IS_INTRINSIC,
00059                       NOT_FORMAL);
00060     symtab.ins(intr);
00061     symtab.rename_and_ins(var_ptr);
00062     }
00063 }
00064 
00065 void
00066 remove_min_max_var_conflicts(Symtab &symtab)
00067 {
00068     Symbol *min_sym = symtab.find_ref("MIN");
00069 
00070     if (min_sym)
00071     _fix_intr_var_conflicts(symtab, *min_sym);
00072 
00073     Symbol *max_sym = symtab.find_ref("MAX");
00074 
00075     if (max_sym)
00076     _fix_intr_var_conflicts(symtab, *max_sym);
00077 }
00078 
00079 
00080 /// stmt_maymods
00081 ///   If the given statement has a MAYMODS assertion, return the set of
00082 ///   possibly modified variables.  Otherwise, return NULL.
00083 
00084 RefSet<Symbol> *
00085 stmt_maymods(const Statement &stmt)
00086 {
00087     RefSet<Symbol> *maymods = 0;
00088     Iterator<Assertion> asrt_iter = stmt.assertions();
00089 
00090     for ( ; asrt_iter.valid(); ++asrt_iter) {
00091         Assertion &asrt = asrt_iter.current();
00092 
00093         if (asrt.type() == AS_MAYMOD) {
00094         if (! maymods)
00095         maymods = new RefSet<Symbol>;
00096 
00097         if (asrt.arg_list_valid()) {
00098         Iterator<Expression> aexpr_iter = asrt.arg_list_guarded();
00099         
00100         for ( ; aexpr_iter.valid(); ++aexpr_iter) {
00101             Symbol *var_ref = aexpr_iter.current().base_variable_ref();
00102             
00103             if (var_ref)
00104             maymods->ins(*var_ref);
00105         }
00106         }
00107         }
00108     }
00109 
00110     return maymods;
00111 }
00112 
00113 
00114 static void get_array_refs(Expression& expr, RefList<Expression>& array_refs){
00115   if (expr.op()==ARRAY_REF_OP){
00116     array_refs.ins_last(expr);
00117   }
00118   for(Iterator<Expression> expit=expr.arg_list(); expit.valid(); ++expit){
00119     get_array_refs(expit.current(), array_refs);
00120   }
00121 }
00122 
00123 /// Return the last statement that is within the same block as 'ref'.
00124 static Statement* skip_blocks(Statement* ref){
00125   Statement* toret=ref;
00126   Statement* next=toret;
00127   while(next){
00128     switch(next->stmt_class()){
00129     case ENDDO_STMT:
00130     case ENDIF_STMT:
00131     case FLOW_EXIT_STMT:
00132       /// ...  Got to the end of the block.
00133       return toret;
00134     case DO_STMT:
00135     case WHILE_STMT:
00136       /// ...  Skip this block.
00137       toret=next->follow_ref();
00138       break;
00139     case IF_STMT:
00140       /// ...  Skip this block.
00141       toret=next->matching_endif_ref();
00142       break;
00143     default:
00144       toret=next->next_ref();
00145     }
00146     next=toret;
00147   }
00148   return toret;
00149 }
00150 
00151 /// Silvius: force insertion of ranges according to the Fortran 77
00152 /// standard for the following case:
00153 /// DIMENSION A(m,n:p,*)
00154 /// DO i=1,k
00155 ///   DO j=h,100
00156 ///     A(i,j,...)=...
00157 /// In this case, since the access on A must be within bounds we
00158 /// will add to the dictionary the following ranges:
00159 /// k=[1,m] and h=[n:p].
00160 /// Silvius: since I do not want to get to the guts of the AIRangeDict,
00161 /// we will force the insertionof the ranges by inserting some guards in
00162 /// the code, such as:
00163 /// IF (1.LE.k.AND.k.LE.m) THEN
00164 ///   DO i=1,k
00165 /// Silvius: for now we do not catch all possible ranges, just look at some
00166 /// particular cases.
00167 void enforce_standard_within_bounds(ProgramUnit& pgm, 
00168                     RefList<Statement>& new_ifs){
00169 /// silvius: not sure this is right
00170   return;
00171 
00172 /// First find DO loops and select "inits" and "limits"
00173   Iterator<Statement> loopit=pgm.stmts().stmts_of_type(DO_STMT);
00174   for( ; loopit.valid(); ++loopit){
00175     /// ...  Go through all the statements in the loop.
00176 ///     cerr<<"\nAt loop "<<loopit.current();
00177     /// ...  Check whether the init or limit are ID_OP.
00178     RefList<Expression> base;
00179     if (loopit.current().init().op()==ID_OP){
00180       base.ins_last(loopit.current().init());
00181     }
00182     if (loopit.current().limit().op()==ID_OP){
00183     base.ins_last(loopit.current().limit());
00184     }
00185     if (base.entries()==0){
00186 ///       cerr<<"\nNo suitable init/limit found.";
00187       continue;
00188     }
00189     map<Symbol*, pair<Expression*, Expression*> > solutions;
00190     for(Statement* stit=loopit.current().next_ref();
00191     stit!=loopit.current().follow_ref(); stit=stit->next_ref()){
00192 ///       cerr<<"\nAt statement: "<<*stit;
00193       /// ...  Go through all the array references in the statement.
00194       for(Iterator<Expression> expit=stit->iterate_expressions();
00195       expit.valid(); ++expit){
00196     RefList<Expression> array_refs;
00197     get_array_refs(expit.current(), array_refs);
00198     for(Iterator<Expression> arit=array_refs; arit.valid(); ++arit){
00199       // Check whether this array reference matches our pattern.
00200       Expression& ar=arit.current();
00201 ///       cerr<<"\n\tFor array ref "<<ar;
00202       Symbol& sym=ar.array().symbol();
00203       // Check all dimensions except for last.
00204       ArrayDims& dims=sym.dim();
00205       List<Expression>& subs=ar.subscript().arg_list();
00206       for (int i=0; i<dims.entries()-1; ++i){
00207         Expression& expr=subs[i];
00208         if (expr.op()!=ID_OP){
00209           continue;
00210         }
00211         if (expr!=loopit.current().index()){
00212           continue;
00213         }
00214         /// ...  If it gets here, it is the loop index.
00215         ArrayBounds& ab=dims[i];
00216         Expression* lower=0;
00217         Expression* upper=0;
00218         if (ab.lower_exists()){
00219           lower=ab.lower_guarded().clone();
00220         } else {
00221           lower=constant(1);
00222         }
00223         if (ab.upper_exists()){
00224           upper=ab.upper_guarded().clone();
00225         } else {
00226           upper=constant(1);
00227           p_abort("Upper bound not declared in array inner dimension.");
00228         }
00229         /// ...  Report it for now.
00230         for(Iterator<Expression> bit=base; bit.valid(); ++bit){
00231           /// ...  Insert if not already found.
00232           map<Symbol*, pair<Expression*, Expression*> >::iterator found=
00233         solutions.find(&bit.current().symbol());
00234           if (found==solutions.end()){
00235 ///         cerr<<"\n\t\tInsert relation: "
00236 ///             <<*lower<<"<="<<bit.current()<<"<="<<*upper;
00237         solutions.insert(make_pair(&bit.current().symbol(),
00238                        make_pair(lower->clone(), 
00239                              upper->clone())));
00240           }
00241         }
00242         delete lower;
00243         delete upper;
00244       }
00245     }
00246       }
00247     }
00248 
00249     /// ...  At this point we have all the solutions for this loop.
00250     /// ...  Let us insert the solutions as pgm guards.
00251     for(map<Symbol*, pair<Expression*, Expression*> >::iterator 
00252       sit=solutions.begin(); sit!=solutions.end(); ++sit){
00253       Expression* guard=simplify(and(le((*sit).second.first,
00254                     id(*(*sit).first)),
00255                      le(id(*(*sit).first),
00256                     (*sit).second.second)));
00257       Statement* if_after=pgm.stmts().first_ref()->next_ref();
00258       Statement* endif_after=pgm.stmts().last_ref()->prev_ref();
00259       VariableSymbol& vsym=(VariableSymbol&)*(*sit).first;
00260       if (vsym.is_gsa_symbol()){
00261     continue;
00262       }
00263       pgm.stmts().ins_IF_after(guard, 
00264                    if_after,
00265                    endif_after);
00266       new_ifs.ins_last(*pgm.stmts().first_ref()->next_ref()->next_ref());
00267     }
00268   }
00269 }
00270 
00271 
00272 /// Clean up after enforce_standard_within_bounds.
00273 void clean_after_standard_enforcement(ProgramUnit& pgm, 
00274                       RefList<Statement>& new_ifs){
00275   for(Iterator<Statement> stit=new_ifs; stit.valid(); ++stit){
00276     Statement& ifstmt=stit.current();
00277     Statement& endif=*ifstmt.matching_endif_ref();
00278     Statement& after_if=*ifstmt.next_ref();
00279     Statement& before_implicit_goto=
00280       *ifstmt.matching_endif_ref()->prev_ref()->prev_ref();
00281     pgm.stmts().move_block_before(after_if,
00282                   before_implicit_goto,
00283                   &ifstmt);
00284     pgm.stmts().del(ifstmt, endif);
00285   }
00286 }
 © 1995-2005 University of Illinois, Urbana-Champaign. All rights reserved.  Fri Mar 25 23:06:03 2005