diff --git a/mlir/include/mlir/Analysis/Presburger/IntegerRelation.h b/mlir/include/mlir/Analysis/Presburger/IntegerRelation.h --- a/mlir/include/mlir/Analysis/Presburger/IntegerRelation.h +++ b/mlir/include/mlir/Analysis/Presburger/IntegerRelation.h @@ -274,7 +274,7 @@ void setAndEliminate(unsigned pos, ArrayRef values); /// Replaces the contents of this IntegerRelation with `other`. - virtual void clearAndCopyFrom(const IntegerRelation &other); + void clearAndCopyFrom(const IntegerRelation &other); /// Gather positions of all lower and upper bounds of the identifier at `pos`, /// and optionally any equalities on it. In addition, the bounds are to be @@ -527,8 +527,8 @@ /// set to true, a potential under approximation (subset) of the rational /// shadow / exact integer shadow is computed. // See implementation comments for more details. - virtual void fourierMotzkinEliminate(unsigned pos, bool darkShadow = false, - bool *isResultIntegerExact = nullptr); + void fourierMotzkinEliminate(unsigned pos, bool darkShadow = false, + bool *isResultIntegerExact = nullptr); /// Tightens inequalities given that we are dealing with integer spaces. This /// is similar to the GCD test but applied to inequalities. The constant term @@ -554,7 +554,7 @@ /// Returns false if the fields corresponding to various identifier counts, or /// equality/inequality buffer sizes aren't consistent; true otherwise. This /// is meant to be used within an assert internally. - virtual bool hasConsistentState() const; + bool hasConsistentState() const; /// Prints the number of constraints, dimensions, symbols and locals in the /// IntegerRelation. diff --git a/mlir/include/mlir/Analysis/Presburger/PresburgerSpace.h b/mlir/include/mlir/Analysis/Presburger/PresburgerSpace.h --- a/mlir/include/mlir/Analysis/Presburger/PresburgerSpace.h +++ b/mlir/include/mlir/Analysis/Presburger/PresburgerSpace.h @@ -6,14 +6,16 @@ // //===----------------------------------------------------------------------===// // -// Classes representing space information like number of identifiers and kind of -// identifiers. +// Classes representing space information like number of identifiers, kind of +// identifiers and values attached to identifiers. // //===----------------------------------------------------------------------===// #ifndef MLIR_ANALYSIS_PRESBURGER_PRESBURGERSPACE_H #define MLIR_ANALYSIS_PRESBURGER_PRESBURGERSPACE_H +#include "mlir/IR/Value.h" +#include "mlir/Support/LLVM.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" @@ -59,6 +61,8 @@ /// be implemented as a space with zero domain. IdKind::SetDim should be used /// to refer to dimensions in such spaces. /// +/// Each variable in the space can have a mlir::Value attached to it. +/// /// Compatibility of two spaces implies that number of identifiers of each kind /// other than Locals are equal. Equality of two spaces implies that number of /// identifiers of each kind are equal. @@ -92,6 +96,13 @@ return numDomain + numRange + numSymbols + numLocals; } + Optional &atValue(unsigned pos) { return values[pos]; } + const Optional &atValue(unsigned pos) const { return values[pos]; } + + ArrayRef> getMaybeValues() const { + return {values.data(), values.size()}; + } + /// Get the number of ids of the specified kind. unsigned getNumIdKind(IdKind kind) const; @@ -120,14 +131,24 @@ void removeIdRange(IdKind kind, unsigned idStart, unsigned idLimit); /// Returns true if both the spaces are compatible i.e. if both spaces have - /// the same number of identifiers of each kind (excluding locals). + /// the same number of identifiers of each kind (excluding locals) and + /// have the same values for each identifier (excluding locals). bool isCompatible(const PresburgerSpace &other) const; + /// Returns true if both the spaces are compatible i.e. if both spaces have + /// the same number of identifiers of each kind (excluding locals). + bool isCompatibleWithoutValues(const PresburgerSpace &other) const; + /// Returns true if both the spaces are equal including local identifiers i.e. /// if both spaces have the same number of identifiers of each kind (including - /// locals). + /// locals) and have the same values for each identifer (excluding locals). bool isEqual(const PresburgerSpace &other) const; + /// Returns true if both the spaces are equal including local identifiers i.e. + /// if both spaces have the same number of identifiers of each kind (including + /// locals). + bool isEqualWithoutValues(const PresburgerSpace &other) const; + /// Changes the partition between dimensions and symbols. Depending on the new /// symbol count, either a chunk of dimensional identifiers immediately before /// the split become symbols, or some of the symbols immediately after the @@ -141,7 +162,11 @@ PresburgerSpace(unsigned numDomain = 0, unsigned numRange = 0, unsigned numSymbols = 0, unsigned numLocals = 0) : numDomain(numDomain), numRange(numRange), numSymbols(numSymbols), - numLocals(numLocals) {} + numLocals(numLocals), + values(numDomain + numRange + numSymbols + numLocals, None) {} + + /// Checks if the number of values are equal to the number of variables. + bool isConsistent() const; private: // Number of identifiers corresponding to domain identifiers. @@ -157,6 +182,11 @@ /// Number of identifers corresponding to locals (identifiers corresponding /// to existentially quantified variables). unsigned numLocals; + + /// Values corresponding to the identifiers of this space. Temporary ones or + /// those that aren't associated with any Value are set to llvm::None. + /// TODO: Remove dependency of Presburger on MLIRIR by making this general. + SmallVector, 8> values; }; } // namespace presburger diff --git a/mlir/include/mlir/Dialect/Affine/Analysis/AffineStructures.h b/mlir/include/mlir/Dialect/Affine/Analysis/AffineStructures.h --- a/mlir/include/mlir/Dialect/Affine/Analysis/AffineStructures.h +++ b/mlir/include/mlir/Dialect/Affine/Analysis/AffineStructures.h @@ -49,11 +49,10 @@ numDims, numSymbols, numLocals)) { assert(numReservedCols >= getNumIds() + 1); assert(valArgs.empty() || valArgs.size() == getNumIds()); - values.reserve(numReservedCols); - if (valArgs.empty()) - values.resize(getNumIds(), None); - else - values.append(valArgs.begin(), valArgs.end()); + + // Set values. + for (unsigned i = 0, e = valArgs.size(); i < e; ++i) + atValue(i) = valArgs[i]; } /// Constructs a constraint system with the specified number of @@ -71,10 +70,10 @@ ArrayRef> valArgs = {}) : IntegerPolyhedron(fac) { assert(valArgs.empty() || valArgs.size() == getNumIds()); - if (valArgs.empty()) - values.resize(getNumIds(), None); - else - values.append(valArgs.begin(), valArgs.end()); + + // Set values. + for (unsigned i = 0, e = valArgs.size(); i < e; ++i) + atValue(i) = valArgs[i]; } /// Create a flat affine constraint system from an AffineValueMap or a list of @@ -270,9 +269,8 @@ } unsigned insertDimId(unsigned pos, ValueRange vals); unsigned insertSymbolId(unsigned pos, ValueRange vals); - unsigned insertId(presburger::IdKind kind, unsigned pos, - unsigned num = 1) override; unsigned insertId(presburger::IdKind kind, unsigned pos, ValueRange vals); + using IntegerPolyhedron::insertId; /// Append identifiers of the specified kind after the last identifier of that /// kind. The coefficient columns corresponding to the added identifiers are @@ -292,13 +290,6 @@ return appendId(IdKind::Local, num); } - /// Removes identifiers in the column range [idStart, idLimit), and copies any - /// remaining valid data into place, updates member variables, and resizes - /// arrays as needed. - void removeIdRange(presburger::IdKind kind, unsigned idStart, - unsigned idLimit) override; - using IntegerPolyhedron::removeIdRange; - /// Add the specified values as a dim or symbol id depending on its nature, if /// it already doesn't exist in the system. `val` has to be either a terminal /// symbol or a loop IV, i.e., it cannot be the result affine.apply of any @@ -370,18 +361,20 @@ /// appearing in the same order. Returns false otherwise. bool areIdsAlignedWithOther(const FlatAffineValueConstraints &other); - /// Replaces the contents of this FlatAffineValueConstraints with `other`. - void clearAndCopyFrom(const IntegerRelation &other) override; + Optional &atValue(unsigned pos) { return space.atValue(pos); } + const Optional &atValue(unsigned pos) const { + return space.atValue(pos); + } /// Returns the Value associated with the pos^th identifier. Asserts if /// no Value identifier was associated. inline Value getValue(unsigned pos) const { assert(hasValue(pos) && "identifier's Value not set"); - return values[pos].getValue(); + return atValue(pos).getValue(); } /// Returns true if the pos^th identifier has an associated Value. - inline bool hasValue(unsigned pos) const { return values[pos].hasValue(); } + inline bool hasValue(unsigned pos) const { return atValue(pos).hasValue(); } /// Returns true if at least one identifier has an associated Value. bool hasValues() const; @@ -402,25 +395,28 @@ } inline ArrayRef> getMaybeValues() const { - return {values.data(), values.size()}; + return space.getMaybeValues(); } inline ArrayRef> getMaybeDimValues() const { - return {values.data(), getNumDimIds()}; + return getMaybeValues().slice(space.getIdKindOffset(IdKind::SetDim), + space.getNumIdKind(IdKind::SetDim)); } inline ArrayRef> getMaybeSymbolValues() const { - return {values.data() + getNumDimIds(), getNumSymbolIds()}; + return getMaybeValues().slice(space.getIdKindOffset(IdKind::Symbol), + space.getNumIdKind(IdKind::Symbol)); } inline ArrayRef> getMaybeDimAndSymbolValues() const { - return {values.data(), getNumDimIds() + getNumSymbolIds()}; + return getMaybeValues().slice(space.getIdKindOffset(IdKind::SetDim), + space.getNumDimAndSymbolIds()); } /// Sets the Value associated with the pos^th identifier. inline void setValue(unsigned pos, Value val) { assert(pos < getNumIds() && "invalid id position"); - values[pos] = val; + atValue(pos) = val; } /// Sets the Values associated with the identifiers in the range [start, end). @@ -441,11 +437,6 @@ protected: using IdKind = presburger::IdKind; - /// Returns false if the fields corresponding to various identifier counts, or - /// equality/inequality buffer sizes aren't consistent; true otherwise. This - /// is meant to be used within an assert internally. - bool hasConsistentState() const override; - /// Given an affine map that is aligned with this constraint system: /// * Flatten the map. /// * Add newly introduced local columns at the beginning of this constraint @@ -459,26 +450,10 @@ LogicalResult flattenAlignedMapAndMergeLocals( AffineMap map, std::vector> *flattenedExprs); - /// Eliminates the identifier at the specified position using Fourier-Motzkin - /// variable elimination, but uses Gaussian elimination if there is an - /// equality involving that identifier. If the result of the elimination is - /// integer exact, `*isResultIntegerExact` is set to true. If `darkShadow` is - /// set to true, a potential under approximation (subset) of the rational - /// shadow / exact integer shadow is computed. - // See implementation comments for more details. - void fourierMotzkinEliminate(unsigned pos, bool darkShadow = false, - bool *isResultIntegerExact = nullptr) override; - /// Prints the number of constraints, dimensions, symbols and locals in the /// FlatAffineConstraints. Also, prints for each identifier whether there is /// an SSA Value attached to it. void printSpace(raw_ostream &os) const override; - - /// Values corresponding to the (column) identifiers of this constraint - /// system appearing in the order the identifiers correspond to columns. - /// Temporary ones or those that aren't associated with any Value are set to - /// None. - SmallVector, 8> values; }; /// A FlatAffineRelation represents a set of ordered pairs (domain -> range) diff --git a/mlir/lib/Analysis/Presburger/CMakeLists.txt b/mlir/lib/Analysis/Presburger/CMakeLists.txt --- a/mlir/lib/Analysis/Presburger/CMakeLists.txt +++ b/mlir/lib/Analysis/Presburger/CMakeLists.txt @@ -10,4 +10,5 @@ LINK_LIBS PUBLIC MLIRSupport + MLIRIR ) diff --git a/mlir/lib/Analysis/Presburger/IntegerRelation.cpp b/mlir/lib/Analysis/Presburger/IntegerRelation.cpp --- a/mlir/lib/Analysis/Presburger/IntegerRelation.cpp +++ b/mlir/lib/Analysis/Presburger/IntegerRelation.cpp @@ -39,7 +39,8 @@ } void IntegerRelation::append(const IntegerRelation &other) { - assert(space.isEqual(other.getSpace()) && "Spaces must be equal."); + assert(space.isEqualWithoutValues(other.getSpace()) && + "Spaces must be equal."); inequalities.reserveRows(inequalities.getNumRows() + other.getNumInequalities()); @@ -61,12 +62,14 @@ } bool IntegerRelation::isEqual(const IntegerRelation &other) const { - assert(space.isEqual(other.getSpace()) && "Spaces must be equal."); + assert(space.isEqualWithoutValues(other.getSpace()) && + "Spaces must be equal."); return PresburgerRelation(*this).isEqual(PresburgerRelation(other)); } bool IntegerRelation::isSubsetOf(const IntegerRelation &other) const { - assert(space.isEqual(other.getSpace()) && "Spaces must be equal."); + assert(space.isEqualWithoutValues(other.getSpace()) && + "Spaces must be equal."); return PresburgerRelation(*this).isSubsetOf(PresburgerRelation(other)); } @@ -1089,7 +1092,7 @@ /// division representation for some local id cannot be obtained, and thus these /// local ids are not considered for detecting duplicates. void IntegerRelation::mergeLocalIds(IntegerRelation &other) { - assert(space.isCompatible(other.getSpace()) && + assert(space.isCompatibleWithoutValues(other.getSpace()) && "Spaces should be compatible."); IntegerRelation &relA = *this; @@ -1920,7 +1923,8 @@ // lower bounds and the max of the upper bounds along each of the dimensions. LogicalResult IntegerRelation::unionBoundingBox(const IntegerRelation &otherCst) { - assert(space.isEqual(otherCst.getSpace()) && "Spaces should match."); + assert(space.isEqualWithoutValues(otherCst.getSpace()) && + "Spaces should match."); assert(getNumLocalIds() == 0 && "local ids not supported yet here"); // Get the constraints common to both systems; these will be added as is to diff --git a/mlir/lib/Analysis/Presburger/PWMAFunction.cpp b/mlir/lib/Analysis/Presburger/PWMAFunction.cpp --- a/mlir/lib/Analysis/Presburger/PWMAFunction.cpp +++ b/mlir/lib/Analysis/Presburger/PWMAFunction.cpp @@ -83,7 +83,7 @@ void MultiAffineFunction::dump() const { print(llvm::errs()); } bool MultiAffineFunction::isEqual(const MultiAffineFunction &other) const { - return space.isCompatible(other.getSpace()) && + return space.isCompatibleWithoutValues(other.getSpace()) && getDomain().isEqual(other.getDomain()) && isEqualWhereDomainsOverlap(other); } @@ -129,7 +129,7 @@ bool MultiAffineFunction::isEqualWhereDomainsOverlap( MultiAffineFunction other) const { - if (!space.isCompatible(other.getSpace())) + if (!space.isCompatibleWithoutValues(other.getSpace())) return false; // `commonFunc` has the same output as `this`. @@ -162,7 +162,7 @@ /// Two PWMAFunctions are equal if they have the same dimensionalities, /// the same domain, and take the same value at every point in the domain. bool PWMAFunction::isEqual(const PWMAFunction &other) const { - if (!space.isCompatible(other.space)) + if (!space.isCompatibleWithoutValues(other.space)) return false; if (!this->getDomain().isEqual(other.getDomain())) @@ -180,7 +180,7 @@ } void PWMAFunction::addPiece(const MultiAffineFunction &piece) { - assert(space.isCompatible(piece.getSpace()) && + assert(space.isCompatibleWithoutValues(piece.getSpace()) && "Piece to be added is not compatible with this PWMAFunction!"); assert(piece.isConsistent() && "Piece is internally inconsistent!"); assert(this->getDomain() diff --git a/mlir/lib/Analysis/Presburger/PresburgerRelation.cpp b/mlir/lib/Analysis/Presburger/PresburgerRelation.cpp --- a/mlir/lib/Analysis/Presburger/PresburgerRelation.cpp +++ b/mlir/lib/Analysis/Presburger/PresburgerRelation.cpp @@ -37,7 +37,8 @@ /// Mutate this set, turning it into the union of this set and the given /// IntegerRelation. void PresburgerRelation::unionInPlace(const IntegerRelation &disjunct) { - assert(space.isCompatible(disjunct.getSpace()) && "Spaces should match"); + assert(space.isCompatibleWithoutValues(disjunct.getSpace()) && + "Spaces should match"); disjuncts.push_back(disjunct); } @@ -46,7 +47,8 @@ /// This is accomplished by simply adding all the disjuncts of the given set /// to this set. void PresburgerRelation::unionInPlace(const PresburgerRelation &set) { - assert(space.isCompatible(set.getSpace()) && "Spaces should match"); + assert(space.isCompatibleWithoutValues(set.getSpace()) && + "Spaces should match"); for (const IntegerRelation &disjunct : set.disjuncts) unionInPlace(disjunct); } @@ -54,7 +56,8 @@ /// Return the union of this set and the given set. PresburgerRelation PresburgerRelation::unionSet(const PresburgerRelation &set) const { - assert(space.isCompatible(set.getSpace()) && "Spaces should match"); + assert(space.isCompatibleWithoutValues(set.getSpace()) && + "Spaces should match"); PresburgerRelation result = *this; result.unionInPlace(set); return result; @@ -87,7 +90,8 @@ // variables of both. PresburgerRelation PresburgerRelation::intersect(const PresburgerRelation &set) const { - assert(space.isCompatible(set.getSpace()) && "Spaces should match"); + assert(space.isCompatibleWithoutValues(set.getSpace()) && + "Spaces should match"); PresburgerRelation result(getSpace()); for (const IntegerRelation &csA : disjuncts) { @@ -163,7 +167,8 @@ /// static PresburgerRelation getSetDifference(IntegerRelation b, const PresburgerRelation &s) { - assert(b.getSpace().isCompatible(s.getSpace()) && "Spaces should match"); + assert(b.getSpace().isCompatibleWithoutValues(s.getSpace()) && + "Spaces should match"); if (b.isEmptyByGCDTest()) return PresburgerRelation::getEmpty(b.getSpaceWithoutLocals()); @@ -364,7 +369,8 @@ /// return `this \ set`. PresburgerRelation PresburgerRelation::subtract(const PresburgerRelation &set) const { - assert(space.isCompatible(set.getSpace()) && "Spaces should match"); + assert(space.isCompatibleWithoutValues(set.getSpace()) && + "Spaces should match"); PresburgerRelation result(getSpace()); // We compute (U_i t_i) \ (U_i set_i) as U_i (t_i \ V_i set_i). for (const IntegerRelation &disjunct : disjuncts) @@ -381,7 +387,8 @@ /// Two sets are equal iff they are subsets of each other. bool PresburgerRelation::isEqual(const PresburgerRelation &set) const { - assert(space.isCompatible(set.getSpace()) && "Spaces should match"); + assert(space.isCompatibleWithoutValues(set.getSpace()) && + "Spaces should match"); return this->isSubsetOf(set) && set.isSubsetOf(*this); } diff --git a/mlir/lib/Analysis/Presburger/PresburgerSpace.cpp b/mlir/lib/Analysis/Presburger/PresburgerSpace.cpp --- a/mlir/lib/Analysis/Presburger/PresburgerSpace.cpp +++ b/mlir/lib/Analysis/Presburger/PresburgerSpace.cpp @@ -83,6 +83,11 @@ else numLocals += num; + // Insert values for newly added variables. + values.insert(values.begin() + absolutePos, num, None); + + assert(isConsistent() && "Space must be consistent."); + return absolutePos; } @@ -102,21 +107,51 @@ numSymbols -= numIdsEliminated; else numLocals -= numIdsEliminated; + + // Remove values for removed variables. + unsigned offset = getIdKindOffset(kind); + values.erase(values.begin() + offset + idStart, + values.begin() + offset + idLimit); + + assert(isConsistent() && "Space must be consistent."); +} + +bool PresburgerSpace::isConsistent() const { + return values.size() == getNumIds(); } bool PresburgerSpace::isCompatible(const PresburgerSpace &other) const { + assert(isConsistent() && "Space must be consistent."); + return isCompatibleWithoutValues(other) && + getMaybeValues().slice(0, getNumDimAndSymbolIds()) == + other.getMaybeValues().slice(0, other.getNumDimAndSymbolIds()); +} + +bool PresburgerSpace::isCompatibleWithoutValues( + const PresburgerSpace &other) const { + assert(isConsistent() && "Space must be consistent."); return getNumDomainIds() == other.getNumDomainIds() && getNumRangeIds() == other.getNumRangeIds() && getNumSymbolIds() == other.getNumSymbolIds(); } bool PresburgerSpace::isEqual(const PresburgerSpace &other) const { - return isCompatible(other) && getNumLocalIds() == other.getNumLocalIds(); + assert(isConsistent() && "Space must be consistent."); + return isEqualWithoutValues(other) && + getMaybeValues() == other.getMaybeValues(); +} + +bool PresburgerSpace::isEqualWithoutValues(const PresburgerSpace &other) const { + assert(isConsistent() && "Space must be consistent."); + return isCompatibleWithoutValues(other) && + getNumLocalIds() == other.getNumLocalIds(); } void PresburgerSpace::setDimSymbolSeparation(unsigned newSymbolCount) { + assert(isConsistent() && "Space must be consistent."); assert(newSymbolCount <= getNumDimAndSymbolIds() && "invalid separation position"); + // No need to modify `values`, since only the seperation is changed. numRange = numRange + numSymbols - newSymbolCount; numSymbols = newSymbolCount; } diff --git a/mlir/lib/Dialect/Affine/Analysis/AffineStructures.cpp b/mlir/lib/Dialect/Affine/Analysis/AffineStructures.cpp --- a/mlir/lib/Dialect/Affine/Analysis/AffineStructures.cpp +++ b/mlir/lib/Dialect/Affine/Analysis/AffineStructures.cpp @@ -156,9 +156,6 @@ set.getNumSymbols(), /*numLocals=*/0)) { - // Resize values. - values.resize(getNumIds(), None); - // Flatten expressions and add them to the constraint system. std::vector> flatExprs; FlatAffineValueConstraints localVarCst; @@ -291,14 +288,6 @@ return insertId(IdKind::Symbol, pos, vals); } -unsigned FlatAffineValueConstraints::insertId(IdKind kind, unsigned pos, - unsigned num) { - unsigned absolutePos = IntegerPolyhedron::insertId(kind, pos, num); - values.insert(values.begin() + absolutePos, num, None); - assert(values.size() == getNumIds()); - return absolutePos; -} - unsigned FlatAffineValueConstraints::insertId(IdKind kind, unsigned pos, ValueRange vals) { assert(!vals.empty() && "expected ValueRange with Values"); @@ -307,17 +296,16 @@ // If a Value is provided, insert it; otherwise use None. for (unsigned i = 0; i < num; ++i) - values.insert(values.begin() + absolutePos + i, - vals[i] ? Optional(vals[i]) : None); + atValue(absolutePos + i) = vals[i] ? Optional(vals[i]) : None; - assert(values.size() == getNumIds()); return absolutePos; } bool FlatAffineValueConstraints::hasValues() const { - return llvm::find_if(values, [](Optional id) { - return id.hasValue(); - }) != values.end(); + for (unsigned i = 0, e = getNumIds(); i < e; ++i) + if (atValue(i).hasValue()) + return true; + return false; } /// Checks if two constraint systems are in the same space, i.e., if they are @@ -700,19 +688,6 @@ append(cst); } -bool FlatAffineValueConstraints::hasConsistentState() const { - return IntegerPolyhedron::hasConsistentState() && - values.size() == getNumIds(); -} - -void FlatAffineValueConstraints::removeIdRange(IdKind kind, unsigned idStart, - unsigned idLimit) { - IntegerPolyhedron::removeIdRange(kind, idStart, idLimit); - unsigned offset = getIdKindOffset(kind); - values.erase(values.begin() + idStart + offset, - values.begin() + idLimit + offset); -} - // Determine whether the identifier at 'pos' (say id_r) can be expressed as // modulo of another known identifier (say id_n) w.r.t a constant. For example, // if the following constraints hold true: @@ -1222,11 +1197,11 @@ for (unsigned i = getIdKindOffset(IdKind::SetDim), e = getIdKindEnd(IdKind::SetDim); i < e; ++i) - dims.push_back(values[i] ? *values[i] : Value()); + dims.push_back(atValue(i) ? *atValue(i) : Value()); for (unsigned i = getIdKindOffset(IdKind::Symbol), e = getIdKindEnd(IdKind::Symbol); i < e; ++i) - syms.push_back(values[i] ? *values[i] : Value()); + syms.push_back(atValue(i) ? *atValue(i) : Value()); AffineMap alignedMap = alignAffineMapWithValues(map, operands, dims, syms, newSymsPtr); @@ -1305,26 +1280,25 @@ } bool FlatAffineValueConstraints::findId(Value val, unsigned *pos) const { - unsigned i = 0; - for (const auto &mayBeId : values) { - if (mayBeId.hasValue() && mayBeId.getValue() == val) { + for (unsigned i = 0, e = getNumIds(); i < e; ++i) { + const Optional &spaceVal = atValue(i); + if (spaceVal.hasValue() && spaceVal.getValue() == val) { *pos = i; return true; } - i++; } + return false; } bool FlatAffineValueConstraints::containsId(Value val) const { - return llvm::any_of(values, [&](const Optional &mayBeId) { - return mayBeId.hasValue() && mayBeId.getValue() == val; - }); + unsigned pos; + return findId(val, &pos); } void FlatAffineValueConstraints::swapId(unsigned posA, unsigned posB) { IntegerPolyhedron::swapId(posA, posB); - std::swap(values[posA], values[posB]); + std::swap(atValue(posA), atValue(posB)); } void FlatAffineValueConstraints::addBound(BoundType type, Value val, @@ -1348,32 +1322,6 @@ os << " const)\n"; } -void FlatAffineValueConstraints::clearAndCopyFrom( - const IntegerRelation &other) { - - if (auto *otherValueSet = - dyn_cast(&other)) { - *this = *otherValueSet; - } else { - *static_cast(this) = other; - values.clear(); - values.resize(getNumIds(), None); - } -} - -void FlatAffineValueConstraints::fourierMotzkinEliminate( - unsigned pos, bool darkShadow, bool *isResultIntegerExact) { - SmallVector, 8> newVals; - newVals.reserve(getNumIds() - 1); - newVals.append(values.begin(), values.begin() + pos); - newVals.append(values.begin() + pos + 1, values.end()); - // Note: Base implementation discards all associated Values. - IntegerPolyhedron::fourierMotzkinEliminate(pos, darkShadow, - isResultIntegerExact); - values = newVals; - assert(values.size() == getNumIds()); -} - void FlatAffineValueConstraints::projectOut(Value val) { unsigned pos; bool ret = findId(val, &pos); @@ -1597,8 +1545,9 @@ void FlatAffineRelation::compose(const FlatAffineRelation &other) { assert(getNumDomainDims() == other.getNumRangeDims() && "Domain of this and range of other do not match"); - assert(std::equal(values.begin(), values.begin() + getNumDomainDims(), - other.values.begin() + other.getNumDomainDims()) && + assert(getMaybeValues().take_front(getNumDomainDims()) == + other.getMaybeValues().slice(other.getNumDomainDims(), + getNumDomainDims()) && "Domain of this and range of other do not match"); FlatAffineRelation rel = other; diff --git a/mlir/unittests/Dialect/Affine/Analysis/AffineStructuresParser.cpp b/mlir/unittests/Dialect/Affine/Analysis/AffineStructuresParser.cpp --- a/mlir/unittests/Dialect/Affine/Analysis/AffineStructuresParser.cpp +++ b/mlir/unittests/Dialect/Affine/Analysis/AffineStructuresParser.cpp @@ -21,5 +21,11 @@ if (!set) return failure(); - return FlatAffineValueConstraints(set); + // Set values in FAC to llvm::None. + // TODO: Check if we can also introduce use Value in tests. + FlatAffineValueConstraints fac(set); + for (unsigned i = 0, e = fac.getNumIds(); i < e; ++i) + fac.atValue(i) = llvm::None; + + return fac; }