Polaris: GSAFullRangeDict.cc Source File

GSAFullRangeDict.cc

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