Polaris: SSAFullRangeDict.cc Source File

SSAFullRangeDict.cc

Go to the documentation of this file.
00001 ///
00002 ///
00003 /// \file ControlRangeDict.cc
00004 ///
00005 #include "Program.h"
00006 #include "SSAProgramUnit.h"
00007 #include "Statement/Statement.h"
00008 #include "Symbol/Symbol.h"
00009 #include "Symtab.h"
00010 #include "Expression/Expression.h"
00011 #include "utilities/expression_util.h"
00012 #include "Array.h"
00013 #include "IntSet.h"
00014 #include "Timer.h"
00015 #include "p-assert.h"
00016 
00017 #include "SSAFullRangeDict.h"
00018 #include "SSAFullRangeData.h"
00019 #include "RangeExpr.h"
00020 #include "range_util.h"
00021 #include "range_dict_util.h"
00022 #include "stmt_toporder.h"
00023 
00024 #include "SSAFullRangeData.cc"
00025 
00026 #define min(x,y)  ((x) < (y)) ? (x) : (y)
00027 
00028 static int _debug_level = 0;
00029 
00030 /// Template instantiations
00031 
00032 template class Array<SSAFullRangeData *>;
00033 
00034 
00035 /// SSAFullRangeDict
00036 
00037 SSAFullRangeDict::SSAFullRangeDict(SSAProgramUnit &pgm, int debug GIV(0))
00038 : RangeDict(pgm.symtab()), _control_ranges(pgm, debug - 20)
00039 {
00040     if (pgm.stmts().entries() == 0)
00041     return;
00042 
00043     _debug_level = debug;
00044     _pgm_ref = &pgm;
00045     _num_poisoned_ranges = 0;
00046     _timestamp = 0;
00047     _stmt_toporder = stmt_toporder(pgm.stmts());
00048     remove_min_max_var_conflicts(pgm.symtab());
00049 }
00050 
00051 
00052 /// Destructor
00053 
00054 SSAFullRangeDict::~SSAFullRangeDict()
00055 {
00056     delete _stmt_toporder;
00057 }
00058 
00059 
00060 /// touch
00061 
00062 void
00063 SSAFullRangeDict::touch()
00064 {
00065     data_touch();
00066 
00067     Iterator<Statement> stmt_iter = _pgm_ref->stmts().iterator();
00068 
00069     for ( ; stmt_iter.valid(); ++stmt_iter) {
00070         const Statement &stmt = stmt_iter.current();
00071         const Statement &rep_stmt = _control_ranges.representative_stmt(stmt);
00072 
00073         if (&stmt == &rep_stmt) {
00074         RefSet<Symbol> *vars = _control_ranges.range_vars(stmt);
00075             Iterator<Symbol> def_iter = *vars;
00076             
00077             for ( ; def_iter.valid(); ++def_iter)
00078                 _get_range_ref(def_iter.current(), stmt);
00079 
00080         delete vars;
00081         }
00082     }
00083 }
00084 
00085 
00086 /// control_touch
00087 
00088 void
00089 SSAFullRangeDict::control_touch()
00090 {
00091     _control_ranges.touch();
00092 }
00093 
00094 
00095 /// data_touch
00096 
00097 void
00098 SSAFullRangeDict::data_touch()
00099 {
00100     KeyIterator<Symbol,Statement> def_iter = _pgm_ref->_def_map;
00101 
00102     for ( ; def_iter.valid(); ++def_iter) {
00103     bool is_poisoned;
00104     const Symbol &var = def_iter.current_key();
00105 
00106     if (var.type().data_type() == INTEGER_TYPE && ! var.is_array())
00107         _get_data_range_ref(var, is_poisoned);
00108     }
00109 }
00110 
00111 
00112 /// num_data_ranges
00113 
00114 int
00115 SSAFullRangeDict::num_data_ranges() const
00116 {
00117     return _data_ranges.entries();
00118 }
00119 
00120 
00121 /// num_poisoned_ranges
00122 
00123 int
00124 SSAFullRangeDict::num_poisoned_ranges() const
00125 {
00126     return _num_poisoned_ranges;
00127 }
00128 
00129 
00130 /// set_range
00131 
00132 void
00133 SSAFullRangeDict::_set_range(const Symbol &var,
00134             const Statement &stmt, Expression *range)
00135 {
00136     p_abort("Ranges cannot be modified in a SSAFullRangeDict object.");
00137 }
00138 
00139   
00140 
00141 /// del_range
00142 
00143 void
00144 SSAFullRangeDict::_del_range(const Symbol &var, const Statement &stmt)
00145 {
00146     p_abort("Ranges cannot be modified in a SSAFullRangeDict object.");
00147 }
00148 
00149 
00150 /// ins_data_range
00151 ///   Add a new data range.  Also delete the associated poisoned data
00152 ///   range, if it exists, since it would no longer be needed.
00153 
00154 const Expression &
00155 SSAFullRangeDict::_ins_data_range(const Symbol &var,
00156                   Expression *range)
00157 {
00158     if (! range)
00159     range = omega();
00160 
00161     _data_ranges.ins(var, range);
00162 
00163     if (_debug_level >= 10)
00164     cout << "! Inserted data range: " << var.name_ref()
00165         << " = " << *range << endl;
00166 
00167     return *range;
00168 }
00169 
00170 
00171 /// _are_all_id_args
00172 ///   Return true if the arguments of the given expression is all ID exprs.
00173 
00174 static bool
00175 _are_all_id_args(const Expression &expr)
00176 {
00177     Iterator<Expression> iter = expr.arg_list();
00178 
00179     for ( ; iter.valid(); ++iter)
00180     if (iter.current().op() != ID_OP)
00181         return false;
00182 
00183     return true;
00184 }
00185 
00186 
00187 /// _init_data_preds
00188 ///   Initialize the arg_preds field of the given SSAFullRangeData object.
00189 
00190 static void
00191 _init_data_preds(SSAFullRangeData &data)
00192 {
00193     const Statement *flow_join_stmt = &data.stmt();
00194 
00195     while (flow_join_stmt
00196        && flow_join_stmt->pred().entries() == 1
00197        && flow_join_stmt->pred().member(*flow_join_stmt->prev_ref()))
00198     flow_join_stmt = flow_join_stmt->prev_ref();
00199 
00200     p_assert(flow_join_stmt,
00201          "Couldn't find the control flow join statement for the given phi-statement.");
00202     const List<Expression> &phi_args = data.stmt().rhs().parameters_guarded().arg_list();
00203 
00204     /// ...  Don't build the arg_preds field for unreachable phi-statements.
00205 
00206     if (flow_join_stmt->pred().entries() == 0)
00207     return;
00208 
00209     p_assert(flow_join_stmt->pred().entries() == phi_args.entries(),
00210          "There number of phi arguments and the number of flow predecessors differ.");
00211 
00212     RefSet<Symbol> multiple_args;
00213     Iterator<Statement> pred_iter = flow_join_stmt->pred();
00214     int arg_num = 0;
00215 
00216     for ( ; pred_iter.valid(); ++pred_iter, ++arg_num) {
00217     const Symbol &arg_var = phi_args[arg_num].symbol();
00218 
00219     if (! multiple_args.member(CASTAWAY(Symbol &) arg_var))
00220         if (data.arg_preds.member(CASTAWAY(Symbol &) arg_var)) {
00221         /// ...  Variable occurs in more than one argument of the phi
00222         /// ...  function.  So, conservatively make it have no predecessors.
00223 
00224         data.arg_preds.del(CASTAWAY(Symbol &) arg_var);
00225         multiple_args.ins(CASTAWAY(Symbol &) arg_var);
00226         }
00227         else
00228         data.arg_preds.ins(arg_var, pred_iter.current());
00229     }
00230 }
00231 
00232 
00233 /// _order_args
00234 ///   Sort the SSAFullRangeData arguments in topological order.
00235 
00236 void
00237 SSAFullRangeDict::_order_args(SSAFullRangeData &data) const
00238 {
00239     RefList<Symbol> unordered_args = data.args;
00240     data.args.clear();
00241     Map<Symbol,IntElem> arg_order;
00242 
00243     while (unordered_args.entries()) {
00244         Symbol &arg = unordered_args.grab(0);
00245         const Statement *def = _pgm_ref->_def_map.find_ref(arg);
00246         int order = -1;
00247 
00248         if (def) {
00249             const IntElem *order_elem = _stmt_toporder->find_ref(def->tag());
00250 
00251             if (order_elem)
00252                 order = order_elem->value();
00253         }
00254 
00255     Iterator<Symbol> iter = data.args;
00256     for ( ; iter.valid() && order > arg_order[iter.current()]; ++iter);
00257 
00258     if (iter.valid())
00259         data.args.ins_before(arg, iter.current());
00260     else
00261         data.args.ins_last(arg);
00262 
00263         arg_order.ins(arg, new IntElem(order));
00264     }
00265 }        
00266 
00267 
00268 /// _create_data
00269 ///   Create an SSAFullRangeData object for the given statement.
00270 ///   Return NULL if this creation fails.
00271 
00272 SSAFullRangeData *
00273 SSAFullRangeDict::_create_data(const Statement &stmt, int &df_num,
00274                    RefList<SSAFullRangeData> &scc_node_stack)
00275 {
00276     SSAFullRangeData *data = new SSAFullRangeData(stmt, _timestamp, *this,
00277                           _debug_level);
00278 
00279     /// ...  Speed (vs. accurracy) optimization.
00280 
00281     data->union_arg_ranges = true;
00282 
00283     if (data->is_phi_stmt
00284     && ! _are_all_id_args(stmt.rhs().parameters_guarded())) {
00285 
00286     if (_debug_level >= 20) {
00287         cout << "! Couldn't create SSAFullRangeData object for definition: ";
00288         int zero = 0;
00289         stmt.write(cout, zero);
00290     }
00291 
00292     delete data;
00293     return 0;
00294     }
00295 
00296     if (data->is_phi_stmt)
00297     _init_data_preds(*data);
00298 
00299     _pending_ranges.ins(stmt.lhs().symbol(), data);
00300     ++df_num;
00301     data->df_order = df_num;
00302     data->low_link = df_num;
00303     scc_node_stack.ins_first(*data);
00304 
00305     /// ...  Add links to the ranges or SSAFullRangeData objects
00306     /// ...  that are needed by my data object to compute my value.
00307 
00308     Iterator<Expression> use_iter = stmt.in_refs();
00309 
00310     for ( ; use_iter.valid(); ++use_iter) {
00311     const Symbol *var = use_iter.current().base_variable_ref();
00312 
00313         if (! data->args.member(* CASTAWAY(Symbol *) var))
00314             data->args.ins_last(* CASTAWAY(Symbol *) var);
00315 
00316     SSARangeOrData *link;
00317 
00318     if (! var
00319         || var->is_array()
00320         || var->type().data_type() != INTEGER_TYPE)
00321 
00322         link = new SSARangeOrData(0);
00323     else
00324         link = new SSARangeOrData(_probe_data_ranges(*var, df_num,
00325                              scc_node_stack));
00326 
00327     data->arg_ranges_or_data.ins(*var, link);
00328 
00329     if (link->is_data() && link->data().timestamp() == _timestamp) {
00330         data->needs_iteration = true;
00331 
00332         if (scc_node_stack.member(link->data()))
00333         if (data->df_order < link->data().df_order)
00334             data->low_link = min(data->low_link, link->data().low_link);
00335         else
00336             data->low_link = min(data->low_link, link->data().df_order);
00337     }
00338     }
00339 
00340     if (data->needs_iteration) {
00341     if (data->is_phi_stmt)
00342         _order_args(*data);
00343     
00344     /// ...  Put myself in the users fields of the SSAFullRangeData objects
00345     /// ...  I depend upon.
00346     
00347     RefSet<SSAFullRangeData> *succs = data->succs();
00348     Iterator<SSAFullRangeData> succ_iter = *succs;
00349     
00350     for ( ; succ_iter.valid(); ++succ_iter)
00351         succ_iter.current().users.ins(*data);
00352     }
00353     
00354     return data;
00355 }
00356 
00357 
00358 /// _mark_data_as_computed
00359 ///   Set the computed field to true for all nodes in the graph rooted at
00360 ///   data.
00361 
00362 void
00363 SSAFullRangeDict::_mark_data_as_computed(SSAFullRangeData &data)
00364 {
00365     const Symbol &var = data.stmt().lhs().symbol();
00366     
00367     if (! data.computed) {
00368     p_assert(data.is_poisoned && data.timestamp() != _timestamp,
00369          "Non-poisoned data cannot be marked as computed.");
00370     data.computed = true;
00371     RefSet<SSAFullRangeData> *succs = data.succs();
00372     Iterator<SSAFullRangeData> iter = *succs;
00373 
00374     for ( ; iter.valid(); ++iter)
00375         _mark_data_as_computed(iter.current());
00376 
00377     delete succs;
00378     }
00379 }
00380 
00381 
00382 /// _commit_data
00383 ///   Commit the range computed by my data object, as well as ranges
00384 ///   computed by the data objects for my arguments.
00385 ///   Return NULL if this creation fails.
00386 
00387 void
00388 SSAFullRangeDict::_commit_data(SSAFullRangeData &data)
00389 {
00390     p_assert(! data.is_poisoned && data.timestamp() == _timestamp,
00391          "Poisoned data cannot be committed.");
00392     const Symbol &var = data.stmt().lhs().symbol();
00393     
00394     if (! _data_ranges.member(var)) {
00395     _ins_data_range(var, data.grab_range());
00396     data.computed = true;
00397     RefSet<SSAFullRangeData> *succs = data.succs();
00398     Iterator<SSAFullRangeData> iter = *succs;
00399 
00400     for ( ; iter.valid(); ++iter)
00401         _commit_data(iter.current());
00402 
00403     delete succs;
00404     }
00405 }
00406 
00407 
00408 /// _delete_data
00409 ///   Delete my data object and all data objects belonging to my arguments.
00410 
00411 void
00412 SSAFullRangeDict::_delete_data(SSAFullRangeData &data)
00413 {
00414     if (data.timestamp() == _timestamp) {
00415     Symbol & temp = CASTAWAY(Symbol &) data.stmt().lhs().symbol();
00416     SSAFullRangeData *my_data = _pending_ranges.grab(temp);
00417     p_assert(my_data, "Tried to delete an already deleted SSAFullRangeData object.");
00418     KeyIterator<Symbol,SSARangeOrData> iter = data.arg_ranges_or_data;
00419     
00420     for ( ; iter.valid(); ++iter)
00421         if (_pending_ranges.member(iter.current_key())
00422         && iter.current_data().is_data())
00423         
00424         _delete_data(iter.current_data().data());
00425     
00426     delete my_data;
00427     }
00428 }
00429 
00430 
00431 /// add_leaf_nodes_to_set
00432 ///   Add all nodes whose ordering is smaller than all of its successors
00433 ///   to the set.
00434 
00435 static void
00436 _add_leaf_nodes_to_set(const Array<SSAFullRangeData *> &iter_order,
00437                IntSet &start_nodes)
00438 {
00439     for (int i = 0; i < iter_order.entries(); ++i) {
00440     const SSAFullRangeData &data = *iter_order[i];
00441     bool smaller_than_args = true;
00442     RefSet<SSAFullRangeData> *succs = data.succs();
00443     Iterator<SSAFullRangeData> succ_iter = *succs;
00444     
00445     for ( ; succ_iter.valid() && smaller_than_args; ++succ_iter) {
00446         SSAFullRangeData &succ_data = succ_iter.current();
00447 
00448         if (succ_data.needs_iteration
00449         && succ_data.toporder < data.toporder)
00450 
00451         smaller_than_args = false;
00452     }
00453 
00454     delete succs;
00455 
00456     if (smaller_than_args)
00457         start_nodes.ins(data.toporder);
00458     }
00459 }
00460 
00461 
00462 /// add_phi_nodes_to_set
00463 ///   Add all nodes for phi-statements to the set.
00464 
00465 static void
00466 _add_phi_nodes_to_set(const Array<SSAFullRangeData *> &iter_order,
00467               IntSet &phi_nodes)
00468 {
00469     for (int i = 0; i < iter_order.entries(); ++i) {
00470     const SSAFullRangeData &data = *iter_order[i];
00471 
00472     if (data.is_phi_stmt)
00473         phi_nodes.ins(data.toporder);
00474     }
00475 }
00476 
00477 
00478 /// calc_iter_order
00479 ///   Compute an order to visit the SSAFullRangeDict nodes during an
00480 ///   iteration.  This order is a reverse topological ordering of the
00481 ///   graph, ignoring back edges.  (Reverse topological ordering means
00482 ///   that if there is an edge (U --> V), then rtoporder(U) >= rtoporder(V).)
00483 
00484 void
00485 SSAFullRangeDict::_calc_iter_order1(SSAFullRangeData &data,
00486                     RefList<SSAFullRangeData> &iter_order_list)
00487 {
00488     if (data.toporder < 0) {
00489     const IntElem *toporder_elem = _stmt_toporder->find_ref(data.stmt().tag());
00490     p_assert(toporder_elem,
00491          "Statement was not assigned a topological ordering value.");
00492     int to = toporder_elem->value();
00493     p_assert(to >= 0,
00494          "Statement has a negative topological ordering value.");
00495     data.toporder = to;
00496     
00497     /// ...  Insert data into iter_order_list, which is sorted by toporder.
00498     
00499     Iterator<SSAFullRangeData> order_iter = iter_order_list;
00500     
00501     for ( ; order_iter.valid() && to > order_iter.current().toporder;
00502          ++order_iter);
00503     
00504     p_assert(! order_iter.valid() || to < order_iter.current().toporder,
00505          "Internal error:  SSAFullRangeData object was inserted twice in iter_order.");
00506     
00507     if (order_iter.valid())
00508         iter_order_list.ins_before(data, order_iter.current());
00509     else
00510         iter_order_list.ins_last(data);
00511     
00512     /// ...  Visit the data object's successors.
00513     
00514     RefSet<SSAFullRangeData> *succs = data.succs();
00515     Iterator<SSAFullRangeData> succ_iter = *succs;
00516     
00517     for ( ; succ_iter.valid(); ++succ_iter)
00518         _calc_iter_order1(succ_iter.current(), iter_order_list);
00519     }
00520 }
00521     
00522 
00523 Array<SSAFullRangeData *> *
00524 SSAFullRangeDict::_calc_iter_order(SSAFullRangeData &root_node)
00525 {
00526     RefList<SSAFullRangeData> iter_order_list;
00527     _calc_iter_order1(root_node, iter_order_list);
00528 
00529     Array<SSAFullRangeData *> *iter_order = new Array<SSAFullRangeData *>(iter_order_list.entries());
00530 
00531     for (int i = 0; i < iter_order->entries(); ++i) {
00532     (*iter_order)[i] = &iter_order_list.grab(0);
00533     (*iter_order)[i]->toporder = i;
00534     }
00535 
00536     p_assert(iter_order_list.entries() == 0,
00537          "Internal Error: not all SSAFullRangeData objects were places in iter_order.");
00538     return iter_order;
00539 }
00540 
00541 
00542 /// iterate_to_fixed_point_phase
00543 ///   Iterate over the pending SSAFullRangeData nodes until a fixed point
00544 ///   is reached.
00545 
00546 void
00547 SSAFullRangeDict::_iterate_to_fixed_point_phase(const Array<SSAFullRangeData *> &rtoporder_to_stmt,
00548                         const IntSet &start_stmts,
00549                         bool widening_phase)
00550 {
00551     IntSet work_list(start_stmts);
00552     /// ...  List of statements that need to be updated.
00553 
00554     /// ...  Iterate until there are no more elements on the work list
00555 
00556     while (work_list.entries() > 0) {
00557     for (int data_num = work_list.first();
00558          data_num != -1;
00559          data_num = work_list.next(data_num)) {
00560 
00561         SSAFullRangeData &data = *rtoporder_to_stmt[data_num];
00562         work_list.del(data_num);
00563 
00564         if (data.update(widening_phase)) {
00565         Iterator<SSAFullRangeData> user_iter = data.users;
00566 
00567         for ( ; user_iter.valid(); ++user_iter)
00568             work_list.ins(user_iter.current().toporder);
00569         }
00570     }
00571     }
00572 }
00573     
00574 
00575 /// iterate_to_fixed_point
00576 ///   Iterate on the given range dependence graph, starting at the given
00577 ///   node, until a fixed point is reached.
00578 
00579 void
00580 SSAFullRangeDict::_iterate_to_fixed_point(SSAFullRangeData &root_node)
00581 {
00582     /// ...  Determine a good order to visit the SSAFullRangeData nodes.
00583 
00584     Array<SSAFullRangeData *> *iter_order = _calc_iter_order(root_node);
00585 
00586     /// ...  Widening phase:
00587     /// ...    This phase iterates to a fixed point, applying the widening operator
00588     /// ...    on all statements with back edges.
00589     /// ...    The widening operator makes an overly conservative estimate of the
00590     /// ...    fixed point value, so as to guarrantee convergence.
00591 
00592     if (_debug_level >= 20)
00593     cout << "\nWidening Phase:\n";
00594 
00595     IntSet start_nodes(iter_order->entries());
00596     _add_phi_nodes_to_set(*iter_order, start_nodes);
00597     /// ...  _add_leaf_nodes_to_set(*iter_order, start_nodes);
00598 
00599     for (int data_num = start_nodes.first();
00600      data_num != -1;
00601      data_num = start_nodes.next(data_num))
00602     (* iter_order)[data_num]->needs_widening = true;
00603 
00604     _iterate_to_fixed_point_phase(*iter_order, start_nodes, true);
00605     
00606     /// ...  Narrowing phase:
00607     /// ...    This phase iterates to a fixed point, applying the narrowing operator
00608     /// ...    on all statements with back edges.
00609     /// ...    The narrowing operator attempts to regain some of the information
00610     /// ...    lost by the widening operator.
00611 
00612     if (_debug_level >= 20)
00613     cout << "\nNarrowing Phase:\n";
00614 
00615     IntSet phi_nodes(iter_order->entries());
00616     _add_phi_nodes_to_set(*iter_order, phi_nodes);
00617 
00618     _iterate_to_fixed_point_phase(*iter_order, phi_nodes, false);
00619 
00620     delete iter_order;
00621 }
00622 
00623 
00624 /// probe_data_ranges
00625 ///   Search through the program to collect all phi statements that may
00626 ///   affect the values of the arguments of the phi statement for the
00627 ///   given variable.  If the dependences between these phi statements are
00628 ///   acyclic, immediately compute and return the range for the given phi
00629 ///   statement.  Otherwise, return a SSAFullRangeData object representing
00630 ///   the root node of this cyclic dependency graph.
00631 
00632 SSARangeOrData
00633 SSAFullRangeDict::_probe_data_ranges(const Symbol &var, int &df_num,
00634                      RefList<SSAFullRangeData> &scc_node_stack)
00635 {
00636     const Expression *range = _data_ranges.find_ref(var);
00637 
00638     if (range) {
00639     /// ...  Range has already been computed.  So return it.
00640 
00641     return SSARangeOrData(range);
00642     }
00643     else {
00644     const Statement *def = _pgm_ref->_def_map.find_ref(var);
00645 
00646     if (! def
00647         || def->stmt_class() != ASSIGNMENT_STMT
00648         || def->rhs().type().data_type() != INTEGER_TYPE
00649         || contains_func_call(*def)) {
00650         
00651         /// ...  Definition for variable is not a legal assignment statement.
00652         /// ...  So set its range to NULL.
00653 
00654         if (_debug_level >= 20) {
00655         if (def) {
00656             cout << "! Unknown statement type for definition: ";
00657             int zero = 0;
00658             def->write(cout, zero);
00659         }
00660         else
00661             cout << "! No definition for variable "
00662             << var.name_ref() << endl;
00663         }
00664 
00665         return SSARangeOrData(&_ins_data_range(var, 0));
00666     }
00667     else {
00668         /// ...  Definition of variable is an assignment statement.
00669         // So build a SSAFullRangeData object to hold/compute
00670         /// ...  the variable's range.
00671 
00672         SSAFullRangeData *data = _pending_ranges.find_ref(var);
00673 
00674         if (data) {
00675         /// ...  Definition already has a SSAFullRangeData object.
00676         /// ...  So return it.
00677 
00678         return SSARangeOrData(*data);
00679         }
00680         else {
00681         /// ...  Create and initialize a SSAFullRangeDict object.
00682 
00683         data = _create_data(*def, df_num, scc_node_stack);
00684 
00685         if (! data)
00686             return SSARangeOrData(&_ins_data_range(var, 0));
00687         else {
00688             if (data->needs_iteration) {
00689             /// ...  My computed range needs iteration to a fixed
00690             /// ...  point.
00691 
00692             if (data->df_order != data->low_link) {
00693                 /// ...  Node is an internal node in a strongly-
00694                 /// ...  connected-component (SCC), (Tarjan's algorithm
00695                 /// ...  is used to determine this).  So return the
00696                 /// ...  object.
00697 
00698                 return SSARangeOrData(*data);
00699             }
00700             else {
00701                 /// ...  Node is the root node of a SCC.  So, iterate
00702                 /// ...  to a fixed point to compute its value.
00703 
00704                 _iterate_to_fixed_point(*data);
00705 
00706                 while (scc_node_stack.entries()
00707                    && scc_node_stack[0].df_order >= data->df_order)
00708                 scc_node_stack.del(0);
00709 
00710                 if (data->is_poisoned) {
00711                 _mark_data_as_computed(*data);
00712                 return SSARangeOrData(*data);
00713                 }
00714                 else {
00715                 _commit_data(*data);
00716                 const Expression *range = _data_ranges.find_ref(var);
00717                 p_assert(range, "_commit_data() did not commit my range.");
00718                 _delete_data(*data);
00719                 return SSARangeOrData(range);
00720                 }
00721             }
00722             }
00723             else {
00724             data->update();
00725             data->computed = true;
00726             p_assert(scc_node_stack.entries() > 0
00727                  && &scc_node_stack[0] == data,
00728                  "Some nodes were missed by SCC algorithm.");
00729             scc_node_stack.del(0);
00730             
00731             if (data->is_poisoned) {
00732                 /// ...  My computed range was poisoned, (i.e., may be
00733                 /// ...  inaccurate because it couldn't be completely
00734                 /// ...  computed), so let my caller worry about it.
00735 
00736                 return SSARangeOrData(*data);
00737             }
00738             else {
00739                 /// ...  I was able to fully compute my range.
00740                 /// ...  So delete my data object and store and return
00741                 /// ...  the computed range.
00742                 
00743                 SSARangeOrData result(&_ins_data_range(var, data->grab_range()));
00744                 Symbol & temp = CASTAWAY(Symbol &)data->stmt().lhs().symbol();
00745                 _pending_ranges.del(temp);
00746                 return result;
00747             }
00748             }
00749         }
00750         }           
00751     }    
00752     }
00753 }
00754 
00755 
00756 /// get_data_range_ref
00757 ///   Get the range from the set of data ranges.  If the range has not
00758 ///   been computed, compute it now.
00759 
00760 const Expression *
00761 SSAFullRangeDict::_get_data_range_ref(const Symbol &var, bool &is_poisoned)
00762 {
00763     is_poisoned = false;
00764 
00765     if (var.is_array() || var.type().data_type() != INTEGER_TYPE)
00766     return 0;
00767 
00768     ++_timestamp;
00769     int orig_num_pending_ranges = _pending_ranges.entries();
00770     int df_num = 0;
00771     RefList<SSAFullRangeData> scc_node_stack;
00772     SSARangeOrData range_or_data = _probe_data_ranges(var, df_num,
00773                               scc_node_stack);
00774     p_assert(scc_node_stack.entries() == 0,
00775          "Some nodes were missed by SCC algorithm.");
00776     const Expression *range;
00777 
00778     if (range_or_data.is_range())
00779     range = range_or_data.range_ref();
00780     else {
00781     SSAFullRangeData &data = range_or_data.data();
00782 
00783     p_assert(data.is_poisoned || data.timestamp() != _timestamp,
00784          "Unpoisoned SSAFullRangeData object returned by _probe_data_ranges().");
00785 
00786     if (data.range_ref()) {
00787         range = &_poisoned_ranges.ins(data.range_ref()->clone());
00788         ++_num_poisoned_ranges;
00789     }
00790     else
00791         range = 0;
00792     
00793     is_poisoned = true;
00794     
00795     if (_debug_level >= 20) {
00796         cout << "! Computed data range is poisoned: ";
00797         cout << var.name_ref() << " = ";
00798         
00799         if (range)
00800         cout << *range;
00801         else
00802         cout << "NULL";
00803         
00804         cout << endl;
00805     }
00806 
00807     p_assert(_timestamp > 1, "A base data range was poisoned.");
00808 
00809     _delete_data(data);
00810     }
00811 
00812     p_assert(_pending_ranges.entries() == orig_num_pending_ranges,
00813          "Method SSAFullRangeDict::_get_data_range_ref() did not discard all of its temporary data structures.");
00814     --_timestamp;
00815 
00816     return range;
00817 }
00818 
00819 
00820 /// get_range_ref
00821 
00822 const Expression *
00823 SSAFullRangeDict::_get_range_ref(const Symbol &var, const Statement &stmt)
00824 {
00825     if (var.is_array() || var.type().data_type() != INTEGER_TYPE)
00826     return 0;
00827 
00828     if (_timestamp == 0)
00829     _num_poisoned_ranges = 0;
00830 
00831     const Statement &rep_stmt = _control_ranges.representative_stmt(stmt);
00832     RefMap<Symbol, Expression> *stmt_ranges = _pgm_ranges.find_ref(rep_stmt);
00833     const Expression *range;
00834 
00835     if (stmt_ranges)
00836     range = stmt_ranges->find_ref(var);
00837     else
00838     range = 0;
00839 
00840     if (! range) {
00841     /// ...  Range hasn`t been computed yet.  So, compute it now.
00842 
00843     bool is_poisoned = false;
00844     const Expression *data_range_ref = _get_data_range_ref(var, is_poisoned);
00845     RangeAccessor control_accessor(_control_ranges, rep_stmt);
00846     const Expression *control_range_ref
00847         = control_accessor.get_range_ref(var);
00848 
00849     if (data_range_ref && data_range_ref->op() != OMEGA_OP) {
00850         if (control_range_ref && control_range_ref->op() != OMEGA_OP) {
00851         if (! stmt_ranges) {
00852             stmt_ranges = new RefMap<Symbol, Expression>;
00853             _pgm_ranges.ins(rep_stmt, stmt_ranges);
00854         }
00855 
00856         stmt_ranges->ins(var, *control_range_ref);
00857         RangeAccessor accessor(*this, rep_stmt);
00858         Expression *new_range = intersect_ranges(data_range_ref,
00859                              accessor,
00860                              control_range_ref,
00861                              accessor);
00862         
00863         if (! new_range)
00864             new_range = omega();
00865 
00866         if (is_poisoned) {
00867             range = &_poisoned_ranges.ins(new_range);
00868             /// ...  ++_num_poisoned_ranges;
00869             stmt_ranges->del(CASTAWAY(Symbol &) var);
00870         }
00871         else {
00872             range = &_range_values.ins(new_range);
00873             stmt_ranges->ins(var, *range);
00874         }
00875         }
00876         else
00877         range = data_range_ref;
00878     }
00879     else if (control_range_ref && control_range_ref->op() != OMEGA_OP)
00880         range = control_range_ref;
00881     else
00882         range = 0;
00883     }
00884 
00885     if (range && range->op() == OMEGA_OP)
00886     range = 0;
00887 
00888     if (_timestamp == 0)
00889     _poisoned_ranges.clear();
00890 
00891     return range;
00892 }
00893 
00894 
00895 /// clear
00896 
00897 void
00898 SSAFullRangeDict::clear()
00899 {
00900     _control_ranges.clear();
00901     _data_ranges.clear();
00902     _pgm_ranges.clear();
00903     _pending_ranges.clear();
00904     _range_values.clear();
00905     _poisoned_ranges.clear();
00906     _timestamp = 0;
00907     _num_poisoned_ranges = 0;
00908 }
00909 
00910 
00911 /// clear
00912 
00913 void
00914 SSAFullRangeDict::clear_ranges()
00915 {
00916     _control_ranges.clear_ranges();
00917 
00918     _data_ranges.clear();
00919     _pgm_ranges.clear();
00920     _pending_ranges.clear();
00921     _range_values.clear();
00922     _poisoned_ranges.clear();
00923     _timestamp = 0;
00924     _num_poisoned_ranges = 0;
00925 }
00926 
00927 
00928 /// control_range_dict
00929 
00930 SSAControlRangeDict &
00931 SSAFullRangeDict::control_range_dict()
00932 {
00933     return _control_ranges;
00934 }
00935 
00936 
00937 /// print
00938 
00939 void
00940 SSAFullRangeDict::print(ostream & o) const
00941 {
00942     o << "[";
00943     o << "pgm_ranges={";
00944     
00945     KeyIterator<Statement, RefMap<Symbol, Expression> > pgm_range_iter = _pgm_ranges;
00946     bool first_stmt = true;
00947 
00948     for ( ; pgm_range_iter.valid(); ++pgm_range_iter) {
00949     if (! first_stmt)
00950         o << ", ";
00951     else
00952         first_stmt = false;
00953     
00954     o << pgm_range_iter.current_key().tag() << ": {";
00955 
00956     KeyIterator<Symbol, Expression> stmt_range_iter = pgm_range_iter.current_data();
00957     bool first_symbol = true;
00958 
00959     for ( ; stmt_range_iter.valid(); ++stmt_range_iter) {
00960         if (! first_symbol)
00961         o << ", ";
00962         else
00963         first_symbol = false;
00964 
00965         o << stmt_range_iter.current_key().name_ref()
00966         << ": " << stmt_range_iter.current_data();
00967     }
00968 
00969     o << "}";
00970     }
00971 
00972     o << "}";
00973     /// ...  o << ", control_ranges=" << _control_ranges;
00974     o << ", data_ranges={";
00975 
00976     KeyIterator<Symbol, Expression> data_range_iter = _data_ranges;
00977     bool first_symbol = true;
00978     
00979     for ( ; data_range_iter.valid(); ++data_range_iter) {
00980     if (! first_symbol)
00981         o << ", ";
00982     else
00983         first_symbol = false;
00984     
00985     o << data_range_iter.current_key().name_ref()
00986         << ": " << data_range_iter.current_data();
00987     }
00988     
00989     o << "}";
00990     o << ", pending_ranges={";
00991 
00992     KeyIterator<Symbol, SSAFullRangeData> pend_iter = _pending_ranges;
00993     first_symbol = true;
00994     
00995     for ( ; pend_iter.valid(); ++pend_iter) {
00996     if (! first_symbol)
00997         o << ", ";
00998     else
00999         first_symbol = false;
01000     
01001     o << pend_iter.current_key().name_ref()
01002         << ": " << pend_iter.current_data();
01003     }
01004     
01005     o << "}";
01006     o << ", timestamp=" << _timestamp;
01007     o << "]";
01008 }
01009 
01010 
01011 /// pretty_print
01012 
01013 void
01014 SSAFullRangeDict::pretty_print(ostream & o, const Statement &stmt) const
01015 {
01016     o << "[";
01017     o << "control ranges = ";
01018     _control_ranges.pretty_print(o, stmt);
01019     o << ", data ranges = {";
01020 
01021     RefList<Symbol> sorted_keys;
01022     KeyIterator<Symbol,Expression> data_iter = _data_ranges;
01023     
01024     for ( ; data_iter.valid(); ++data_iter)
01025     sorted_keys.ins_last(data_iter.current_key());
01026 
01027     sort_sym_list(sorted_keys);
01028 
01029     Iterator<Symbol> key_iter = sorted_keys;
01030     bool first = true;
01031     bool need_comma = true;
01032     
01033     for ( ; key_iter.valid(); ++key_iter) {
01034     if (! first && need_comma)
01035         o << ", ";
01036     else
01037         first = false;
01038     
01039     const Symbol &var = key_iter.current();
01040     const Expression *value = _data_ranges.find_ref(var);
01041 
01042     if (value->op() != OMEGA_OP || _debug_level >= 30) {
01043         pretty_print_range(o, *value, var);
01044         need_comma = true;
01045     }
01046     else
01047         need_comma = false;
01048     }
01049 
01050     o << "}";
01051     o << ", merged ranges = {";
01052 
01053     const RefMap<Symbol,Expression> *stmt_ranges = _pgm_ranges.find_ref(stmt);
01054 
01055     if (stmt_ranges) {
01056     sorted_keys.clear();
01057     KeyIterator<Symbol,Expression> merged_iter = *stmt_ranges;
01058     
01059     for ( ; merged_iter.valid(); ++merged_iter)
01060         sorted_keys.ins_last(merged_iter.current_key());
01061 
01062     sort_sym_list(sorted_keys);
01063     first = true;
01064     need_comma = true;
01065     
01066     for (key_iter.reset(); key_iter.valid(); ++key_iter) {
01067         if (! first && need_comma)
01068         o << ", ";
01069         else
01070         first = false;
01071         
01072         const Symbol &var = key_iter.current();
01073         const Expression *value = stmt_ranges->find_ref(var);
01074         
01075         if (value->op() != OMEGA_OP || _debug_level >= 30) {
01076         pretty_print_range(o, *value, var);
01077         need_comma = true;
01078         }
01079         else
01080         need_comma = false;
01081     }
01082     }
01083 
01084     o << "}";
01085     o << "]";
01086 }
01087 
01088 
01089 /// listable_clone
01090 
01091 Listable *
01092 SSAFullRangeDict::listable_clone(void) const
01093 {
01094     p_abort("SSAFullRangeDicts cannot be duplicated.");
01095     return 0;
01096 }
01097 
01098 
01099 
01100 /// structures_OK
01101 
01102 int
01103 SSAFullRangeDict::structures_OK() const
01104 {
01105     return 1;
01106 }
 © 1995-2005 University of Illinois, Urbana-Champaign. All rights reserved.  Fri Mar 25 23:06:08 2005