Polaris: loop_util.cc Source File

loop_util.cc

Go to the documentation of this file.
00001 ///
00002 #include "../ProgramUnit.h"
00003 #include "../Collection/Mutator.h"
00004 #include "../Directive/Assertion.h"
00005 #include "../Directive/AssertLoopLabel.h"
00006 #include "../Expression/Expression.h"
00007 #include "../Expression/StringConstExpr.h"
00008 #include "../Statement/AssignmentStmt.h"
00009 #include "../Statement/Statement.h"
00010 #include "../Symbol/FunctionSymbol.h"
00011 #include "../Symbol/VariableSymbol.h"
00012 #include "../Symbol/Symbol.h"
00013 #include "../Traverser.h"
00014 #include "../Collection/KeyDatabase.h"
00015 #include "../Collection/RefSet.h"
00016 #include "../p-assert.h"
00017 
00018 #include "expression_util.h"
00019 #include "invariant_util.h"
00020 #include "loop_util.h"
00021 #include "precalc_util.h"
00022 
00023 static Expression *
00024 _icall_id( const char *fn, ProgramUnit &pgm )
00025 {
00026     return id( pgm.symtab().ins_intrinsic(fn) );
00027 }
00028 
00029 static Expression *
00030 _loop_range( Statement &do_stmt )
00031 {
00032     return simplify( div( add ( sub( do_stmt.limit().clone(),
00033                                      do_stmt.init().clone() ),
00034                                 do_stmt.step().clone() ),
00035                           do_stmt.step().clone() ) );
00036 }
00037 
00038 static Boolean
00039 is_ID_OP (const Expression & expr)
00040 {
00041     if (expr.op() == ID_OP) { 
00042     return True;
00043     } else {
00044     return False;
00045     }
00046 }
00047 
00048 static void
00049 _subst_var_in_assert(Statement &stmt, const Symbol &var,
00050              const Expression &replacement)
00051 {
00052     /// ...  Substitute the variable in the assertions of the statement.
00053 
00054     for (Iterator<Assertion> ass_iter = stmt.assertions();
00055      ass_iter.valid(); ++ass_iter) {
00056     if (ass_iter.current().arg_list_valid()) {
00057 
00058         List<Expression> new_vars;
00059 
00060         for (Mutator<Expression> aexpr_iter = ass_iter.current().arg_list_guarded(); 
00061          aexpr_iter.valid(); ++aexpr_iter) {
00062         if (is_var_in_expr(aexpr_iter.current(), var)) {
00063 
00064             /// ...  For RANGEWRITTEN, substitute only when the 
00065             /// ...  variable to be replaced is found inside an expression.
00066 
00067             if ((ass_iter.current().type() == AS_RANGEWRITTEN) &&
00068             (aexpr_iter.current().op() == ID_OP)) {
00069 
00070             /// ...  Do nothing!
00071 
00072             /// ...  For FIRSTVALUE, substitute only when the 
00073             /// ...  variable to be replaced is found inside an expression.
00074             /// ...  When the variable is found by itself, add all variables
00075             /// ...  from the replacement expression are to be added to the
00076             /// ...  assertion.
00077 
00078             } else if ((ass_iter.current().type() == AS_FIRSTVALUE) &&
00079                    (aexpr_iter.current().op() == ID_OP)) {
00080 
00081             Traverser trav (replacement, is_ID_OP);
00082             for ( ; trav.valid(); ++trav) {
00083                 new_vars.ins_last(trav.current().clone());
00084             }
00085             } else {
00086             
00087                 Assign<Expression> aexpr_as(aexpr_iter.assign());
00088             aexpr_as = substitute_var(aexpr_iter.pull(),
00089                           var, replacement);
00090             }
00091         }
00092         }
00093         for (Iterator<Expression> new_iter = new_vars;
00094          new_iter.valid();
00095          ++new_iter) {
00096         ass_iter.current().arg_list_guarded().ins_last( new_iter.current().clone() );
00097         }
00098     }
00099     }
00100 }
00101 
00102 static void
00103 _subst_var_in_outer_assert(Statement &stmt, const Symbol &var,
00104                const Expression &replacement)
00105 {
00106     /// ...  Substitute the variable in the assertions of the statement
00107     /// ...  and all statements enclosing the statement (via the outer() field.)
00108 
00109     for (Statement *enclosing_stmt = &stmt;
00110      enclosing_stmt;
00111      enclosing_stmt = enclosing_stmt->outer_ref())
00112     _subst_var_in_assert(*enclosing_stmt, var, replacement);
00113 }
00114 
00115 static void
00116 _subst_var_in_stmt(Statement &stmt, const Symbol &var,
00117                    const Expression &replacement)
00118 {
00119     /// ...  Substitute the variable in the expression arguments of the statement.
00120 
00121     Boolean modified_stmt_expr = False;
00122 
00123     for ( Mutator<Expression> mutr = stmt.iterate_expressions();
00124      mutr.valid(); ++mutr) {
00125     if (is_var_in_expr(mutr.current(), var)) {
00126 
00127         Assign<Expression> expr_as(mutr.assign());
00128         expr_as = simplify(substitute_var(mutr.pull(),
00129                           var, replacement));
00130         modified_stmt_expr = True;
00131     }
00132     }
00133 
00134     if (modified_stmt_expr)
00135         stmt.build_refs();
00136 
00137     /// ...  Substitute the variable in the assertions of the statement.
00138 
00139     _subst_var_in_assert(stmt, var, replacement);
00140 }
00141 
00142 void
00143 simplify_control_flow( ProgramUnit &pgm, Statement & s )
00144 {
00145     if ( s.stmt_class() == IF_STMT &&
00146          s.follow_ref()->stmt_class() == ENDIF_STMT) {
00147 
00148         Expression *expr = simplify( s.expr().clone() );
00149 
00150         if (expr->op() == LOGICAL_CONSTANT_OP) {
00151             if (expr->str_data() == ".TRUE.") {
00152                 /// ...  Delete the IF statement and leave everything else.
00153                 pgm.stmts().del( s );
00154             }
00155             else if (expr->str_data() == ".FALSE.") {
00156                 /// ...  Delete everything in the IF statement.
00157                 pgm.stmts().del( s, *s.follow_ref() );
00158             }
00159         }
00160 
00161         delete expr;
00162     }
00163 }
00164 
00165 Boolean
00166 coalese_loop(ProgramUnit & pgm, 
00167              Statement & outer_do_stmt, 
00168              Statement & inner_do_stmt)
00169 {
00170     p_assert(outer_do_stmt.stmt_class() == DO_STMT, "outer not a DO loop");
00171     p_assert(inner_do_stmt.stmt_class() == DO_STMT, "outer not a DO loop");
00172 
00173     precalc_loop( pgm, outer_do_stmt );
00174     precalc_loop( pgm, inner_do_stmt );
00175 
00176     if (outer_do_stmt.next_ref() != & inner_do_stmt)
00177         return False;
00178 
00179     /// ...  Get a reference to the index variables
00180 
00181     Symbol & outer_index_var = outer_do_stmt.index().symbol();
00182     Symbol & inner_index_var = inner_do_stmt.index().symbol();
00183 
00184     /// ...  Create a new index variable for the new loop.
00185 
00186     Symbol & new_index_var 
00187         = pgm.symtab().rename_and_ins( outer_index_var.clone() );
00188 
00189     /// ...  Get copies of all the expressions.
00190 
00191     Expression * outer_init  = outer_do_stmt.init().clone();
00192 ///    Expression * outer_limit = outer_do_stmt.limit().clone();
00193 ///    Expression * outer_step  = outer_do_stmt.step().clone();
00194 
00195     Expression * inner_init  = inner_do_stmt.init().clone();
00196 ///    Expression * inner_limit = inner_do_stmt.limit().clone();
00197 ///    Expression * inner_step  = inner_do_stmt.step().clone();
00198 
00199     /// ...  Calculate the ranges.
00200 
00201     Expression *outer_range = _loop_range( outer_do_stmt );
00202     Expression *inner_range = _loop_range( inner_do_stmt );
00203 
00204     /// ...  Remove the inner DO loop, it is no longer needed.
00205 
00206     pgm.stmts().del( inner_do_stmt );
00207 
00208     /// ...  Calculate the new expressions for the OLD index variables.
00209 
00210     Expression * outer_do_expr = simplify( add( div( id(new_index_var),
00211                                                      inner_range->clone() ),
00212                                                 outer_init ));
00213 
00214     Expression * inner_do_expr 
00215         = simplify( add( intrinsic_call( _icall_id("MOD", pgm), 
00216                                          comma( id(new_index_var), 
00217                                                 inner_range->clone() )), 
00218                          inner_init));
00219 
00220     pgm.stmts().ins_after( new AssignmentStmt( pgm.stmts().new_tag(), 
00221                                                id(inner_index_var), 
00222                                                inner_do_expr ),
00223                            &outer_do_stmt );
00224 
00225     pgm.stmts().ins_after( new AssignmentStmt( pgm.stmts().new_tag(), 
00226                                                id(outer_index_var), 
00227                                                outer_do_expr ),
00228                            &outer_do_stmt );
00229 
00230     /// ...  Calculate the new limit.
00231 
00232     Expression * new_limit = simplify( sub( mul( outer_range, inner_range ),
00233                                             constant(1) ));
00234 
00235     /// ...  Rebuild the single DO loop.
00236 
00237     outer_do_stmt.index( id(new_index_var) );
00238 
00239     outer_do_stmt.init(  constant(0) );
00240     outer_do_stmt.limit( new_limit );
00241     outer_do_stmt.step(  constant(1) );
00242 
00243     return True;
00244 }
00245 
00246 /// determine if there are any escaping goto statements.  returns True if there are.
00247 static Boolean
00248 _any_escaping_gotos(ProgramUnit &pgm, Statement &loop) {
00249 
00250     for (Iterator<Statement> scan = pgm.stmts().iterate_loop_body(&loop);
00251      scan.valid(); ++scan) {
00252 
00253         switch (scan.current().stmt_class()) {
00254 
00255         case GOTO_STMT: {
00256 
00257             Statement      *outer_scan = scan.current().target_ref();
00258 
00259         /// ...  check to see if target is inside of the loop by looking
00260         /// ...  for our loop in it's containing loop list
00261         while ((outer_scan != NULL) && (outer_scan != &loop)) {
00262 
00263             outer_scan = outer_scan->outer_ref();
00264         }
00265 
00266         if (outer_scan == NULL) {
00267 
00268             /// ...  scan left procedure without hitting our loop
00269             return True;
00270         }
00271         }
00272         break;
00273 
00274         case COMPUTED_GOTO_STMT:
00275         case ARITHMETIC_IF_STMT: {
00276 
00277             for (Iterator<Statement> chk = scan.current().label_list();
00278              chk.valid(); ++chk) {
00279 
00280             Statement      *outer_scan = chk.current().outer_ref();
00281 
00282             /// ...  check to see if target is inside of the loop by looking
00283             /// ...  for our loop in it's containing loop list
00284             while ((outer_scan != NULL) && (outer_scan != &loop)) {
00285 
00286                 outer_scan = outer_scan->outer_ref();
00287             }
00288 
00289             if (outer_scan == NULL) {
00290 
00291                 /// ...  scan left procedure without hitting our loop
00292                 return True;
00293             }
00294         }
00295         }
00296         break;
00297 
00298         case RETURN_STMT:
00299         case ASSIGN_STMT:
00300         case ASSIGNED_GOTO_STMT:
00301             return True;
00302     default:
00303       return False;
00304         }
00305     }
00306 
00307     return False;
00308 }
00309 
00310 /// compute loop index last value
00311 static void
00312 _loop_index_last_val(ProgramUnit &pgm, Symbol &index_var,
00313              Statement &do_stmt, Statement &after_me) {
00314 
00315     /// ...  obtain the intrinsic MAX
00316     Symbol          *max = pgm.symtab().find_ref("MAX");
00317     if (max == NULL) {
00318 
00319         max = new FunctionSymbol("MAX",INTEGER_TYPE,NOT_EXTERNAL,IS_INTRINSIC,NOT_FORMAL);
00320         pgm.symtab().ins(max);
00321 
00322     } else {
00323 
00324         p_assert((max->sym_class() == FUNCTION_CLASS)
00325                  && (max->intrinsic() == IS_INTRINSIC),
00326                  "_loop_index_last_val:  MAX intrinsic used for some other purpose");
00327     }
00328 
00329     /// ...  obtain the intrinsic INT
00330     Symbol          *inte = pgm.symtab().find_ref("INT");
00331     if (inte == NULL) {
00332 
00333         inte = new FunctionSymbol("INT",INTEGER_TYPE,NOT_EXTERNAL,IS_INTRINSIC,NOT_FORMAL);
00334         pgm.symtab().ins(inte);
00335 
00336     } else {
00337 
00338         p_assert((inte->sym_class() == FUNCTION_CLASS)
00339                  && (inte->intrinsic() == IS_INTRINSIC),
00340                  "_loop_index_last_val:  INT intrinsic used for some other purpose");
00341     }
00342 
00343     // step * max(int((limit - init + step)/step),0)
00344     Statement           *set_lastval = new AssignmentStmt(pgm.stmts().new_tag(),
00345               id(index_var),
00346                           simplify(
00347                             add(
00348                               do_stmt.init().clone(),
00349                               mul(
00350                                 do_stmt.step().clone(),
00351                                 intrinsic_call(
00352                                   id(*max),
00353                                   comma(
00354                                     intrinsic_call(
00355                                       id(*inte),
00356                                       comma(
00357                                         div(
00358                                           add(
00359                                             sub(
00360                                               do_stmt.limit().clone(),
00361                                               do_stmt.init().clone()),
00362                                             do_stmt.step().clone()),
00363                                       do_stmt.step().clone()))),
00364                                     constant(0)))))));
00365     pgm.stmts().ins_after(set_lastval,&after_me);
00366 }
00367 
00368 /// this function finds out if there are any uses of scalar "var" that can be
00369 /// reached from the statement "stmt".  it returns True if so, or False if not.
00370 static Boolean
00371 _any_reached_uses(ProgramUnit & NOTUSED(pgm), Symbol &var, Statement &stmt) {
00372 
00373     p_assert(!var.is_array(),"normalize_loop:  _any_reached_uses:  only handles scalars");
00374 
00375     /// ...  if the variable isn't local, then don't bother continuing
00376     /// ...  we may be able to do better with equivalences.
00377     if ((var.saved() == IS_SAVED) || (var.external() == IS_EXTERNAL)
00378     || (var.common_ref() != NULL) || (var.equivalence_ref() != NULL)
00379     || (var.formal() == IS_FORMAL)) {
00380 
00381         return True;
00382     }
00383 
00384 
00385     /// ...  list of statements that have already been visited, so we don't get
00386     /// ...  stuck on flow-graph cycles
00387     RefSet<Statement>   visited;
00388 
00389     /// ...  list of statements that need to be inspected
00390     RefSet<Statement>   worklist;
00391 
00392 
00393     /// ...  initialize the worklist
00394     worklist.ins(stmt);
00395 
00396     /// ...  iterate until there are no more statements in the worklist to deal with
00397     while (worklist.entries() != 0) {
00398 
00399         /// ...  grab a guy
00400         Statement            &scan_me = worklist.grab();
00401     /// ...  worklist.del(scan_me);
00402 
00403     /// ...  see if we should bother looking at him
00404     if (!visited.member(scan_me)) {
00405 
00406         /// ...  add this guy to the visited list
00407         visited.ins(scan_me);
00408 
00409         /// ...  flag keeping track if search has been pruned or not
00410         /// ...  True = not pruned, so check successors
00411         Boolean              follow_flow = True;
00412 
00413         /// ...  check reads
00414         for (Iterator<Expression> inrefs = scan_me.in_refs(); inrefs.valid(); ++inrefs) {
00415 
00416             Expression      &inref = inrefs.current();
00417 
00418         if ((inref.op() == ID_OP) && (inref.base_variable_ref() == &var)) {
00419 
00420             /// ...  found a use
00421             return True;
00422         }
00423         }
00424 
00425         /// ...  check modifications
00426         switch (scan_me.stmt_class()) {
00427 
00428             /// ...  generic statements read all subexpressions
00429             default:
00430             break;
00431 
00432         /// ...  do loop writes it's index, reads all others
00433         case DO_STMT:
00434             if (scan_me.index().base_variable_ref() == &var) {
00435 
00436                 /// ...  the variable is killed here
00437                 follow_flow = False;
00438             }
00439             break;
00440 
00441         /// ...  assignment writes lhs top-level and reads other crud
00442         case ASSIGNMENT_STMT:
00443             if (scan_me.lhs().base_variable_ref() == &var) {
00444 
00445                 /// ...  the variable is killed here
00446                 follow_flow = False;
00447             }
00448             break;
00449         }
00450 
00451         /// ...  add successors to the worklist
00452         if (follow_flow) {
00453 
00454             for (Iterator<Statement> succs = scan_me.succ(); succs.valid(); ++succs) {
00455 
00456             if (!visited.member(succs.current())
00457             && !worklist.member(succs.current())) {
00458 
00459                 worklist.ins(succs.current());
00460             }
00461         }
00462         }
00463     } // visited IF
00464     }
00465 
00466     /// ...  well, we didn't find anything
00467     return False;
00468 }
00469 
00470 void
00471 normalize_loop(ProgramUnit & pgm, Statement & do_stmt, int origin GIV(1))
00472 {
00473     p_assert(do_stmt.stmt_class() == DO_STMT, "not a DO loop");
00474 
00475     /// ...  Normalize loop do_stmt to have a lower bound of <origin> and a step of 1
00476 
00477     if (is_integer_constant(do_stmt.init()) &&
00478         is_integer_constant(do_stmt.step()) ) {
00479         if (do_stmt.init().value() == origin && do_stmt.step().value() == 1)
00480             return;
00481     }
00482 
00483     /// ...  Get new copies of the DO's init, limit and step expressions,
00484 
00485     Expression     *init = do_stmt.init().clone();
00486     Expression     *limit = do_stmt.limit().clone();
00487     Expression     *step = do_stmt.step().clone();
00488 
00489     Expression     *range = _loop_range( do_stmt );
00490 
00491     Expression     *new_init  = constant(origin);
00492     Expression     *new_limit = simplify( add( sub( range, 
00493                            constant(1) ),
00494                           constant(origin) ));
00495     Expression     *new_step  = constant(1);
00496                           
00497     /// ...  Get a reference to the index variable
00498 
00499     Symbol & index_var = do_stmt.index().symbol();
00500 
00501     /// ...  First we need to specify the replacement expression
00502 
00503     Expression *replacement 
00504         = simplify( add( mul( sub( id(index_var), 
00505                                    new_init->clone() ),
00506                               step->clone() ), 
00507                          init->clone() ) );
00508 
00509     /// ...  determine if zero trip is definitely not the case
00510     Boolean         no_zero_trip = ((is_integer_constant(do_stmt.init())
00511                      && is_integer_constant(do_stmt.limit())
00512                      && is_integer_constant(do_stmt.step()))
00513                     && (0 < (do_stmt.limit().value() - do_stmt.init().value()
00514                          + do_stmt.step().value()) / do_stmt.step().value()));
00515     /// ...  determine if loop index is not local
00516     Boolean         non_local_loop_index = ((do_stmt.index().symbol().formal() != NOT_FORMAL)
00517                         || (do_stmt.index().symbol().saved() != NOT_SAVED)
00518                         || (do_stmt.index().symbol().global() != NOT_GLOBAL)
00519                         || (do_stmt.index().symbol().equivalence_ref() != NULL)
00520                         || (do_stmt.index().symbol().common_ref() != NULL));
00521 
00522     precalc_loop( pgm, do_stmt );
00523 
00524     /// ...  Replace the init expression with the constant
00525     // CC 09/20/96  - we want to postpone the assignment of the new initial expression
00526     /// ...  until we compute the last value of the index. In case of a zero_trip loop which
00527     /// ...  goes undetected we want to make sure the last value of the index is correct.
00528     /// ...      do_stmt.init( new_init );
00529 
00530     // Replace limit expression with (limit - init) / step
00531 
00532     /// ...     do_stmt.limit( new_limit );
00533 
00534     /// ...  Replace the step expression with the constant 1
00535 
00536     /// ...     do_stmt.step( new_step );
00537 
00538     /// ...  Now find all occurrences of the use of the index variable
00539     /// ...  inside the loop and replace them with the expression
00540     /// ...  (((index_variable-new_init)*step) + old_init)
00541 
00542     /// ...  Loop through all statements within the loop body
00543 
00544     Iterator<Statement> stmts = pgm.stmts().iterate_loop_body(&do_stmt);
00545 
00546     /// ...  Skip over the DO statement itself.
00547 
00548     for ( ++stmts; stmts.valid(); ++stmts)
00549     _subst_var_in_stmt(stmts.current(), index_var, *replacement);
00550 
00551     /// ...  Now, replace the index variable with the expresion above in
00552     /// ...  the assertion statements for the loop.
00553 
00554     _subst_var_in_assert(do_stmt, index_var, *replacement);
00555 
00556     /// ...  if the loop is possibly zero trip, then put an initial assignment to the
00557     /// ...  original variable
00558     if (!no_zero_trip) {
00559 
00560     Statement       *initassign = new AssignmentStmt(pgm.stmts().new_tag(),
00561                              id(index_var),init->clone());
00562     pgm.stmts().ins_before(initassign,&do_stmt);
00563     }
00564 
00565     /// ...  are there any escaping gotos in the loop
00566     Boolean         escaping_gotos = _any_escaping_gotos(pgm,do_stmt);
00567 
00568     /// ...  if there are escaping gotos, then we rename the loop index variable so we can
00569     /// ...  assign the proper value to the real loop index variable at the beginning of each
00570     /// ...  iteration so it is valid at the escape point.
00571     /// ...  if the loop may also be zero-trip, then we assign the first value to the real index
00572     /// ...  before the loop so it is valid if the loop is skipped.
00573 
00574     if (escaping_gotos) {
00575 
00576         Symbol          *new_loop_var = new VariableSymbol(index_var.name_ref(),
00577                                index_var.type(),NOT_FORMAL,NOT_SAVED);
00578     pgm.symtab().rename_and_ins(new_loop_var);
00579 
00580     /// ...  convert all old symbols to new ones
00581     Expression      *myreplacement = id(*new_loop_var);
00582     for (Iterator<Statement> stmtscn = pgm.stmts().iterate_loop_body(&do_stmt);
00583          stmtscn.valid(); ++stmtscn) {
00584 
00585         Statement       &stmt = stmtscn.current();
00586 
00587         _subst_var_in_stmt(stmt,index_var,*myreplacement);
00588     }
00589     _subst_var_in_assert(do_stmt,index_var,*myreplacement);
00590 
00591     /// ...  add iteration assignment of loop value
00592         Statement       *assigner = new AssignmentStmt(pgm.stmts().new_tag(),
00593                                id(index_var),replacement->clone());
00594     _subst_var_in_stmt(*assigner,index_var,*myreplacement);
00595     assigner->lhs(id(index_var));
00596     pgm.stmts().ins_after(assigner,&do_stmt);
00597 
00598     delete myreplacement;
00599 
00600     } else {
00601 
00602         /// ...  if there are no escaping gotos, then we only need a last value at the end
00603         if (non_local_loop_index
00604         || _any_reached_uses(pgm,index_var,*do_stmt.follow_ref()->next_ref())) {
00605         
00606         _loop_index_last_val(pgm,index_var,do_stmt,*do_stmt.follow_ref());
00607     }
00608     }
00609 
00610     do_stmt.init(new_init);
00611     do_stmt.limit( new_limit );
00612     do_stmt.step( new_step );
00613 
00614     /// ...  Delete the copies.
00615     delete init;
00616     delete limit;
00617     delete step;
00618 
00619     /// ...  We don't need this expression anymore--garbage collect it
00620     delete replacement;
00621 }
00622 
00623 /// Change 
00624 ///  DO I = LOWER, UPPER, STEP
00625 ///    S1
00626 ///  END DO
00627 ///
00628 /// into the following if we can prove the loop is one trip.:
00629 ///
00630 ///  I = LOWER
00631 ///  S1
00632 ///  I = LOWER+STEP
00633 
00634 void
00635 eliminate_loop(ProgramUnit & pgm, Statement & do_stmt )
00636 {
00637     p_assert(do_stmt.stmt_class() == DO_STMT, "not a DO loop");
00638 
00639     precalc_loop( pgm, do_stmt );
00640 
00641 ///    Expression *init  = do_stmt.init().clone();
00642 ///    Expression *limit = do_stmt.limit().clone();
00643 ///    Expression *step  = do_stmt.step().clone();
00644 
00645     Expression *range = _loop_range( do_stmt );
00646 
00647     if ((is_integer_constant(*range)) && (range->value() <= 1)) {
00648         Boolean zero_trip = (range->value() < 1);
00649 
00650         /// ...  Get a reference to the index variable
00651         Symbol & index_var = do_stmt.index().symbol();
00652 
00653         Statement  *s;
00654         Expression *lhs, *rhs;
00655 
00656         /// ...  Maybe needed if the index variable is used after the loop.
00657         lhs = id(index_var);
00658 
00659         if (zero_trip)
00660             rhs = do_stmt.init().clone();
00661         else {
00662             rhs = simplify( add( do_stmt.init().clone(), 
00663                                  do_stmt.step().clone() ));
00664         }
00665 
00666         s = new AssignmentStmt( pgm.stmts().new_tag(), lhs, rhs );
00667 
00668         /// ...  Add lastvalue assignment.
00669         pgm.stmts().ins_after( s, do_stmt.follow_ref() );
00670 
00671         if (zero_trip) {
00672             /// ...  Remove the DO loop and the statements inside of it since it is
00673             /// ...  never executed.
00674             pgm.stmts().del( do_stmt, *do_stmt.follow_ref() );
00675         }
00676         else {
00677             Expression *replacement = do_stmt.init().clone();
00678 
00679             /// ...  Loop through all statements within the loop body
00680 
00681             Iterator<Statement> stmts = pgm.stmts().iterate_loop_body(&do_stmt);
00682 
00683             /// ...  Skip over the DO statement itself.
00684 
00685             for ( ++stmts; stmts.valid(); ++stmts)
00686         _subst_var_in_stmt(stmts.current(), index_var, *replacement);
00687 
00688             /// ...  Delete the copies.
00689 
00690             delete replacement;
00691 
00692             /// ...  Remove the DO loop, since it is only executed once.
00693             pgm.stmts().del( do_stmt );
00694         }
00695     }
00696 
00697     delete range;
00698 }
00699 
00700 void
00701 peel_loop_first(ProgramUnit & pgm, Statement & do_stmt)
00702 {
00703     p_assert(do_stmt.stmt_class() == DO_STMT, "not a DO loop");
00704 
00705     /// ...  Precalculate the DO loop if needed.
00706 
00707     precalc_loop( pgm, do_stmt );
00708 
00709     if (!is_integer_constant(do_stmt.step()) || do_stmt.step().value() < 0)
00710         normalize_loop( pgm, do_stmt );
00711 
00712     /// ...  Get a copy of the lower bound of the loop.
00713 
00714     Expression     *init  = do_stmt.init().clone();
00715     Expression     *limit = do_stmt.limit().clone();
00716     Expression     *step  = do_stmt.step().clone();
00717 
00718     Expression     *range = _loop_range( do_stmt );
00719 
00720     Statement & if_stmt 
00721         = pgm.stmts().ins_IF_after( gt( range, constant(0) ),
00722                                     do_stmt.prev_ref(), 
00723                                     do_stmt.follow_ref() );
00724 
00725     /// ...  Modify the bounds to insure that the loops do not overlap.
00726 
00727     Expression     *new_init  
00728         = simplify( add( step->clone(), init->clone()) );
00729 
00730     Expression     *new_limit = init->clone();
00731 
00732     /// ...  Get a copy of the DO loop.
00733 
00734     List<Statement> *stmt_block;
00735 
00736     stmt_block = clone_loop(pgm, do_stmt, "PF");
00737 
00738     /// ...  Get a pointer to the new copy of the DO loop header.
00739 
00740     Statement *new_do = stmt_block->first_ref();
00741 
00742     /// ...  Put them back into the program in front of the original loop.
00743 
00744     pgm.stmts().ins_before(stmt_block, &do_stmt);
00745 
00746     new_do->limit( new_limit );
00747     do_stmt.init( new_init );
00748 
00749     delete init;
00750     delete limit;
00751     delete step;
00752 
00753     if (pgm.stmts().member(if_stmt))
00754         simplify_control_flow( pgm, if_stmt );
00755 
00756     if (pgm.stmts().member(*new_do))
00757         eliminate_loop( pgm, *new_do );
00758 
00759     if (pgm.stmts().member(do_stmt))
00760         eliminate_loop( pgm, do_stmt );
00761 }
00762 
00763 void
00764 peel_loop_first(ProgramUnit & pgm, Statement & do_stmt, int count)
00765 {
00766     p_assert(do_stmt.stmt_class() == DO_STMT, "not a DO loop");
00767     p_assert( count > 0, "amount to peel must be positive" );
00768 
00769     /// ...  Precalculate the DO loop if needed.
00770 
00771     precalc_loop( pgm, do_stmt );
00772 
00773     if (!is_integer_constant(do_stmt.step()) || do_stmt.step().value() < 0)
00774         normalize_loop( pgm, do_stmt );
00775 
00776     /// ...  Perform special peeling if we only want the first iteration.
00777 
00778     if (count == 1) {
00779         peel_loop_first( pgm, do_stmt );
00780         return;
00781     }
00782 
00783     List<Statement> *stmt_block;
00784 
00785     /// ...  Get a copy of the DO loop.
00786 
00787     stmt_block = clone_loop (pgm, do_stmt, "PF");
00788 
00789     /// ...  Get a pointer to the new copy of the DO loop header.
00790 
00791     Statement      *new_do = stmt_block->first_ref();
00792 
00793     /// ...  Put them back into the program in front of the original loop.
00794 
00795     pgm.stmts().ins_before(stmt_block, &do_stmt);
00796 
00797     /// ...  Get a copy of the lower bound of the loop.
00798 
00799     Expression     *init = do_stmt.init().clone();
00800     Expression     *limit = do_stmt.limit().clone();
00801     Expression     *step  = do_stmt.step().clone();
00802 
00803     /// ...  Modify the bounds to insure that the loops do not overlap.
00804 
00805     Expression     *new_init  
00806         = simplify( add( mul( step->clone(), 
00807                               constant(count)), 
00808                          init->clone()) );
00809 
00810     Expression     *new_limit 
00811         = simplify( intrinsic_call( _icall_id("MIN", pgm), 
00812                                     comma( sub( add( constant(count), 
00813                                                      init->clone() ),
00814                                                 constant(1) ),
00815                                            limit->clone() )));
00816     new_do->limit( new_limit );
00817     do_stmt.init( new_init );
00818 
00819     delete init;
00820     delete limit;
00821 }
00822 
00823 /// Peel the last iteration off the loop
00824 
00825 void
00826 peel_loop_last(ProgramUnit & pgm, Statement & do_stmt)
00827 {
00828     p_assert(do_stmt.stmt_class() == DO_STMT, "not a DO loop");
00829 
00830     /// ...  Precalculate the DO loop if needed.
00831     precalc_loop( pgm, do_stmt );
00832     normalize_loop( pgm, do_stmt );
00833 
00834     /// ...  Get a copy of the DO loop.
00835 
00836     List<Statement> *stmt_block;
00837     stmt_block = clone_loop (pgm, do_stmt, "PL");
00838 
00839     /// ...  Get a pointer to the new copy of the DO loop header.
00840 
00841     Statement      *new_do = stmt_block->first_ref();
00842 
00843     /// ...  Put them back into the program in front of the original loop.
00844 
00845     Statement *enddo_stmt = do_stmt.follow_ref();
00846     
00847     pgm.stmts().ins_after(stmt_block, enddo_stmt);
00848 
00849     /// ...  Get a copy of the lower bound of the loop.
00850 
00851     Expression     *init = do_stmt.init().clone();
00852     Expression     *limit = do_stmt.limit().clone();
00853     Expression     *step  = do_stmt.step().clone();
00854 
00855     Symbol         &index = do_stmt.index().symbol();
00856 
00857     Expression     *range = _loop_range( do_stmt );
00858 
00859     Statement & if_stmt 
00860         = pgm.stmts().ins_IF_after( gt( range, constant(0) ),
00861                                     enddo_stmt, 
00862                                     new_do->follow_ref() );
00863 
00864     /// ...  Get the loop label of the peeled loop
00865 
00866     String loop_label = new_do->get_loop_name();
00867 
00868     /// ...  Change references to the loop index into usages of the upper loop bound
00869 
00870     Iterator<Statement> stmts = pgm.stmts().iterate_loop_body(new_do);
00871 
00872     /// ...  Skip over the DO statement itself.
00873     /// ...  Replace the loop index by the limit expression from the original loop and 
00874     /// ...  remove all references to the original outer loop for PRIVATEREFS
00875     /// ...  and READONLYREFS assertions in the peeled part
00876     
00877     for ( ++stmts; stmts.valid(); ++stmts) {
00878 
00879     Statement & peel_st = stmts.current();
00880 
00881     _subst_var_in_stmt(peel_st, index, *range);
00882 
00883     for (Mutator<Assertion> peel_aiter = peel_st.assertions();
00884          peel_aiter.valid();
00885          ++peel_aiter) {
00886 
00887         Assertion & el_assert = peel_aiter.current();
00888 
00889         if (((el_assert.type() == AS_PRIVATEREFS) ||
00890          (el_assert.type() == AS_READONLYREFS)) &&
00891         (el_assert.arg_list_valid())) {
00892         /// ...  list of parenthesized comma exprs
00893         for (Mutator<Expression> el_assert_eiter =
00894              el_assert.arg_list_guarded();
00895              el_assert_eiter.valid();
00896              ++el_assert_eiter) {
00897             
00898             p_assert(el_assert_eiter.current().op() == PAREN_OP,
00899                  "PrivateRefs needs list of parenthesized COMMA_OPs");
00900                 
00901             /// ...  Each is a PAREN_OP
00902             if (el_assert_eiter.current().expr_valid()) {
00903             Expression &e = el_assert_eiter.current().expr_guarded();
00904 
00905             /// ...  The parenthesized expr should be a CommaExpr:
00906 
00907             p_assert(e.op() == COMMA_OP,
00908                  "PrivateRefs needs parenthesized COMMA_OPs");
00909             
00910             const String & asrt_str = e.arg_list()[0].str_data();
00911             /* String asrt_loop_name(asrt_str, 1, asrt_str.len() - 2);
00912                if (asrt_loop_name == loop_label) { */
00913             if (asrt_str == loop_label) {
00914                 el_assert_eiter.del();
00915             }
00916             }
00917             if (el_assert.arg_list_guarded().entries() == 0) {
00918             peel_st.assertions().del(el_assert);
00919             }
00920         }
00921         }
00922     }
00923     }
00924 
00925     Expression *new_limit 
00926         = simplify( sub( limit->clone(), constant(1) ));
00927     
00928     do_stmt.limit( new_limit );
00929 
00930     // Delete the DO/END DO of the 1-iteration loop
00931 
00932     pgm.stmts().del(*new_do);
00933 
00934     delete init;
00935     delete limit;
00936     delete step;
00937 
00938     if (pgm.stmts().member(if_stmt))
00939         simplify_control_flow( pgm, if_stmt );
00940 
00941 }
00942 
00943 void
00944 peel_loop_last(ProgramUnit & pgm, Statement & do_stmt, int count)
00945 {
00946     p_assert(do_stmt.stmt_class() == DO_STMT, "not a DO loop");
00947     p_assert( count > 0, "count must be positive" );
00948 
00949     if (count == 1) {
00950         peel_loop_last( pgm, do_stmt );
00951         return;
00952     }
00953 
00954     /// ...  Precalculate the DO loop if needed.
00955     precalc_loop( pgm, do_stmt );
00956     normalize_loop( pgm, do_stmt );
00957 
00958     List<Statement> *stmt_block;
00959 
00960     /// ...  Get a copy of the DO loop.
00961 
00962     stmt_block = clone_loop (pgm, do_stmt, "PF");
00963 
00964     /// ...  Get a pointer to the new copy of the DO loop header.
00965 
00966     Statement      *new_do = stmt_block->first_ref();
00967 
00968     /// ...  Put them back into the program in front of the original loop.
00969 
00970     pgm.stmts().ins_before(stmt_block, &do_stmt);
00971 
00972     /// ...  Get a copy of the lower bound of the loop.
00973 
00974     Expression     *init = do_stmt.init().clone();
00975     Expression     *limit = do_stmt.limit().clone();
00976 
00977     /// ...  Modify the bounds to insure that the loops do not overlap.
00978 
00979     Expression *new_init  
00980         = simplify( intrinsic_call( _icall_id("MAX", pgm), 
00981                                     comma( add( sub( limit->clone(), 
00982                                                      constant(count) ),
00983                                                 constant(1) ),
00984                                            init->clone() )));
00985     Expression *new_limit 
00986         = simplify( sub( limit->clone(), constant(count) ));
00987 
00988     new_do->limit( new_limit );
00989 
00990     do_stmt.init( new_init );
00991 
00992     delete init;
00993     delete limit;
00994 }
00995 
00996 void
00997 precalc_loop(ProgramUnit & pgm, Statement & do_stmt)
00998 {
00999     p_assert(do_stmt.stmt_class() == DO_STMT, "not a DO loop");
01000 
01001     /// ...  Get a reference to the index variable
01002 
01003     Symbol & index_var = do_stmt.index().symbol();
01004 
01005     /// ...  Get new copies of the DO's init, limit and step expressions.
01006 
01007     Expression *init  = do_stmt.init().clone();
01008     Expression *limit = do_stmt.limit().clone();
01009     Expression *step  = do_stmt.step().clone();
01010 
01011     /// ...  Coerce init, limit and step to the type of the loop index
01012     /// ...  by applying intrinsic functions to the expressions
01013     /// ...  (only if necessary)
01014 
01015     init  = coerce(init, index_var.type().data_type(), pgm);
01016     limit = coerce(limit, index_var.type().data_type(), pgm);
01017     step  = coerce(step, index_var.type().data_type(), pgm);
01018 
01019     /// ...  If the bound expressions could have side effects, they must
01020     /// ...  be precalculated.
01021 
01022     init  = get_precalc(init, pgm, do_stmt, PRECALC_IF_SIDE_EFFECTS, "INIT");
01023     limit = get_precalc(limit, pgm, do_stmt, PRECALC_IF_SIDE_EFFECTS, "LIMIT");
01024     step  = get_precalc(step, pgm, do_stmt, PRECALC_IF_SIDE_EFFECTS, "STEP");
01025 
01026     /// ...  Put them back into the statement.
01027 
01028     do_stmt.init( init );
01029     do_stmt.limit( limit );
01030     do_stmt.step( step );
01031 
01032     RefSet<Symbol> *variant   = loop_variant_vars( pgm, do_stmt );
01033     RefSet<Symbol> *invariant = loop_invariant_vars( pgm, *variant );
01034 
01035     if (! invariant_expression( do_stmt.init(), *invariant )) {
01036         do_stmt.init( get_precalc( do_stmt.init().clone(), pgm, do_stmt,
01037                                    PRECALC_ALWAYS, "INIT" ));
01038     }
01039 
01040     if (! invariant_expression( do_stmt.limit(), *invariant )) {
01041         do_stmt.limit( get_precalc( do_stmt.limit().clone(), pgm, do_stmt,
01042                                     PRECALC_ALWAYS, "LIMIT" ));
01043     }
01044 
01045     if (! invariant_expression( do_stmt.step(), *invariant )) {
01046         do_stmt.step( get_precalc( do_stmt.step().clone(), pgm, do_stmt, 
01047                                    PRECALC_ALWAYS, "STEP" ));
01048     }
01049 
01050     delete variant;
01051     delete invariant;
01052 }
01053 
01054 void
01055 stripmine_horiz_loop(ProgramUnit & pgm, Statement & do_stmt, Expression *strip)
01056 {
01057     p_assert(do_stmt.stmt_class() == DO_STMT, "not a DO loop");
01058 
01059     precalc_loop( pgm, do_stmt );
01060 
01061     if (!is_integer_constant(do_stmt.step()) || do_stmt.step().value() < 0)
01062         normalize_loop( pgm, do_stmt );
01063 
01064     Expression *limit = do_stmt.limit().clone();
01065     Expression *step  = do_stmt.step().clone();
01066 
01067     /// ...  Get a reference to the index variable
01068 
01069     Symbol & index_var = do_stmt.index().symbol();
01070 
01071     /// ...  Get the index variable for the second loop.
01072 
01073     Symbol & new_index_var = pgm.symtab().rename_and_ins( index_var.clone() );
01074 
01075     /// ...  Calculate the new limit.
01076 
01077     Expression * new_limit 
01078         = simplify( intrinsic_call( _icall_id("MIN", pgm), 
01079                                     comma( sub( add( id(new_index_var), 
01080                                                      mul( strip->clone(),
01081                                                           step->clone() )),
01082                                                 constant(1)),
01083                                            limit )));
01084 
01085     /// ...  Build a new DO loop to be nested inside of the current loop.
01086 
01087     /// ...     Statement & new_do_stmt =
01088     pgm.stmts().ins_DO_after( id(index_var), 
01089                   id(new_index_var), new_limit, step->clone(),
01090                   &do_stmt, 
01091                   do_stmt.follow_ref()->prev_ref() );
01092 
01093     do_stmt.index( id(new_index_var) );
01094     do_stmt.step( simplify( mul( step, strip )));
01095 }
01096 
01097 void
01098 stripmine_vert_loop(ProgramUnit & pgm, Statement & do_stmt, Expression *strip)
01099 {
01100     p_assert(do_stmt.stmt_class() == DO_STMT, "not a DO loop");
01101 
01102     precalc_loop( pgm, do_stmt );
01103 
01104     if (!is_integer_constant(do_stmt.step()) || do_stmt.step().value() < 0)
01105         normalize_loop( pgm, do_stmt );
01106 
01107     Expression *init  = do_stmt.init().clone();
01108     Expression *limit = do_stmt.limit().clone();
01109     Expression *step  = do_stmt.step().clone();
01110 
01111     /// ...  Get a reference to the index variable
01112 
01113     Symbol & index_var = do_stmt.index().symbol();
01114 
01115     /// ...  Get the index variable for the second loop.
01116 
01117     Symbol & new_index_var = pgm.symtab().rename_and_ins( index_var.clone() );
01118 
01119     /// ...  Calculate the inner strip size.
01120 
01121     Expression     *range = _loop_range( do_stmt );
01122 
01123     Expression *inner_strip 
01124         = simplify( intrinsic_call( _icall_id( "MAX", pgm ),
01125                         comma( constant(1),
01126                                div( range->clone(),
01127                                     strip->clone() ))));
01128 
01129     /// ...  Compute the initial value and limit for the new DO loop.
01130 
01131     Expression * new_init = simplify( add( init->clone(),
01132                                            mul( id(new_index_var),
01133                                                 inner_strip->clone() )));
01134     Expression * new_limit 
01135         = simplify( intrinsic_call( _icall_id("MIN", pgm), 
01136                         comma( limit->clone(),
01137                                sub( add( new_init->clone(),
01138                                          inner_strip->clone() ),
01139                                     constant(1) ))));
01140 
01141     /// ...  Build a new DO loop to be nested inside of the current loop.
01142 
01143     /// ...     Statement & new_do_stmt =
01144       pgm.stmts().ins_DO_after( id(index_var), 
01145                 new_init, new_limit, step,
01146                 &do_stmt, 
01147                 do_stmt.follow_ref()->prev_ref() );
01148 
01149     do_stmt.index( id(new_index_var) );
01150 
01151     do_stmt.init( constant(0) );
01152     do_stmt.limit( simplify( sub( strip, constant(1) ) ));
01153     do_stmt.step( constant(1) );
01154 }
01155 
01156 void
01157 unroll_loop(ProgramUnit & pgm, Statement & do_stmt, int count)
01158 {
01159     p_assert(do_stmt.stmt_class() == DO_STMT, "not a DO loop");
01160 
01161     /// ...  Unroll the loop, maybe we need to normalize first.
01162 
01163     if (!is_integer_constant(do_stmt.step()) || do_stmt.step().value() != 1)
01164         return;
01165 
01166     Statement *first = do_stmt.next_ref();
01167     Statement *last  = do_stmt.follow_ref()->prev_ref();
01168 
01169     /// ...  If there are no statements in the loop body then this is a NO-OP.
01170 
01171     if (&do_stmt == last)
01172         return;
01173 
01174     precalc_loop( pgm, do_stmt );
01175 
01176     /// ...  Get a copy of the old step expression.
01177 
01178     Expression *step = do_stmt.step().clone();
01179 
01180     /// ...  Get a reference to the index variable
01181     Symbol & index_var = do_stmt.index().symbol();
01182 
01183     for (int i = 1; i < count; ++i) {
01184         /// ...  Get a copy of the DO loop body.
01185         List<Statement> *stmt_block = clone_loop (pgm, do_stmt, "UR");
01186     cout<<"The loop body is"<<endl; stmt_block->print(cout); cout<<endl;
01187 
01188         Expression *replacement 
01189             = simplify( add( id(index_var), 
01190                              mul( step->clone(), constant(i) )));
01191 
01192         for (Iterator<Statement> stmts = *stmt_block; stmts.valid(); ++stmts)
01193         _subst_var_in_stmt(stmts.current(), index_var, *replacement);
01194 
01195         delete replacement;
01196 
01197         pgm.stmts().ins_before( stmt_block, do_stmt.follow_ref() );
01198     }
01199 
01200     do_stmt.step( simplify( mul( step, constant(count) ) ));
01201 }
01202 
01203 void
01204 preroll_loop(ProgramUnit & pgm, Statement & do_stmt, int count)
01205 {
01206     p_assert(do_stmt.stmt_class() == DO_STMT, "not a DO loop");
01207     p_assert( count > 0, "count must be positive" );
01208 
01209     /// ...  Precalculate the DO loop if needed.
01210 
01211     precalc_loop( pgm, do_stmt );
01212 
01213     if (!is_integer_constant(do_stmt.step()) || do_stmt.step().value() < 0)
01214         normalize_loop( pgm, do_stmt );
01215 
01216     /// ...  Get a copy of the lower bound of the loop.
01217 
01218     Expression     *init = do_stmt.init().clone();
01219     Expression     *limit = do_stmt.limit().clone();
01220     Expression     *step  = do_stmt.step().clone();
01221 
01222     Expression     *range = _loop_range( do_stmt );
01223 
01224     /// ...  Modify the bounds to insure that the loops do not overlap.
01225 
01226     Expression     *new_limit 
01227         = simplify( sub( add( init->clone(),
01228                              intrinsic_call( _icall_id( "MOD", pgm ),
01229                                  comma( range->clone(),
01230                                         constant(count) ))),
01231                          constant(1) ));
01232 
01233     Expression     *new_init  
01234         = simplify( add( step->clone(), new_limit->clone()) );
01235 
01236     /// ...  Get a copy of the DO loop.
01237 
01238     List<Statement> *stmt_block;
01239 
01240     stmt_block = clone_loop (pgm, do_stmt, "PR");
01241 
01242     /// ...  Get a pointer to the new copy of the DO loop header.
01243 
01244     Statement *new_do = stmt_block->first_ref();
01245 
01246     /// ...  Put them back into the program in front of the original loop.
01247 
01248     pgm.stmts().ins_before(stmt_block, &do_stmt);
01249 
01250     new_do->limit( new_limit );
01251     do_stmt.init( new_init );
01252 
01253     delete init;
01254     delete limit;
01255     delete step;
01256 
01257     Expression     *new_range = _loop_range( *new_do );
01258 
01259     if (is_integer_constant(*new_range) && 
01260         new_range->value() > 0 && new_range->value() < 8)
01261         unroll_loop( pgm, *new_do, new_range->value() );
01262 
01263     if (pgm.stmts().member(*new_do))
01264         eliminate_loop( pgm, *new_do );
01265 
01266     if (pgm.stmts().member(do_stmt))
01267         eliminate_loop( pgm, do_stmt );
01268 
01269     delete new_range;
01270 }
01271 
01272 void
01273 reverse_loop(ProgramUnit & pgm, Statement & do_stmt)
01274 {
01275     p_assert(do_stmt.stmt_class() == DO_STMT, "not a DO loop");
01276 
01277     /// ...  Brute force approach, make sure we are stride 1, and precalc'd
01278 
01279     normalize_loop( pgm, do_stmt );
01280 
01281     /// ...  Get new copies of the DO's init, limit and step expressions,
01282 
01283     Expression     *init  = do_stmt.init().clone();
01284     Expression     *limit = do_stmt.limit().clone();
01285 
01286     do_stmt.init( limit );
01287     do_stmt.limit( init );
01288 
01289     do_stmt.step( simplify( unary_minus( do_stmt.step().clone())));
01290 }
01291 
01292 /// This routine copies a whole loop nest and returns it as a List<Statement>
01293 /// to the caller.  It adds _<suffix>1 to the original loop nest's loop labels
01294 /// and _<suffix>2 to the copy's loop labels.
01295 
01296 List<Statement> *
01297 clone_loop(ProgramUnit & pgm, Statement & do_stmt, const String & suffix)
01298 {
01299 
01300     p_assert(do_stmt.stmt_class() == DO_STMT, "not a DO loop");
01301 
01302     /// ...  Build suffix strings for later use
01303 
01304     const char * suffix_ptr(suffix);
01305 
01306     int suffix_len = strlen(suffix_ptr) + 3;
01307     char * suffix_buf = new char[suffix_len];
01308     p_assert(suffix_buf, "Out of space in clone_loop");
01309     suffix_buf[0] = '_';
01310     /// ...  Copy over suffix
01311     strcpy(suffix_buf + 1, suffix_ptr);
01312     /// ...  Null out last character of buffer
01313     --suffix_len;
01314     suffix_buf[suffix_len]  = '\0';
01315     /// ...  Build suffix1 in buffer
01316     --suffix_len;
01317     suffix_buf[suffix_len] = '1';
01318     String suffix1(suffix_buf);
01319     /// ...  Build suffix2 in buffer
01320     suffix_buf[suffix_len] = '2';
01321     String suffix2(suffix_buf);
01322     delete [] suffix_buf;
01323 
01324     List<Statement> *stmt_block;
01325     KeyDatabase<String,StringElem>  label_map;
01326     KeyDatabase<String,StringElem>  new_label_map;
01327 
01328     stmt_block = pgm.stmts().copy(do_stmt, *(do_stmt.follow_ref()));
01329 
01330     Iterator<Statement> stmts = pgm.stmts().iterate_loop_body(&do_stmt);
01331     for ( ;
01332     stmts.valid();
01333      ++stmts) {
01334     Statement & stmt = stmts.current();
01335 
01336     if (stmt.stmt_class() == DO_STMT) {
01337 
01338         /// ...   Find the first looplabel assertion (then later delete all that may exist)
01339 
01340         String* orig_name = 
01341           new String(stmt.get_loop_name());
01342         StringElem *new_name = new StringElem( *orig_name);
01343         *new_name += suffix1;
01344         label_map.ins(orig_name, new_name);
01345 
01346         for (Iterator<Assertion> a_iter = stmt.assertions();
01347          a_iter.valid();
01348          ++a_iter) {
01349         Assertion & assert = a_iter.current();
01350         if (assert.type() == AS_LOOPLABEL) {
01351             stmt.assertions().del( assert );
01352         }
01353         /// ...  Replace the old loop name with new loop names
01354 
01355         if ((assert.type() == AS_PRIVATEREFS) ||
01356             (assert.type() == AS_READONLYREFS)) {
01357             if (assert.arg_list_valid()) {
01358             Mutator<Expression> item_iter = assert.arg_list_guarded();
01359             for ( ; item_iter.valid(); ++item_iter) {
01360                 Expression & asrt_expr = item_iter.current();
01361                 String & asrt_str = asrt_expr.expr_guarded().arg_list()[0].str_data();
01362                 /* String label(asrt_str, 1, asrt_str.len()-2);
01363                    String * flabel = label_map.find_ref(label); */
01364                 String * flabel = label_map.find_ref(asrt_str);
01365                 if (flabel) {
01366                   /* String xlabel = "'" + *flabel + "'";
01367                 StringConstExpr * new_label  = new StringConstExpr ((const char *) xlabel); */
01368                     StringConstExpr * new_label  = new StringConstExpr ((const char *) *flabel);
01369                 asrt_expr.expr_guarded().arg_list().modify(0,new_label);
01370                 }
01371             }
01372             }
01373         }
01374         }
01375         /// ...  Make new loop name for this DO: original + <suffix>1
01376 
01377         AssertLoopLabel *as = new AssertLoopLabel;
01378         as->string_arg_list_guarded().ins_last(new StringElem(*new_name));
01379         stmt.assertions().ins_last(as);
01380     }
01381     }
01382 
01383     /// ...  Now, append _<suffix>2 to the labels of the loops in the new nest
01384 
01385     Iterator<Statement> newstmts = stmt_block;
01386     for ( ;
01387     newstmts.valid();
01388      ++newstmts) {
01389     Statement & stmt = newstmts.current();
01390 
01391     if (stmt.stmt_class() == DO_STMT) {
01392 
01393         /// ...   Find the first looplabel assertion (then later delete them all)
01394 
01395         String * orig_name = 
01396           new String(stmt.get_loop_name());
01397         StringElem *new_name = new StringElem( *orig_name);
01398         *new_name += suffix2;
01399         new_label_map.ins(orig_name, new_name);
01400 
01401         for (Iterator<Assertion> a_iter = stmt.assertions();
01402          a_iter.valid();
01403          ++a_iter) {
01404         Assertion & assert = a_iter.current();
01405         if (assert.type() == AS_LOOPLABEL) {
01406             stmt.assertions().del( assert );
01407         }
01408         /// ...  Replace the old loop name with new loop names
01409 
01410         if ((assert.type() == AS_PRIVATEREFS) ||
01411             (assert.type() == AS_READONLYREFS)) {
01412             if (assert.arg_list_valid()) {
01413             Mutator<Expression> item_iter = assert.arg_list_guarded();
01414             for ( ; item_iter.valid(); ++item_iter) {
01415                 Expression & asrt_expr = item_iter.current();
01416                 String & asrt_str = asrt_expr.expr_guarded().arg_list()[0].str_data();
01417                 /* String label(asrt_str, 1, asrt_str.len()-2);
01418                    String * flabel = new_label_map.find_ref(label); */
01419                 String * flabel = new_label_map.find_ref(asrt_str);
01420                 if (flabel) {
01421                   /* String xlabel = "'" + *flabel + "'";
01422                 StringConstExpr * new_label  = new StringConstExpr ((const char *) xlabel); */
01423                     StringConstExpr * new_label  = new StringConstExpr ((const char *) *flabel);
01424                 asrt_expr.expr_guarded().arg_list().modify(0,new_label);
01425                 }
01426             }
01427             }
01428         }
01429         }
01430         /// ...  Make new loop name for this DO: original + <suffix>2
01431 
01432         AssertLoopLabel *as = new AssertLoopLabel;
01433         StringElem * as_elem = new StringElem(*orig_name);
01434         *as_elem += suffix2;
01435         as->string_arg_list_guarded().ins_last(as_elem);
01436         stmt.assertions().ins_last(as);
01437     }
01438     }
01439     return stmt_block;
01440 }
01441 
01442 List<Statement> *
01443 clone_loop_body(ProgramUnit & pgm, Statement & do_stmt, const String & suffix)
01444 {
01445 
01446     p_assert(do_stmt.stmt_class() == DO_STMT, "not a DO loop");
01447 
01448     /// ...  Build suffix strings for later use
01449 
01450     const char * suffix_ptr(suffix);
01451 
01452     int suffix_len = strlen(suffix_ptr) + 3;
01453     char * suffix_buf = new char[suffix_len];
01454     p_assert(suffix_buf, "Out of space in clone_loop");
01455     suffix_buf[0] = '_';
01456     /// ...  Copy over suffix
01457     strcpy(suffix_buf + 1, suffix_ptr);
01458     /// ...  Null out last character of buffer
01459     --suffix_len;
01460     suffix_buf[suffix_len]  = '\0';
01461     /// ...  Build suffix1 in buffer
01462     --suffix_len;
01463     suffix_buf[suffix_len] = '1';
01464     String suffix1(suffix_buf);
01465     /// ...  Build suffix2 in buffer
01466     suffix_buf[suffix_len] = '2';
01467     String suffix2(suffix_buf);
01468     delete [] suffix_buf;
01469 
01470     List<Statement> *stmt_block;
01471     KeyDatabase<String,StringElem>  label_map;
01472     KeyDatabase<String,StringElem>  new_label_map;
01473 
01474     stmt_block = pgm.stmts().copy(*(do_stmt.next_ref()), 
01475                   *(do_stmt.follow_ref()->prev_ref()));
01476 
01477     Iterator<Statement> stmts = pgm.stmts().iterate_loop_body(&do_stmt);
01478     for ( ++stmts;      /// ...  Skip the DO stmt
01479     stmts.valid();
01480      ++stmts) {
01481     Statement & stmt = stmts.current();
01482 
01483     if (stmt.stmt_class() == DO_STMT) {
01484 
01485         /// ...   Find the first looplabel assertion (then later delete all that may exist)
01486 
01487         String* orig_name = 
01488           new String(stmt.get_loop_name());
01489         StringElem *new_name = new StringElem( *orig_name);
01490         *new_name += suffix1;
01491         label_map.ins(orig_name, new_name);
01492 
01493         for (Iterator<Assertion> a_iter = stmt.assertions();
01494          a_iter.valid();
01495          ++a_iter) {
01496         Assertion & assert = a_iter.current();
01497         if (assert.type() == AS_LOOPLABEL) {
01498             stmt.assertions().del( assert );
01499         }
01500         /// ...  Replace the old loop name with new loop names
01501 
01502         if ((assert.type() == AS_PRIVATEREFS) ||
01503             (assert.type() == AS_READONLYREFS)) {
01504             if (assert.arg_list_valid()) {
01505             Mutator<Expression> item_iter = assert.arg_list_guarded();
01506             for ( ; item_iter.valid(); ++item_iter) {
01507                 Expression & asrt_expr = item_iter.current();
01508                 String & asrt_str = asrt_expr.expr_guarded().arg_list()[0].str_data();
01509                 /* String label(asrt_str, 1, asrt_str.len()-2);
01510                    String * flabel = label_map.find_ref(label); */
01511                 String * flabel = label_map.find_ref(asrt_str);
01512                 if (flabel) {
01513                   /* String xlabel = "'" + *flabel + "'";
01514                 StringConstExpr * new_label  = new StringConstExpr ((const char *) xlabel); */
01515                     StringConstExpr * new_label  = new StringConstExpr ((const char *) *flabel);
01516                 asrt_expr.expr_guarded().arg_list().modify(0,new_label);
01517                 }
01518             }
01519             }
01520         }
01521         }
01522         /// ...  Make new loop name for this DO: original + <suffix>1
01523 
01524         AssertLoopLabel *as = new AssertLoopLabel;
01525         as->string_arg_list_guarded().ins_last(new StringElem(*new_name));
01526         stmt.assertions().ins_last(as);
01527     }
01528     }
01529 
01530     /// ...  Now, append _<suffix>2 to the labels of the loops in the new nest
01531 
01532     Iterator<Statement> newstmts = stmt_block;
01533     for ( ;
01534     newstmts.valid();
01535      ++newstmts) {
01536     Statement & stmt = newstmts.current();
01537 
01538     if (stmt.stmt_class() == DO_STMT) {
01539 
01540         /// ...   Find the first looplabel assertion (then later delete them all)
01541 
01542         String * orig_name = 
01543           new String(stmt.get_loop_name());
01544         StringElem *new_name = new StringElem( *orig_name);
01545         *new_name += suffix2;
01546         new_label_map.ins(orig_name, new_name);
01547 
01548         for (Iterator<Assertion> a_iter = stmt.assertions();
01549          a_iter.valid();
01550          ++a_iter) {
01551         Assertion & assert = a_iter.current();
01552         if (assert.type() == AS_LOOPLABEL) {
01553             stmt.assertions().del( assert );
01554         }
01555         /// ...  Replace the old loop name with new loop names
01556 
01557         if ((assert.type() == AS_PRIVATEREFS) ||
01558             (assert.type() == AS_READONLYREFS)) {
01559             if (assert.arg_list_valid()) {
01560             Mutator<Expression> item_iter = assert.arg_list_guarded();
01561             for ( ; item_iter.valid(); ++item_iter) {
01562                 Expression & asrt_expr = item_iter.current();
01563                 String & asrt_str = asrt_expr.expr_guarded().arg_list()[0].str_data();
01564                 /* String label(asrt_str, 1, asrt_str.len()-2);
01565                    String * flabel = new_label_map.find_ref(label); */
01566                 String * flabel = new_label_map.find_ref(asrt_str);
01567                 if (flabel) {
01568                   /* String xlabel = "'" + *flabel + "'";
01569                 StringConstExpr * new_label  = new StringConstExpr ((const char *) xlabel); */
01570                     StringConstExpr * new_label  = new StringConstExpr ((const char *) *flabel);
01571                 asrt_expr.expr_guarded().arg_list().modify(0,new_label);
01572                 }
01573             }
01574             }
01575         }
01576         }
01577         /// ...  Make new loop name for this DO: original + <suffix>2
01578 
01579         AssertLoopLabel *as = new AssertLoopLabel;
01580         StringElem * as_elem = new StringElem(*orig_name);
01581         *as_elem += suffix2;
01582         as->string_arg_list_guarded().ins_last(as_elem);
01583         stmt.assertions().ins_last(as);
01584     }
01585     }
01586     return stmt_block;
01587 }
01588 
01589 /// Begin OpenMP Modification
01590 Boolean is_perfect_nest(Statement * do_stmt) {
01591     Statement *start,*current;
01592     Statement *stop,*end;
01593 
01594     start = current = do_stmt;
01595     stop = end = do_stmt->follow_ref();
01596 
01597     while(  (current->stmt_class() == DO_STMT)
01598           &&(current->follow_ref() == end)) {
01599         current = current->next_ref();
01600         end = end->prev_ref();
01601         while (end->stmt_class() == LABEL_STMT)
01602             end = end->prev_ref();
01603     }
01604 
01605     while( (current != stop) && (end != start)) {
01606         if (current->stmt_class() == DO_STMT)
01607             return False;
01608         if (end->stmt_class() == ENDDO_STMT)
01609             return False;
01610         current = current->next_ref();
01611         end = end->prev_ref();
01612     }
01613     return True;
01614 }
01615 /// End OpenMP Modification
 © 1995-2005 University of Illinois, Urbana-Champaign. All rights reserved.  Fri Mar 25 23:05:58 2005