-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[MLIR][Presburger] Use Identifiers outside Presburger library #77316
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
✅ With the latest revision this PR passed the C/C++ code formatter. |
094fca3
to
cf055b4
Compare
bee9836
to
fd0a492
Compare
fd0a492
to
0dc618e
Compare
3993edb
to
eb70c0e
Compare
6a86353
to
a1aa8e7
Compare
@llvm/pr-subscribers-mlir-presburger @llvm/pr-subscribers-mlir Author: Bharathi Ramana Joshi (iambrj) ChangesPatch is 44.47 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/77316.diff 10 Files Affected:
diff --git a/mlir/include/mlir/Analysis/FlatLinearValueConstraints.h b/mlir/include/mlir/Analysis/FlatLinearValueConstraints.h
index e4de5b0661571c..22eaba94aa950e 100644
--- a/mlir/include/mlir/Analysis/FlatLinearValueConstraints.h
+++ b/mlir/include/mlir/Analysis/FlatLinearValueConstraints.h
@@ -205,6 +205,8 @@ class FlatLinearConstraints : public presburger::IntegerPolyhedron {
/// where each non-local variable can have an SSA Value attached to it.
class FlatLinearValueConstraints : public FlatLinearConstraints {
public:
+ using Identifier = presburger::Identifier;
+
/// Constructs a constraint system reserving memory for the specified number
/// of constraints and variables. `valArgs` are the optional SSA values
/// associated with each dimension/symbol. These must either be empty or match
@@ -217,11 +219,11 @@ class FlatLinearValueConstraints : public FlatLinearConstraints {
: FlatLinearConstraints(numReservedInequalities, numReservedEqualities,
numReservedCols, numDims, numSymbols, numLocals) {
assert(valArgs.empty() || valArgs.size() == getNumDimAndSymbolVars());
- values.reserve(numReservedCols);
- if (valArgs.empty())
- values.resize(getNumDimAndSymbolVars(), std::nullopt);
- else
- values.append(valArgs.begin(), valArgs.end());
+ // Store Values in space's identifiers.
+ space.resetIds();
+ for (unsigned i = 0, e = valArgs.size(); i < e; ++i)
+ if (valArgs[i])
+ setValue(i, *valArgs[i]);
}
/// Constructs a constraint system reserving memory for the specified number
@@ -236,11 +238,11 @@ class FlatLinearValueConstraints : public FlatLinearConstraints {
: FlatLinearConstraints(numReservedInequalities, numReservedEqualities,
numReservedCols, numDims, numSymbols, numLocals) {
assert(valArgs.empty() || valArgs.size() == getNumDimAndSymbolVars());
- values.reserve(numReservedCols);
- if (valArgs.empty())
- values.resize(getNumDimAndSymbolVars(), std::nullopt);
- else
- values.append(valArgs.begin(), valArgs.end());
+ // Store Values in space's identifiers.
+ space.resetIds();
+ for (unsigned i = 0, e = valArgs.size(); i < e; ++i)
+ if (valArgs[i])
+ setValue(i, valArgs[i]);
}
/// Constructs a constraint system with the specified number of dimensions
@@ -272,11 +274,15 @@ class FlatLinearValueConstraints : public FlatLinearConstraints {
FlatLinearValueConstraints(const IntegerPolyhedron &fac,
ArrayRef<std::optional<Value>> valArgs = {})
: FlatLinearConstraints(fac) {
- assert(valArgs.empty() || valArgs.size() == getNumDimAndSymbolVars());
+ // Do not reset values assigned by FlatLinearConstraints' constructor.
if (valArgs.empty())
- values.resize(getNumDimAndSymbolVars(), std::nullopt);
- else
- values.append(valArgs.begin(), valArgs.end());
+ return;
+ assert(valArgs.size() == getNumDimAndSymbolVars());
+ // Store Values in space's identifiers.
+ space.resetIds();
+ for (unsigned i = 0, e = valArgs.size(); i < e; ++i)
+ if (valArgs[i])
+ setValue(i, *valArgs[i]);
}
/// Creates an affine constraint system from an IntegerSet.
@@ -290,9 +296,6 @@ class FlatLinearValueConstraints : public FlatLinearConstraints {
cst->getKind() <= Kind::FlatAffineRelation;
}
- /// Replaces the contents of this FlatLinearValueConstraints with `other`.
- void clearAndCopyFrom(const IntegerRelation &other) override;
-
/// Adds a constant bound for the variable associated with the given Value.
void addBound(presburger::BoundType type, Value val, int64_t value);
using FlatLinearConstraints::addBound;
@@ -302,7 +305,9 @@ class FlatLinearValueConstraints : public FlatLinearConstraints {
inline Value getValue(unsigned pos) const {
assert(pos < getNumDimAndSymbolVars() && "Invalid position");
assert(hasValue(pos) && "variable's Value not set");
- return *values[pos];
+ VarKind kind = getVarKindAt(pos);
+ unsigned relativePos = pos - getVarKindOffset(kind);
+ return space.getId(kind, relativePos).getValue<Value>();
}
/// Returns the Values associated with variables in range [start, end).
@@ -313,27 +318,47 @@ class FlatLinearValueConstraints : public FlatLinearConstraints {
assert(start <= end && "invalid start position");
values->clear();
values->reserve(end - start);
- for (unsigned i = start; i < end; i++)
+ for (unsigned i = start; i < end; ++i)
values->push_back(getValue(i));
}
- inline ArrayRef<std::optional<Value>> getMaybeValues() const {
- return {values.data(), values.size()};
+ inline SmallVector<std::optional<Value>> getMaybeValues() const {
+ SmallVector<std::optional<Value>> maybeValues;
+ maybeValues.reserve(getNumDimAndSymbolVars());
+ for (unsigned i = 0, e = getNumDimAndSymbolVars(); i < e; ++i)
+ if (hasValue(i))
+ maybeValues.push_back(getValue(i));
+ else
+ maybeValues.push_back(std::nullopt);
+ return maybeValues;
}
- inline ArrayRef<std::optional<Value>>
+ inline SmallVector<std::optional<Value>>
getMaybeValues(presburger::VarKind kind) const {
assert(kind != VarKind::Local &&
"Local variables do not have any value attached to them.");
- return {values.data() + getVarKindOffset(kind), getNumVarKind(kind)};
+ SmallVector<std::optional<Value>> maybeValues;
+ maybeValues.reserve(getNumVarKind(kind));
+ for (unsigned i = 0, e = getNumVarKind(kind); i < e; ++i) {
+ const Identifier id = space.getId(kind, i);
+ if (id.hasValue())
+ maybeValues.push_back(id.getValue<Value>());
+ else
+ maybeValues.push_back(std::nullopt);
+ }
+ return maybeValues;
}
/// Returns true if the pos^th variable has an associated Value.
inline bool hasValue(unsigned pos) const {
assert(pos < getNumDimAndSymbolVars() && "Invalid position");
- return values[pos].has_value();
+ VarKind kind = getVarKindAt(pos);
+ unsigned relativePos = pos - getVarKindOffset(kind);
+ return space.getId(kind, relativePos).hasValue();
}
+ void resetValues() { space.resetIds(); }
+
unsigned appendDimVar(ValueRange vals);
using FlatLinearConstraints::appendDimVar;
@@ -360,7 +385,9 @@ class FlatLinearValueConstraints : public FlatLinearConstraints {
/// Sets the Value associated with the pos^th variable.
inline void setValue(unsigned pos, Value val) {
assert(pos < getNumDimAndSymbolVars() && "invalid var position");
- values[pos] = val;
+ VarKind kind = getVarKindAt(pos);
+ unsigned relativePos = pos - getVarKindOffset(kind);
+ space.getId(kind, relativePos) = presburger::Identifier(val);
}
/// Sets the Values associated with the variables in the range [start, end).
@@ -387,9 +414,6 @@ class FlatLinearValueConstraints : public FlatLinearConstraints {
void projectOut(Value val);
using IntegerPolyhedron::projectOut;
- /// Swap the posA^th variable with the posB^th variable.
- void swapVar(unsigned posA, unsigned posB) override;
-
/// Prints the number of constraints, dimensions, symbols and locals in the
/// FlatAffineValueConstraints. Also, prints for each variable whether there
/// is an SSA Value attached to it.
@@ -444,28 +468,6 @@ class FlatLinearValueConstraints : public FlatLinearConstraints {
/// output = {0 <= d0 <= 6, 1 <= d1 <= 15}
LogicalResult unionBoundingBox(const FlatLinearValueConstraints &other);
using IntegerPolyhedron::unionBoundingBox;
-
-protected:
- /// Eliminates the variable at the specified position using Fourier-Motzkin
- /// variable elimination, but uses Gaussian elimination if there is an
- /// equality involving that variable. 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;
-
- /// Returns false if the fields corresponding to various variable 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;
-
- /// Values corresponding to the (column) non-local variables of this
- /// constraint system appearing in the order the variables correspond to
- /// columns. Variables that aren't associated with any Value are set to
- /// std::nullopt.
- SmallVector<std::optional<Value>, 8> values;
};
/// Flattens 'expr' into 'flattenedExpr', which contains the coefficients of the
diff --git a/mlir/include/mlir/Analysis/Presburger/IntegerRelation.h b/mlir/include/mlir/Analysis/Presburger/IntegerRelation.h
index c476a022a48272..a63703e8ef38f0 100644
--- a/mlir/include/mlir/Analysis/Presburger/IntegerRelation.h
+++ b/mlir/include/mlir/Analysis/Presburger/IntegerRelation.h
@@ -674,6 +674,11 @@ class IntegerRelation {
/// this for uniformity with `applyDomain`.
void applyRange(const IntegerRelation &rel);
+ /// Given a relation `other: (A -> B)`, this operation merges the symbol and
+ /// local variables and then takes the composition of `other` on `this: (B ->
+ /// C)`. The resulting relation represents tuples of the form: `A -> C`.
+ void mergeAndCompose(const IntegerRelation &other);
+
/// Compute an equivalent representation of the same set, such that all local
/// vars in all disjuncts have division representations. This representation
/// may involve local vars that correspond to divisions, and may also be a
diff --git a/mlir/include/mlir/Analysis/Presburger/PresburgerSpace.h b/mlir/include/mlir/Analysis/Presburger/PresburgerSpace.h
index 91ed349f461c69..a2442ede7a2d7a 100644
--- a/mlir/include/mlir/Analysis/Presburger/PresburgerSpace.h
+++ b/mlir/include/mlir/Analysis/Presburger/PresburgerSpace.h
@@ -265,6 +265,8 @@ class PresburgerSpace {
return {identifiers.data() + getVarKindOffset(kind), getNumVarKind(kind)};
}
+ ArrayRef<Identifier> getIds() const { return identifiers; }
+
/// Returns if identifiers are being used.
bool isUsingIds() const { return usingIds; }
diff --git a/mlir/include/mlir/Dialect/Affine/Analysis/AffineAnalysis.h b/mlir/include/mlir/Dialect/Affine/Analysis/AffineAnalysis.h
index a27583877b603c..4134aef8174bc1 100644
--- a/mlir/include/mlir/Dialect/Affine/Analysis/AffineAnalysis.h
+++ b/mlir/include/mlir/Dialect/Affine/Analysis/AffineAnalysis.h
@@ -15,6 +15,7 @@
#ifndef MLIR_DIALECT_AFFINE_ANALYSIS_AFFINEANALYSIS_H
#define MLIR_DIALECT_AFFINE_ANALYSIS_AFFINEANALYSIS_H
+#include "mlir/Analysis/Presburger/IntegerRelation.h"
#include "mlir/Dialect/Arith/IR/Arith.h"
#include "mlir/IR/Value.h"
#include "llvm/ADT/SmallVector.h"
@@ -115,7 +116,7 @@ struct MemRefAccess {
///
/// Returns failure for yet unimplemented/unsupported cases (see docs of
/// mlir::getIndexSet and mlir::getRelationFromMap for these cases).
- LogicalResult getAccessRelation(FlatAffineRelation &accessRel) const;
+ LogicalResult getAccessRelation(presburger::IntegerRelation &accessRel) const;
/// Populates 'accessMap' with composition of AffineApplyOps reachable from
/// 'indices'.
diff --git a/mlir/include/mlir/Dialect/Affine/Analysis/AffineStructures.h b/mlir/include/mlir/Dialect/Affine/Analysis/AffineStructures.h
index 7c500f13895af1..c932792fbed756 100644
--- a/mlir/include/mlir/Dialect/Affine/Analysis/AffineStructures.h
+++ b/mlir/include/mlir/Dialect/Affine/Analysis/AffineStructures.h
@@ -251,9 +251,10 @@ class FlatAffineRelation : public FlatAffineValueConstraints {
/// For AffineValueMap, the domain and symbols have Value set corresponding to
/// the Value in `map`. Returns failure if the AffineMap could not be flattened
/// (i.e., semi-affine is not yet handled).
-LogicalResult getRelationFromMap(AffineMap &map, FlatAffineRelation &rel);
+LogicalResult getRelationFromMap(AffineMap &map,
+ presburger::IntegerRelation &rel);
LogicalResult getRelationFromMap(const AffineValueMap &map,
- FlatAffineRelation &rel);
+ presburger::IntegerRelation &rel);
} // namespace affine
} // namespace mlir
diff --git a/mlir/lib/Analysis/FlatLinearValueConstraints.cpp b/mlir/lib/Analysis/FlatLinearValueConstraints.cpp
index 69846a356e0cc4..8a09c741979ffb 100644
--- a/mlir/lib/Analysis/FlatLinearValueConstraints.cpp
+++ b/mlir/lib/Analysis/FlatLinearValueConstraints.cpp
@@ -9,6 +9,7 @@
#include "mlir/Analysis//FlatLinearValueConstraints.h"
#include "mlir/Analysis/Presburger/LinearTransform.h"
+#include "mlir/Analysis/Presburger/PresburgerSpace.h"
#include "mlir/Analysis/Presburger/Simplex.h"
#include "mlir/Analysis/Presburger/Utils.h"
#include "mlir/IR/AffineExprVisitor.h"
@@ -817,13 +818,13 @@ FlatLinearValueConstraints::FlatLinearValueConstraints(IntegerSet set,
set.getNumDims() + set.getNumSymbols() + 1,
set.getNumDims(), set.getNumSymbols(),
/*numLocals=*/0) {
- // Populate values.
- if (operands.empty()) {
- values.resize(getNumDimAndSymbolVars(), std::nullopt);
- } else {
- assert(set.getNumInputs() == operands.size() && "operand count mismatch");
- values.assign(operands.begin(), operands.end());
- }
+ assert(operands.empty() ||
+ set.getNumInputs() == operands.size() && "operand count mismatch");
+ // Use values in space for FlatLinearValueConstraints.
+ space.resetIds();
+ // Set the values for the non-local variables.
+ for (unsigned i = 0, e = operands.size(); i < e; ++i)
+ setValue(i, operands[i]);
// Flatten expressions and add them to the constraint system.
std::vector<SmallVector<int64_t, 8>> flatExprs;
@@ -873,11 +874,6 @@ unsigned FlatLinearValueConstraints::insertVar(VarKind kind, unsigned pos,
unsigned num) {
unsigned absolutePos = IntegerPolyhedron::insertVar(kind, pos, num);
- if (kind != VarKind::Local) {
- values.insert(values.begin() + absolutePos, num, std::nullopt);
- assert(values.size() == getNumDimAndSymbolVars());
- }
-
return absolutePos;
}
@@ -890,11 +886,10 @@ unsigned FlatLinearValueConstraints::insertVar(VarKind kind, unsigned pos,
unsigned absolutePos = IntegerPolyhedron::insertVar(kind, pos, num);
// If a Value is provided, insert it; otherwise use std::nullopt.
- for (unsigned i = 0; i < num; ++i)
- values.insert(values.begin() + absolutePos + i,
- vals[i] ? std::optional<Value>(vals[i]) : std::nullopt);
+ for (unsigned i = 0, e = vals.size(); i < e; ++i)
+ if (vals[i])
+ setValue(absolutePos + i, vals[i]);
- assert(values.size() == getNumDimAndSymbolVars());
return absolutePos;
}
@@ -902,10 +897,14 @@ unsigned FlatLinearValueConstraints::insertVar(VarKind kind, unsigned pos,
/// associated with the same set of variables, appearing in the same order.
static bool areVarsAligned(const FlatLinearValueConstraints &a,
const FlatLinearValueConstraints &b) {
- return a.getNumDimVars() == b.getNumDimVars() &&
- a.getNumSymbolVars() == b.getNumSymbolVars() &&
- a.getNumVars() == b.getNumVars() &&
- a.getMaybeValues().equals(b.getMaybeValues());
+ if (a.getNumDomainVars() != b.getNumDomainVars() ||
+ a.getNumRangeVars() != b.getNumRangeVars() ||
+ a.getNumSymbolVars() != b.getNumSymbolVars())
+ return false;
+ SmallVector<std::optional<Value>> aMaybeValues = a.getMaybeValues(),
+ bMaybeValues = b.getMaybeValues();
+ return std::equal(aMaybeValues.begin(), aMaybeValues.end(),
+ bMaybeValues.begin(), bMaybeValues.end());
}
/// Calls areVarsAligned to check if two constraint systems have the same set
@@ -928,12 +927,14 @@ static bool LLVM_ATTRIBUTE_UNUSED areVarsUnique(
return true;
SmallPtrSet<Value, 8> uniqueVars;
- ArrayRef<std::optional<Value>> maybeValues =
- cst.getMaybeValues().slice(start, end - start);
- for (std::optional<Value> val : maybeValues) {
+ SmallVector<std::optional<Value>, 8> maybeValuesAll = cst.getMaybeValues();
+ ArrayRef<std::optional<Value>> maybeValues = {maybeValuesAll.data() + start,
+ maybeValuesAll.data() + end};
+
+ for (std::optional<Value> val : maybeValues)
if (val && !uniqueVars.insert(*val).second)
return false;
- }
+
return true;
}
@@ -1058,20 +1059,9 @@ void FlatLinearValueConstraints::mergeSymbolVars(
"expected same number of symbols");
}
-bool FlatLinearValueConstraints::hasConsistentState() const {
- return IntegerPolyhedron::hasConsistentState() &&
- values.size() == getNumDimAndSymbolVars();
-}
-
void FlatLinearValueConstraints::removeVarRange(VarKind kind, unsigned varStart,
unsigned varLimit) {
IntegerPolyhedron::removeVarRange(kind, varStart, varLimit);
- unsigned offset = getVarKindOffset(kind);
-
- if (kind != VarKind::Local) {
- values.erase(values.begin() + varStart + offset,
- values.begin() + varLimit + offset);
- }
}
AffineMap
@@ -1089,14 +1079,14 @@ FlatLinearValueConstraints::computeAlignedMap(AffineMap map,
dims.reserve(getNumDimVars());
syms.reserve(getNumSymbolVars());
- for (unsigned i = getVarKindOffset(VarKind::SetDim),
- e = getVarKindEnd(VarKind::SetDim);
- i < e; ++i)
- dims.push_back(values[i] ? *values[i] : Value());
- for (unsigned i = getVarKindOffset(VarKind::Symbol),
- e = getVarKindEnd(VarKind::Symbol);
- i < e; ++i)
- syms.push_back(values[i] ? *values[i] : Value());
+ for (unsigned i = 0, e = getNumVarKind(VarKind::SetDim); i < e; ++i) {
+ Identifier id = space.getId(VarKind::SetDim, i);
+ dims.push_back(id.hasValue() ? Value(id.getValue<Value>()) : Value());
+ }
+ for (unsigned i = 0, e = getNumVarKind(VarKind::Symbol); i < e; ++i) {
+ Identifier id = space.getId(VarKind::Symbol, i);
+ syms.push_back(id.hasValue() ? Value(id.getValue<Value>()) : Value());
+ }
AffineMap alignedMap =
alignAffineMapWithValues(map, operands, dims, syms, newSymsPtr);
@@ -1109,38 +1099,18 @@ FlatLinearValueConstraints::computeAlignedMap(AffineMap map,
bool FlatLinearValueConstraints::findVar(Value val, unsigned *pos,
unsigned offset) const {
- unsigned i = offset;
- for (const auto &mayBeVar :
- ArrayRef<std::optional<Value>>(values).drop_front(offset)) {
- if (mayBeVar && *mayBeVar == val) {
+ SmallVector<std::optional<Value>> maybeValues = getMaybeValues();
+ for (unsigned i = offset, e = maybeValues.size(); i < e; ++i)
+ if (maybeValues[i] && maybeValues[i].value() == val) {
*pos = i;
return true;
}
- i++;
- }
return false;
}
bool FlatLinearValueConstraints::containsVar(Value val) const {
- return llvm::any_of(values, [&](const std::optional<Value> &mayBeVar) {
- return mayBeVar && *mayBeVar == val;
- });
-}
-
-void FlatLinearValueConstraints::swapVar(unsigned posA, unsigned posB) {
- IntegerPolyhedron::swapVar(posA, posB);
-
- if (getVarKindAt(posA) == VarKind::Local &&
- getVarKindAt(posB) == VarKind::Local)
- return;
-
- // Treat value of a local variable as std::nullopt.
- if (getVarKindAt(posA) == VarKind::Local)
- values[posB] = std::nullopt;
- else if (getVarKindAt(posB) == VarKind::Local)
- values[posA] = std::nullopt;
- else
- std::swap(values[posA], values[posB]);
+ unsigned pos;
+ return findVar(val, &pos, 0);
}
void FlatLinearValueConstraints::addBound(BoundType type, Value val,
@@ -1180,31 +1150,6 @@ void FlatLinearValueConstraints::printSpace(raw_ostream &os) const {
os << "const)\n";
}
-void FlatLinearValueConstraints::clearAndCopyFrom(
- const IntegerRelation &other) {
-
- if (auto *otherValueSet =
- dyn_cast<const FlatLinearValueConstraints>(&other)) {
- *this = *otherValueSet;
- ...
[truncated]
|
@llvm/pr-subscribers-mlir-affine Author: Bharathi Ramana Joshi (iambrj) ChangesPatch is 44.47 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/77316.diff 10 Files Affected:
diff --git a/mlir/include/mlir/Analysis/FlatLinearValueConstraints.h b/mlir/include/mlir/Analysis/FlatLinearValueConstraints.h
index e4de5b0661571c..22eaba94aa950e 100644
--- a/mlir/include/mlir/Analysis/FlatLinearValueConstraints.h
+++ b/mlir/include/mlir/Analysis/FlatLinearValueConstraints.h
@@ -205,6 +205,8 @@ class FlatLinearConstraints : public presburger::IntegerPolyhedron {
/// where each non-local variable can have an SSA Value attached to it.
class FlatLinearValueConstraints : public FlatLinearConstraints {
public:
+ using Identifier = presburger::Identifier;
+
/// Constructs a constraint system reserving memory for the specified number
/// of constraints and variables. `valArgs` are the optional SSA values
/// associated with each dimension/symbol. These must either be empty or match
@@ -217,11 +219,11 @@ class FlatLinearValueConstraints : public FlatLinearConstraints {
: FlatLinearConstraints(numReservedInequalities, numReservedEqualities,
numReservedCols, numDims, numSymbols, numLocals) {
assert(valArgs.empty() || valArgs.size() == getNumDimAndSymbolVars());
- values.reserve(numReservedCols);
- if (valArgs.empty())
- values.resize(getNumDimAndSymbolVars(), std::nullopt);
- else
- values.append(valArgs.begin(), valArgs.end());
+ // Store Values in space's identifiers.
+ space.resetIds();
+ for (unsigned i = 0, e = valArgs.size(); i < e; ++i)
+ if (valArgs[i])
+ setValue(i, *valArgs[i]);
}
/// Constructs a constraint system reserving memory for the specified number
@@ -236,11 +238,11 @@ class FlatLinearValueConstraints : public FlatLinearConstraints {
: FlatLinearConstraints(numReservedInequalities, numReservedEqualities,
numReservedCols, numDims, numSymbols, numLocals) {
assert(valArgs.empty() || valArgs.size() == getNumDimAndSymbolVars());
- values.reserve(numReservedCols);
- if (valArgs.empty())
- values.resize(getNumDimAndSymbolVars(), std::nullopt);
- else
- values.append(valArgs.begin(), valArgs.end());
+ // Store Values in space's identifiers.
+ space.resetIds();
+ for (unsigned i = 0, e = valArgs.size(); i < e; ++i)
+ if (valArgs[i])
+ setValue(i, valArgs[i]);
}
/// Constructs a constraint system with the specified number of dimensions
@@ -272,11 +274,15 @@ class FlatLinearValueConstraints : public FlatLinearConstraints {
FlatLinearValueConstraints(const IntegerPolyhedron &fac,
ArrayRef<std::optional<Value>> valArgs = {})
: FlatLinearConstraints(fac) {
- assert(valArgs.empty() || valArgs.size() == getNumDimAndSymbolVars());
+ // Do not reset values assigned by FlatLinearConstraints' constructor.
if (valArgs.empty())
- values.resize(getNumDimAndSymbolVars(), std::nullopt);
- else
- values.append(valArgs.begin(), valArgs.end());
+ return;
+ assert(valArgs.size() == getNumDimAndSymbolVars());
+ // Store Values in space's identifiers.
+ space.resetIds();
+ for (unsigned i = 0, e = valArgs.size(); i < e; ++i)
+ if (valArgs[i])
+ setValue(i, *valArgs[i]);
}
/// Creates an affine constraint system from an IntegerSet.
@@ -290,9 +296,6 @@ class FlatLinearValueConstraints : public FlatLinearConstraints {
cst->getKind() <= Kind::FlatAffineRelation;
}
- /// Replaces the contents of this FlatLinearValueConstraints with `other`.
- void clearAndCopyFrom(const IntegerRelation &other) override;
-
/// Adds a constant bound for the variable associated with the given Value.
void addBound(presburger::BoundType type, Value val, int64_t value);
using FlatLinearConstraints::addBound;
@@ -302,7 +305,9 @@ class FlatLinearValueConstraints : public FlatLinearConstraints {
inline Value getValue(unsigned pos) const {
assert(pos < getNumDimAndSymbolVars() && "Invalid position");
assert(hasValue(pos) && "variable's Value not set");
- return *values[pos];
+ VarKind kind = getVarKindAt(pos);
+ unsigned relativePos = pos - getVarKindOffset(kind);
+ return space.getId(kind, relativePos).getValue<Value>();
}
/// Returns the Values associated with variables in range [start, end).
@@ -313,27 +318,47 @@ class FlatLinearValueConstraints : public FlatLinearConstraints {
assert(start <= end && "invalid start position");
values->clear();
values->reserve(end - start);
- for (unsigned i = start; i < end; i++)
+ for (unsigned i = start; i < end; ++i)
values->push_back(getValue(i));
}
- inline ArrayRef<std::optional<Value>> getMaybeValues() const {
- return {values.data(), values.size()};
+ inline SmallVector<std::optional<Value>> getMaybeValues() const {
+ SmallVector<std::optional<Value>> maybeValues;
+ maybeValues.reserve(getNumDimAndSymbolVars());
+ for (unsigned i = 0, e = getNumDimAndSymbolVars(); i < e; ++i)
+ if (hasValue(i))
+ maybeValues.push_back(getValue(i));
+ else
+ maybeValues.push_back(std::nullopt);
+ return maybeValues;
}
- inline ArrayRef<std::optional<Value>>
+ inline SmallVector<std::optional<Value>>
getMaybeValues(presburger::VarKind kind) const {
assert(kind != VarKind::Local &&
"Local variables do not have any value attached to them.");
- return {values.data() + getVarKindOffset(kind), getNumVarKind(kind)};
+ SmallVector<std::optional<Value>> maybeValues;
+ maybeValues.reserve(getNumVarKind(kind));
+ for (unsigned i = 0, e = getNumVarKind(kind); i < e; ++i) {
+ const Identifier id = space.getId(kind, i);
+ if (id.hasValue())
+ maybeValues.push_back(id.getValue<Value>());
+ else
+ maybeValues.push_back(std::nullopt);
+ }
+ return maybeValues;
}
/// Returns true if the pos^th variable has an associated Value.
inline bool hasValue(unsigned pos) const {
assert(pos < getNumDimAndSymbolVars() && "Invalid position");
- return values[pos].has_value();
+ VarKind kind = getVarKindAt(pos);
+ unsigned relativePos = pos - getVarKindOffset(kind);
+ return space.getId(kind, relativePos).hasValue();
}
+ void resetValues() { space.resetIds(); }
+
unsigned appendDimVar(ValueRange vals);
using FlatLinearConstraints::appendDimVar;
@@ -360,7 +385,9 @@ class FlatLinearValueConstraints : public FlatLinearConstraints {
/// Sets the Value associated with the pos^th variable.
inline void setValue(unsigned pos, Value val) {
assert(pos < getNumDimAndSymbolVars() && "invalid var position");
- values[pos] = val;
+ VarKind kind = getVarKindAt(pos);
+ unsigned relativePos = pos - getVarKindOffset(kind);
+ space.getId(kind, relativePos) = presburger::Identifier(val);
}
/// Sets the Values associated with the variables in the range [start, end).
@@ -387,9 +414,6 @@ class FlatLinearValueConstraints : public FlatLinearConstraints {
void projectOut(Value val);
using IntegerPolyhedron::projectOut;
- /// Swap the posA^th variable with the posB^th variable.
- void swapVar(unsigned posA, unsigned posB) override;
-
/// Prints the number of constraints, dimensions, symbols and locals in the
/// FlatAffineValueConstraints. Also, prints for each variable whether there
/// is an SSA Value attached to it.
@@ -444,28 +468,6 @@ class FlatLinearValueConstraints : public FlatLinearConstraints {
/// output = {0 <= d0 <= 6, 1 <= d1 <= 15}
LogicalResult unionBoundingBox(const FlatLinearValueConstraints &other);
using IntegerPolyhedron::unionBoundingBox;
-
-protected:
- /// Eliminates the variable at the specified position using Fourier-Motzkin
- /// variable elimination, but uses Gaussian elimination if there is an
- /// equality involving that variable. 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;
-
- /// Returns false if the fields corresponding to various variable 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;
-
- /// Values corresponding to the (column) non-local variables of this
- /// constraint system appearing in the order the variables correspond to
- /// columns. Variables that aren't associated with any Value are set to
- /// std::nullopt.
- SmallVector<std::optional<Value>, 8> values;
};
/// Flattens 'expr' into 'flattenedExpr', which contains the coefficients of the
diff --git a/mlir/include/mlir/Analysis/Presburger/IntegerRelation.h b/mlir/include/mlir/Analysis/Presburger/IntegerRelation.h
index c476a022a48272..a63703e8ef38f0 100644
--- a/mlir/include/mlir/Analysis/Presburger/IntegerRelation.h
+++ b/mlir/include/mlir/Analysis/Presburger/IntegerRelation.h
@@ -674,6 +674,11 @@ class IntegerRelation {
/// this for uniformity with `applyDomain`.
void applyRange(const IntegerRelation &rel);
+ /// Given a relation `other: (A -> B)`, this operation merges the symbol and
+ /// local variables and then takes the composition of `other` on `this: (B ->
+ /// C)`. The resulting relation represents tuples of the form: `A -> C`.
+ void mergeAndCompose(const IntegerRelation &other);
+
/// Compute an equivalent representation of the same set, such that all local
/// vars in all disjuncts have division representations. This representation
/// may involve local vars that correspond to divisions, and may also be a
diff --git a/mlir/include/mlir/Analysis/Presburger/PresburgerSpace.h b/mlir/include/mlir/Analysis/Presburger/PresburgerSpace.h
index 91ed349f461c69..a2442ede7a2d7a 100644
--- a/mlir/include/mlir/Analysis/Presburger/PresburgerSpace.h
+++ b/mlir/include/mlir/Analysis/Presburger/PresburgerSpace.h
@@ -265,6 +265,8 @@ class PresburgerSpace {
return {identifiers.data() + getVarKindOffset(kind), getNumVarKind(kind)};
}
+ ArrayRef<Identifier> getIds() const { return identifiers; }
+
/// Returns if identifiers are being used.
bool isUsingIds() const { return usingIds; }
diff --git a/mlir/include/mlir/Dialect/Affine/Analysis/AffineAnalysis.h b/mlir/include/mlir/Dialect/Affine/Analysis/AffineAnalysis.h
index a27583877b603c..4134aef8174bc1 100644
--- a/mlir/include/mlir/Dialect/Affine/Analysis/AffineAnalysis.h
+++ b/mlir/include/mlir/Dialect/Affine/Analysis/AffineAnalysis.h
@@ -15,6 +15,7 @@
#ifndef MLIR_DIALECT_AFFINE_ANALYSIS_AFFINEANALYSIS_H
#define MLIR_DIALECT_AFFINE_ANALYSIS_AFFINEANALYSIS_H
+#include "mlir/Analysis/Presburger/IntegerRelation.h"
#include "mlir/Dialect/Arith/IR/Arith.h"
#include "mlir/IR/Value.h"
#include "llvm/ADT/SmallVector.h"
@@ -115,7 +116,7 @@ struct MemRefAccess {
///
/// Returns failure for yet unimplemented/unsupported cases (see docs of
/// mlir::getIndexSet and mlir::getRelationFromMap for these cases).
- LogicalResult getAccessRelation(FlatAffineRelation &accessRel) const;
+ LogicalResult getAccessRelation(presburger::IntegerRelation &accessRel) const;
/// Populates 'accessMap' with composition of AffineApplyOps reachable from
/// 'indices'.
diff --git a/mlir/include/mlir/Dialect/Affine/Analysis/AffineStructures.h b/mlir/include/mlir/Dialect/Affine/Analysis/AffineStructures.h
index 7c500f13895af1..c932792fbed756 100644
--- a/mlir/include/mlir/Dialect/Affine/Analysis/AffineStructures.h
+++ b/mlir/include/mlir/Dialect/Affine/Analysis/AffineStructures.h
@@ -251,9 +251,10 @@ class FlatAffineRelation : public FlatAffineValueConstraints {
/// For AffineValueMap, the domain and symbols have Value set corresponding to
/// the Value in `map`. Returns failure if the AffineMap could not be flattened
/// (i.e., semi-affine is not yet handled).
-LogicalResult getRelationFromMap(AffineMap &map, FlatAffineRelation &rel);
+LogicalResult getRelationFromMap(AffineMap &map,
+ presburger::IntegerRelation &rel);
LogicalResult getRelationFromMap(const AffineValueMap &map,
- FlatAffineRelation &rel);
+ presburger::IntegerRelation &rel);
} // namespace affine
} // namespace mlir
diff --git a/mlir/lib/Analysis/FlatLinearValueConstraints.cpp b/mlir/lib/Analysis/FlatLinearValueConstraints.cpp
index 69846a356e0cc4..8a09c741979ffb 100644
--- a/mlir/lib/Analysis/FlatLinearValueConstraints.cpp
+++ b/mlir/lib/Analysis/FlatLinearValueConstraints.cpp
@@ -9,6 +9,7 @@
#include "mlir/Analysis//FlatLinearValueConstraints.h"
#include "mlir/Analysis/Presburger/LinearTransform.h"
+#include "mlir/Analysis/Presburger/PresburgerSpace.h"
#include "mlir/Analysis/Presburger/Simplex.h"
#include "mlir/Analysis/Presburger/Utils.h"
#include "mlir/IR/AffineExprVisitor.h"
@@ -817,13 +818,13 @@ FlatLinearValueConstraints::FlatLinearValueConstraints(IntegerSet set,
set.getNumDims() + set.getNumSymbols() + 1,
set.getNumDims(), set.getNumSymbols(),
/*numLocals=*/0) {
- // Populate values.
- if (operands.empty()) {
- values.resize(getNumDimAndSymbolVars(), std::nullopt);
- } else {
- assert(set.getNumInputs() == operands.size() && "operand count mismatch");
- values.assign(operands.begin(), operands.end());
- }
+ assert(operands.empty() ||
+ set.getNumInputs() == operands.size() && "operand count mismatch");
+ // Use values in space for FlatLinearValueConstraints.
+ space.resetIds();
+ // Set the values for the non-local variables.
+ for (unsigned i = 0, e = operands.size(); i < e; ++i)
+ setValue(i, operands[i]);
// Flatten expressions and add them to the constraint system.
std::vector<SmallVector<int64_t, 8>> flatExprs;
@@ -873,11 +874,6 @@ unsigned FlatLinearValueConstraints::insertVar(VarKind kind, unsigned pos,
unsigned num) {
unsigned absolutePos = IntegerPolyhedron::insertVar(kind, pos, num);
- if (kind != VarKind::Local) {
- values.insert(values.begin() + absolutePos, num, std::nullopt);
- assert(values.size() == getNumDimAndSymbolVars());
- }
-
return absolutePos;
}
@@ -890,11 +886,10 @@ unsigned FlatLinearValueConstraints::insertVar(VarKind kind, unsigned pos,
unsigned absolutePos = IntegerPolyhedron::insertVar(kind, pos, num);
// If a Value is provided, insert it; otherwise use std::nullopt.
- for (unsigned i = 0; i < num; ++i)
- values.insert(values.begin() + absolutePos + i,
- vals[i] ? std::optional<Value>(vals[i]) : std::nullopt);
+ for (unsigned i = 0, e = vals.size(); i < e; ++i)
+ if (vals[i])
+ setValue(absolutePos + i, vals[i]);
- assert(values.size() == getNumDimAndSymbolVars());
return absolutePos;
}
@@ -902,10 +897,14 @@ unsigned FlatLinearValueConstraints::insertVar(VarKind kind, unsigned pos,
/// associated with the same set of variables, appearing in the same order.
static bool areVarsAligned(const FlatLinearValueConstraints &a,
const FlatLinearValueConstraints &b) {
- return a.getNumDimVars() == b.getNumDimVars() &&
- a.getNumSymbolVars() == b.getNumSymbolVars() &&
- a.getNumVars() == b.getNumVars() &&
- a.getMaybeValues().equals(b.getMaybeValues());
+ if (a.getNumDomainVars() != b.getNumDomainVars() ||
+ a.getNumRangeVars() != b.getNumRangeVars() ||
+ a.getNumSymbolVars() != b.getNumSymbolVars())
+ return false;
+ SmallVector<std::optional<Value>> aMaybeValues = a.getMaybeValues(),
+ bMaybeValues = b.getMaybeValues();
+ return std::equal(aMaybeValues.begin(), aMaybeValues.end(),
+ bMaybeValues.begin(), bMaybeValues.end());
}
/// Calls areVarsAligned to check if two constraint systems have the same set
@@ -928,12 +927,14 @@ static bool LLVM_ATTRIBUTE_UNUSED areVarsUnique(
return true;
SmallPtrSet<Value, 8> uniqueVars;
- ArrayRef<std::optional<Value>> maybeValues =
- cst.getMaybeValues().slice(start, end - start);
- for (std::optional<Value> val : maybeValues) {
+ SmallVector<std::optional<Value>, 8> maybeValuesAll = cst.getMaybeValues();
+ ArrayRef<std::optional<Value>> maybeValues = {maybeValuesAll.data() + start,
+ maybeValuesAll.data() + end};
+
+ for (std::optional<Value> val : maybeValues)
if (val && !uniqueVars.insert(*val).second)
return false;
- }
+
return true;
}
@@ -1058,20 +1059,9 @@ void FlatLinearValueConstraints::mergeSymbolVars(
"expected same number of symbols");
}
-bool FlatLinearValueConstraints::hasConsistentState() const {
- return IntegerPolyhedron::hasConsistentState() &&
- values.size() == getNumDimAndSymbolVars();
-}
-
void FlatLinearValueConstraints::removeVarRange(VarKind kind, unsigned varStart,
unsigned varLimit) {
IntegerPolyhedron::removeVarRange(kind, varStart, varLimit);
- unsigned offset = getVarKindOffset(kind);
-
- if (kind != VarKind::Local) {
- values.erase(values.begin() + varStart + offset,
- values.begin() + varLimit + offset);
- }
}
AffineMap
@@ -1089,14 +1079,14 @@ FlatLinearValueConstraints::computeAlignedMap(AffineMap map,
dims.reserve(getNumDimVars());
syms.reserve(getNumSymbolVars());
- for (unsigned i = getVarKindOffset(VarKind::SetDim),
- e = getVarKindEnd(VarKind::SetDim);
- i < e; ++i)
- dims.push_back(values[i] ? *values[i] : Value());
- for (unsigned i = getVarKindOffset(VarKind::Symbol),
- e = getVarKindEnd(VarKind::Symbol);
- i < e; ++i)
- syms.push_back(values[i] ? *values[i] : Value());
+ for (unsigned i = 0, e = getNumVarKind(VarKind::SetDim); i < e; ++i) {
+ Identifier id = space.getId(VarKind::SetDim, i);
+ dims.push_back(id.hasValue() ? Value(id.getValue<Value>()) : Value());
+ }
+ for (unsigned i = 0, e = getNumVarKind(VarKind::Symbol); i < e; ++i) {
+ Identifier id = space.getId(VarKind::Symbol, i);
+ syms.push_back(id.hasValue() ? Value(id.getValue<Value>()) : Value());
+ }
AffineMap alignedMap =
alignAffineMapWithValues(map, operands, dims, syms, newSymsPtr);
@@ -1109,38 +1099,18 @@ FlatLinearValueConstraints::computeAlignedMap(AffineMap map,
bool FlatLinearValueConstraints::findVar(Value val, unsigned *pos,
unsigned offset) const {
- unsigned i = offset;
- for (const auto &mayBeVar :
- ArrayRef<std::optional<Value>>(values).drop_front(offset)) {
- if (mayBeVar && *mayBeVar == val) {
+ SmallVector<std::optional<Value>> maybeValues = getMaybeValues();
+ for (unsigned i = offset, e = maybeValues.size(); i < e; ++i)
+ if (maybeValues[i] && maybeValues[i].value() == val) {
*pos = i;
return true;
}
- i++;
- }
return false;
}
bool FlatLinearValueConstraints::containsVar(Value val) const {
- return llvm::any_of(values, [&](const std::optional<Value> &mayBeVar) {
- return mayBeVar && *mayBeVar == val;
- });
-}
-
-void FlatLinearValueConstraints::swapVar(unsigned posA, unsigned posB) {
- IntegerPolyhedron::swapVar(posA, posB);
-
- if (getVarKindAt(posA) == VarKind::Local &&
- getVarKindAt(posB) == VarKind::Local)
- return;
-
- // Treat value of a local variable as std::nullopt.
- if (getVarKindAt(posA) == VarKind::Local)
- values[posB] = std::nullopt;
- else if (getVarKindAt(posB) == VarKind::Local)
- values[posA] = std::nullopt;
- else
- std::swap(values[posA], values[posB]);
+ unsigned pos;
+ return findVar(val, &pos, 0);
}
void FlatLinearValueConstraints::addBound(BoundType type, Value val,
@@ -1180,31 +1150,6 @@ void FlatLinearValueConstraints::printSpace(raw_ostream &os) const {
os << "const)\n";
}
-void FlatLinearValueConstraints::clearAndCopyFrom(
- const IntegerRelation &other) {
-
- if (auto *otherValueSet =
- dyn_cast<const FlatLinearValueConstraints>(&other)) {
- *this = *otherValueSet;
- ...
[truncated]
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add a description of the patch. My only major comment is that we should hide resetIds and instead PresburgerSpace should automatically enable ids if someone is trying to use them.
a8aad6f
to
1bd0c43
Compare
1bd0c43
to
5b78210
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM with some minor comments. This would be great to land! 🥳
5b78210
to
4b8f4a6
Compare
Changes: 1. Refactors the interface to `PresburgerSpace::identifiers` to `setId` and a const `getId`, instead of previous `getId` which returned a mutable reference. `resetIds` does not need to be called to use identifiers, `setId` calls `resetIds` if identifiers are not enabled. 2. Deprecates `FlatAffineRelation` by refactoring all usages of `FlatAffineRelation` to `IntegerRelation`. To achieve this, `FlatAffineRelation::compose` is refactored into `IntegerRelation::mergeAndCompose`. 3. Deletes unneeded overrides of virtual functions `hasConsistentState`, `clearAndCopyFrom` and `fourierMotzkinEliminate` from `FlatLinearValueConstraints` as these were only used through `FlatAffineRelation` and we now use `IntegerRelation`'s member functions instead. 4. Fixes an existing bug in FlatLinearValueConstraints' constructor which caused identifiers set by superclass FlatLinearConstraints' constructor to be erased.
4b8f4a6
to
7ab9393
Compare
The pull request includes the following changes.
PresburgerSpace::identifiers
tosetId
and aconst
getId
, instead of previousgetId
which returned a mutable reference.resetIds
does not need to be called to use identifiers,setId
callsresetIds
if identifiers are not enabled.FlatAffineRelation
by refactoring all usages ofFlatAffineRelation
toIntegerRelation
. To achieve this,FlatAffineRelation::compose
is refactored intoIntegerRelation::mergeAndCompose
.hasConsistentState
,clearAndCopyFrom
andfourierMotzkinEliminate
fromFlatLinearValueConstraints
as these were only used throughFlatAffineRelation
and we now useIntegerRelation
's member functionsinstead.
identifiers set by superclass FlatLinearConstraints' constructor to be erased.
IntegerRelation::convertVarKind
not preserving identifiers.