Polaris: ControlRangeDict.cc Source File

ControlRangeDict.cc

Go to the documentation of this file.
00001 ///
00002 ///
00003 /// \file ControlRangeDict.cc
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 //#include "PropCtrlRangeWS.cc"
00027 
00028 static unsigned int _pass_tag;  /// ...  Pass tag associated with this pass
00029 
00030 static int _debug_level = 0;
00031 
00032 
00033 /// init_workspaces
00034 ///   Initialize the workspaces for each statement in the program.
00035 ///   Note: A lot of the initialization for eliminate_dead_code are hidden
00036 ///   in the constructor for PropCtrlRangeWS.
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 /// get_workspace
00052 ///   Get the workspace for the given statement.
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 /// dump_workspaces
00066 ///   Dump out the data inside all of the workspaces of the program
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 /// _make_nonlocals_modified_at_calls
00085 ///   Make all non-local variables be marked as potentially modified for all
00086 ///   call statements and all statements containing function calls.
00087 
00088 static void
00089 _make_nonlocals_modified_at_calls(ProgramUnit &pgm)
00090 {
00091     /// ...  Calculate the set of non-local variables.
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         /// ...  Also place any aliased variables in the set.
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     /// ...  Add the non-local variables to the mod_set of all statements that
00125     /// ...  are either call statements or contain function calls.
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 /// _calc_toporder
00172 ///   Calculate toporder for the flow graph.  Essentially, this algorithm
00173 ///   performs a topological sort on the flow graph, ignoring back
00174 ///   edges.
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     /// ...  Calculate the topological order for each statement
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     /// ...  Initialize toporder_to_stmt
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 /// is_else_branch
00229 ///   Return true if the control flow edge between statements pred and succ
00230 ///   corresponds to the else branch of an IF statement.
00231 ///   Note: the exit branch of a DO statement is assumed to be an else
00232 ///   branch.
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 /// intersect_range_maps
00246 ///   Intersect the ranges of the two variable to range set maps.
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 /// range_maps_equal
00280 ///   Return true if the two range maps are equal
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 /// put_succ_on_work_list
00306 ///   Put all of my successors on the work list.
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 /// iterate_to_fixed_point
00319 ///   Propagate the constants contained in the statement's const_maps until
00320 ///   a fixed point is reached.
00321 
00322 static void
00323 _iterate_to_fixed_point(ProgramUnit &pgm, 
00324             const Array<Statement *> &toporder_to_stmt)
00325 {
00326     /// ...  List of statements that need to be updated.
00327 
00328     IntSet work_list(toporder_to_stmt.entries());
00329 
00330     /// ...  Mark all variables for entry statements as non-const and put all
00331     /// ...  entries on the work list.
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     /// ...  Iterate until there are no more elements on the work list
00339 
00340     while (work_list.entries() > 0) {
00341     /// ...  Visit each statement in the work list, in topological order
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         /// ...  Generate the new live variable set for the end of the statement.
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         /// ...  New entering live variable set differs from the old
00384         /// ...  one.  So update the entering and exiting live variable
00385         /// ...  sets for the statement.
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             /// ...  Exiting live var set has changed, so place
00398             /// ...  the statement's predecessors on the work list so
00399             /// ...  that they can update their live variable sets
00400             /// ...  with my live var set.
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 /// _add_safe_cond_ranges
00416 ///   Add any SafeCondition ranges to the PropCtrlRangeWS in_ranges on each statement
00417 ///   within a loop body.
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 /// generate_map
00479 ///   Generate the mapping from statement/variable pairs to ranges from
00480 ///   the range information contained in my WorkSpaces.
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         /// ...  Optimization.  If my input range map is identical to the
00505         /// ...  previous statement's input range map, then my computed
00506         /// ...  variable to range map would be identical to the previous
00507         /// ...  statement's.  So, in such a case, I can just copy the
00508         /// ...  previous statement's variable to range map.
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             /// ...  Intersect all the ranges in the given set to form
00524             /// ...  a single range.
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         /// ...  Insert the computed ranges into stmt_ranges.
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             /// ...  Add the given range to range_values, making sure
00566             /// ...  that there are no duplicate expressions in range_values.
00567             
00568             const Expression &range_ref = _range_values.ins(range_expr);
00569 
00570             // Add the range to the statement/variable to range map.
00571             
00572             stmt_ranges->ins(rmap_iter.current_key(), range_ref);
00573         }
00574         }
00575     }
00576     }
00577 }
00578         
00579 
00580 /// ControlRangeDict
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     /// ...  An array that maps integers to statements.
00589     Array<Statement *> toporder_to_stmt;
00590 
00591     _debug_level = debug;
00592     Timer tot_timer;
00593     Timer timer;
00594 
00595     /// ...  Initialize
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     /// ...  Iteratively propagate the constants throughout the program until a
00613     /// ...  fixed point is reached.
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     /// ...  Dump ranges from the SafeCondition assertions into the PropCtrlRangeWS
00623     /// ...  on each statement of a loop body.  This may change in the future with
00624     /// ...  the demand-driven structure.  We may want to keep the SafeCondition
00625     /// ...  assertions separate, and use them only if we can't prove a loop parallel
00626     /// ...  with the "known" ranges.
00627 
00628     _add_safe_cond_ranges(pgm);
00629 
00630     /// ...  Build the map of variable assertions for each statement..
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     /// ...  Clean up
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 /// Destructor
00652 
00653 ControlRangeDict::~ControlRangeDict()
00654 {
00655     /// ...  nothing to do
00656 }
00657 
00658 
00659 /// set_range
00660 
00661 void
00662 ControlRangeDict::_set_range(const Symbol & /* var */,
00663             const Statement &/* stmt */, Expression * /* range */)
00664 {
00665     p_abort("Ranges cannot be modified in a ControlRangeDict object.");
00666 }
00667 
00668   
00669 
00670 /// del_range
00671 
00672 void
00673 ControlRangeDict::_del_range(const Symbol & /* var */, 
00674                  const Statement & /* stmt */)
00675 {
00676     p_abort("Ranges cannot be modified in a ControlRangeDict object.");
00677 }
00678 
00679 
00680 
00681 /// get_range_ref
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 /// print
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 /// pretty_print
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 /// listable_clone
00765 
00766 Listable *
00767 ControlRangeDict::listable_clone(void) const
00768 {
00769     return 0;
00770 }
00771 
00772 
00773 
00774 /// structures_OK
00775 
00776 int
00777 ControlRangeDict::structures_OK() const
00778 {
00779     return (_range_values.structures_OK()
00780         && _pgm_ranges.structures_OK());
00781 }
 © 1995-2005 University of Illinois, Urbana-Champaign. All rights reserved.  Fri Mar 25 23:05:43 2005