00001
00002
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
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
00031 int _ipa_reasons = -1;
00032
00033 int _ar_coalesce = -1;
00034
00035 int _ar_aggregate = -1;
00036
00037 int _ar_interleave = -1;
00038
00039 int _ar_match_dims = -1;
00040
00041 int _ar_logging = -1;
00042
00043 ofstream arlog;
00044
00045 int _ar_leave_descr = -1;
00046
00047 int _ar_prtstats = -1;
00048
00049 int _ar_approx_thresh = -1;
00050
00051
00052 int _ar_effort = -1;
00053
00054
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
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
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
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
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
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
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
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
00416
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
00432
00433
00434
00435
00436
00437
00438
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
00485
00486
00487
00488
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
00508
00509
00510
00511
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
00577
00578
00579 }
00580
00581
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
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;
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
00847
00848
00849
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
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
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
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
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
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
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
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
01096
01097
01098
01099
01100
01101
01102 void
01103 AbstractAccess::calc_overlap( int which_dim )
01104 {
01105 int entries = _dims.entries();
01106
01107
01108
01109 if (which_dim == -1) {
01110 _no_overlap = 0;
01111 return;
01112 } else if (entries <= 1) {
01113 _no_overlap = 1;
01114 return;
01115 }
01116
01117
01118
01119
01120 if (_imprecise_sorting) {
01121 _dims[which_dim]._check_overlap = true;
01122 _no_overlap = 2;
01123 return;
01124 }
01125
01126
01127
01128 Statement * r_stmt = range_stmt(*_summarized_to);
01129 RangeAccessor range_acc(_pgm_summarized_to->range_dict_guarded(),
01130 *r_stmt );
01131
01132
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
01162
01163
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
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
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
01198
01199
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
01223
01224
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
01247
01248
01249
01250
01251
01252
01253
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
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
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
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
01309
01310 if (is_var_in_expr( *start, index)) {
01311
01312
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
01330
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
01343
01344
01345 new_start = simplify( substitute_var( start->clone(), index, *pseudo_beg ) );
01346
01347
01348
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
01361
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
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
01381
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
01394
01395
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);
01421 this->pgm_summarized_to(&pgm);
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
01435
01436
01437
01438
01439
01440 void
01441 AbstractAccess::check_access_patterns ( )
01442 {
01443 static LambdaInfo lambda(0, 0, INLINE_CALL);
01444 RefList<AbstractAccess> aa_list;
01445
01446
01447
01448
01449
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
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
01489
01490
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
01503
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
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
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
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
01586
01587
01588
01589
01590
01591 bool
01592 AbstractAccess::coalesce( )
01593 {
01594
01595 bool coalesced = false;
01596
01597
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
01611
01612
01613
01614
01615
01616
01617
01618
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
01641
01642
01643
01644
01645
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
01677
01678 if (rel.is_equal()) {
01679 _no_overlap = 1;
01680 } else if (rel.is_not_equal()) {
01681 _no_overlap = 0;
01682 } else {
01683 dim_lo._check_overlap = true;
01684 }
01685
01686
01687 _dims.del(hidim);
01688
01689
01690
01691
01692
01693
01694 if (_imprecise_sorting) this->check_sort();
01695
01696 if (_ar_logging && _ar_logging % 2 == 0) {
01697 arlog << *this << endl;
01698 }
01699
01700
01701
01702
01703
01704
01705 ugi.coalesce_nodes( lodim, hidim );
01706 }
01707 }
01708 return coalesced;
01709 }
01710
01711
01712
01713
01714 void
01715 AbstractAccess::translate_GSA_symbols ( TranslateObject * tobj )
01716 {
01717
01718
01719
01720 for (Iterator<AccessDimension> iter = _dims;
01721 iter.valid();
01722 ++iter) {
01723
01724 iter.current().translate_GSA_symbols( tobj );
01725 }
01726
01727
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
01768
01769
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
01781
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 }