21#include "llvm/ADT/SmallVector.h"
22#include "llvm/Support/Debug.h"
23#include "llvm/Support/raw_ostream.h"
26#define DEBUG_TYPE "affine-structures"
32FailureOr<FlatAffineValueConstraints>
49 LLVM_DEBUG(llvm::dbgs()
50 <<
"only valid terminal symbols and affine IVs supported\n");
58 loop.emitWarning(
"failed to add domain info to constraint system"));
67 LLVM_DEBUG(parallel.emitWarning(
68 "failed to add domain info to constraint system"));
78 addBound(BoundType::EQ, val, constOp.value());
86 if (!
findVar(forOp.getInductionVar(), &pos)) {
87 assert(
false &&
"Value not found");
91 int64_t step = forOp.getStepAsInt();
93 if (!forOp.hasConstantLowerBound())
94 LLVM_DEBUG(forOp.emitWarning(
"domain conservatively approximated"));
102 int64_t lb = forOp.getConstantLowerBound();
104 dividend.back() -= lb;
116 if (forOp.hasConstantLowerBound()) {
117 addBound(BoundType::LB, pos, forOp.getConstantLowerBound());
120 if (failed(
addBound(BoundType::LB, pos, forOp.getLowerBoundMap(),
121 forOp.getLowerBoundOperands())))
125 if (forOp.hasConstantUpperBound()) {
126 addBound(BoundType::UB, pos, forOp.getConstantUpperBound() - 1);
130 return addBound(BoundType::UB, pos, forOp.getUpperBoundMap(),
131 forOp.getUpperBoundOperands());
135 AffineParallelOp parallelOp) {
137 for (
Value iv : parallelOp.getIVs()) {
140 assert(
false &&
"variable expected for the IV value");
144 AffineMap lowerBound = parallelOp.getLowerBoundMap(ivPos);
147 else if (failed(
addBound(BoundType::LB, pos, lowerBound,
148 parallelOp.getLowerBoundsOperands())))
151 auto upperBound = parallelOp.getUpperBoundMap(ivPos);
152 if (upperBound.isSingleConstant())
153 addBound(BoundType::UB, pos, upperBound.getSingleConstantResult() - 1);
154 else if (failed(
addBound(BoundType::UB, pos, upperBound,
155 parallelOp.getUpperBoundsOperands())))
166 assert(lbMaps.size() == ubMaps.size());
169 for (
unsigned i = 0, e = lbMaps.size(); i < e; ++i) {
172 assert(!lbMap || lbMap.
getNumInputs() == operands.size());
173 assert(!ubMap || ubMap.
getNumInputs() == operands.size());
184 !isa<AffineConstantExpr>(lbMap.
getResult(0))) {
204 if (lbMap && failed(
addBound(BoundType::LB, i, lbMap, operands)))
206 if (ubMap && failed(
addBound(BoundType::UB, i, ubMap, operands)))
220 FailureOr<FlatAffineValueConstraints> cst =
223 assert(
false &&
"semi-affine integer sets are unsupported here");
244 for (
Value operand : operands) {
263 assert(values.size() == lbMaps.size());
264 assert(lbMaps.size() == ubMaps.size());
266 for (
unsigned i = 0, e = lbMaps.size(); i < e; ++i) {
273 assert(!lbMap || lbMap.
getNumInputs() == operands.size());
274 assert(!ubMap || ubMap.
getNumInputs() == operands.size());
280 if (failed(
addBound(BoundType::EQ, pos, lbMap, operands)))
290 if (failed(
addBound(BoundType::LB, pos, lbMap, operands)))
292 if (failed(
addBound(BoundType::UB, pos, ubMap, operands)))
313 pos < cst->getNumDimAndSymbolVars()) {
328 for (
auto iv : loopIVs) {
339 assert(pos < numDims &&
"invalid position");
346 "one or more local exprs do not have an explicit representation");
354 bound.append(inequality.begin(), inequality.begin() + pos);
355 bound.append(inequality.begin() + pos + 1, inequality.end());
357 if (inequality[pos] > 0)
359 llvm::transform(bound, bound.begin(), std::negate<int64_t>());
366 localExprs, context);
373 operands.append(trailingOperands.begin(), trailingOperands.end());
394 "Domain of this and range of other do not match");
396 "Values of domain of this and range of other do not match");
432 if (relMaybeValues[i].has_value())
437 if (thisMaybeValues[rangeIdx].has_value())
438 rel.
setValue(rangeIdx, *thisMaybeValues[rangeIdx]);
454 for (
unsigned i = 0; i < oldDomain; ++i)
455 swapVar(i, oldDomain + oldRange + i);
465 "Var cannot be inserted at invalid position");
472 "Var cannot be inserted at invalid position");
490 if (varStart >= varLimit)
496 if (kind != VarKind::SetDim)
502 unsigned intersectDomainRHS = varStart;
503 unsigned intersectRangeLHS = std::min(varLimit,
getNumDimVars());
506 if (intersectDomainLHS > intersectDomainRHS)
508 if (intersectRangeLHS > intersectRangeRHS)
515 std::vector<SmallVector<int64_t, 8>> flatExprs;
521 const unsigned oldCols = localVarCst.
getNumCols();
523 const unsigned numDomainVars = map.
getNumDims();
539 for (
unsigned j = 0, f = oldDimNum;
j < f; ++
j)
540 eq[
j] = flatExprs[i][
j];
541 for (
unsigned j = oldDimNum, f = oldCols;
j < f; ++
j)
542 eq[
j + numRangeVars] = flatExprs[i][
j];
544 eq[numDomainVars + i] = -1;
560 for (
unsigned i = 0, e = affineMap.
getNumDims(); i < e; ++i)
static void turnSymbolIntoDim(FlatAffineValueConstraints *cst, Value value)
A dimensional identifier appearing in an affine expression.
Base type for affine expression.
A multi-dimensional affine map Affine map's are immutable like Type's, and they are uniqued.
int64_t getSingleConstantResult() const
Returns the constant result of this map.
static AffineMap get(MLIRContext *context)
Returns a zero result affine map with no dimensions or symbols: () -> ().
bool isSingleConstant() const
Returns true if this affine map is a single result constant function.
unsigned getNumDims() const
unsigned getNumResults() const
unsigned getNumInputs() const
AffineExpr getResult(unsigned idx) const
LogicalResult composeMatchingMap(AffineMap other)
Composes an affine map whose dimensions and symbols match one to one with the dimensions and symbols ...
presburger::VarKind VarKind
LogicalResult computeLocalVars(SmallVectorImpl< AffineExpr > &memo, MLIRContext *context) const
Compute an explicit representation for local vars.
unsigned insertDimVar(unsigned pos, ValueRange vals)
void mergeAndAlignVarsWithOther(unsigned offset, FlatLinearValueConstraints *other)
Merge and align the variables of this and other starting at offset, so that both constraint systems g...
bool hasValue(unsigned pos) const
Returns true if the pos^th variable has an associated Value.
Value getValue(unsigned pos) const
Returns the Value associated with the pos^th variable.
void mergeSymbolVars(FlatLinearValueConstraints &other)
Merge and align symbols of this and other such that both get union of of symbols that are unique.
bool containsVar(Value val) const
Returns true if a variable with the specified Value exists, false otherwise.
void removeVarRange(presburger::VarKind kind, unsigned varStart, unsigned varLimit) override
Removes variables in the column range [varStart, varLimit), and copies any remaining valid data into ...
unsigned appendDimVar(ValueRange vals)
bool findVar(Value val, unsigned *pos, unsigned offset=0) const
Looks up the position of the variable with the specified Value starting with variables at offset offs...
AffineMap computeAlignedMap(AffineMap map, ValueRange operands) const
Align map with this constraint system based on operands.
void getValues(unsigned start, unsigned end, SmallVectorImpl< Value > *values) const
Returns the Values associated with variables in range [start, end).
void setValue(unsigned pos, Value val)
Sets the Value associated with the pos^th variable.
SmallVector< std::optional< Value > > getMaybeValues() const
unsigned appendSymbolVar(ValueRange vals)
An integer set representing a conjunction of one or more affine equalities and inequalities.
MLIRContext is the top-level object for a collection of MLIR operations.
This class provides an abstraction over the different types of ranges over Values.
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Operation * getDefiningOp() const
If this value is the result of an operation, return the operation that defines it.
An AffineValueMap is an affine map plus its ML value operands and results for analysis purposes.
Value getOperand(unsigned i) const
ArrayRef< Value > getOperands() const
AffineMap getAffineMap() const
void reset(AffineMap map, ValueRange operands, ValueRange results={})
FlatAffineRelation(unsigned numReservedInequalities, unsigned numReservedEqualities, unsigned numReservedCols, unsigned numDomainDims, unsigned numRangeDims, unsigned numSymbols, unsigned numLocals, ArrayRef< std::optional< Value > > valArgs={})
void appendDomainVar(unsigned num=1)
Append num variables of the specified kind after the last variable of that kind.
void compose(const FlatAffineRelation &other)
Given affine relation other: (domainOther -> rangeOther), this operation takes the composition of oth...
unsigned getNumDomainDims() const
Returns the number of variables corresponding to domain/range of relation.
void inverse()
Swap domain and range of the relation.
FlatAffineValueConstraints getDomainSet() const
Returns a set corresponding to the domain/range of the affine relation.
void removeVarRange(VarKind kind, unsigned varStart, unsigned varLimit) override
Removes variables in the column range [varStart, varLimit), and copies any remaining valid data into ...
void appendRangeVar(unsigned num=1)
unsigned getNumRangeDims() const
FlatAffineValueConstraints getRangeSet() const
void insertRangeVar(unsigned pos, unsigned num=1)
void insertDomainVar(unsigned pos, unsigned num=1)
Insert num variables of the specified kind after the pos variable of that kind.
FlatAffineValueConstraints is an extension of FlatLinearValueConstraints with helper functions for Af...
LogicalResult addBound(presburger::BoundType type, unsigned pos, AffineMap boundMap, ValueRange operands)
Adds a bound for the variable at the specified position with constraints being drawn from the specifi...
void addAffineIfOpDomain(AffineIfOp ifOp)
Adds constraints imposed by the affine.if operation.
void convertLoopIVSymbolsToDims()
Changes all symbol variables which are loop IVs to dim variables.
LogicalResult addDomainFromSliceMaps(ArrayRef< AffineMap > lbMaps, ArrayRef< AffineMap > ubMaps, ArrayRef< Value > operands)
Adds constraints (lower and upper bounds) for each loop in the loop nest described by the bound maps ...
LogicalResult addAffineParallelOpDomain(AffineParallelOp parallelOp)
Add constraints (lower and upper bounds) for the specified 'affine.parallel' operation's Value using ...
LogicalResult addAffineForOpDomain(AffineForOp forOp)
Adds constraints (lower and upper bounds) for the specified 'affine.for' operation's Value using IR i...
static FailureOr< FlatAffineValueConstraints > create(IntegerSet set, ValueRange operands={})
Creates an affine constraint system from an IntegerSet.
void getIneqAsAffineValueMap(unsigned pos, unsigned ineqPos, AffineValueMap &vmap, MLIRContext *context) const
Returns the bound for the variable at pos from the inequality at ineqPos as a 1-d affine value map (a...
LogicalResult addSliceBounds(ArrayRef< Value > values, ArrayRef< AffineMap > lbMaps, ArrayRef< AffineMap > ubMaps, ArrayRef< Value > operands)
Adds slice lower bounds represented by lower bounds in lbMaps and upper bounds in ubMaps to each vari...
LogicalResult composeMap(const AffineValueMap *vMap)
Composes the affine value map with this FlatAffineValueConstrains, adding the results of the map as d...
LogicalResult addInductionVarOrTerminalSymbol(Value val)
Add the specified values as a dim or symbol var depending on its nature, if it already doesn't exist ...
An Identifier stores a pointer to an object, such as a Value or an Operation.
An IntegerRelation represents the set of points from a PresburgerSpace that satisfy a list of affine ...
void setId(VarKind kind, unsigned i, Identifier id)
Set the identifier for the ith variable of the specified kind of the IntegerRelation's PresburgerSpac...
virtual void swapVar(unsigned posA, unsigned posB)
Swap the posA^th variable with the posB^th variable.
unsigned getNumSymbolVars() const
SmallVector< int64_t, 8 > getInequality64(unsigned idx) const
unsigned getNumVarKind(VarKind kind) const
Get the number of vars of the specified kind.
void convertToLocal(VarKind kind, unsigned varStart, unsigned varLimit)
const PresburgerSpace & getSpace() const
Returns a reference to the underlying space.
unsigned getNumVars() const
void append(const IntegerRelation &other)
Appends constraints from other into this.
unsigned addLocalFloorDiv(ArrayRef< DynamicAPInt > dividend, const DynamicAPInt &divisor)
Adds a new local variable as the floordiv of an affine function of other variables,...
void addEquality(ArrayRef< DynamicAPInt > eq)
Adds an equality from the coefficients specified in eq.
void setDimSymbolSeparation(unsigned newSymbolCount)
Changes the partition between dimensions and symbols.
unsigned getNumLocalVars() const
unsigned getNumDimAndSymbolVars() const
unsigned getNumCols() const
Returns the number of columns in the constraint system.
void removeRedundantLocalVars()
Removes local variables using equalities.
unsigned mergeLocalVars(IntegerRelation &other)
Adds additional local vars to the sets such that they both have the union of the local vars in each s...
unsigned getNumInequalities() const
unsigned getNumDimVars() const
PresburgerSpace getRangeSpace() const
bool isAffineInductionVar(Value val)
Returns true if the provided value is the induction variable of an AffineForOp or AffineParallelOp.
AffineForOp getForInductionVarOwner(Value val)
Returns the loop parent of an induction variable.
void canonicalizeMapAndOperands(AffineMap *map, SmallVectorImpl< Value > *operands)
Modifies both map and operands in-place so as to:
void fullyComposeAffineMapAndOperands(AffineMap *map, SmallVectorImpl< Value > *operands, bool composeAffineMin=false)
Given an affine map map and its input operands, this method composes into map, maps of AffineApplyOps...
void canonicalizeSetAndOperands(IntegerSet *set, SmallVectorImpl< Value > *operands)
Canonicalizes an integer set the same way canonicalizeMapAndOperands does for affine maps.
LogicalResult getRelationFromMap(AffineMap &map, presburger::IntegerRelation &rel)
Builds a relation from the given AffineMap/AffineValueMap map, containing all pairs of the form opera...
bool isValidSymbol(Value value)
Returns true if the given value can be used as a symbol in the region of the closest surrounding op t...
AffineParallelOp getAffineParallelInductionVarOwner(Value val)
Returns true if the provided value is among the induction variables of an AffineParallelOp.
BoundType
The type of bound: equal, lower bound or upper bound.
Include the generated interface declarations.
AffineMap simplifyAffineMap(AffineMap map)
Simplifies an affine map by simplifying its underlying AffineExpr results.
std::optional< int64_t > getConstantIntValue(OpFoldResult ofr)
If ofr is a constant integer or an IntegerAttr, return the integer.
AffineExpr getAffineExprFromFlatForm(ArrayRef< int64_t > flatExprs, unsigned numDims, unsigned numSymbols, ArrayRef< AffineExpr > localExprs, MLIRContext *context)
Constructs an affine expression from a flat ArrayRef.
LogicalResult getFlattenedAffineExprs(AffineMap map, std::vector< SmallVector< int64_t, 8 > > *flattenedExprs, FlatLinearConstraints *cst=nullptr, bool addConservativeSemiAffineBounds=false)
Flattens the result expressions of the map to their corresponding flattened forms and set in 'flatten...
Eliminates variable at the specified position using Fourier-Motzkin variable elimination.