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/expression_util.h"
00014 #include "../utilities/equivalence_util.h"
00015 #include "../Array.h"
00016 #include "../IntSet.h"
00017 #include "../Timer.h"
00018 #include "../p-assert.h"
00019
00020 #include "ControlRangeDict.h"
00021 #include "PropCtrlRangeWS.h"
00022 #include "RangeExpr.h"
00023 #include "range_util.h"
00024 #include "range_dict_util.h"
00025
00026
00027
00028 static unsigned int _pass_tag;
00029
00030 static int _debug_level = 0;
00031
00032
00033
00034
00035
00036
00037
00038 static void
00039 _init_workspaces(ProgramUnit &pgm)
00040 {
00041 Iterator<Statement> iter = pgm.stmts().iterator();
00042
00043 for ( ; iter.valid(); ++iter) {
00044 PropCtrlRangeWS *my_ws = new PropCtrlRangeWS(_pass_tag, iter.current());
00045
00046 iter.current().work_stack().push(my_ws);
00047 }
00048 }
00049
00050
00051
00052
00053
00054 static PropCtrlRangeWS &
00055 _get_workspace(const Statement &stmt)
00056 {
00057 WorkSpace *ws = stmt.work_stack().top_ref(_pass_tag);
00058
00059 p_assert(ws, "Statement doesn't have a PropCtrlRangeWS.");
00060
00061 return * (PropCtrlRangeWS *) ws;
00062 }
00063
00064
00065
00066
00067
00068 static void
00069 _dump_workspaces(ostream &o, const ProgramUnit &pgm)
00070 {
00071 Iterator<Statement> iter = pgm.stmts().iterator();
00072
00073 for ( ; iter.valid(); ++iter) {
00074 iter.current().structures_OK();
00075 o << iter.current().tag() << ": ";
00076 iter.current().print_debug(o, 0);
00077 o << endl;
00078 _get_workspace(iter.current()).print(o);
00079 o << endl;
00080 }
00081 }
00082
00083
00084
00085
00086
00087
00088 static void
00089 _make_nonlocals_modified_at_calls(ProgramUnit &pgm)
00090 {
00091
00092
00093 RefSet<Symbol> non_local_set;
00094 DictionaryIter<Symbol> sym_iter = pgm.symtab().iterator();
00095
00096 for ( ; sym_iter.valid(); ++sym_iter) {
00097 Symbol &symbol = sym_iter.current();
00098
00099 if (symbol.sym_class() == VARIABLE_CLASS
00100 && (symbol.formal() == IS_FORMAL || symbol.common_ref())) {
00101
00102 if (symbol.type().data_type() == INTEGER_TYPE)
00103 non_local_set.ins(symbol);
00104
00105
00106
00107 RefSet<Symbol> *aliases = equiv_aliases(symbol);
00108
00109 if (aliases) {
00110 Iterator<Symbol> alias_iter = *aliases;
00111
00112 for ( ; alias_iter.valid(); ++alias_iter) {
00113 Symbol &alias_symbol = alias_iter.current();
00114
00115 if (alias_symbol.type().data_type() == INTEGER_TYPE)
00116 non_local_set.ins(alias_symbol);
00117 }
00118
00119 delete aliases;
00120 }
00121 }
00122 }
00123
00124
00125
00126
00127 Iterator<Statement> stmt_iter = pgm.stmts().iterator();
00128
00129 for ( ; stmt_iter.valid(); ++stmt_iter) {
00130 Statement &stmt = stmt_iter.current();
00131
00132 if (stmt.stmt_class() == CALL_STMT || contains_func_call(stmt)) {
00133 RefSet<Symbol> &mod_set = _get_workspace(stmt).mod_set;
00134 RefSet<Symbol> *maymods = stmt_maymods(stmt);
00135
00136 if (maymods) {
00137 Iterator<Expression> act_iter = stmt.act_refs();
00138
00139 for ( ; act_iter.valid(); ++act_iter) {
00140 Symbol *var_ref = act_iter.current().base_variable_ref();
00141
00142 if (var_ref)
00143 mod_set.del(*var_ref);
00144 }
00145
00146 if (stmt.stmt_class() == ASSIGNMENT_STMT) {
00147 Symbol *var_ref = stmt.lhs().base_variable_ref();
00148
00149 if (var_ref)
00150 mod_set.ins(*var_ref);
00151 }
00152
00153 Iterator<Symbol> nl_iter = *maymods;
00154
00155 for ( ; nl_iter.valid(); ++nl_iter)
00156 mod_set.ins(nl_iter.current());
00157
00158 delete maymods;
00159 }
00160 else {
00161 Iterator<Symbol> nl_iter = non_local_set;
00162
00163 for ( ; nl_iter.valid(); ++nl_iter)
00164 mod_set.ins(nl_iter.current());
00165 }
00166 }
00167 }
00168 }
00169
00170
00171
00172
00173
00174
00175
00176 static void
00177 _calc_toporder1(Statement &stmt, int &toporder)
00178 {
00179 PropCtrlRangeWS &my_ws = _get_workspace(stmt);
00180
00181 if (! my_ws.visited()) {
00182 my_ws.visited(1);
00183
00184 Iterator<Statement> succ_iter = stmt.succ();
00185
00186 for ( ; succ_iter.valid(); ++succ_iter)
00187 _calc_toporder1(succ_iter.current(), toporder);
00188
00189 my_ws.toporder(toporder--);
00190 }
00191 }
00192
00193 static void
00194 _calc_toporder(ProgramUnit &pgm, Array<Statement *> &toporder_to_stmt)
00195 {
00196
00197
00198 int toporder = pgm.stmts().entries() - 1;
00199
00200 if (toporder >= 0) {
00201 Iterator<Statement> entry_iter = pgm.stmts().iterate_entry_points();
00202
00203 for ( ; entry_iter.valid(); ++entry_iter)
00204 _calc_toporder1(entry_iter.current(), toporder);
00205
00206 p_assert(toporder >= -1,
00207 "_calc_toporder visited a stmt more than once.");
00208 }
00209
00210
00211
00212 toporder_to_stmt.resize(pgm.stmts().entries());
00213
00214 for (int i = 0; i <= toporder; ++i)
00215 toporder_to_stmt[i] = 0;
00216
00217 Iterator<Statement> iter = pgm.stmts().iterator();
00218
00219 for ( ; iter.valid(); ++iter) {
00220 int stmt_toporder = _get_workspace(iter.current()).toporder();
00221
00222 if (stmt_toporder >= 0)
00223 toporder_to_stmt[stmt_toporder] = &iter.current();
00224 }
00225 }
00226
00227
00228
00229
00230
00231
00232
00233
00234 static bool
00235 _is_else_branch(const Statement &pred, const Statement &succ)
00236 {
00237 return ((pred.stmt_class() == IF_STMT
00238 || pred.stmt_class() == ELSEIF_STMT
00239 || pred.stmt_class() == DO_STMT)
00240 && pred.succ().entries() == 2
00241 && pred.next_ref() != &succ);
00242 }
00243
00244
00245
00246
00247 void
00248 _intersect_range_maps(Map< Symbol, RefSet<Expression> > &range_map,
00249 const Map< Symbol, RefSet<Expression> > &inter_map)
00250 {
00251 KeyIterator<Symbol, RefSet<Expression> > rmap_iter = range_map;
00252 RefSet<Symbol> dead_vars;
00253
00254 for ( ; rmap_iter.valid(); ++rmap_iter) {
00255 const RefSet<Expression> *inter_ranges
00256 = inter_map.find_ref(rmap_iter.current_key());
00257
00258 if (! inter_ranges)
00259 rmap_iter.current_data().clear();
00260 else {
00261 Mutator<Expression> ranges_iter = rmap_iter.current_data();
00262
00263 for ( ; ranges_iter.valid(); ++ranges_iter)
00264 if (! inter_ranges->member(ranges_iter.current()))
00265 ranges_iter.del();
00266 }
00267
00268 if (rmap_iter.current_data().entries() == 0)
00269 dead_vars.ins(rmap_iter.current_key());
00270 }
00271
00272 Iterator<Symbol> dead_iter = dead_vars;
00273
00274 for ( ; dead_iter.valid(); ++dead_iter)
00275 range_map.del(dead_iter.current());
00276 }
00277
00278
00279
00280
00281
00282 static bool
00283 _range_maps_equal(const Map< Symbol, RefSet<Expression> > &range_map1,
00284 const Map< Symbol, RefSet<Expression> > &range_map2)
00285 {
00286 if (range_map1.entries() != range_map2.entries())
00287 return false;
00288
00289 KeyIterator<Symbol, RefSet<Expression> > rmap_iter = range_map1;
00290
00291 for ( ; rmap_iter.valid(); ++rmap_iter) {
00292 const RefSet<Expression> *var_ranges2
00293 = range_map2.find_ref(rmap_iter.current_key());
00294
00295 if (! var_ranges2
00296 || ! (rmap_iter.current_data() == *var_ranges2))
00297
00298 return false;
00299 }
00300
00301 return true;
00302 }
00303
00304
00305
00306
00307
00308 static void
00309 _put_succ_on_work_list(IntSet &work_list, Statement &stmt)
00310 {
00311 Iterator<Statement> succ_iter = stmt.succ();
00312
00313 for ( ; succ_iter.valid(); ++succ_iter)
00314 work_list.ins(_get_workspace(succ_iter.current()).toporder());
00315 }
00316
00317
00318
00319
00320
00321
00322 static void
00323 _iterate_to_fixed_point(ProgramUnit &pgm,
00324 const Array<Statement *> &toporder_to_stmt)
00325 {
00326
00327
00328 IntSet work_list(toporder_to_stmt.entries());
00329
00330
00331
00332
00333 Iterator<Statement> entry_iter = pgm.stmts().iterate_entry_points();
00334
00335 for ( ; entry_iter.valid(); ++entry_iter)
00336 work_list.ins(_get_workspace(entry_iter.current()).toporder());
00337
00338
00339
00340 while (work_list.entries() > 0) {
00341
00342
00343 for (int stmt_num = work_list.first();
00344 stmt_num != -1;
00345 stmt_num = work_list.next(stmt_num)) {
00346
00347 Statement &curr = *toporder_to_stmt[stmt_num];
00348 work_list.del(stmt_num);
00349 PropCtrlRangeWS &curr_ws = _get_workspace(curr);
00350 curr_ws.incr_num_visits();
00351 bool changed = false;
00352
00353
00354
00355 Map< Symbol, RefSet<Expression> > new_ranges;
00356
00357 Iterator<Statement> pred_iter = curr.pred();
00358 bool is_first_pred = true;
00359
00360 for ( ; pred_iter.valid(); ++pred_iter) {
00361 PropCtrlRangeWS &pred_ws
00362 = _get_workspace(pred_iter.current());
00363
00364 if (pred_ws.num_visits() > 0)
00365 if (is_first_pred) {
00366 is_first_pred = false;
00367
00368 if (_is_else_branch(pred_iter.current(), curr))
00369 new_ranges = pred_ws.out_else_ranges;
00370 else
00371 new_ranges = pred_ws.out_ranges;
00372 }
00373 else
00374 if (_is_else_branch(pred_iter.current(), curr))
00375 _intersect_range_maps(new_ranges, pred_ws.out_else_ranges);
00376 else
00377 _intersect_range_maps(new_ranges, pred_ws.out_ranges);
00378 }
00379
00380 if (curr_ws.num_visits() == 1
00381 || ! _range_maps_equal(new_ranges, curr_ws.in_ranges)) {
00382
00383
00384
00385
00386
00387 if (_debug_level >= 20) {
00388 cout << "! Statement ";
00389 curr.print_debug(cout, 0);
00390 cout << " was visited and updated.\n";
00391 }
00392
00393 curr_ws.in_ranges = new_ranges;
00394 changed = curr_ws.update_out_ranges();
00395
00396 if (changed || curr_ws.num_visits() == 1) {
00397
00398
00399
00400
00401
00402 _put_succ_on_work_list(work_list, curr);
00403 }
00404
00405 if (_debug_level >= 30) {
00406 curr_ws.print(cout);
00407 cout << endl;
00408 }
00409 }
00410 }
00411 }
00412 }
00413
00414
00415
00416
00417
00418 void
00419 ControlRangeDict::_add_safe_cond_ranges(const ProgramUnit &pgm)
00420 {
00421 Iterator<Statement> iter = pgm.stmts().iterator();
00422
00423 for ( ; iter.valid(); ++iter) {
00424 Statement &stmt = iter.current();
00425
00426 if (stmt.stmt_class() == DO_STMT) {
00427 Iterator<Assertion> assert_iter = stmt.assertions();
00428
00429 for ( ; assert_iter.valid(); ++assert_iter) {
00430 const Assertion &assert = assert_iter.current();
00431
00432 if (assert.type() == AS_SAFE_CONDITION) {
00433 for (Iterator<Statement> do_iter = pgm.stmts().iterate_loop_body(&stmt);
00434 do_iter.valid();
00435 ++do_iter) {
00436
00437 Statement & body_stmt = do_iter.current();
00438
00439 PropCtrlRangeWS &ws = _get_workspace(body_stmt);
00440 Iterator<Expression> arg_iter = assert.arg_list_guarded();
00441
00442 for ( ; arg_iter.valid(); ++arg_iter) {
00443 Map< Symbol, Set<Expression> > *assert_ranges
00444 = extract_ranges(arg_iter.current());
00445
00446 KeyIterator<Symbol, Set<Expression> > ar_iter = *assert_ranges;
00447 for ( ; ar_iter.valid(); ++ar_iter) {
00448 const Symbol &var = ar_iter.current_key();
00449 RefSet<Expression> *var_ranges = ws.in_ranges.find_ref(var);
00450
00451 if (! var_ranges) {
00452 RefSet<Expression> *set = new RefSet<Expression>;
00453 for (Iterator<Expression> eiter = ar_iter.current_data();
00454 eiter.valid();
00455 ++eiter) {
00456 set->ins(eiter.current());
00457 }
00458
00459 ws.in_ranges.ins(var, set);
00460
00461 } else {
00462 Iterator<Expression> range_iter = ar_iter.current_data();
00463
00464 for ( ; range_iter.valid(); ++range_iter)
00465 var_ranges->ins(range_iter.current());
00466 }
00467 }
00468 }
00469 }
00470 }
00471 }
00472 }
00473 }
00474 }
00475
00476
00477
00478
00479
00480
00481
00482 void
00483 ControlRangeDict::_generate_map(const ProgramUnit &pgm)
00484 {
00485 Iterator<Statement> iter = pgm.stmts().iterator();
00486
00487 for ( ; iter.valid(); ++iter) {
00488 Statement &stmt = iter.current();
00489 PropCtrlRangeWS &ws = _get_workspace(stmt);
00490 RefMap<Symbol, Expression> *stmt_ranges
00491 = _pgm_ranges.find_ref(stmt.tag());
00492
00493 if (! stmt_ranges) {
00494 stmt_ranges = new RefMap<Symbol, Expression>;
00495 _pgm_ranges.ins(stmt.tag(), stmt_ranges);
00496 }
00497
00498 PropCtrlRangeWS *prev_ws = 0;
00499
00500 if (stmt.prev_ref())
00501 prev_ws = &_get_workspace(*stmt.prev_ref());
00502
00503 if (prev_ws && _range_maps_equal(prev_ws->in_ranges, ws.in_ranges)) {
00504
00505
00506
00507
00508
00509
00510 *stmt_ranges = _pgm_ranges[stmt.prev_ref()->tag()];
00511 }
00512 else {
00513 StmtRanges ranges(symtab());
00514 KeyIterator<Symbol, RefSet<Expression> > rmap_iter = ws.in_ranges;
00515
00516 for ( ; rmap_iter.valid(); ++rmap_iter) {
00517 if (rmap_iter.current_data().entries() > 0) {
00518 Iterator<Expression> range_iter = rmap_iter.current_data();
00519 Expression *range_expr = range_iter.current().clone();
00520 ++range_iter;
00521
00522 if (range_iter.valid()) {
00523
00524
00525
00526 RangeExpr *range = convert_to_range(range_expr);
00527
00528 for ( ; range_iter.valid(); ++range_iter) {
00529 RangeExpr *inter_range
00530 = convert_to_range(range_iter.current().clone());
00531 range->lb(max_expr(range->grab_lb(),
00532 inter_range->grab_lb(),
00533 symtab()));
00534 range->ub(min_expr(range->grab_ub(),
00535 inter_range->grab_ub(),
00536 symtab()));
00537 delete inter_range;
00538 }
00539
00540 if (range->has_lb() && range->lb() == range->ub()) {
00541 range_expr = range->grab_lb();
00542 delete range;
00543 }
00544 else
00545 range_expr = range;
00546 }
00547
00548 range_expr = simplify(range_expr);
00549 ranges.set_range(rmap_iter.current_key(), range_expr);
00550 }
00551 }
00552
00553 ranges.simplify_min_max();
00554
00555
00556
00557 for (rmap_iter.reset(); rmap_iter.valid(); ++rmap_iter) {
00558 if (rmap_iter.current_data().entries() > 0) {
00559
00560 Expression *range_expr
00561 = ranges.grab_range(rmap_iter.current_key());
00562 p_assert(range_expr,
00563 "ControlRangeDict:_generate_ranges(): Lost a range.");
00564
00565
00566
00567
00568 const Expression &range_ref = _range_values.ins(range_expr);
00569
00570
00571
00572 stmt_ranges->ins(rmap_iter.current_key(), range_ref);
00573 }
00574 }
00575 }
00576 }
00577 }
00578
00579
00580
00581
00582 ControlRangeDict::ControlRangeDict(ProgramUnit &pgm, int debug GIV(0))
00583 : RangeDict(pgm.symtab())
00584 {
00585
00586 if (switch_value("range_off") > 1) return;
00587
00588
00589 Array<Statement *> toporder_to_stmt;
00590
00591 _debug_level = debug;
00592 Timer tot_timer;
00593 Timer timer;
00594
00595
00596
00597 remove_min_max_var_conflicts(pgm.symtab());
00598
00599 ::_pass_tag = create_pass_tag();
00600 _init_workspaces(pgm);
00601
00602 if (switch_value("pc_call_mods") != 1)
00603 _make_nonlocals_modified_at_calls(pgm);
00604
00605 _calc_toporder(pgm, toporder_to_stmt);
00606
00607 if (_debug_level > 0) {
00608 cout << "! Initialization: " << timer << endl;
00609 timer.reset();
00610 }
00611
00612
00613
00614
00615 _iterate_to_fixed_point(pgm, toporder_to_stmt);
00616
00617 if (_debug_level > 0) {
00618 cout << "! Iterating to fixed point: " << timer << endl;
00619 timer.reset();
00620 }
00621
00622
00623
00624
00625
00626
00627
00628 _add_safe_cond_ranges(pgm);
00629
00630
00631
00632 _generate_map(pgm);
00633
00634 if (_debug_level > 0)
00635 cout << "! Generating stmt_ranges: " << timer << endl;
00636
00637 if (_debug_level >= 10)
00638 _dump_workspaces(cout, pgm);
00639
00640
00641
00642 pgm.clean_workspace(::_pass_tag);
00643
00644 if (_debug_level > 0) {
00645 cout << "! Total time: " << tot_timer << endl;
00646 cout << "! Number of statements: " << pgm.stmts().entries() << endl;
00647 }
00648 }
00649
00650
00651
00652
00653 ControlRangeDict::~ControlRangeDict()
00654 {
00655
00656 }
00657
00658
00659
00660
00661 void
00662 ControlRangeDict::_set_range(const Symbol & ,
00663 const Statement &, Expression * )
00664 {
00665 p_abort("Ranges cannot be modified in a ControlRangeDict object.");
00666 }
00667
00668
00669
00670
00671
00672 void
00673 ControlRangeDict::_del_range(const Symbol & ,
00674 const Statement & )
00675 {
00676 p_abort("Ranges cannot be modified in a ControlRangeDict object.");
00677 }
00678
00679
00680
00681
00682
00683 const Expression *
00684 ControlRangeDict::_get_range_ref(const Symbol &var, const Statement &stmt)
00685 {
00686 RefMap<Symbol, Expression> *stmt_ranges
00687 = _pgm_ranges.find_ref(stmt.tag());
00688
00689 if (stmt_ranges)
00690 return stmt_ranges->find_ref(var);
00691
00692 return 0;
00693 }
00694
00695
00696
00697
00698
00699 void
00700 ControlRangeDict::print(ostream & o) const
00701 {
00702 o << "{";
00703 o << "_range_values={" << _range_values << "}";
00704 o << "_pgm_ranges={";
00705
00706 KeyIterator< String, RefMap<Symbol, Expression> > stmt_iter = _pgm_ranges;
00707
00708 for ( ; stmt_iter.valid(); ++stmt_iter) {
00709 o << stmt_iter.current_key() << ": {";
00710
00711 KeyIterator<Symbol, Expression> var_iter = stmt_iter.current_data();
00712
00713 for ( ; var_iter.valid(); ++var_iter)
00714 o << var_iter.current_key().name_ref()
00715 << var_iter.current_data() << ", ";
00716
00717 o << "}, ";
00718 }
00719
00720 o << "}}";
00721 }
00722
00723
00724
00725
00726 void
00727 ControlRangeDict::pretty_print(ostream & o, const Statement &stmt) const
00728 {
00729
00730 const RefMap<Symbol, Expression> *stmt_ranges
00731 = _pgm_ranges.find_ref(stmt.tag());
00732
00733 if (! stmt_ranges)
00734 o << "{}";
00735 else {
00736 RefList<Symbol> sorted_keys;
00737 KeyIterator<Symbol, Expression> c_iter = *stmt_ranges;
00738
00739 for ( ; c_iter.valid(); ++c_iter)
00740 sorted_keys.ins_last(c_iter.current_key());
00741
00742 sort_sym_list(sorted_keys);
00743 Iterator<Symbol> key_iter = sorted_keys;
00744 bool first = true;
00745
00746 o << "{";
00747
00748 for ( ; key_iter.valid(); ++key_iter) {
00749 if (! first)
00750 o << ", ";
00751 else
00752 first = false;
00753
00754 const Symbol &var = key_iter.current();
00755 const Expression &value = (* stmt_ranges)[var];
00756 pretty_print_range(o, value, var);
00757 }
00758
00759 o << "}";
00760 }
00761 }
00762
00763
00764
00765
00766 Listable *
00767 ControlRangeDict::listable_clone(void) const
00768 {
00769 return 0;
00770 }
00771
00772
00773
00774
00775
00776 int
00777 ControlRangeDict::structures_OK() const
00778 {
00779 return (_range_values.structures_OK()
00780 && _pgm_ranges.structures_OK());
00781 }