Polaris: AbstractAccess.cc Source File

AbstractAccess.cc

Go to the documentation of this file.
00001 ///
00002 /// \file AbstractAccess.cc
00003 ///
00004 #ifdef POLARIS_GNU_PRAGMAS
00005 #pragma implementation
00006 #endif
00007 ///
00008 #include "utilities/access_util.h"
00009 #include "utilities/lambda_util.h"
00010 #include "utilities/mem_util.h"
00011 #include "utilities/expression_util.h"
00012 #include "AbstractAccess.h"
00013 #include "InlineObject.h"
00014 #include "Monotonicity.h"
00015 #include "ProgramUnit.h"
00016 #include "SmallIntSet.h"
00017 #include "Range/RangeAccessor.h"
00018 #include "Range/AIRangeDict.h"
00019 //#include "Range/StmtRanges.h"
00020 #include "Range/range_util.h"
00021 #include "Traverser.h"
00022 #include "TranslateObject.h"
00023 #include "translateobject.h"
00024 #include "UGraphIterator.h"
00025 #include "utilities/expression_util.h"
00026 #include "utilities/gsa_util.h"
00027 #include "utilities/stmt_util.h"
00028 
00029 int _ipa = -1;
00030 /// A static global to hold the value of the ipa switch
00031 int _ipa_reasons = -1;
00032 /// A static global to hold the value of the ipa switch
00033 int _ar_coalesce = -1;
00034 /// A static global to hold the value of the ar_coalesce switch
00035 int _ar_aggregate = -1;
00036 /// A static global to hold the value of the ar_aggregate switch
00037 int _ar_interleave = -1;
00038 /// A static global to hold the value of the ar_interleave switch
00039 int _ar_match_dims = -1;
00040 /// A static global to hold the value of the ar_match_dims switch
00041 int _ar_logging = -1;
00042 /// A static global to hold the value of the ar_match_dims switch
00043 ofstream arlog;
00044 /// The file for writing the Access Region log.
00045 int _ar_leave_descr = -1;
00046 /// Controls whether descriptors are left on statements or not
00047 int _ar_prtstats = -1;
00048 /// Controls collecting and printing of statistics (ar_prtstats switch)
00049 int _ar_approx_thresh = -1;
00050 /// Set the threshold for list size which causes the list to be replaced by 
00051 /// a single "approximate LMAD"
00052 int _ar_effort = -1;
00053 /// Controls how hard we work on simplifying a set of descriptors 
00054 /// (scale of 1 to 10, 10 being to work the hardest)
00055 int _ar_reshape = -1;
00056 ofstream stats_out;
00057 
00058 static Boolean
00059 is_array_ref (const Expression & expr)
00060 {
00061     switch (expr.op()) 
00062     {
00063     case ARRAY_REF_OP:
00064         return True;
00065     default:
00066         return False;
00067     }
00068 }
00069 
00070 AbstractAccess::AbstractAccess( ) {
00071     #ifdef CLASS_INSTANCE_REGISTRY
00072     register_instance(ABSTRACT_ACCESS, sizeof(AbstractAccess), this);
00073     #endif
00074 
00075     _symbol = NULL;
00076     _start   = NULL;
00077     _accuracy = ACCU_UNKNOWN;
00078     _actual = NULL;
00079     _actual_stmt = NULL;
00080     _visited = 0;
00081     _read_only = false;
00082     _write_first = false;
00083     _approximate = false;
00084     _no_overlap = 0;
00085     _correctness = 0;
00086     _imprecise_sorting = false;
00087     _exec_pred = -1;
00088     _possible_reduction = false;
00089     _possible_induction = false;
00090     _reduct_op = RED_OP_NONE;
00091     _summarized_to = NULL;
00092     _pgm_summarized_to = NULL;
00093     _triangular = 0;
00094     _subsub = 0;
00095     _nonaffine = 0;
00096     _monoton = AR_UNKNOWN_MONO;
00097     _access_type = AR_UNKNOWN;
00098     _nesting_level = 0;
00099     _bytesize = 0;
00100 }
00101 
00102 /// We take ownership of the start expression
00103 
00104 AbstractAccess::AbstractAccess( const Symbol & sym,
00105                     const List<AccessDimension> & dims,
00106                     Expression * start ) {
00107     #ifdef CLASS_INSTANCE_REGISTRY
00108     register_instance(ABSTRACT_ACCESS, sizeof(AbstractAccess), this);
00109     #endif
00110 
00111     _symbol = (Symbol *)&sym;
00112 
00113     /// ...  Copy the dimension list
00114     for (Iterator<AccessDimension> iter = dims;
00115      iter.valid();
00116      ++iter) {
00117     add_dimension( iter.current().clone() );
00118     }
00119     _start   = start;
00120     _accuracy = ACCU_UNKNOWN;
00121     _actual = NULL;
00122     _actual_stmt = NULL;
00123     _visited = 0;
00124     _read_only = false;
00125     _write_first = false;
00126     _approximate = false;
00127     _no_overlap = 0;
00128     _correctness = 0;
00129     _exec_pred = -1;
00130     _possible_reduction = false;
00131     _possible_induction = false;
00132     _reduct_op = RED_OP_NONE;
00133     _imprecise_sorting = false;
00134     _summarized_to = NULL;
00135     _pgm_summarized_to = NULL;
00136     _triangular = 0;
00137     _subsub = 0;
00138     _nonaffine = 0;
00139     _monoton = AR_UNKNOWN_MONO;
00140     _access_type = AR_UNKNOWN;
00141     _nesting_level = 0;
00142     _bytesize = 0;
00143 }
00144 
00145 /// We take ownership of the start expression
00146 
00147 AbstractAccess::AbstractAccess( const Symbol & sym,
00148                     const List<AccessDimension> & dims,
00149                     Expression * start, 
00150                     ACCURACY accu, AR_TYPE artype ) {
00151     #ifdef CLASS_INSTANCE_REGISTRY
00152     register_instance(ABSTRACT_ACCESS, sizeof(AbstractAccess), this);
00153     #endif
00154 
00155     _symbol = (Symbol *)&sym;
00156 
00157     /// ...  Copy the dimension list
00158     for (Iterator<AccessDimension> iter = dims;
00159      iter.valid();
00160      ++iter) {
00161     add_dimension( iter.current().clone() );
00162     }
00163     _start   = start;
00164     _accuracy = accu;
00165     _actual = NULL;
00166     _actual_stmt = NULL;
00167     _visited = 0;
00168     _read_only = false;
00169     _write_first = false;
00170     _approximate = false;
00171     _no_overlap = 0;
00172     _correctness = 0;
00173     _exec_pred = -1;
00174     _possible_reduction = false;
00175     _possible_induction = false;
00176     _reduct_op = RED_OP_NONE;
00177     _imprecise_sorting = false;
00178     _summarized_to = NULL;
00179     _pgm_summarized_to = NULL;
00180     _triangular = 0;
00181     _subsub = 0;
00182     _nonaffine = 0;
00183     _monoton = AR_UNKNOWN_MONO;
00184     _access_type = artype;
00185     _nesting_level = 0;
00186     _bytesize = 0;
00187 }
00188 
00189 /// We take ownership of the start expression
00190 
00191 AbstractAccess::AbstractAccess( const Symbol & sym,
00192                     const List<AccessDimension> & dims,
00193                     Expression * start, 
00194                     AbstractAccess * model_aa ) {
00195     #ifdef CLASS_INSTANCE_REGISTRY
00196     register_instance(ABSTRACT_ACCESS, sizeof(AbstractAccess), this);
00197     #endif
00198 
00199     _symbol = (Symbol *)&sym;
00200 
00201     /// ...  Copy the dimension list
00202     for (Iterator<AccessDimension> iter = dims;
00203      iter.valid();
00204      ++iter) {
00205     add_dimension( iter.current().clone() );
00206     }
00207     _start   = start;
00208     _accuracy = model_aa->_accuracy;
00209     _actual = model_aa->_actual;
00210     _actual_stmt = model_aa->_actual_stmt;
00211     _visited = 0;
00212     _read_only = model_aa->_read_only;
00213     _write_first = model_aa->_write_first;
00214     _approximate = model_aa->_approximate;
00215     _no_overlap = model_aa->_no_overlap;
00216     if (model_aa->_correctness) {
00217     _correctness = model_aa->_correctness->clone();
00218     } else {
00219     _correctness = 0;
00220     }
00221     _exec_pred = model_aa->_exec_pred;
00222     _possible_reduction = model_aa->_possible_reduction;
00223     _possible_induction = model_aa->_possible_induction;
00224     _reduct_op = model_aa->_reduct_op;
00225     _imprecise_sorting = model_aa->_imprecise_sorting;
00226     _summarized_to = model_aa->_summarized_to;
00227     _pgm_summarized_to = model_aa->_pgm_summarized_to;
00228     _triangular = model_aa->_triangular;
00229     _subsub = model_aa->_subsub;
00230     _nonaffine = model_aa->_nonaffine;
00231     _monoton = model_aa->_monoton;
00232     _access_type = model_aa->_access_type;
00233     _nesting_level = model_aa->_nesting_level;
00234     _bytesize = model_aa->_bytesize;
00235 }
00236 
00237 AbstractAccess::AbstractAccess( const AbstractAccess & other ) {
00238 
00239     #ifdef CLASS_INSTANCE_REGISTRY
00240     register_instance(ABSTRACT_ACCESS, sizeof(AbstractAccess), this);
00241     #endif
00242 
00243     _symbol = other._symbol;
00244     _visited = 0;
00245 
00246     /// ...  Copy the dimension list
00247     for (Iterator<AccessDimension> iter = other._dims;
00248      iter.valid();
00249      ++iter) {
00250     add_dimension( iter.current().clone() );
00251     }
00252 
00253     if (other._start) {
00254     _start = other._start->clone();
00255     } else {
00256     _start = NULL;
00257     }
00258 
00259     _exec_pred = other._exec_pred;
00260 
00261     if (other._correctness) {
00262     _correctness = other._correctness->clone();
00263     } else {
00264     _correctness = NULL;
00265     }
00266     _accuracy = other._accuracy;
00267 
00268     if (other._actual) {
00269     _actual = other._actual->clone();
00270     } else {
00271     _actual = 0;
00272     }
00273     _actual_stmt = other._actual_stmt;
00274 
00275     _read_only = other._read_only;
00276     _approximate = other._approximate;
00277     _write_first = other._write_first;
00278     _no_overlap = other._no_overlap;
00279     _possible_reduction = other._possible_reduction;
00280     _possible_induction = other._possible_induction;;
00281     _reduct_op = other._reduct_op;
00282     _imprecise_sorting = other._imprecise_sorting;
00283     _summarized_to = other._summarized_to;
00284     _pgm_summarized_to = other._pgm_summarized_to;
00285     _triangular = other._triangular;
00286     _subsub = other._subsub;
00287     _nonaffine = other._nonaffine;
00288     _monoton = other._monoton;
00289     _access_type = other._access_type;
00290     _nesting_level = other._nesting_level;
00291     _bytesize = other._bytesize;
00292 }
00293 
00294 AbstractAccess::~AbstractAccess( ) {
00295     #ifdef CLASS_INSTANCE_REGISTRY
00296     unregister_instance(ABSTRACT_ACCESS, this);
00297     #endif
00298 
00299     if (_start) {
00300     delete _start;
00301     }
00302     if (_actual) {
00303     delete _actual;
00304     }
00305     if (_correctness) {
00306     delete _correctness;
00307     }
00308 }
00309 
00310 Symbol &
00311 AbstractAccess::symbol( ) const{
00312     return (Symbol &) *_symbol;
00313 }
00314 
00315 Statement *
00316 AbstractAccess::summarized_to( ) {
00317     return _summarized_to;
00318 }
00319 
00320 void
00321 AbstractAccess::summarized_to( Statement * stmt) {
00322     _summarized_to = stmt;
00323 }
00324 
00325 ProgramUnit *
00326 AbstractAccess::pgm_summarized_to( ) {
00327     return _pgm_summarized_to;
00328 }
00329 
00330 void
00331 AbstractAccess::pgm_summarized_to( ProgramUnit * stmt) {
00332     _pgm_summarized_to = stmt;
00333 }
00334 
00335 int
00336 AbstractAccess::nesting_level( ) {
00337     return _nesting_level;
00338 }
00339 
00340 Expression *
00341 AbstractAccess::lastoffset( ) const {
00342 
00343     if (_dims.entries() == 0) {
00344     if (start_exists()) {
00345         return _start->clone();
00346     } else {
00347         return constant(0);
00348     }
00349     } else {
00350     List<Expression> * list = new List<Expression>;
00351 
00352     if (start_exists()) {
00353         list->ins_first(_start->clone());
00354     } else {
00355         list->ins_first(constant(0));
00356     }
00357 
00358     for (Iterator<AccessDimension> iter = _dims;
00359          iter.valid();
00360          ++iter) {
00361         AccessDimension & dim = iter.current();
00362 
00363         if ((dim.span_guarded().op() == INTEGER_CONSTANT_OP) &&
00364         (dim.span_guarded().value() == 0)) {
00365         } else {
00366         list->ins_first(dim.span_guarded().clone());
00367         }
00368     }
00369     return add(list);
00370     }
00371 }
00372 
00373 void
00374 AbstractAccess::nesting_level( int level ) {
00375      _nesting_level = level;
00376 }
00377 
00378 void
00379 AbstractAccess::inc_nesting( ) {
00380      ++_nesting_level;
00381 }
00382 
00383 Expression &
00384 AbstractAccess::start_guarded( ) const {
00385     p_assert(_start, "AbstractAccess: start does not exist");
00386     return (Expression &) *_start;
00387 }
00388 
00389 Boolean
00390 AbstractAccess::start_exists( ) const {
00391     if (_start) {
00392     return True;
00393     } else {
00394     return False;
00395     }
00396 }
00397 
00398 Boolean
00399 AbstractAccess::actual_exists( ) const {
00400     if (_actual) {
00401     return True;
00402     } else {
00403     return False;
00404     }
00405 }
00406 
00407 AbstractAccess *
00408 AbstractAccess::remap_interface_vars( InlineObject * inl_obj, 
00409                                       Statement & stmt,
00410                       const Symbol & sym, const REF_TYPE ref,
00411                       int exec_pred ) const
00412 {
00413     static LambdaInfo lambda(0, 0, INLINE_CALL);
00414     
00415     /// ...  Go through all the symbols in the range dictionary of the current
00416     /// ...  AbstractAccess object, translating them for the calling context.
00417 
00418     String tag = stmt.tag();
00419     Statement * r_stmt = range_stmt(*_summarized_to);
00420 
00421     AIRangeDict & range_dict = (AIRangeDict &)(this->_pgm_summarized_to->range_dict_guarded());
00422 
00423     RefSet<Symbol> * set = range_dict.range_vars(tag);
00424     if (set) {
00425     for (Iterator<Symbol> iter = *set;
00426          iter.valid();
00427          ++iter) {
00428 
00429         VariableSymbol * trsym = inl_obj->translate_symbol( iter.current() );
00430 
00431         /// ...  If no translation exists for this symbol, it means that this is not
00432         /// ...  an interface variable.  Nevertheless, it needs to exist in the StmtRanges
00433         /// ...  object of this AbstractAccess so that we can compare its elements
00434         /// ...  symbolically.  Therefore, we find a non-conflicting name for the symbol
00435         /// ...  in the calling routine, and insert a new symbol in the calling routine's
00436         /// ...  symbol table.  We also provide a mapping for the symbol in the InlineObject
00437         /// ...  so that wherever it appears in the AbstractAccess object, it will be translated
00438         /// ...  to the new symbol.
00439 
00440         if (!trsym) {
00441         VariableSymbol * sym = (VariableSymbol *)(&(iter.current()));
00442         if (sym->is_gsa_symbol()) {
00443             sym = (VariableSymbol *) (&(sym->gsa_base_symbol()));
00444         }
00445         Symbol * symclone = sym->clone();
00446         Symbol & newsym = inl_obj->pgm_main().symtab().rename_and_ins(symclone);
00447         inl_obj->TranslateObject::GSA_mapping(iter.current(), newsym);
00448         }
00449     }
00450     }
00451      
00452     List<AccessDimension> * listdim = new List<AccessDimension>;
00453     for (Iterator<AccessDimension> iter = _dims;
00454      iter.valid();
00455      ++iter) 
00456     {
00457         AccessDimension * new_dim = iter.current().remap_interface_vars( inl_obj, ref );
00458         listdim->ins_last ( new_dim );
00459     }
00460     Expression * new_start  = 0;
00461 
00462     const AbstractAccess * caller_aa = inl_obj->access_region(sym);
00463 
00464     if (this->start_exists()) {
00465     Expression * trans_start = this->start_guarded().clone();
00466     trans_start = trans_update_expr(inl_obj, trans_start);
00467     if (caller_aa && caller_aa->start_exists()) {
00468         new_start = simplify(add(caller_aa->start_guarded().clone(),
00469                      trans_start));
00470     } else {
00471         new_start = trans_start;
00472     }
00473     }   
00474 
00475     VariableSymbol * newsym = inl_obj->translate_symbol( sym );
00476 
00477     if (newsym->is_gsa_symbol()) {
00478     newsym = (VariableSymbol *) (&(newsym->gsa_base_symbol()));
00479     }
00480 
00481     AbstractAccess * new_aa = 
00482     new AbstractAccess(*newsym, 
00483                *listdim, new_start, (AbstractAccess *) this);
00484 //             this->accuracy(), 
00485 //             (AR_TYPE) (this->_access_type) );
00486 
00487     /// ...  If an actual expression for this access appears on the CALL stmt, copy it
00488     /// ...  If not, set the fields to NULL
00489 
00490     if (caller_aa && caller_aa->_actual) {
00491     new_aa->_actual = caller_aa->_actual->clone();
00492     new_aa->_actual_stmt = caller_aa->_actual_stmt;
00493     }
00494 
00495     if (this->_correctness) {
00496     Expression * trans_corr = _correctness->clone();
00497     trans_corr = trans_update_expr(inl_obj, trans_corr);
00498     new_aa->_correctness = trans_corr;
00499     }
00500     if (this->_exec_pred != -1) {
00501     Expression * trans_pred = _pgm_summarized_to->pred_repos().predicate(this->_exec_pred)->clone();
00502     trans_pred = trans_update_expr(inl_obj, trans_pred);
00503     int index = inl_obj->pgm_main().pred_repos().ins(trans_pred);
00504     new_aa->_exec_pred = index;
00505     }
00506 
00507 ///    StmtRanges * new_ranges = new StmtRanges(this->_pgm_summarized_to->symtab());
00508     
00509     /// ...  Go through all the symbols in the range dictionary of the current
00510     /// ...  AbstractAccess object, translating the symbols and translating 
00511     /// ...  the ranges.
00512 
00513     delete set;
00514 
00515     set = range_dict.range_vars(tag);
00516     if (set) {
00517     for (Iterator<Symbol> iter = *set;
00518          iter.valid();
00519          ++iter) {
00520 
00521         const Expression * range = 
00522         range_dict._get_range_ref(iter.current(), *r_stmt );
00523         if (range) {
00524         
00525         Expression *new_range = range->clone();
00526         inl_obj->remap_expr( &new_range, lambda, ref);
00527 
00528         VariableSymbol * trsym = inl_obj->translate_symbol( iter.current() );
00529         inl_obj->pgm_main().range_dict_guarded()._set_range(*trsym, *r_stmt, 
00530                                     new_range);
00531         }
00532     }
00533     }
00534 
00535     delete set;
00536 
00537     new_aa->_read_only = this->_read_only;
00538     new_aa->_approximate = this->_approximate;
00539     new_aa->_write_first = this->_write_first;
00540     new_aa->_triangular = this->_triangular;
00541     new_aa->_diagonal = this->_diagonal;
00542     new_aa->_subsub = this->_subsub;
00543     new_aa->_nonaffine = this->_nonaffine;
00544     new_aa->_monoton = this->_monoton;
00545     new_aa->_nesting_level = this->_nesting_level;
00546     return new_aa;
00547 }
00548 
00549 AbstractAccess * 
00550 AbstractAccess::clone( ) const {
00551     return new AbstractAccess( *this );
00552 }
00553     
00554 Listable *
00555 AbstractAccess::listable_clone() const
00556 {
00557     return (Listable *) clone();
00558 }
00559 
00560 void 
00561 AbstractAccess::relink_eptrs( ProgramUnit & p ) {
00562 
00563     for (Iterator<AccessDimension> iter = _dims;
00564      iter.valid();
00565      ++iter) {
00566     iter.current().relink_eptrs( p );
00567     }
00568 
00569     if (_start) {
00570     _start->relink_eptrs( p );
00571     }
00572 
00573     if (_correctness) {
00574     _correctness->relink_eptrs( p );
00575     }
00576 ///    if (_exec_pred) {
00577 //  _exec_pred->relink_eptrs( p );
00578 ///    }
00579 }
00580 
00581 /// We take ownership of the start expression:
00582 
00583 void 
00584 AbstractAccess::start( Expression * start ) {
00585     if (_start) {
00586     delete _start;
00587     }
00588     _start = start;
00589 }
00590 
00591 void
00592 AbstractAccess::print( ostream & o ) const {
00593 
00594     o << endl;
00595 
00596     o << _symbol->name_ref() << "-";
00597 
00598     if (_imprecise_sorting) o << "?SORT:";
00599 
00600     if (_read_only || _write_first || _no_overlap || _approximate) {
00601     o << "<";
00602     if (_read_only) {
00603         o << "R";
00604     }
00605     if (_approximate) {
00606         o << "A";
00607     }
00608     if (_write_first) {
00609         o << "W";
00610     }
00611     if (_no_overlap == 1) {
00612         o << "=";
00613     } else if (_no_overlap == 2) {
00614         o << "=?";
00615     }
00616     o << ">";
00617     }
00618 
00619     /// ...  Don't print the predicate, if it's .TRUE.
00620     if (!(this->exec_predicate_true())) {
00621     if (_exec_pred == -11) {
00622         o << "{<uninitialized>}:";
00623     } else if (_exec_pred != -1) {
00624         o << "{" << *(_pgm_summarized_to->pred_repos().predicate(_exec_pred)) << "}:";
00625     }
00626     }
00627 
00628     if (_possible_reduction) {
00629     o << "<RED:" ;
00630     if (_possible_induction) o << "I";
00631     switch (_reduct_op) {
00632     case RED_OP_NONE: o << "?"; break;
00633     case RED_OP_PLUS: o << "+"; break;
00634     case RED_OP_MUL: o << "*"; break;
00635     case RED_OP_MIN: o << "MIN"; break;
00636     case RED_OP_MAX: o << "MAX"; break;
00637     default: p_abort("bad value for reduction operator");
00638     }
00639     o << ">";
00640     }
00641 
00642 
00643     o << "^[";
00644 
00645     Iterator<AccessDimension> iter = _dims;
00646     for (int i=0; iter.valid(); ++i)
00647     {
00648         if (iter.current()._check_overlap) o << "#";
00649 
00650         if (iter.current().stride_exists()) {
00651         ACCURACY acc = iter.current().accuracy();
00652         if (acc == ACCU_EXACT) {
00653             o << iter.current().stride_guarded();
00654         } else if (acc == ACCU_SUPERSET) {
00655             o << "~" << iter.current().stride_guarded();
00656         } else if (acc == ACCU_SUBSET) {
00657             o << "_" << iter.current().stride_guarded();
00658         } else {
00659             o << "?" << iter.current().stride_guarded();
00660         }
00661         }
00662         ++iter;
00663         if (iter.valid()) {
00664         o << ",";
00665         }
00666     }
00667 
00668     o << "]v[";
00669     
00670     for (iter.reset(); iter.valid(); ) 
00671     {
00672         if (iter.current().span_exists()) {
00673         ACCURACY acc = iter.current().accuracy();
00674         if (acc == ACCU_EXACT) {
00675             o <<  iter.current().span_guarded();
00676         } else if (acc == ACCU_SUPERSET) {
00677             o << "~" << iter.current().span_guarded();
00678         } else if (acc == ACCU_SUBSET) {
00679             o << "_" << iter.current().span_guarded();
00680         } else {
00681             o << "?" << iter.current().span_guarded();
00682         }
00683         }
00684         ++iter;
00685         if (iter.valid()) {
00686         o << ",";
00687         }
00688     }
00689     o << "]";
00690 
00691     o  << "+" << *_start;
00692 }
00693 
00694 ostream & 
00695 operator << (ostream & o, const AbstractAccess & aa) 
00696 {
00697     aa.print(o);
00698     return o;
00699 }
00700 
00701 void 
00702 AbstractAccess::accuracy( ACCURACY accu ) {
00703     _accuracy = accu;
00704 }
00705 
00706 ACCURACY 
00707 AbstractAccess::accuracy ( ) const {
00708     return _accuracy;
00709 }
00710 
00711 void
00712 AbstractAccess::add_actual ( Statement * stmt, Expression * expr ) {
00713     _actual_stmt = stmt;
00714     _actual = expr;    /// ...  Take possession of the actual expression
00715 }
00716 
00717 Expression & 
00718 AbstractAccess::actual_guarded ( ) const {
00719     return (Expression &) *_actual;
00720 }
00721 
00722 void 
00723 AbstractAccess::remove_actual( ) {
00724     if (_actual) {
00725     delete _actual;
00726     _actual = 0;
00727     }
00728 }
00729 
00730 Statement *
00731 AbstractAccess::actual_stmt() const 
00732 {
00733     return _actual_stmt;
00734 }
00735 
00736 int
00737 AbstractAccess::number_of_dimensions( ) const
00738 {
00739     return this->_dims.entries();
00740 }
00741 
00742 void
00743 AbstractAccess::byte_size( int bytes )
00744 {
00745     _bytesize = bytes;
00746 }
00747 
00748 bool 
00749 AbstractAccess::poss_reduct( )
00750 {
00751     return _possible_reduction;
00752 }
00753 
00754 bool 
00755 AbstractAccess::poss_induct( )
00756 {
00757     return _possible_induction;
00758 }
00759 
00760 void
00761 AbstractAccess::poss_reduct( bool val )
00762 {
00763     _possible_reduction = val;
00764 }
00765 
00766 void
00767 AbstractAccess::poss_induct( bool val )
00768 {
00769     _possible_induction = val;
00770 }
00771 
00772 void
00773 AbstractAccess::reduct_op( RED_OP op )
00774 {
00775     _reduct_op = op;
00776 }
00777 
00778 RED_OP
00779 AbstractAccess::reduct_op( )
00780 {
00781     return (RED_OP) _reduct_op;
00782 }
00783 
00784 void
00785 AbstractAccess::exec_predicate( int pred )
00786 {
00787     _exec_pred = pred;
00788 }
00789 
00790 bool
00791 AbstractAccess::exec_predicate_exists() const
00792 {
00793     if (_exec_pred != -11) {
00794     return true;
00795     } else {
00796     return false;
00797     }
00798 }
00799 
00800 bool
00801 AbstractAccess::exec_predicate_true() const
00802 {
00803     if (_exec_pred == -1) {
00804     return true;
00805     } else if (_exec_pred == -2) { 
00806     return false;
00807     } else {
00808     Expression * expr = _pgm_summarized_to->pred_repos().predicate(_exec_pred);
00809     if ((expr->op() == LOGICAL_CONSTANT_OP) && 
00810         (expr->str_data() == ".TRUE.")) {
00811         return true;
00812     }
00813     }
00814     return false;
00815 }
00816 
00817 bool
00818 AbstractAccess::exec_predicate_false() const
00819 {
00820     if (_exec_pred == -2) {
00821     return true;
00822     } else if (_exec_pred == -1) {
00823     return false;
00824     } else {
00825     Expression * expr = _pgm_summarized_to->pred_repos().predicate(_exec_pred);
00826     if ((expr->op() == LOGICAL_CONSTANT_OP) && 
00827         (expr->str_data() == ".FALSE.")) {
00828         return true;
00829     }
00830     }
00831     return false;
00832 }
00833 
00834 int
00835 AbstractAccess::exec_predicate( )
00836 {
00837     return _exec_pred;
00838 }
00839 
00840 int
00841 AbstractAccess::byte_size( )
00842 {
00843     return _bytesize;
00844 }
00845 
00846 /// Convert this descriptor to a new bytesize.  The new size must be
00847 /// smaller than the current bytesize, and also must divide the current
00848 /// bytesize.  The standard Fortran sizes always fit this criteria:
00849 /// 16, 8, 4, 2, 1.
00850 
00851 void
00852 AbstractAccess::convert_size (int new_size)
00853 {
00854     p_assert((new_size < _bytesize) && (_bytesize % new_size == 0),
00855          "improper size for converting AbstractAccess");
00856 
00857     _start = simplify(mul(constant(4),_start));
00858 
00859     for (Iterator<AccessDimension> iter = _dims;
00860      iter.valid();
00861      ++iter) {
00862 
00863     AccessDimension & accdim = iter.current();
00864     
00865     accdim._span = simplify(mul(constant(4),accdim._span));
00866     accdim._stride = simplify(mul(constant(4),accdim._stride));
00867     }
00868 
00869     AccessDimension * newdim = new AccessDimension(constant(1), constant(new_size - 1));
00870     newdim->singleton(true);
00871     add_dimension(newdim);
00872 }
00873 
00874 void 
00875 AbstractAccess::add_dimension( const AccessDimension * dim ) {
00876   if (dim->stride_exists()) {
00877       _dims.ins_last(dim);
00878   }
00879 }
00880 
00881 void 
00882 AbstractAccess::add_dimension( const AccessDimension * dim, int which_dim ) {
00883 
00884     if (which_dim < 0) return;
00885 
00886     if (dim->stride_exists()) {
00887     _dims.ins(dim, which_dim);
00888     }
00889 }
00890 
00891 AccessDimension &
00892 AbstractAccess::dimension( int i ) {
00893     return _dims[i];
00894 }
00895 
00896 
00897 Iterator<AccessDimension> 
00898 AbstractAccess::iter_dims( ) {
00899     Iterator<AccessDimension> iter = _dims;
00900     return iter;
00901 }
00902 
00903 /// Look for an exact match on all major parts of the access regions
00904 
00905 bool
00906 AbstractAccess::match( AbstractAccess * other )
00907 {
00908     if ( this->accuracy() != other->accuracy() ) 
00909     return false;
00910 
00911     int dims = this->number_of_dimensions();
00912 
00913     if ( dims != other->number_of_dimensions() )
00914     return false;
00915 
00916     if ( ! (this->start_guarded().match( other->start_guarded() )) )
00917     return false;
00918 
00919     int number_matches = this->match_dims( other );
00920 
00921     if (number_matches == dims)
00922     return true;
00923     else 
00924     return false;
00925 }
00926 
00927 /// Look for a match ignoring the start expression
00928 
00929 bool 
00930 AbstractAccess::match_by_dims( AbstractAccess * other )
00931 {
00932 
00933     if ( this->accuracy() != other->accuracy() ) 
00934     return false;
00935 
00936     int dims = this->number_of_dimensions();
00937 
00938     if ( dims != other->number_of_dimensions() )
00939     return false;
00940 
00941     int number_matches = this->match_dims( other );
00942 
00943     if (number_matches == dims)
00944     return true;
00945     else 
00946     return false;
00947 }
00948 
00949 /// Look for an exact match on strides of two access regions
00950 
00951 bool
00952 AbstractAccess::match_by_strides( AbstractAccess * other )
00953 {
00954     if ( this->accuracy() != other->accuracy() ) 
00955     return false;
00956 
00957     int dims = this->number_of_dimensions();
00958 
00959     if ( dims != other->number_of_dimensions() )
00960     return false;
00961 
00962     int number_matches = this->match_dims_stride( other );
00963 
00964     if (number_matches == dims)
00965     return true;
00966     else 
00967     return false;
00968 }
00969 
00970 /// Look for an exact match on start and all dimensions except 1
00971 
00972 bool
00973 AbstractAccess::match_by_start_dims_except_1( AbstractAccess * other )
00974 {
00975     if ( this->accuracy() != other->accuracy() ) 
00976     return false;
00977 
00978     int dims = this->number_of_dimensions();
00979 
00980     if ( dims != other->number_of_dimensions() )
00981     return false;
00982 
00983     if ( ! this->start_guarded().match( other->start_guarded() ) )
00984     return false;
00985 
00986     int number_matches = this->match_dims( other );
00987 
00988     if (number_matches >= dims-1)
00989     return true;
00990     else 
00991     return false;
00992 }
00993 
00994 /// Look for an exact match on all dimensions except 1 (ignoring start)
00995 
00996 bool
00997 AbstractAccess::match_by_dims_except_1( AbstractAccess * other )
00998 {
00999     if ( this->accuracy() != other->accuracy() ) 
01000     return false;
01001 
01002     int dims = this->number_of_dimensions();
01003 
01004     if ( dims != other->number_of_dimensions() )
01005     return false;
01006 
01007     int number_matches = this->match_dims( other );
01008 
01009     if (number_matches >= dims-1)
01010     return true;
01011     else 
01012     return false;
01013 }
01014 
01015 /// Match up the dimensions and return how many matching pairs there are
01016 
01017 int 
01018 AbstractAccess::match_dims( AbstractAccess * other )
01019 {
01020     SmallIntSet matched_dims;
01021 
01022     int matches = 0;
01023 
01024     for (Iterator<AccessDimension> iter = _dims;
01025      iter.valid();
01026      ++iter)
01027     {
01028         AccessDimension & dim = iter.current();
01029 
01030         int inner = 0;
01031         for (Iterator<AccessDimension> other_iter = other->iter_dims();
01032          other_iter.valid();
01033          ++other_iter,++inner)
01034         {
01035             if ( matched_dims[inner] ) continue;
01036 
01037             AccessDimension & other_dim = other_iter.current();
01038 
01039             if (dim.stride_guarded().match(other_dim.stride_guarded()) &&
01040             ((! dim.span_exists() && ! other_dim.span_exists()) ||
01041              (( dim.span_exists() && other_dim.span_exists()) &&
01042               (dim.span_guarded().match(other_dim.span_guarded()))) )) {
01043             
01044             matched_dims.ins(inner);
01045             matches++;
01046             break;
01047             }
01048         }
01049     }
01050     
01051     return matches;
01052 }
01053 
01054 /// Match up the strides and return how many matching pairs there are
01055 
01056 int 
01057 AbstractAccess::match_dims_stride( AbstractAccess * other )
01058 {
01059     SmallIntSet matched_dims;
01060 
01061     int matches = 0;
01062 
01063     for (Iterator<AccessDimension> iter = _dims;
01064      iter.valid();
01065      ++iter)
01066     {
01067         AccessDimension & dim = iter.current();
01068 
01069         int inner = 0;
01070         for (Iterator<AccessDimension> other_iter = other->iter_dims();
01071          other_iter.valid();
01072          ++other_iter,++inner)
01073         {
01074             if ( matched_dims[inner] ) continue;
01075 
01076             AccessDimension & other_dim = other_iter.current();
01077 
01078             if (dim.stride_guarded().match(other_dim.stride_guarded())) {
01079             matched_dims.ins(inner);
01080             matches++;
01081             break;
01082             }
01083         }
01084     }
01085     
01086     return matches;
01087 }
01088             
01089 void
01090 AbstractAccess::set_check_overlap( int which_dim, bool value )
01091 {
01092     _dims[which_dim]._check_overlap = value;
01093 }
01094 
01095 /// Calculate the overlap value.  This is accomplished by computing
01096 /// the sum of the spans of all dimensions before "which_dim" and
01097 /// checking whether it is less than the stride of dimension "which_dim".
01098 /// Likewise, we have to make sure that the span of "which_dim" is 
01099 /// not larger than the stride of the next outer dimension (at which_dim+1).
01100 /// If so, we say there is "No overlap".  Otherwise, there is overlap.
01101 
01102 void
01103 AbstractAccess::calc_overlap( int which_dim )
01104 {
01105   int entries = _dims.entries();
01106 
01107 /// which_dim == -1 means that expand didn't find the loop index in the start expression.
01108 /// This definitely means there is an overlap.
01109   if (which_dim == -1) {
01110       _no_overlap = 0;
01111       return;
01112   } else if (entries <= 1) {  /// ...  If index appeared in start expression, and < 2 dimensions, there can be no overlap
01113       _no_overlap = 1;
01114       return;
01115   }
01116 
01117 /// If we couldn't sort the dimensions, then nothing can be done
01118 /// at compile time to determine overlap.
01119 
01120   if (_imprecise_sorting) {
01121       _dims[which_dim]._check_overlap = true;
01122       _no_overlap = 2;
01123       return;
01124   }
01125 
01126 /// The rest of this routine assumes that sorting was precise!
01127 
01128   Statement * r_stmt = range_stmt(*_summarized_to);
01129   RangeAccessor range_acc(_pgm_summarized_to->range_dict_guarded(), 
01130                 *r_stmt );
01131 
01132 /// Check the sum of the spans inside this dimension against this stride
01133 
01134   Expression * sum = 0;
01135   Expression * stride = 0;
01136   Expression * span = 0;
01137 
01138   if (which_dim > 0) {
01139 
01140       p_assert(_dims[0].span_exists(), "Span does not exist");
01141 
01142       sum = _dims[0].span_guarded().clone();
01143       for (int i = 1; i<which_dim; ++i) {
01144       p_assert(_dims[i].span_exists(), "Span does not exist");
01145       sum = add(sum, _dims[i].span_guarded().clone());
01146       }
01147 
01148       sum = simplify(sum);
01149 
01150       p_assert(_dims[which_dim].stride_exists(), "Stride does not exist");
01151 
01152       stride = _dims[which_dim].stride_guarded().clone();
01153       Relation rel = range_acc.compare(*sum, *stride);
01154 
01155       if (rel.is_greater_equal()) {
01156       _no_overlap = 0;
01157       delete stride;
01158       delete sum;
01159       return;
01160       }
01161       /// ...  If the Relation couldn't say that sum >= stride AND
01162       /// ...  can't say that sum<stride, it obviously doesn't know,
01163       /// ...  so this is where we need a correctness condition.
01164 
01165       if (!(rel.is_less_than())) {
01166       if (_correctness) {
01167           _correctness = and(_correctness, lt(sum->clone(), stride->clone()));
01168       } else {
01169           _correctness = lt(sum->clone(), stride->clone());
01170       }
01171       _dims[which_dim]._check_overlap = true;
01172       _no_overlap = 2;
01173       }
01174   }
01175 
01176   delete stride;
01177 
01178 /// Check the span of this dim against the stride of the next outer dim
01179 
01180   if (which_dim < entries-1) {
01181       p_assert(_dims[which_dim+1].stride_exists(), "Stride does not exist");
01182       p_assert(_dims[which_dim].span_exists(), "Span does not exist");
01183       
01184       stride = _dims[which_dim+1].stride_guarded().clone();
01185       span   = _dims[which_dim].span_guarded().clone();
01186 
01187       /// ...  If there were no prior dimensions, just compare which_dim to outer
01188 
01189       if (sum == 0) {
01190       Relation rel = range_acc.compare(*stride, *span);
01191       if (rel.is_less_equal()) {
01192           _no_overlap = 0;
01193           delete stride;
01194           delete span;
01195           return;
01196       }
01197       // If we can't say that stride <= span and we can't say
01198       // that stride > span, then we need a correctness condition
01199       // to be tested at runtime.
01200 
01201       if (!(rel.is_greater_than())) {
01202           if (_correctness) {
01203           _correctness = and(_correctness, gt(stride->clone(), span->clone()));
01204           } else {
01205           _correctness = gt(stride->clone(), span->clone());
01206           }
01207           _dims[which_dim]._check_overlap = true;
01208           _no_overlap = 2;
01209       }
01210       delete stride;
01211       delete span;
01212       } else {
01213       sum = simplify(add(sum, span->clone()));
01214       Relation rel = range_acc.compare(*stride, *sum);
01215       if (rel.is_less_equal()) {
01216           _no_overlap = 0;
01217           delete stride;
01218           delete span;
01219           delete sum;
01220           return;
01221       }
01222       // If we can't say that stride <= sum and we can't say
01223       // that stride > sum, then we need a correctness condition
01224       // to be tested at runtime.
01225 
01226       if (!(rel.is_greater_than())) {
01227           if (_correctness) {
01228           _correctness = and(_correctness, gt(stride->clone(), sum->clone()));
01229           } else {
01230           _correctness = gt(stride->clone(), sum->clone());
01231           }
01232           _dims[which_dim]._check_overlap = true;
01233           _no_overlap = 2;
01234       }
01235       delete stride;
01236       delete span;
01237       }
01238   } 
01239 
01240   if (_no_overlap != 2)  _no_overlap = 1;
01241 
01242   delete sum;
01243   return;
01244 }
01245 
01246 /// compute a new dimension holding at a point in the program,
01247 /// using expressions as from a DO statement:
01248 ///    index = lo, hi, by
01249 /// Insert the new dimension in the AbstractAccess object, in 
01250 /// sorted order (by stride).
01251 ///
01252 /// The return value is the position of the new dimension in the 
01253 /// resulting AbstractAccess object.
01254 int
01255 AbstractAccess::compute_new_dimension(ProgramUnit & pgm, Statement & stmt, 
01256                       Symbol & index, 
01257                       Expression & lo, Expression & hi, Expression & by)
01258 {
01259     Expression * start = start_guarded().clone();
01260     int which_dim;
01261 
01262     Statement * r_stmt = range_stmt(stmt);
01263     String stmt_tag = r_stmt->tag();
01264     RangeAccessor range_acc( pgm.range_dict_guarded(), *r_stmt );
01265 
01266     Symbol *max_sym = pgm.symtab().find_ref("MAX");
01267     
01268     Expression * beg = lo.clone();
01269     Expression * stride = by.clone();
01270     Expression * end = &hi;
01271 
01272     if ((stride->op() == INTEGER_CONSTANT_OP) &&
01273     ((stride->value() == 1) || 
01274      (stride->value() == -1))) {
01275     end = hi.clone();
01276     } else {
01277       /// ...  silvius: -1 shows in some cases as ( U_MINUS_OP ( INTEGER_CONSTANT_OP ( 1 ) ) )
01278       if (stride->op() == U_MINUS_OP){
01279     Expression& val=stride->expr_guarded();
01280     if (val.op()==INTEGER_CONSTANT_OP &&
01281         (val.value() == 1 || val.value() == -1) ) {
01282       end = hi.clone();
01283     }
01284       } else {
01285 
01286     /// ...  Form the most general expression for the ending value
01287     end = ((AIRangeDict &)(pgm.range_dict_guarded())).elim_known_facts(stmt_tag, 
01288                        add(mul(sub(intrinsic_call(id(*max_sym),
01289                                   comma(div(add(sub(end->clone(),
01290                                             beg->clone()),
01291                                         stride->clone()),
01292                                         stride->clone()),
01293                                     constant(0))),
01294                            constant(1)),
01295                            stride->clone()),
01296                        beg->clone())
01297                        );
01298       }
01299     }
01300 
01301     /// ...  Form pseudo-index with begin:end:stride => pseudo_beg:pseudo_end:pseudo_stride
01302 
01303     Expression * pseudo_beg = 0;
01304     Expression * pseudo_end = 0;
01305     Expression * pseudo_stride = 0;
01306     Expression * new_start,  * new_stride, * new_span;
01307 
01308     /// ...  If the index appears in the start, calc a new dimension
01309 
01310     if (is_var_in_expr( *start, index)) {
01311 
01312     /// ...  Test the monotonicity of the start expression
01313     Monotonicity * mono = test_monotonicity(range_acc, index, stride, start );
01314 
01315     if (_monoton == AR_UNKNOWN_MONO) {
01316         if (mono->unknown_dir()) {
01317         monoton( AR_MONO_UNSURE );
01318         } else {
01319         monoton( AR_PROVEN_MONO);
01320         }
01321     } else {
01322         if (mono->unknown_dir()) {
01323         monoton( AR_MONO_UNSURE );
01324         }
01325     }
01326 
01327     if (mono->negative()) {
01328 
01329         /// ...  If monotonically decreasing, then reverse the 
01330         /// ...  beginning and ending values and negate the stride.
01331 
01332         pseudo_beg = end->clone();
01333         pseudo_end = beg->clone();
01334         pseudo_stride = mul(stride->clone(), constant(-1));
01335 
01336     } else {
01337         pseudo_beg = beg->clone();
01338         pseudo_end = end->clone();
01339         pseudo_stride = stride->clone();
01340     }
01341 
01342     /// ...  Form the new starting expression
01343     /// ...     new_start = start(I = pseudo_beg)
01344 
01345     new_start = simplify( substitute_var( start->clone(), index, *pseudo_beg ) );
01346     
01347     /// ...  Form the new stride expression
01348     /// ...     new_stride = start(I = I+pseudo_stride) - start(I)
01349     
01350     Expression * index_plus_stride = add(id(index),
01351                          pseudo_stride->clone());
01352     
01353     new_stride = simplify(sub(substitute_var(start->clone(), 
01354                          index, 
01355                          *index_plus_stride),
01356                   start->clone()));
01357 
01358     delete index_plus_stride;
01359     
01360     /// ...  Form the new span expression
01361     /// ...     new_span = start(I = pseudo_end) - new_start
01362 
01363     new_span = simplify(sub(substitute_var(start->clone(), 
01364                            index, 
01365                            *pseudo_end),
01366                 new_start->clone()));
01367 
01368     AccessDimension *ad;
01369 
01370     /// ...  Don't add a new dimension if the stride is a integer constant 0
01371 
01372     if ((new_stride->op() != INTEGER_CONSTANT_OP) ||
01373         (new_stride->value() != 0)) {
01374 
01375         ad = new AccessDimension( new_stride, new_span, ACCU_EXACT, mono );
01376         
01377 
01378         ad->_index = &index;
01379         
01380         /// ...  Determine which position this dimension should occupy (keep the
01381         /// ...  dimensions sorted by increasing stride value).
01382         
01383         which_dim = sort_add_dim(ad, range_acc);
01384 
01385     }  else {
01386         which_dim = -1;
01387     }
01388 
01389     } else {
01390     which_dim = -1;
01391     new_start = start->clone();
01392 
01393     /// ...  Now, check whether the index occurs in any existing span for the descriptor
01394     /// ...  If it does, we have to replace the occurence with the index value which
01395     /// ...  maximizes the span
01396 
01397     for (Iterator<AccessDimension> iter = _dims;
01398          iter.valid();
01399          ++iter) {
01400         AccessDimension & ad = iter.current();
01401         Expression & span = ad.span_guarded();
01402 
01403         if (is_var_in_expr( span, index )) {
01404         Expression * one = constant(1);
01405         Monotonicity * mono2 = test_monotonicity(range_acc, index, one, &span);
01406         delete one;
01407 
01408         if (mono2->positive()) {
01409             ad.span(substitute_var(ad._span->clone(), index, *end->clone()));
01410         } else if (mono2->negative()) {
01411             ad.span(substitute_var(ad._span->clone(), index, *beg->clone()));
01412         }
01413         delete mono2;
01414         }
01415     }
01416     }
01417 
01418     this->start( new_start );
01419 
01420     this->summarized_to(&stmt);   /// ...  Link AbstractAccess to the statement
01421     this->pgm_summarized_to(&pgm);  /// ...  ...and the ProgramUnit
01422 
01423     delete beg;
01424     delete end;
01425     delete stride;
01426     delete start;
01427     delete pseudo_beg;
01428     delete pseudo_end;
01429     delete pseudo_stride;
01430 
01431     return which_dim;
01432 }
01433 
01434 /// Check whether a particular access tree contains any access regions 
01435 /// exhibiting trans-dimensional access (diagonality), triangularity, 
01436 /// non-affinity,  or subscripted subscripts.
01437 ///
01438 /// If so, mark the AbstractAccess objects as such.
01439 
01440 void
01441 AbstractAccess::check_access_patterns ( )
01442 {
01443     static LambdaInfo lambda(0, 0, INLINE_CALL);
01444     RefList<AbstractAccess> aa_list;
01445 
01446     /// ...  Collect the list of AbstractAccess objects defining the 
01447     /// ...  nestings of this access, the list of actual array references
01448     /// ...  for these AbstractAccess objects, and 
01449     /// ...  the list of loop indices of the loops in the nest.
01450 
01451     Statement * stmt;
01452 
01453     for (Iterator<AbstractAccess> aa_iter = aa_list;
01454      aa_iter.valid();
01455      ++aa_iter) {
01456 
01457     AbstractAccess & aa = aa_iter.current();
01458     int ndims = aa.number_of_dimensions();
01459 
01460     if (ndims == 0) continue;
01461 
01462     bool is_diagonal   = false;
01463     bool is_triangular = false;
01464     bool is_nonaffine  = false;
01465     bool is_subsub     = false;
01466 
01467     /// ...  Test monotonicity of the whole Access Descriptor
01468 
01469     bool nonmono = false;
01470     for (int i=0; i<ndims; ++i) {
01471         const AccessDimension & dim = aa.dimension(i);
01472 
01473         if (dim.monotonicity().varying() &&
01474         dim.monotonicity().unknown_dir()) {
01475         nonmono = true;
01476         }
01477     }
01478     if (nonmono) {
01479         aa.monoton( AR_PROVEN_NON_MONO );
01480     } else {
01481         aa.monoton( AR_PROVEN_MONO );
01482     }
01483 
01484     stmt = aa.summarized_to();
01485 
01486     if (stmt->stmt_class() != DO_STMT) continue;
01487 
01488     /// ...  Test for the various subscript forms - 
01489     /// ...  First subscripted-subscripts, second non-affinity, 
01490     /// ...  third triangularity, fourth trans-dimensionality.
01491 
01492     for (int j=0; j<ndims; ++j) {
01493         const AccessDimension & dimj = aa.dimension(j);
01494 
01495         if (dimj._index == 0) continue;
01496 
01497         Symbol & index = *(dimj._index);
01498 
01499         for (int i=0; i<ndims; ++i) {
01500         const AccessDimension & dimi = aa.dimension(i);
01501 
01502         /// ...  Find an ARRAY_REF_OP  -  
01503         /// ...  If subscripted-subscript in either stride or span, mark it.
01504 
01505         for (Traverser trav(dimi.stride_guarded(), is_array_ref);
01506              trav.valid();
01507              ++trav) 
01508             {
01509             const Expression & exprnode = trav.current();
01510             
01511             if (is_var_in_expr(exprnode.subscript(), index)) {
01512                 aa.mark_subsub();
01513                 is_subsub = true;
01514                 break;
01515             }
01516             }
01517 
01518         if (is_subsub) break;
01519 
01520         for (Traverser trav(dimi.span_guarded(), is_array_ref);
01521              trav.valid();
01522              ++trav) 
01523             {
01524             const Expression & exprnode = trav.current();
01525             
01526             if (is_var_in_expr(exprnode.subscript(), index)) {
01527                 aa.mark_subsub();
01528                 is_subsub = true;
01529                 break;
01530             }
01531             }
01532 
01533         if (is_subsub) break;
01534 
01535         /// ...  Check stride for an index (non-affine)
01536         if ((! is_subsub) && (! is_nonaffine)) {
01537             if (is_var_in_expr(dimi.stride_guarded(), index)) {
01538             aa.mark_nonaffine();
01539             is_nonaffine = true;
01540             }
01541         }
01542 
01543         /// ...  Check span for an index (triangular)
01544         if ((! is_subsub) && (! is_nonaffine) && (! is_triangular)) {
01545             if (is_var_in_expr(dimi.span_guarded(), index)) {
01546             aa.mark_triangular();
01547             is_triangular = true;
01548             }
01549         }
01550         }
01551         if (is_subsub) break;
01552 
01553         if ((! is_subsub) && (! is_nonaffine) && (! is_triangular) && (! is_diagonal)) {
01554 
01555         if (aa.actual_exists()) {
01556 
01557             /// ...  Test trans-dimensional (diagonal) access
01558             
01559             Expression & expr = aa.actual_guarded();
01560             bool index_appears = false;
01561 
01562             if (expr.op() == ARRAY_REF_OP) {
01563             for (Iterator<Expression> subscr_iter = expr.subscript().arg_list();
01564                  subscr_iter.valid();
01565                  ++subscr_iter) {
01566 
01567                 Expression & subscr_expr = subscr_iter.current();
01568                 if (is_var_in_expr(subscr_expr, index)) {
01569                 if (index_appears) {
01570                     aa.mark_diagonal();
01571                     is_diagonal = true;
01572                 } else {
01573                     index_appears = true;
01574                 }
01575                 }
01576             }
01577             }
01578         }
01579         }
01580         if (is_subsub) break;
01581     }
01582     }
01583 }
01584 
01585 /// coalesce( ) - Perform the coalescing operation which reduces two
01586 /// dimensions to a single one.  The conditions are:
01587 /// Given n dimensions D0, D1, ... Dn, find a Di and a Dj such that
01588 /// SPANi divides SPANj and SPANi+STRIDEi <= STRIDEj.  If some coalescing
01589 /// happens, return TRUE, otherwise FALSE.
01590 
01591 bool
01592 AbstractAccess::coalesce( )
01593 {
01594 
01595     bool coalesced = false;
01596 
01597     /// ...  Need at least 2 dimensions for coalescing
01598     int ndims = _dims.entries();
01599 
01600     if (ndims <= 1) return coalesced;
01601 
01602     Statement * r_stmt = range_stmt(*_summarized_to);
01603     RangeAccessor range_acc( _pgm_summarized_to->range_dict_guarded(), *r_stmt );
01604 
01605     for (int i=0; i<ndims; ++i) {
01606     p_assert(_dims[i].stride_exists(),"coalesce: Stride missing");
01607     p_assert(_dims[i].span_exists(),  "coalesce: Span missing");
01608     }
01609 
01610     /// ...  Use a complete undirected graph as a device to visit
01611     /// ...  all combinations of dimensions, to try to coalesce them.
01612     /// ...  The UGraphIterator will not return self-edges (edges in which
01613     /// ...  both endpoints are the same node).
01614     
01615     /// ...  The coalesce_nodes call below signals the UGraphIterator that
01616     /// ...  coalescing has occured.  It adjusts the internal graph and 
01617     /// ...  resets the iterator so that it will continue by returning only
01618     /// ...  the dimension combinations which still need to be tested for coalescing.
01619 
01620     UGraphIterator ugi( ndims );
01621 
01622     for ( ; ugi.valid(); ++ugi) {
01623 
01624     UEdge & edge = ugi.current();
01625     int lodim = edge.node_1( );
01626     int hidim = edge.node_2( );
01627     
01628     AccessDimension & dim_lo = _dims[lodim];
01629     AccessDimension & dim_hi = _dims[hidim];
01630 
01631     coalesced = this->try_coalescing(range_acc, dim_lo, lodim, dim_hi, hidim, ugi);
01632 
01633     if (_imprecise_sorting && !coalesced) {
01634         coalesced = this->try_coalescing(range_acc, dim_hi, hidim, dim_lo, lodim, ugi);
01635     }
01636     }
01637     return coalesced;
01638 }
01639 
01640 /// Try coalescing on two specific dimensions.  If it's legal, do it and adjust
01641 /// the given UGraph.  We don't need to adjust the _singleton index flag here
01642 /// since it should be the same as the _singleton index flag of the 
01643 /// dimension with the smaller stride, which is the dimension which gets modified
01644 /// to hold the new coalesced dimension, so it will be carried across by virtue
01645 /// of that.
01646 
01647 bool
01648 AbstractAccess::try_coalescing(RangeAccessor & range_acc, 
01649                    AccessDimension & dim_lo, int lodim,
01650                    AccessDimension & dim_hi, int hidim,
01651                    UGraphIterator & ugi)
01652 {
01653     bool coalesced = false;
01654 
01655     if (expr_divides(dim_lo.stride_guarded(), dim_hi.stride_guarded())==AR_YES) {
01656     Expression * width = simplify(add(dim_lo.span_guarded().clone(),
01657                       dim_lo.stride_guarded().clone()));
01658     Expression * step = simplify(dim_hi.stride_guarded().clone());
01659     
01660     Relation rel = range_acc.compare(*width, *step);
01661     
01662     if (rel.is_greater_equal()) {
01663         
01664         coalesced    = true;
01665 
01666         if (_ar_logging && _ar_logging % 2 == 0) {
01667         arlog << "Coalesce: " << *this << " => ";
01668         }
01669 
01670         Expression * new_span = simplify(add(dim_lo.span_guarded().clone(),
01671                          dim_hi.span_guarded().clone()));
01672         dim_lo.span( new_span );
01673         
01674         dim_lo._index = 0;
01675 
01676         /// ...  Calculate the overlap characteristic
01677 
01678         if (rel.is_equal()) {
01679         _no_overlap = 1;
01680         } else if (rel.is_not_equal()) {
01681         _no_overlap = 0;
01682         } else {  /// ...  If rel can't tell equal or not equal, do runtime check
01683         dim_lo._check_overlap = true;
01684         }
01685 
01686         /// ...  remove the dimension
01687         _dims.del(hidim);
01688 
01689         /// ...  If the sorting was imprecise before, it might have been because
01690         /// ...  of the eliminated dimension.  Recheck the sorting.  If sorting
01691         /// ...  is now precise again, the check_sort() function will reset 
01692         /// ...  _imprecise_sorting.
01693 
01694         if (_imprecise_sorting) this->check_sort();
01695         
01696         if (_ar_logging && _ar_logging % 2 == 0) {
01697         arlog << *this << endl;
01698         }
01699 
01700         /// ...  Coalesce the nodes in the UGraph:
01701         /// ...  This will reset the UGraphIterator, causing it
01702         /// ...  to return all the edges still needing to be tested,
01703         /// ...  without returning those edges it has already returned.
01704         
01705         ugi.coalesce_nodes( lodim, hidim );
01706     }
01707     }
01708     return coalesced;
01709 }
01710 
01711 /// Translate the variable references in an AbstractAccess object from 
01712 /// GSA form to original form.
01713 
01714 void
01715 AbstractAccess::translate_GSA_symbols ( TranslateObject * tobj )
01716 {
01717 
01718     /// ...  First, translate the dimensions
01719 
01720     for (Iterator<AccessDimension> iter = _dims;
01721      iter.valid();
01722      ++iter) {
01723     
01724     iter.current().translate_GSA_symbols( tobj );
01725     }
01726     
01727     /// ...  Then, translate the start expression
01728 
01729     _start = tobj->translate_GSA_refs_expr(_start);
01730 }
01731 
01732 void
01733 AbstractAccess::check_sort( )
01734 {
01735     Statement * r_stmt = range_stmt(*_summarized_to);
01736     RangeAccessor range_acc( _pgm_summarized_to->range_dict_guarded(), *r_stmt );
01737     
01738     int entries = _dims.entries();
01739 
01740     bool problem = false;
01741     for (int i=0; i<entries-1; ++i) {
01742     Relation rel = range_acc.compare(_dims[i].stride_guarded(),
01743                      _dims[i+1].stride_guarded());
01744     if (! rel.is_less_than()) {
01745         _imprecise_sorting = true;
01746         problem = true;
01747         break;
01748     }
01749     }
01750 
01751     if (! problem) {
01752     _imprecise_sorting = false;
01753     }
01754 }
01755 
01756 int
01757 AbstractAccess::sort_add_dim (AccessDimension * newdim, RangeAccessor & range_acc)
01758 {
01759     int which_dim;
01760     int entries = _dims.entries();
01761 
01762     if (entries == 0) {
01763     which_dim = 0;
01764     } else {
01765     which_dim = entries;
01766 
01767     /// ...  If the sorting has been precise up to now, check where to place the
01768     /// ...  new dimension.  If not, skip the sorting check, because we'll have to 
01769     /// ...  check at runtime anyway.
01770 
01771     if (!_imprecise_sorting) {
01772         for (int i=0; i<entries; ++i) {
01773         Relation rel = range_acc.compare(*newdim->_stride,
01774                          _dims[i].stride_guarded());
01775         if (rel.is_less_than()) {
01776             which_dim = i;
01777             _imprecise_sorting = false;
01778             break;
01779         }
01780         /// ...  If we couldn't place the new dimension prior to the last existing dim,
01781         /// ...  then check whether the new stride is legitimately greater than the last one.
01782 
01783         if (i == entries-1) {
01784             if (rel.is_greater_than()) {
01785             _imprecise_sorting = false;
01786             } else {
01787             _imprecise_sorting = true;
01788             }
01789         }
01790         }
01791     }
01792     }
01793 
01794     add_dimension( newdim, which_dim );
01795 
01796     return which_dim;
01797 }
01798 
01799 void 
01800 AbstractAccess::del_dimension( int which_dim )
01801 {
01802     p_assert((which_dim >= 0) && (which_dim < _dims.entries()),"Dimension index out of range");
01803 
01804     _dims.del(which_dim);
01805 }
01806 
01807 void
01808 AbstractAccess::correctness( Expression * e )
01809 {
01810     _correctness = e;
01811 }
 © 1995-2005 University of Illinois, Urbana-Champaign. All rights reserved.  Fri Mar 25 23:05:35 2005