00001
00002
00003
00004
00005 #include "../Program.h"
00006 #include "../ProgramUnit.h"
00007 #include "../Statement/Statement.h"
00008 #include "../Symbol/Symbol.h"
00009 #include "../Symtab.h"
00010 #include "../Expression/Expression.h"
00011 #include "../Directive/Assertion.h"
00012 #include "../utilities/switches_util.h"
00013 #include "../utilities/invariant_util.h"
00014 #include "../utilities/expression_util.h"
00015 #include "../Dictionary.h"
00016 #include "../utilities/equivalence_util.h"
00017 #include "../Array.h"
00018 #include "../IntSet.h"
00019 #include "../Timer.h"
00020 #include "../Traverser.h"
00021 #include "../p-assert.h"
00022
00023 #include "AIRangeDict.h"
00024 #include "PropRangeWS.h"
00025 #include "PropRangeEdge.h"
00026 #include "RangeExpr.h"
00027 #include "range_util.h"
00028 #include "range_dict_util.h"
00029
00030
00031
00032 #define MAX_SELECTIVE_WIDENING 6
00033
00034
00035
00036
00037
00038
00039
00040 static unsigned int _pass_tag;
00041
00042 static int _debug_level = 0;
00043
00044 static int _refine_ranges = -1;
00045
00046
00047
00048 template class TypedBaseMap<String,StmtRanges>;
00049 template class ProtoDatabase<String,StmtRanges>;
00050 template class Database<String,StmtRanges>;
00051 template ostream & operator << (ostream &,
00052 const Database<String,StmtRanges> &);
00053 template class KeyIterator<String,StmtRanges>;
00054
00055
00056
00057
00058
00059
00060
00061 static void
00062 _init_workspaces(StmtList &stmts)
00063 {
00064 Iterator<Statement> iter = stmts.iterator();
00065
00066 for ( ; iter.valid(); ++iter) {
00067 PropRangeWS *my_ws = new PropRangeWS(_pass_tag, iter.current());
00068 iter.current().work_stack().push(my_ws);
00069 }
00070 }
00071
00072
00073
00074
00075
00076 static PropRangeWS &
00077 _get_workspace(const Statement &stmt)
00078 {
00079 WorkSpace *ws = stmt.work_stack().top_ref(_pass_tag);
00080
00081 p_assert(ws, "Statement doesn't have a RangeWS.");
00082
00083 return * (PropRangeWS *) ws;
00084 }
00085
00086
00087
00088
00089
00090 static void
00091 _dump_workspaces(ostream &o, const StmtList &stmts)
00092 {
00093 Iterator<Statement> iter = stmts.iterator();
00094
00095 for ( ; iter.valid(); ++iter) {
00096 iter.current().structures_OK();
00097 o << iter.current().tag() << ": ";
00098 int zero = 0;
00099 iter.current().fortran_write(o, zero);
00100 o << "\n ";
00101 _get_workspace(iter.current()).print(o);
00102 o << endl;
00103 }
00104 }
00105
00106
00107
00108
00109
00110
00111
00112 static void
00113 _collect_stats(const StmtList &stmts, float &avg_visits, float &avg_cd_entries)
00114 {
00115 int num_visits = 0;
00116 int num_cd_entries = 0;
00117 int weighted_stmt_entries = 0;
00118
00119 Iterator<Statement> iter = stmts.iterator();
00120
00121 for ( ; iter.valid(); ++iter) {
00122 PropRangeWS &ws = _get_workspace(iter.current());
00123 num_visits += ws.num_visits();
00124 if (ws.ranges_ref())
00125 num_cd_entries += ws.num_visits() * ws.ranges_ref()->entries();
00126 weighted_stmt_entries += ws.num_visits();
00127 }
00128
00129 avg_visits = (float) num_visits / (float) stmts.entries();
00130 avg_cd_entries = (float) num_cd_entries / (float) weighted_stmt_entries;
00131 }
00132
00133
00134
00135
00136
00137
00138 static void
00139 _make_nonlocals_modified_at_calls(ProgramUnit &pgm)
00140 {
00141
00142
00143 RefSet<Symbol> non_local_set;
00144 DictionaryIter<Symbol> sym_iter = pgm.symtab().iterator();
00145
00146 for ( ; sym_iter.valid(); ++sym_iter) {
00147 Symbol &symbol = sym_iter.current();
00148
00149 if (symbol.sym_class() == VARIABLE_CLASS
00150 && (symbol.formal() == IS_FORMAL || symbol.common_ref())) {
00151
00152 if (symbol.type().data_type() == INTEGER_TYPE)
00153 non_local_set.ins(symbol);
00154
00155
00156
00157 RefSet<Symbol> *aliases = equiv_aliases(symbol);
00158
00159 if (aliases) {
00160 Iterator<Symbol> alias_iter = *aliases;
00161
00162 for ( ; alias_iter.valid(); ++alias_iter) {
00163 Symbol &alias_symbol = alias_iter.current();
00164
00165 if (alias_symbol.type().data_type() == INTEGER_TYPE)
00166 non_local_set.ins(alias_symbol);
00167 }
00168
00169 delete aliases;
00170 }
00171 }
00172 }
00173
00174
00175
00176
00177 Iterator<Statement> stmt_iter = pgm.stmts().iterator();
00178
00179 for ( ; stmt_iter.valid(); ++stmt_iter) {
00180 Statement &stmt = stmt_iter.current();
00181
00182 if (stmt.stmt_class() == CALL_STMT || contains_func_call(stmt)) {
00183 RefSet<Symbol> &mod_set = _get_workspace(stmt).mod_set();
00184 RefSet<Symbol> *maymods = stmt_maymods(stmt);
00185
00186 if (maymods) {
00187 Iterator<Expression> act_iter = stmt.act_refs();
00188
00189 for ( ; act_iter.valid(); ++act_iter) {
00190 Symbol *var_ref = act_iter.current().base_variable_ref();
00191
00192 if (var_ref)
00193 mod_set.del(*var_ref);
00194 }
00195
00196 if (stmt.stmt_class() == ASSIGNMENT_STMT) {
00197 Symbol *var_ref = stmt.lhs().base_variable_ref();
00198
00199 if (var_ref)
00200 mod_set.ins(*var_ref);
00201 }
00202
00203 Iterator<Symbol> nl_iter = *maymods;
00204
00205 for ( ; nl_iter.valid(); ++nl_iter)
00206 mod_set.ins(nl_iter.current());
00207
00208 delete maymods;
00209 }
00210 else {
00211 Iterator<Symbol> nl_iter = non_local_set;
00212
00213 for ( ; nl_iter.valid(); ++nl_iter)
00214 mod_set.ins(nl_iter.current());
00215 }
00216 }
00217 }
00218 }
00219
00220
00221
00222
00223
00224 static void
00225 _add_flow_edges(StmtList &stmts)
00226 {
00227 Iterator<Statement> stmt_iter = stmts.iterator();
00228
00229 for ( ; stmt_iter.valid(); ++stmt_iter) {
00230 Statement &stmt = stmt_iter.current();
00231 PropRangeWS &curr_ws = _get_workspace(stmt);
00232 Iterator<Statement> succ_iter = stmt.succ();
00233
00234 for ( ; succ_iter.valid(); ++succ_iter) {
00235 Statement &succ = succ_iter.current();
00236 PropRangeEdge *edge = new PropRangeEdge(stmt, succ);
00237 curr_ws.succ().ins_last(edge);
00238 _get_workspace(succ).pred().ins(*edge);
00239 }
00240 }
00241 }
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254 static void
00255 _patch_flow_graph(StmtList &stmts)
00256 {
00257 Iterator<Statement> iter = stmts.stmts_of_type(ENDDO_STMT);
00258
00259 for ( ; iter.valid(); ++iter) {
00260 Statement &curr = iter.current();
00261 Statement &next = * (Statement *) curr.next_ref();
00262 PropRangeEdge *enddo_edge = new PropRangeEdge(curr, next);
00263
00264 _get_workspace(curr).succ().ins_last(enddo_edge);
00265 _get_workspace(next).pred().ins(*enddo_edge);
00266 }
00267 }
00268
00269
00270
00271
00272
00273
00274
00275 static void
00276 _calc_toporder1(PropRangeWS &my_ws, int &toporder)
00277 {
00278 my_ws.visited(1);
00279
00280 Iterator<PropRangeEdge> succ_iter = my_ws.succ();
00281
00282 for ( ; succ_iter.valid(); ++succ_iter) {
00283 PropRangeWS &succ_ws = _get_workspace(succ_iter.current().succ());
00284
00285 if (! succ_ws.visited())
00286 _calc_toporder1(succ_ws, toporder);
00287 }
00288
00289 my_ws.toporder(toporder--);
00290 }
00291
00292 static void
00293 _calc_toporder(StmtList &stmts, Array<Statement *> &toporder_to_stmt)
00294 {
00295
00296
00297 int toporder = stmts.entries() - 1;
00298
00299 if (toporder >= 0) {
00300 Iterator<Statement> entry_iter = stmts.iterate_entry_points();
00301
00302 for ( ; entry_iter.valid(); ++entry_iter) {
00303 PropRangeWS &entry_ws = _get_workspace(entry_iter.current());
00304
00305 if (! entry_ws.visited())
00306 _calc_toporder1(entry_ws, toporder);
00307 }
00308
00309 p_assert(toporder >= -1,
00310 "_calc_toporder visited a stmt more than once.");
00311 }
00312
00313
00314
00315 toporder_to_stmt.resize(stmts.entries());
00316
00317 for (int i = 0; i <= toporder; ++i)
00318 toporder_to_stmt[i] = 0;
00319
00320 Iterator<Statement> iter = stmts.iterator();
00321
00322 for ( ; iter.valid(); ++iter) {
00323 int stmt_toporder = _get_workspace(iter.current()).toporder();
00324
00325 if (stmt_toporder >= 0)
00326 toporder_to_stmt[stmt_toporder] = &iter.current();
00327 }
00328 }
00329
00330
00331
00332
00333
00334
00335
00336 static void
00337 _set_needs_widening(StmtList &stmts)
00338 {
00339 Iterator<Statement> stmt_iter = stmts.iterator();
00340
00341 for ( ; stmt_iter.valid(); ++stmt_iter) {
00342 PropRangeWS &curr_ws = _get_workspace(stmt_iter.current());
00343 int stmt_toporder = curr_ws.toporder();
00344 Iterator<PropRangeEdge> pred_iter = curr_ws.pred();
00345
00346 for ( ; pred_iter.valid(); ++pred_iter)
00347 if (stmt_toporder <= _get_workspace(
00348 pred_iter.current().pred()).toporder()) {
00349
00350 curr_ws.needs_widening(true);
00351 break;
00352 }
00353 }
00354 }
00355
00356 static void
00357 _calc_loop_variants(StmtList &stmts)
00358 {
00359 Iterator<Statement> stmt_iter = stmts.stmts_of_type(DO_STMT);
00360
00361 for ( ; stmt_iter.valid(); ++stmt_iter) {
00362 Statement &do_loop = stmt_iter.current();
00363 RefSet<Symbol> *loop_variants = loop_variant_vars(stmts, do_loop);
00364 p_assert(loop_variants,
00365 "Internal error: loop_variant_vars() returned NULL.");
00366 _get_workspace(do_loop).loop_variants(loop_variants);
00367 }
00368 }
00369
00370
00371
00372
00373
00374 static void
00375 _put_succ_on_work_list(IntSet &work_list, PropRangeWS &my_ws)
00376 {
00377 Iterator<PropRangeEdge> succ_iter = my_ws.succ();
00378
00379 for ( ; succ_iter.valid(); ++succ_iter)
00380 work_list.ins(_get_workspace(succ_iter.current().succ()).toporder());
00381 }
00382
00383
00384
00385
00386
00387
00388 static bool
00389 _use_widening_operator(PropRangeWS &curr_ws)
00390 {
00391 if (curr_ws.needs_widening())
00392 if (curr_ws.use_widener())
00393 return true;
00394 else {
00395 bool preds_have_ranges = true;
00396
00397 Iterator<PropRangeEdge> pred_iter = curr_ws.pred();
00398
00399 for ( ; pred_iter.valid(); ++pred_iter)
00400 if (! pred_iter.current().ranges_ref()) {
00401 preds_have_ranges = false;
00402 break;
00403 }
00404
00405 curr_ws.use_widener(preds_have_ranges);
00406 }
00407
00408 return false;
00409 }
00410
00411 static Boolean
00412 is_ARRAY_OP (const Expression & expr)
00413 {
00414 if (expr.op() == ARRAY_REF_OP) {
00415 return True;
00416 } else {
00417 return False;
00418 }
00419 }
00420
00421
00422
00423
00424
00425
00426 static void
00427 _add_subscript_constraints_to_ranges(Statement &stmt, StmtRanges &ranges)
00428 {
00429 Iterator<Expression> expr_iter = stmt.iterate_expressions();
00430
00431 for ( ; expr_iter.valid(); ++expr_iter) {
00432
00433 Traverser trav (expr_iter.current(), is_ARRAY_OP);
00434 for ( ; trav.valid(); ++trav) {
00435
00436 const Expression &expr = trav.current();
00437
00438 Iterator<Expression> subscr_iter = expr.subscript().arg_list();
00439 Iterator<ArrayBounds> declare_iter = expr.array().symbol().dim();
00440
00441 int num_dims = expr.array().symbol().dim().entries();
00442
00443 for (int which_dim = 0; subscr_iter.valid() && declare_iter.valid();
00444 ++subscr_iter,++declare_iter,++which_dim) {
00445
00446 Expression & expr = subscr_iter.current();
00447 ArrayBounds & bounds = declare_iter.current();
00448
00449 Expression * upper = 0;
00450
00451 if (bounds.upper_exists() && (which_dim < num_dims-1)) {
00452 upper = bounds.upper_guarded().clone();
00453 }
00454
00455 Expression * lower;
00456
00457 if (bounds.lower_exists()) {
00458 lower = bounds.lower_guarded().clone();
00459 } else {
00460 lower = constant(1);
00461 }
00462
00463 RefSet<Symbol> symset;
00464 apply_limits(expr, lower, upper, ranges, symset);
00465
00466 symset.clear();
00467 if (lower) {
00468 apply_limits(*lower, 0, upper, ranges, symset);
00469 symset.clear();
00470 }
00471 if (upper) {
00472 apply_limits(*upper, lower, 0, ranges, symset);
00473 }
00474 }
00475 }
00476 }
00477 }
00478
00479
00480
00481
00482
00483
00484 static void
00485 _add_asserts_to_ranges(const Statement &stmt, StmtRanges &ranges)
00486 {
00487 Iterator<Assertion> assert_iter = stmt.assertions();
00488
00489 for ( ; assert_iter.valid(); ++assert_iter) {
00490 const Assertion &assert = assert_iter.current();
00491
00492 if (assert.type() == AS_RELATION) {
00493 Iterator<Expression> arg_iter = assert.arg_list_guarded();
00494
00495 for ( ; arg_iter.valid(); ++arg_iter)
00496 ranges.extract_ranges(arg_iter.current());
00497 }
00498 }
00499 }
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510 static Expression *
00511 _invert_expr(const Expression &rhs, const Symbol &lhs_var)
00512 {
00513
00514
00515
00516 Expression *terms = rhs.clone();
00517 Expression *lhs_term = 0;
00518
00519 if (terms->op() == ID_OP || terms->op() == MULT_OP
00520 || terms->op() == DIV_OP) {
00521
00522 lhs_term = terms;
00523 terms = 0;
00524 }
00525 else if (terms->op() == ADD_OP) {
00526 Mutator<Expression> iter = terms->arg_list();
00527
00528 for ( ; iter.valid(); ++iter)
00529 if (is_var_in_expr(iter.current(), lhs_var))
00530 if (! lhs_term)
00531 lhs_term = iter.grab();
00532 else {
00533 delete lhs_term;
00534 delete terms;
00535 return 0;
00536 }
00537 }
00538
00539 if (! lhs_term) {
00540 delete terms;
00541 return 0;
00542 }
00543
00544
00545
00546 Expression *lhs_expr = 0;
00547 Expression *factor = 0;
00548 Expression *divisor = 0;
00549
00550 if (lhs_term->op() == ID_OP)
00551 lhs_expr = lhs_term;
00552 else if (lhs_term->op() == MULT_OP) {
00553 lhs_expr = lhs_term->member_ref(&lhs_var);
00554
00555 if (lhs_expr) {
00556 lhs_term->arg_list().grab(*lhs_expr);
00557
00558 if (is_var_in_expr(*lhs_term, lhs_var)) {
00559 delete lhs_expr;
00560 lhs_expr = 0;
00561 }
00562 else
00563 factor = lhs_term;
00564 }
00565 }
00566 else if (lhs_term->op() == DIV_OP
00567 && lhs_term->left_guarded().op() == ID_OP
00568 && &lhs_term->left_guarded().symbol() == &lhs_var
00569 && lhs_term->right_guarded().op() == INTEGER_CONSTANT_OP) {
00570 lhs_expr = lhs_term->grab_left();
00571 divisor = lhs_term->grab_right();
00572 delete lhs_term;
00573 }
00574
00575 if (! lhs_expr) {
00576 if (terms) delete terms;
00577 if (lhs_term) delete lhs_term;
00578 if (factor) delete factor;
00579 if (divisor) delete divisor;
00580 return 0;
00581 }
00582
00583
00584
00585 Expression *inverted_expr = lhs_expr;
00586
00587 if (terms)
00588 inverted_expr = sub(inverted_expr, terms);
00589
00590 if (factor)
00591 inverted_expr = div(inverted_expr, factor);
00592
00593 if (divisor) {
00594 int max_abs_mod;
00595
00596 if (divisor->value() >= 0)
00597 max_abs_mod = divisor->value() - 1;
00598 else
00599 max_abs_mod = 1 - divisor->value();
00600
00601 inverted_expr = mul(divisor, inverted_expr);
00602 inverted_expr = new RangeExpr(inverted_expr,
00603 add(inverted_expr->clone(),
00604 constant(max_abs_mod)));
00605 }
00606
00607 inverted_expr = simplify(inverted_expr);
00608 return inverted_expr;
00609 }
00610
00611
00612
00613
00614
00615
00616 static bool
00617 _update_assign_succs(Statement &stmt, StmtRanges *out_ranges)
00618 {
00619
00620 const Symbol *lhs_name = stmt.lhs().base_variable_ref();
00621
00622 if (lhs_name) {
00623 const Expression *old_lhs_range
00624 = out_ranges->get_range_ref(*lhs_name);
00625
00626 if (is_int_scalar(*lhs_name)
00627 && stmt.rhs().is_side_effect_free()
00628 && stmt.rhs().type().data_type() == INTEGER_TYPE) {
00629
00630 Expression *assign_expr = stmt.rhs().clone();
00631
00632 if (is_var_in_expr(*assign_expr, *lhs_name)) {
00633 Expression *inverted_assign = _invert_expr(*assign_expr,
00634 *lhs_name);
00635 if (inverted_assign) {
00636 out_ranges->subst_in_ranges(*lhs_name,
00637 inverted_assign);
00638 delete inverted_assign;
00639 }
00640 else
00641 out_ranges->subst_in_ranges(*lhs_name,
00642 old_lhs_range);
00643
00644 assign_expr = out_ranges->subst_var_and_simplify(
00645 assign_expr, *lhs_name, old_lhs_range);
00646 }
00647 else {
00648 out_ranges->subst_in_ranges(*lhs_name, old_lhs_range);
00649 assign_expr = simplify(assign_expr);
00650 }
00651
00652 out_ranges->set_range(*lhs_name, assign_expr);
00653 }
00654 else {
00655 out_ranges->subst_in_ranges(*lhs_name, old_lhs_range);
00656 out_ranges->del_range(*lhs_name);
00657 }
00658 }
00659
00660 return false;
00661 }
00662
00663
00664
00665
00666
00667
00668 static bool
00669 _update_if_succs(Statement &stmt, StmtRanges *out_ranges)
00670 {
00671 if (! stmt.expr().is_side_effect_free())
00672 return false;
00673
00674 PropRangeWS &curr_ws = _get_workspace(stmt);
00675 p_assert(curr_ws.succ().entries() == 2,
00676 "If statement does not have two flow successors.");
00677 PropRangeEdge *then_edge = NULL, *else_edge = NULL;
00678
00679 if (stmt.next_ref() == &curr_ws.succ().first_ref()->succ()) {
00680 then_edge = curr_ws.succ().first_ref();
00681 else_edge = curr_ws.succ().last_ref();
00682 }
00683 else if (stmt.next_ref() == &curr_ws.succ().last_ref()->succ()) {
00684 then_edge = curr_ws.succ().last_ref();
00685 else_edge = curr_ws.succ().first_ref();
00686 }
00687 else
00688 p_abort("Internal Error in _update_succ_edges");
00689
00690 then_edge->ranges(new StmtRanges(*out_ranges));
00691 then_edge->ranges_ref()->extract_ranges(stmt.expr(), false);
00692
00693 else_edge->ranges(out_ranges);
00694 else_edge->ranges_ref()->extract_ranges(stmt.expr(), true);
00695
00696 return true;
00697 }
00698
00699
00700
00701
00702
00703 static Expression *
00704 _exit_range(const Statement &do_loop, EXPR_SIGN step_sign)
00705 {
00706 Expression *exit_range;
00707
00708 if (step_sign == POS_EXPR) {
00709 if (do_loop.step().op() == INTEGER_CONSTANT_OP
00710 && do_loop.step().value() == 1)
00711
00712 exit_range = add(do_loop.limit().clone(), constant(1));
00713 else
00714 exit_range = new RangeExpr(add(do_loop.limit().clone(),
00715 constant(1)),
00716 add(do_loop.limit().clone(),
00717 do_loop.step().clone()));
00718 }
00719 else {
00720 if (do_loop.step().op() == INTEGER_CONSTANT_OP
00721 && do_loop.step().value() == -1)
00722
00723 exit_range = add(do_loop.limit().clone(), constant(-1));
00724 else
00725 exit_range = new RangeExpr(add(do_loop.limit().clone(),
00726 do_loop.step().clone()),
00727 add(do_loop.limit().clone(),
00728 constant(-1)));
00729 }
00730
00731 exit_range = simplify(exit_range);
00732
00733 return exit_range;
00734 }
00735
00736
00737
00738
00739
00740
00741 static bool
00742 _update_do_succs(Statement &stmt, StmtRanges *out_ranges)
00743 {
00744 EXPR_SIGN step_sign = out_ranges->sign(stmt.step());
00745
00746 if (step_sign == POS_NEG_EXPR || contains_func_call(stmt)
00747 || stmt.index().type().data_type() != INTEGER_TYPE)
00748 return false;
00749
00750 PropRangeWS &curr_ws = _get_workspace(stmt);
00751 p_assert(curr_ws.succ().entries() == 2,
00752 "Do statement does not have two flow successors.");
00753 PropRangeEdge *body_edge = NULL, *exit_edge = NULL;
00754
00755 if (stmt.next_ref() == &curr_ws.succ().first_ref()->succ()) {
00756 body_edge = curr_ws.succ().first_ref();
00757 exit_edge = curr_ws.succ().last_ref();
00758 }
00759 else if (stmt.next_ref() == &curr_ws.succ().last_ref()->succ()) {
00760 body_edge = curr_ws.succ().last_ref();
00761 exit_edge = curr_ws.succ().first_ref();
00762 }
00763 else
00764 p_abort("Internal Error in _update_succ_edges");
00765
00766 Expression *bound_cond, *index_range;
00767
00768 if (step_sign == POS_EXPR) {
00769 bound_cond = le(stmt.init().clone(), stmt.limit().clone());
00770 index_range = new RangeExpr(stmt.init().clone(), stmt.limit().clone());
00771 }
00772 else {
00773 bound_cond = ge(stmt.init().clone(), stmt.limit().clone());
00774 index_range = new RangeExpr(stmt.limit().clone(), stmt.init().clone());
00775 }
00776
00777 index_range = simplify(index_range);
00778 body_edge->ranges(new StmtRanges(*out_ranges));
00779 body_edge->ranges_ref()->extract_ranges(*bound_cond);
00780 body_edge->ranges_ref()->set_range(stmt.index().symbol(), index_range);
00781 delete bound_cond;
00782
00783
00784
00785
00786
00787 exit_edge->ranges(out_ranges);
00788 exit_edge->ranges_ref()->del_range(stmt.index().symbol());
00789
00790 return true;
00791 }
00792
00793
00794
00795
00796
00797
00798 static bool
00799 _update_enddo_succs(Statement &stmt, StmtRanges *out_ranges)
00800 {
00801 Statement &matching_do = *stmt.follow_ref();
00802 EXPR_SIGN step_sign = out_ranges->sign(matching_do.step());
00803
00804 if (step_sign == POS_NEG_EXPR || contains_func_call(matching_do))
00805 return false;
00806
00807 PropRangeWS &curr_ws = _get_workspace(stmt);
00808 p_assert(curr_ws.succ().entries() == 2,
00809 "Enddo statement does not have two flow successors.");
00810 PropRangeEdge *back_edge = NULL, *exit_edge = NULL;
00811
00812 if (&curr_ws.succ().first_ref()->succ() == &matching_do) {
00813 back_edge = curr_ws.succ().first_ref();
00814 exit_edge = curr_ws.succ().last_ref();
00815 }
00816 else if (&curr_ws.succ().last_ref()->succ() == &matching_do) {
00817 back_edge = curr_ws.succ().last_ref();
00818 exit_edge = curr_ws.succ().first_ref();
00819 }
00820 else
00821 p_abort("Internal Error in _update_succ_edges");
00822
00823 back_edge->ranges(new StmtRanges(*out_ranges));
00824
00825 Expression *exit_range = _exit_range(matching_do, step_sign);
00826 exit_edge->ranges(out_ranges);
00827 exit_edge->ranges_ref()->set_range(matching_do.index().symbol(),
00828 exit_range);
00829
00830 return true;
00831 }
00832
00833
00834
00835
00836
00837
00838 static void
00839 _update_succ_edges(Statement &stmt)
00840 {
00841 PropRangeWS &curr_ws = _get_workspace(stmt);
00842
00843
00844
00845 p_assert(curr_ws.ranges_ref(),
00846 "Internal Error: Workspace has NULL StmtRanges pointer.");
00847
00848 StmtRanges *out_ranges
00849 = new StmtRanges(*curr_ws.ranges_ref());
00850
00851 if (stmt.stmt_class() == DO_STMT)
00852 out_ranges->subst_in_ranges(stmt.index().symbol(), 0);
00853
00854 Iterator<Symbol> mod_iter = curr_ws.mod_set();
00855
00856 for ( ; mod_iter.valid(); ++mod_iter)
00857 if (stmt.stmt_class() != ASSIGNMENT_STMT
00858 || ! stmt.lhs().base_variable_ref()
00859 || stmt.lhs().base_variable_ref() != &mod_iter.current()) {
00860
00861 const Expression *range
00862 = out_ranges->get_range_ref(mod_iter.current());
00863
00864 out_ranges->subst_in_ranges(mod_iter.current(), range);
00865 out_ranges->del_range(mod_iter.current());
00866 }
00867
00868 _add_asserts_to_ranges(stmt, *out_ranges);
00869
00870
00871
00872 bool already_updated_succs = false;
00873
00874 switch (stmt.stmt_class()) {
00875
00876 case ASSIGNMENT_STMT:
00877 already_updated_succs = _update_assign_succs(stmt, out_ranges);
00878 break;
00879
00880 case IF_STMT:
00881 case ELSEIF_STMT:
00882 already_updated_succs = _update_if_succs(stmt, out_ranges);
00883 break;
00884
00885 case DO_STMT:
00886 already_updated_succs = _update_do_succs(stmt, out_ranges);
00887 break;
00888
00889 case ENDDO_STMT:
00890
00891 break;
00892
00893 case BLOCK_ENTRY_STMT:
00894 case BLOCK_EXIT_STMT:
00895 if (switch_value("range_block") > 0)
00896 out_ranges->clear();
00897 break;
00898
00899 default:
00900
00901 break;
00902 }
00903
00904
00905
00906
00907 if (! already_updated_succs) {
00908 Iterator<PropRangeEdge> succ_iter = curr_ws.succ();
00909
00910 if (succ_iter.valid()) {
00911 succ_iter.current().ranges(out_ranges);
00912 ++succ_iter;
00913
00914 for ( ; succ_iter.valid(); ++succ_iter)
00915 succ_iter.current().ranges(new StmtRanges(*out_ranges));
00916 }
00917 else
00918 delete out_ranges;
00919 }
00920 }
00921
00922
00923
00924
00925
00926
00927 static void
00928 _iterate_to_fixed_point_phase(ProgramUnit &pgm,
00929 const Array<Statement *> &toporder_to_stmt,
00930 const IntSet &start_stmts,
00931 bool widening_phase)
00932 {
00933
00934
00935 if (_refine_ranges == -1) {
00936 _refine_ranges = switch_value("refine_ranges");
00937 }
00938
00939 IntSet work_list(start_stmts);
00940
00941
00942
00943
00944 while (work_list.entries() > 0) {
00945 for (int stmt_num = work_list.first();
00946 stmt_num != -1;
00947 stmt_num = work_list.next(stmt_num)) {
00948
00949 Statement &curr = *toporder_to_stmt[stmt_num];
00950 work_list.del(stmt_num);
00951 PropRangeWS &curr_ws = _get_workspace(curr);
00952 curr_ws.incr_num_visits();
00953 StmtRanges *new_ranges = 0;
00954 Iterator<PropRangeEdge> pred_iter = curr_ws.pred();
00955
00956 if (curr_ws.pred().entries() == 1) {
00957
00958
00959 new_ranges = pred_iter.current().grab_ranges();
00960 p_assert(! curr_ws.needs_widening(),
00961 "Internal Error: Stmts with single predecesors should never need to be widened.");
00962 p_assert(new_ranges || ! curr_ws.ranges_ref(),
00963 "Internal Error: Constraint information was lost.");
00964 }
00965 else {
00966 for ( ; pred_iter.valid(); ++pred_iter) {
00967 PropRangeEdge &pred_edge = pred_iter.current();
00968 StmtRanges *pred_ranges = pred_edge.ranges_ref();
00969
00970 if (pred_ranges)
00971 if (new_ranges)
00972 new_ranges->union_ranges(*pred_ranges);
00973 else
00974 new_ranges = new StmtRanges(*pred_ranges);
00975 }
00976 }
00977
00978 if (! new_ranges)
00979 new_ranges = new StmtRanges(pgm.symtab());
00980
00981
00982 if (_refine_ranges && (curr_ws.num_visits() == 1)) {
00983 _add_subscript_constraints_to_ranges(curr, *new_ranges);
00984 }
00985
00986 if (curr_ws.ranges_ref()
00987 && curr_ws.needs_widening()) {
00988
00989 StmtRanges &old_ranges = *curr_ws.ranges_ref();
00990
00991 if (widening_phase) {
00992 if (_use_widening_operator(curr_ws))
00993 if (curr_ws.loop_variants_ref()
00994 && curr_ws.num_visits() <= MAX_SELECTIVE_WIDENING) {
00995 new_ranges->widen_some_ranges(old_ranges,
00996 *curr_ws.loop_variants_ref());
00997 }
00998 else
00999 new_ranges->widen_ranges(old_ranges);
01000 }
01001 else
01002 new_ranges->narrow_ranges(old_ranges);
01003 }
01004
01005 if (! curr_ws.ranges_ref()
01006 || *new_ranges != *curr_ws.ranges_ref()) {
01007
01008 curr_ws.ranges(new_ranges);
01009
01010 if (_debug_level >= 20) {
01011 int zero = 0;
01012 curr.write(cout, zero);
01013 cout << " ";
01014 curr_ws.ranges_ref()->pretty_print(cout);
01015 cout << endl;
01016 }
01017
01018 _update_succ_edges(curr);
01019 _put_succ_on_work_list(work_list, curr_ws);
01020 }
01021 else
01022 delete new_ranges;
01023 }
01024 }
01025 }
01026
01027
01028
01029
01030
01031
01032 static void
01033 _iterate_to_fixed_point(ProgramUnit &pgm,
01034 const Array<Statement *> &toporder_to_stmt)
01035 {
01036
01037
01038
01039
01040
01041
01042 if (_debug_level >= 20)
01043 cout << "\nWidening Phase:\n";
01044
01045 IntSet entry_stmts(toporder_to_stmt.entries());
01046 Iterator<Statement> entry_iter = pgm.stmts().iterate_entry_points();
01047
01048 for ( ; entry_iter.valid(); ++entry_iter) {
01049 PropRangeWS &ws = _get_workspace(entry_iter.current());
01050
01051 entry_stmts.ins(ws.toporder());
01052 }
01053
01054 _iterate_to_fixed_point_phase(pgm, toporder_to_stmt, entry_stmts, true);
01055
01056
01057
01058
01059
01060
01061
01062 if (_debug_level >= 20)
01063 cout << "\nNarrowing Phase:\n";
01064
01065 IntSet widened_stmts(toporder_to_stmt.entries());
01066 Iterator<Statement> stmt_iter = pgm.stmts().iterator();
01067
01068 for ( ; stmt_iter.valid(); ++stmt_iter) {
01069 PropRangeWS &ws = _get_workspace(stmt_iter.current());
01070
01071 if (ws.toporder() >= 0 && ws.needs_widening())
01072 widened_stmts.ins(ws.toporder());
01073 }
01074
01075 _iterate_to_fixed_point_phase(pgm, toporder_to_stmt, widened_stmts, false);
01076 }
01077
01078
01079
01080
01081
01082
01083 void
01084 AIRangeDict::_add_safe_cond_ranges(const ProgramUnit &pgm)
01085 {
01086 Iterator<Statement> iter = pgm.stmts().iterator();
01087
01088 for ( ; iter.valid(); ++iter) {
01089 Statement &stmt = iter.current();
01090
01091 if (stmt.stmt_class() == DO_STMT) {
01092 Iterator<Assertion> assert_iter = stmt.assertions();
01093
01094 for ( ; assert_iter.valid(); ++assert_iter) {
01095 const Assertion &assert = assert_iter.current();
01096
01097 if (assert.type() == AS_SAFE_CONDITION) {
01098 for (Iterator<Statement> do_iter = pgm.stmts().iterate_loop_body(&stmt);
01099 do_iter.valid();
01100 ++do_iter) {
01101
01102 Statement & body_stmt = do_iter.current();
01103
01104 PropRangeWS &ws = _get_workspace(body_stmt);
01105 Iterator<Expression> arg_iter = assert.arg_list_guarded();
01106
01107 for ( ; arg_iter.valid(); ++arg_iter) {
01108 if (ws.ranges_ref()) {
01109 ws.ranges_ref()->extract_ranges(arg_iter.current());
01110 }
01111 }
01112 }
01113 }
01114 }
01115 }
01116 }
01117 }
01118
01119
01120
01121
01122
01123
01124
01125 void
01126 AIRangeDict::_generate_map(const ProgramUnit &pgm)
01127 {
01128 Iterator<Statement> iter = pgm.stmts().iterator();
01129
01130 for ( ; iter.valid(); ++iter) {
01131 Statement &stmt = iter.current();
01132 PropRangeWS &ws = _get_workspace(stmt);
01133
01134 if (ws.ranges_ref())
01135 _stmt_ranges.ins(stmt.tag(), ws.grab_ranges());
01136 else
01137 _stmt_ranges.ins(stmt.tag(), new StmtRanges(pgm.symtab()));
01138 }
01139 }
01140
01141
01142
01143
01144 AIRangeDict::AIRangeDict(ProgramUnit &pgm, int debug GIV(0))
01145 : RangeDict(pgm.symtab())
01146 {
01147 #ifdef CLASS_INSTANCE_REGISTRY
01148 register_instance(AIRANGE_DICT, sizeof(AIRangeDict), this);
01149 #endif
01150
01151 if (switch_value("range_off") > 0) return;
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167 RefList<Statement> new_ifs;
01168 enforce_standard_within_bounds(pgm, new_ifs);
01169
01170
01171
01172 Array<Statement *> toporder_to_stmt;
01173
01174 _debug_level = debug;
01175 Timer tot_timer;
01176 Timer timer;
01177 float avg_visits, avg_cd_entries;
01178
01179
01180
01181 remove_min_max_var_conflicts(pgm.symtab());
01182
01183 ::_pass_tag = create_pass_tag();
01184 _init_workspaces(pgm.stmts());
01185
01186 if (switch_value("pc_call_mods") != 1)
01187 _make_nonlocals_modified_at_calls(pgm);
01188
01189 _add_flow_edges(pgm.stmts());
01190
01191 _calc_toporder(pgm.stmts(), toporder_to_stmt);
01192 _set_needs_widening(pgm.stmts());
01193 _calc_loop_variants(pgm.stmts());
01194
01195 if (_debug_level > 0) {
01196 cout << "! Initialization: " << timer << endl;
01197 timer.reset();
01198 }
01199
01200
01201
01202
01203 _iterate_to_fixed_point(pgm, toporder_to_stmt);
01204
01205 if (_debug_level > 0) {
01206 cout << "! Iterating to fixed point: " << timer << endl;
01207 _collect_stats(pgm.stmts(), avg_visits, avg_cd_entries);
01208 timer.reset();
01209 }
01210
01211
01212
01213
01214
01215
01216
01217 _add_safe_cond_ranges(pgm);
01218
01219
01220
01221 _generate_map(pgm);
01222
01223 if (_debug_level > 0)
01224 cout << "! Generating stmt_ranges: " << timer << endl;
01225
01226 if (_debug_level >= 10)
01227 _dump_workspaces(cout, pgm.stmts());
01228
01229
01230
01231 pgm.clean_workspace(::_pass_tag);
01232 clean_after_standard_enforcement(pgm, new_ifs);
01233
01234 if (_debug_level > 0) {
01235 cout << "! Total time: " << tot_timer << endl;
01236 cout << "! Number of statements: " << pgm.stmts().entries() << endl;
01237 cout << "! Average num visits: " << avg_visits << endl;
01238 cout << "! Average StmtRanges entries (weighted): "
01239 << avg_cd_entries << endl;
01240 }
01241 }
01242
01243 AIRangeDict::AIRangeDict(const AIRangeDict &other)
01244 : RangeDict(other)
01245 {
01246 #ifdef CLASS_INSTANCE_REGISTRY
01247 register_instance(AIRANGE_DICT, sizeof(AIRangeDict), this);
01248 #endif
01249
01250 *this = other;
01251 }
01252
01253
01254
01255
01256 AIRangeDict::~AIRangeDict()
01257 {
01258 #ifdef CLASS_INSTANCE_REGISTRY
01259 unregister_instance(AIRANGE_DICT, this);
01260 #endif
01261
01262
01263 }
01264
01265
01266
01267
01268 AIRangeDict &
01269 AIRangeDict::operator = (const AIRangeDict &other)
01270 {
01271 if (this != &other) {
01272 RangeDict::operator=(other);
01273 _stmt_ranges = other._stmt_ranges;
01274 }
01275
01276 return *this;
01277 }
01278
01279
01280
01281
01282
01283
01284
01285 RefSet<Symbol> *
01286 AIRangeDict::range_vars( const String & tag ) const
01287 {
01288 const StmtRanges * ranges = _stmt_ranges.find_ref(tag);
01289
01290 if (ranges) {
01291 return ranges->range_vars( );
01292 } else {
01293 return 0;
01294 }
01295 }
01296
01297
01298
01299
01300 Expression *
01301 AIRangeDict::elim_known_facts( const String & tag, Expression * expr)
01302 {
01303 StmtRanges * ranges = _stmt_ranges.find_ref(tag);
01304
01305 return ::elim_known_facts (expr, *ranges);
01306 }
01307
01308
01309
01310
01311 void
01312 AIRangeDict::_set_range(const Symbol &var,
01313 const Statement &stmt, Expression *range)
01314 {
01315 StmtRanges *ranges = _stmt_ranges.find_ref(stmt.tag());
01316
01317 if (! ranges) {
01318 ranges = new StmtRanges(symtab());
01319 _stmt_ranges.ins(stmt.tag(), ranges);
01320 }
01321
01322 ranges->set_range(var, range);
01323 }
01324
01325
01326
01327
01328
01329 void
01330 AIRangeDict::_del_range(const Symbol &var, const Statement &stmt)
01331 {
01332 StmtRanges *ranges = _stmt_ranges.find_ref(stmt.tag());
01333
01334 if (ranges)
01335 ranges->del_range(var);
01336 }
01337
01338
01339
01340
01341
01342 const Expression *
01343 AIRangeDict::_get_range_ref(const Symbol &var, const Statement &stmt)
01344 {
01345 StmtRanges *ranges = _stmt_ranges.find_ref(stmt.tag());
01346
01347 if (ranges)
01348 return ranges->get_range_ref(var);
01349
01350 return 0;
01351 }
01352
01353
01354
01355
01356
01357 void
01358 AIRangeDict::print(ostream & o) const
01359 {
01360 KeyIterator<String, StmtRanges> iter = _stmt_ranges;
01361
01362 for ( ; iter.valid(); ++iter)
01363 o << iter.current_key() << ": " << iter.current_data() << endl;
01364 }
01365
01366
01367
01368
01369
01370 void
01371 AIRangeDict::pretty_print(ostream & o, const Statement &stmt) const
01372 {
01373 const StmtRanges *ranges = _stmt_ranges.find_ref(stmt.tag());
01374
01375 if (ranges)
01376 ranges->pretty_print(o);
01377 else
01378 o << "{}";
01379 }
01380
01381
01382
01383
01384 Listable *
01385 AIRangeDict::listable_clone(void) const
01386 {
01387 return new AIRangeDict(*this);
01388 }
01389
01390
01391
01392
01393
01394 int
01395 AIRangeDict::structures_OK() const
01396 {
01397 return _stmt_ranges.structures_OK();
01398 }
01399
01400
01401
01402 StmtRanges &
01403 AIRangeDict::_s_ranges(const String & tag)
01404 {
01405 return _stmt_ranges[tag];
01406 }
01407
01408 #if 0
01409
01410
01411
01412
01413 static void
01414 _calc_loop_range(const Statement &do_loop, const StmtList &stmts,
01415 Database<String,StmtRanges> &stmt_ranges,
01416 Database<String,StmtRanges> &loop_ranges)
01417 {
01418 StmtRanges *result = 0;
01419
01420 const Statement *stmt = stmts.next_ref(do_loop);
01421
01422 while (stmt && stmt != do_loop.follow_ref()) {
01423 if (stmt->pred().entries() > 0) {
01424 StmtRanges *ranges
01425 = stmt_ranges.find_ref(stmt->tag());
01426
01427 if (ranges)
01428 if (result)
01429 result->union_ranges(*ranges);
01430 else
01431 result = new StmtRanges(*ranges);
01432 }
01433
01434 if (stmt->stmt_class() == DO_STMT) {
01435 _calc_loop_range(*stmt, stmts, stmt_ranges, loop_ranges);
01436 result->union_ranges(*loop_ranges.find_ref(stmt->tag()));
01437 stmt = stmt->follow_ref();
01438 }
01439 else
01440 stmt = stmts.next_ref(*stmt);
01441 }
01442
01443 loop_ranges.ins(do_loop.tag(), result);
01444 }
01445
01446
01447
01448
01449
01450 void
01451 determine_loop_ranges(const StmtList &stmts,
01452 Database<String,StmtRanges> &stmt_ranges,
01453 Database<String,StmtRanges> &loop_ranges)
01454 {
01455 const Statement *stmt = stmts.first_ref();
01456
01457 while (stmt) {
01458 if (stmt->stmt_class() == DO_STMT) {
01459 _calc_loop_range(*stmt, stmts, stmt_ranges, loop_ranges);
01460 stmt = stmt->follow_ref();
01461 }
01462 else
01463 stmt = stmts.next_ref(*stmt);
01464 }
01465 }
01466
01467 #endif