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
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
00065
00066
00067 if ((ass_iter.current().type() == AS_RANGEWRITTEN) &&
00068 (aexpr_iter.current().op() == ID_OP)) {
00069
00070
00071
00072
00073
00074
00075
00076
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
00107
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
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
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
00153 pgm.stmts().del( s );
00154 }
00155 else if (expr->str_data() == ".FALSE.") {
00156
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
00180
00181 Symbol & outer_index_var = outer_do_stmt.index().symbol();
00182 Symbol & inner_index_var = inner_do_stmt.index().symbol();
00183
00184
00185
00186 Symbol & new_index_var
00187 = pgm.symtab().rename_and_ins( outer_index_var.clone() );
00188
00189
00190
00191 Expression * outer_init = outer_do_stmt.init().clone();
00192
00193
00194
00195 Expression * inner_init = inner_do_stmt.init().clone();
00196
00197
00198
00199
00200
00201 Expression *outer_range = _loop_range( outer_do_stmt );
00202 Expression *inner_range = _loop_range( inner_do_stmt );
00203
00204
00205
00206 pgm.stmts().del( inner_do_stmt );
00207
00208
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
00231
00232 Expression * new_limit = simplify( sub( mul( outer_range, inner_range ),
00233 constant(1) ));
00234
00235
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
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
00260
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
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
00283
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
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
00311 static void
00312 _loop_index_last_val(ProgramUnit &pgm, Symbol &index_var,
00313 Statement &do_stmt, Statement &after_me) {
00314
00315
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
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
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
00369
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
00376
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
00386
00387 RefSet<Statement> visited;
00388
00389
00390 RefSet<Statement> worklist;
00391
00392
00393
00394 worklist.ins(stmt);
00395
00396
00397 while (worklist.entries() != 0) {
00398
00399
00400 Statement &scan_me = worklist.grab();
00401
00402
00403
00404 if (!visited.member(scan_me)) {
00405
00406
00407 visited.ins(scan_me);
00408
00409
00410
00411 Boolean follow_flow = True;
00412
00413
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
00421 return True;
00422 }
00423 }
00424
00425
00426 switch (scan_me.stmt_class()) {
00427
00428
00429 default:
00430 break;
00431
00432
00433 case DO_STMT:
00434 if (scan_me.index().base_variable_ref() == &var) {
00435
00436
00437 follow_flow = False;
00438 }
00439 break;
00440
00441
00442 case ASSIGNMENT_STMT:
00443 if (scan_me.lhs().base_variable_ref() == &var) {
00444
00445
00446 follow_flow = False;
00447 }
00448 break;
00449 }
00450
00451
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 }
00464 }
00465
00466
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
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
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
00498
00499 Symbol & index_var = do_stmt.index().symbol();
00500
00501
00502
00503 Expression *replacement
00504 = simplify( add( mul( sub( id(index_var),
00505 new_init->clone() ),
00506 step->clone() ),
00507 init->clone() ) );
00508
00509
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
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
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544 Iterator<Statement> stmts = pgm.stmts().iterate_loop_body(&do_stmt);
00545
00546
00547
00548 for ( ++stmts; stmts.valid(); ++stmts)
00549 _subst_var_in_stmt(stmts.current(), index_var, *replacement);
00550
00551
00552
00553
00554 _subst_var_in_assert(do_stmt, index_var, *replacement);
00555
00556
00557
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
00566 Boolean escaping_gotos = _any_escaping_gotos(pgm,do_stmt);
00567
00568
00569
00570
00571
00572
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
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
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
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
00615 delete init;
00616 delete limit;
00617 delete step;
00618
00619
00620 delete replacement;
00621 }
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
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
00642
00643
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
00651 Symbol & index_var = do_stmt.index().symbol();
00652
00653 Statement *s;
00654 Expression *lhs, *rhs;
00655
00656
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
00669 pgm.stmts().ins_after( s, do_stmt.follow_ref() );
00670
00671 if (zero_trip) {
00672
00673
00674 pgm.stmts().del( do_stmt, *do_stmt.follow_ref() );
00675 }
00676 else {
00677 Expression *replacement = do_stmt.init().clone();
00678
00679
00680
00681 Iterator<Statement> stmts = pgm.stmts().iterate_loop_body(&do_stmt);
00682
00683
00684
00685 for ( ++stmts; stmts.valid(); ++stmts)
00686 _subst_var_in_stmt(stmts.current(), index_var, *replacement);
00687
00688
00689
00690 delete replacement;
00691
00692
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
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
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
00726
00727 Expression *new_init
00728 = simplify( add( step->clone(), init->clone()) );
00729
00730 Expression *new_limit = init->clone();
00731
00732
00733
00734 List<Statement> *stmt_block;
00735
00736 stmt_block = clone_loop(pgm, do_stmt, "PF");
00737
00738
00739
00740 Statement *new_do = stmt_block->first_ref();
00741
00742
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
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
00777
00778 if (count == 1) {
00779 peel_loop_first( pgm, do_stmt );
00780 return;
00781 }
00782
00783 List<Statement> *stmt_block;
00784
00785
00786
00787 stmt_block = clone_loop (pgm, do_stmt, "PF");
00788
00789
00790
00791 Statement *new_do = stmt_block->first_ref();
00792
00793
00794
00795 pgm.stmts().ins_before(stmt_block, &do_stmt);
00796
00797
00798
00799 Expression *init = do_stmt.init().clone();
00800 Expression *limit = do_stmt.limit().clone();
00801 Expression *step = do_stmt.step().clone();
00802
00803
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
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
00831 precalc_loop( pgm, do_stmt );
00832 normalize_loop( pgm, do_stmt );
00833
00834
00835
00836 List<Statement> *stmt_block;
00837 stmt_block = clone_loop (pgm, do_stmt, "PL");
00838
00839
00840
00841 Statement *new_do = stmt_block->first_ref();
00842
00843
00844
00845 Statement *enddo_stmt = do_stmt.follow_ref();
00846
00847 pgm.stmts().ins_after(stmt_block, enddo_stmt);
00848
00849
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
00865
00866 String loop_label = new_do->get_loop_name();
00867
00868
00869
00870 Iterator<Statement> stmts = pgm.stmts().iterate_loop_body(new_do);
00871
00872
00873
00874
00875
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
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
00902 if (el_assert_eiter.current().expr_valid()) {
00903 Expression &e = el_assert_eiter.current().expr_guarded();
00904
00905
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
00912
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
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
00955 precalc_loop( pgm, do_stmt );
00956 normalize_loop( pgm, do_stmt );
00957
00958 List<Statement> *stmt_block;
00959
00960
00961
00962 stmt_block = clone_loop (pgm, do_stmt, "PF");
00963
00964
00965
00966 Statement *new_do = stmt_block->first_ref();
00967
00968
00969
00970 pgm.stmts().ins_before(stmt_block, &do_stmt);
00971
00972
00973
00974 Expression *init = do_stmt.init().clone();
00975 Expression *limit = do_stmt.limit().clone();
00976
00977
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
01002
01003 Symbol & index_var = do_stmt.index().symbol();
01004
01005
01006
01007 Expression *init = do_stmt.init().clone();
01008 Expression *limit = do_stmt.limit().clone();
01009 Expression *step = do_stmt.step().clone();
01010
01011
01012
01013
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
01020
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
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
01068
01069 Symbol & index_var = do_stmt.index().symbol();
01070
01071
01072
01073 Symbol & new_index_var = pgm.symtab().rename_and_ins( index_var.clone() );
01074
01075
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
01086
01087
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
01112
01113 Symbol & index_var = do_stmt.index().symbol();
01114
01115
01116
01117 Symbol & new_index_var = pgm.symtab().rename_and_ins( index_var.clone() );
01118
01119
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
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
01142
01143
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
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
01170
01171 if (&do_stmt == last)
01172 return;
01173
01174 precalc_loop( pgm, do_stmt );
01175
01176
01177
01178 Expression *step = do_stmt.step().clone();
01179
01180
01181 Symbol & index_var = do_stmt.index().symbol();
01182
01183 for (int i = 1; i < count; ++i) {
01184
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
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
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
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
01237
01238 List<Statement> *stmt_block;
01239
01240 stmt_block = clone_loop (pgm, do_stmt, "PR");
01241
01242
01243
01244 Statement *new_do = stmt_block->first_ref();
01245
01246
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
01278
01279 normalize_loop( pgm, do_stmt );
01280
01281
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
01293
01294
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
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
01311 strcpy(suffix_buf + 1, suffix_ptr);
01312
01313 --suffix_len;
01314 suffix_buf[suffix_len] = '\0';
01315
01316 --suffix_len;
01317 suffix_buf[suffix_len] = '1';
01318 String suffix1(suffix_buf);
01319
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
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
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
01363
01364 String * flabel = label_map.find_ref(asrt_str);
01365 if (flabel) {
01366
01367
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
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
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
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
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
01418
01419 String * flabel = new_label_map.find_ref(asrt_str);
01420 if (flabel) {
01421
01422
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
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
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
01457 strcpy(suffix_buf + 1, suffix_ptr);
01458
01459 --suffix_len;
01460 suffix_buf[suffix_len] = '\0';
01461
01462 --suffix_len;
01463 suffix_buf[suffix_len] = '1';
01464 String suffix1(suffix_buf);
01465
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;
01479 stmts.valid();
01480 ++stmts) {
01481 Statement & stmt = stmts.current();
01482
01483 if (stmt.stmt_class() == DO_STMT) {
01484
01485
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
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
01510
01511 String * flabel = label_map.find_ref(asrt_str);
01512 if (flabel) {
01513
01514
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
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
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
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
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
01565
01566 String * flabel = new_label_map.find_ref(asrt_str);
01567 if (flabel) {
01568
01569
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
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
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