15#include "llvm/ADT/STLExtras.h"
16#include "llvm/ADT/SmallBitVector.h"
17#include "llvm/ADT/SmallVector.h"
18#include "llvm/Support/MathExtras.h"
25using llvm::divideCeilSigned;
26using llvm::divideFloorSigned;
35class AffineExprConstantFolder {
37 AffineExprConstantFolder(
unsigned numDims, ArrayRef<Attribute> operandConsts)
38 : numDims(numDims), operandConsts(operandConsts) {}
42 IntegerAttr constantFold(AffineExpr expr) {
43 if (
auto result = constantFoldImpl(expr))
48 bool hasPoison()
const {
return hasPoison_; }
51 std::optional<int64_t> constantFoldImpl(AffineExpr expr) {
53 case AffineExprKind::Add:
54 return constantFoldBinExpr(
55 expr, [](int64_t
lhs, int64_t
rhs) {
return lhs +
rhs; });
56 case AffineExprKind::Mul:
57 return constantFoldBinExpr(
58 expr, [](int64_t
lhs, int64_t
rhs) {
return lhs *
rhs; });
59 case AffineExprKind::Mod:
60 return constantFoldBinExpr(
61 expr, [
this](int64_t
lhs, int64_t
rhs) -> std::optional<int64_t> {
68 case AffineExprKind::FloorDiv:
69 return constantFoldBinExpr(
70 expr, [
this](int64_t
lhs, int64_t
rhs) -> std::optional<int64_t> {
75 return divideFloorSigned(
lhs,
rhs);
77 case AffineExprKind::CeilDiv:
78 return constantFoldBinExpr(
79 expr, [
this](int64_t
lhs, int64_t
rhs) -> std::optional<int64_t> {
84 return divideCeilSigned(
lhs,
rhs);
86 case AffineExprKind::Constant:
87 return cast<AffineConstantExpr>(expr).getValue();
88 case AffineExprKind::DimId:
89 if (
auto attr = llvm::dyn_cast_or_null<IntegerAttr>(
90 operandConsts[cast<AffineDimExpr>(expr).getPosition()]))
93 case AffineExprKind::SymbolId:
94 if (
auto attr = llvm::dyn_cast_or_null<IntegerAttr>(
95 operandConsts[numDims +
96 cast<AffineSymbolExpr>(expr).getPosition()]))
100 llvm_unreachable(
"Unknown AffineExpr");
104 std::optional<int64_t> constantFoldBinExpr(
106 llvm::function_ref<std::optional<int64_t>(int64_t, int64_t)> op) {
107 auto binOpExpr = cast<AffineBinaryOpExpr>(expr);
108 if (
auto lhs = constantFoldImpl(binOpExpr.getLHS()))
109 if (
auto rhs = constantFoldImpl(binOpExpr.getRHS()))
117 ArrayRef<Attribute> operandConsts;
118 bool hasPoison_{
false};
133 assert(dims >= results &&
"Dimension mismatch");
144 llvm::SmallBitVector dropDimResults(numDims);
145 for (
auto [idx, resultExpr] : llvm::enumerate(identityMap.getResults()))
146 dropDimResults[idx] = !keepDimFilter(cast<AffineDimExpr>(resultExpr));
148 return identityMap.dropResults(dropDimResults);
159 for (
const auto &[resIdx, expr] : llvm::enumerate(
getResults())) {
160 if (
auto constExpr = dyn_cast<AffineConstantExpr>(expr)) {
161 if (constExpr.getValue() != 0)
163 broadcastedDims.push_back(resIdx);
167 return broadcastedDims;
175 broadcastedDims->clear();
179 for (
const auto &idxAndExpr : llvm::enumerate(
getResults())) {
180 unsigned resIdx = idxAndExpr.index();
182 if (
auto constExpr = dyn_cast<AffineConstantExpr>(expr)) {
184 if (constExpr.getValue() != 0)
187 broadcastedDims->push_back(resIdx);
188 }
else if (
auto dimExpr = dyn_cast<AffineDimExpr>(expr)) {
190 if (dimExpr.getPosition() != suffixStart + resIdx)
214 unsigned projectionStart =
216 permutedDims.clear();
222 unsigned leadingBroadcast =
226 for (
const auto &idxAndExpr : llvm::enumerate(
getResults())) {
227 unsigned resIdx = idxAndExpr.index();
231 if (
auto constExpr = dyn_cast<AffineConstantExpr>(expr)) {
232 if (constExpr.getValue() != 0)
234 broadcastDims.push_back(resIdx);
235 }
else if (
auto dimExpr = dyn_cast<AffineDimExpr>(expr)) {
236 if (dimExpr.getPosition() < projectionStart)
238 unsigned newPosition =
239 dimExpr.getPosition() - projectionStart + leadingBroadcast;
240 permutedDims[resIdx] = newPosition;
241 dimFound[newPosition] =
true;
250 for (
auto dim : broadcastDims) {
251 while (pos < dimFound.size() && dimFound[pos]) {
254 permutedDims[dim] = pos++;
262 assert(!permutation.empty() &&
263 "Cannot create permutation map from empty permutation vector");
264 const auto *m = llvm::max_element(permutation);
266 assert(permutationMap.isPermutation() &&
"Invalid permutation vector");
267 return permutationMap;
272 permutation, [](
int64_t i) {
return static_cast<unsigned>(i); });
282 for (
unsigned t : targets)
293template <
typename AffineExprContainer>
297 if (exprsList.empty())
299 int64_t maxDim = -1, maxSym = -1;
302 maps.reserve(exprsList.size());
303 for (
const auto &exprs : exprsList)
305 maxSym + 1, exprs, context));
312 return ::inferFromExprList(exprsList, context);
318 return ::inferFromExprList(exprsList, context);
324 uint64_t thisGcd = resultExpr.getLargestKnownDivisor();
325 gcd = std::gcd(gcd, thisGcd);
328 gcd = std::numeric_limits<uint64_t>::max();
335 dimExprs.reserve(numDims);
336 for (
unsigned i = 0; i < numDims; ++i)
338 return get(numDims, 0, dimExprs, context);
347 for (
unsigned i = 0, numDims =
getNumDims(); i < numDims; ++i) {
348 auto expr = dyn_cast<AffineDimExpr>(results[i]);
349 if (!expr || expr.getPosition() != i)
359 for (
unsigned i = 0, numSymbols =
getNumSymbols(); i < numSymbols; ++i) {
360 auto expr = dyn_cast<AffineDimExpr>(results[i]);
361 if (!expr || expr.getPosition() != i)
376 return llvm::all_of(
getResults(), llvm::IsaPred<AffineConstantExpr>);
381 return cast<AffineConstantExpr>(
getResult(0)).getValue();
385 assert(
isConstant() &&
"map must have only constant results");
388 result.emplace_back(cast<AffineConstantExpr>(expr).getValue());
393 assert(map &&
"uninitialized map storage");
397 assert(map &&
"uninitialized map storage");
398 return map->numSymbols;
402 assert(map &&
"uninitialized map storage");
403 return map->numDims + map->numSymbols;
406 assert(map &&
"uninitialized map storage");
407 return map->results();
414 return cast<AffineDimExpr>(
getResult(idx)).getPosition();
418 if (!isa<AffineDimExpr>(input))
421 for (
unsigned i = 0, numResults =
getNumResults(); i < numResults; i++) {
434 bool *hasPoison)
const {
441 if (integers.empty())
444 auto range = llvm::map_range(integers, [
this](
int64_t i) {
445 return IntegerAttr::get(IndexType::get(
getContext()), i);
447 results.append(range.begin(), range.end());
453 bool *hasPoison)
const {
457 AffineExprConstantFolder exprFolder(
getNumDims(), operandConstants);
462 auto folded = exprFolder.constantFold(expr);
463 if (exprFolder.hasPoison() && hasPoison) {
473 results->push_back(folded.getInt());
475 exprs.push_back(expr);
500 unsigned numResultDims,
501 unsigned numResultSyms)
const {
507 return get(numResultDims, numResultSyms, results,
getContext());
514 unsigned numResultDims,
515 unsigned numResultSyms)
const {
519 newResults.push_back(e.replace(expr,
replacement));
527 unsigned numResultDims,
528 unsigned numResultSyms)
const {
532 newResults.push_back(e.replace(map));
541 newResults.push_back(e.replace(map));
546 auto exprs = llvm::to_vector<4>(
getResults());
548 for (
auto pos = positions.find_last(); pos != -1;
549 pos = positions.find_prev(pos))
550 exprs.erase(exprs.begin() + pos);
555 assert(
getNumDims() == map.getNumResults() &&
"Number of results mismatch");
557 unsigned numDims = map.getNumDims();
559 unsigned numSymbols = numSymbolsThisMap + map.getNumSymbols();
561 for (
unsigned idx = 0; idx < numDims; ++idx) {
565 for (
unsigned idx = numSymbolsThisMap; idx < numSymbols; ++idx) {
566 newSymbols[idx - numSymbolsThisMap] =
570 map.replaceDimsAndSymbols(newDims, newSymbols, numDims, numSymbols);
574 exprs.push_back(expr.
compose(newMap));
575 return AffineMap::get(numDims, numSymbols, exprs, map.getContext());
589 res.push_back(cast<AffineConstantExpr>(e.replaceDims(exprs)).getValue());
596 auto constExpr = dyn_cast<AffineConstantExpr>(expr);
597 if (constExpr && constExpr.getValue() == 0)
608 auto constExpr = dyn_cast<AffineConstantExpr>(expr);
609 if (!constExpr || constExpr.getValue() != 0)
610 newExprs.push_back(expr);
630 if (
auto dim = dyn_cast<AffineDimExpr>(expr)) {
631 if (seen[dim.getPosition()])
633 seen[dim.getPosition()] =
true;
635 auto constExpr = dyn_cast<AffineConstantExpr>(expr);
636 if (!allowZeroInResults || !constExpr || constExpr.getValue() != 0)
653 exprs.reserve(resultPos.size());
654 for (
auto idx : resultPos)
690 allExprs.reserve(maps.size() * maps.front().getNumResults());
691 unsigned numDims = maps.front().getNumDims(),
692 numSymbols = maps.front().getNumSymbols();
693 for (
auto m : maps) {
694 assert(numDims == m.getNumDims() && numSymbols == m.getNumSymbols() &&
695 "expected maps with same num dims and symbols");
696 llvm::append_range(allExprs, m.getResults());
699 AffineMap::get(numDims, numSymbols, allExprs, maps.front().getContext()));
700 unsigned unifiedNumDims = unifiedMap.
getNumDims(),
704 res.reserve(maps.size());
705 for (
auto m : maps) {
707 unifiedResults.take_front(m.getNumResults()),
709 unifiedResults = unifiedResults.drop_front(m.getNumResults());
715 const llvm::SmallBitVector &unusedDims) {
729 const llvm::SmallBitVector &unusedSymbols) {
748 if (
auto attr = dyn_cast<Attribute>(operands[i])) {
749 dimReplacements.push_back(
750 b.getAffineConstantExpr(cast<IntegerAttr>(attr).getInt()));
752 dimReplacements.push_back(
b.getAffineDimExpr(numDims++));
753 remainingValues.push_back(cast<Value>(operands[i]));
758 if (
auto attr = dyn_cast<Attribute>(operands[i + map.
getNumDims()])) {
759 symReplacements.push_back(
760 b.getAffineConstantExpr(cast<IntegerAttr>(attr).getInt()));
762 symReplacements.push_back(
b.getAffineSymbolExpr(numSymbols++));
763 remainingValues.push_back(cast<Value>(operands[i + map.
getNumDims()]));
783 uniqueExprs.erase(llvm::unique(uniqueExprs), uniqueExprs.end());
791 assert(map.
getNumSymbols() == 0 &&
"expected map without symbols");
793 for (
const auto &en : llvm::enumerate(map.
getResults())) {
794 auto expr = en.value();
796 if (
auto d = dyn_cast<AffineDimExpr>(expr)) {
797 if (exprs[d.getPosition()])
804 for (
auto expr : exprs)
806 seenExprs.push_back(expr);
818 for (
unsigned i : llvm::seq(
unsigned(0), map.
getNumResults())) {
820 if (
auto constExpr = dyn_cast<AffineConstantExpr>(map.
getResult(i))) {
821 assert(constExpr.getValue() == 0 &&
822 "Unexpected constant in projected permutation");
837 unsigned numResults = 0, numDims = 0, numSymbols = 0;
839 numResults += m.getNumResults();
841 results.reserve(numResults);
842 for (
auto m : maps) {
843 for (
auto res : m.getResults())
844 results.push_back(res.shiftSymbols(m.getNumSymbols(), numSymbols));
846 numSymbols += m.getNumSymbols();
847 numDims = std::max(m.getNumDims(), numDims);
856template <
typename AffineDimOrSymExpr>
858 const llvm::SmallBitVector &toProject,
860 static_assert(llvm::is_one_of<AffineDimOrSymExpr,
AffineDimExpr,
862 "expected AffineDimExpr or AffineSymbolExpr");
864 constexpr bool isDim = std::is_same<AffineDimOrSymExpr, AffineDimExpr>::value;
867 replacements.reserve(numDimOrSym);
871 using replace_fn_ty =
877 replace_fn_ty replaceSymbols = [](
AffineExpr e,
881 replace_fn_ty replaceNewDimOrSym = (isDim) ? replaceDims : replaceSymbols;
885 for (
unsigned dimOrSym = 0; dimOrSym < numDimOrSym; ++dimOrSym) {
886 if (toProject.test(dimOrSym)) {
890 int64_t newPos = compress ? newNumDimOrSym++ : dimOrSym;
891 replacements.push_back(createNewDimOrSym(newPos, context));
896 resultExprs.push_back(replaceNewDimOrSym(e, replacements));
904 const llvm::SmallBitVector &projectedDimensions,
905 bool compressDimsFlag) {
911 const llvm::SmallBitVector &projectedSymbols,
912 bool compressSymbolsFlag) {
914 compressSymbolsFlag);
918 const llvm::SmallBitVector &projectedDimensions,
919 bool compressDimsFlag,
920 bool compressSymbolsFlag) {
921 map =
projectDims(map, projectedDimensions, compressDimsFlag);
922 if (compressSymbolsFlag)
928 unsigned numDims = maps[0].getNumDims();
929 llvm::SmallBitVector numDimsBitVector(numDims,
true);
931 for (
unsigned i = 0; i < numDims; ++i) {
932 if (m.isFunctionOfDim(i))
933 numDimsBitVector.reset(i);
936 return numDimsBitVector;
940 unsigned numSymbols = maps[0].getNumSymbols();
941 llvm::SmallBitVector numSymbolsBitVector(numSymbols,
true);
943 for (
unsigned i = 0; i < numSymbols; ++i) {
944 if (m.isFunctionOfSymbol(i))
945 numSymbolsBitVector.reset(i);
948 return numSymbolsBitVector;
953 const llvm::SmallBitVector &projectedDimensions) {
972 llvm::append_range(results, map.
getResults());
976 return results[idx].isMultipleOf(factor);
static SmallVector< AffineMap, 4 > inferFromExprList(ArrayRef< AffineExprContainer > exprsList, MLIRContext *context)
Creates an affine map each for each list of AffineExpr's in exprsList while inferring the right numbe...
static SmallVector< AffineMap > compressUnusedListImpl(ArrayRef< AffineMap > maps, llvm::function_ref< AffineMap(AffineMap)> compressionFun)
Implementation detail to compress multiple affine maps with a compressionFun that is expected to be e...
static AffineMap projectCommonImpl(AffineMap map, const llvm::SmallBitVector &toProject, bool compress)
Common implementation to project out dimensions or symbols from an affine map based on the template t...
*if copies could not be generated due to yet unimplemented cases *copyInPlacementStart and copyOutPlacementStart in copyPlacementBlock *specify the insertion points where the incoming copies and outgoing should be the output argument nBegin is set to its * replacement(set to `begin` if no invalidation happens). Since outgoing *copies could have been inserted at `end`
A dimensional identifier appearing in an affine expression.
Base type for affine expression.
AffineExpr replaceDimsAndSymbols(ArrayRef< AffineExpr > dimReplacements, ArrayRef< AffineExpr > symReplacements) const
This method substitutes any uses of dimensions and symbols (e.g.
RetT walk(FnT &&callback) const
Walk all of the AffineExpr's in this expression in postorder.
AffineExprKind getKind() const
Return the classification for this type.
AffineExpr compose(AffineMap map) const
Compose with an AffineMap.
AffineExpr replaceDims(ArrayRef< AffineExpr > dimReplacements) const
Dim-only version of replaceDimsAndSymbols.
MLIRContext * getContext() const
AffineExpr replaceSymbols(ArrayRef< AffineExpr > symReplacements) const
Symbol-only version of replaceDimsAndSymbols.
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 getMinorIdentityMap(unsigned dims, unsigned results, MLIRContext *context)
Returns an identity affine map (d0, ..., dn) -> (dp, ..., dn) on the most minor dimensions.
AffineMap dropResults(ArrayRef< int64_t > positions) const
AffineMap getSliceMap(unsigned start, unsigned length) const
Returns the map consisting of length expressions starting from start.
AffineMap getMajorSubMap(unsigned numResults) const
Returns the map consisting of the most major numResults results.
MLIRContext * getContext() const
bool isMinorIdentity() const
Returns true if this affine map is a minor identity, i.e.
unsigned getDimPosition(unsigned idx) const
Extracts the position of the dimensional expression at the given result, when the caller knows it is ...
bool isConstant() const
Returns true if this affine map has only constant results.
static AffineMap getMultiDimIdentityMap(unsigned numDims, MLIRContext *context)
Returns an AffineMap with 'numDims' identity result dim exprs.
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.
bool isProjectedPermutation(bool allowZeroInResults=false) const
Returns true if the AffineMap represents a subset (i.e.
AffineMap getMinorSubMap(unsigned numResults) const
Returns the map consisting of the most minor numResults results.
uint64_t getLargestKnownDivisorOfMapExprs()
Get the largest known divisor of all map expressions.
constexpr AffineMap()=default
bool isEmpty() const
Returns true if this affine map is an empty map, i.e., () -> ().
std::optional< unsigned > getResultPosition(AffineExpr input) const
Extracts the first result position where input dimension resides.
unsigned getNumSymbols() const
bool isMinorIdentityWithBroadcasting(SmallVectorImpl< unsigned > *broadcastedDims=nullptr) const
Returns true if this affine map is a minor identity up to broadcasted dimensions which are indicated ...
unsigned getNumDims() const
ArrayRef< AffineExpr > getResults() const
SmallVector< int64_t > getConstantResults() const
Returns the constant results of this map.
bool isPermutationOfMinorIdentityWithBroadcasting(SmallVectorImpl< unsigned > &permutedDims) const
Return true if this affine map can be converted to a minor identity with broadcast by doing a permute...
size_t getNumOfZeroResults() const
Returns the number of "zero" results (constant values == 0) in this map.
bool isSymbolIdentity() const
Returns true if this affine map is an identity affine map on the symbol identifiers.
unsigned getNumResults() const
static SmallVector< AffineMap, 4 > inferFromExprList(ArrayRef< ArrayRef< AffineExpr > > exprsList, MLIRContext *context)
Returns a vector of AffineMaps; each with as many results as exprs.size(), as many dims as the larges...
AffineMap replaceDimsAndSymbols(ArrayRef< AffineExpr > dimReplacements, ArrayRef< AffineExpr > symReplacements, unsigned numResultDims, unsigned numResultSyms) const
This method substitutes any uses of dimensions and symbols (e.g.
unsigned getNumInputs() const
AffineExpr getResult(unsigned idx) const
static AffineMap getFilteredIdentityMap(MLIRContext *ctx, unsigned numDims, llvm::function_ref< bool(AffineDimExpr)> keepDimFilter)
Returns an identity affine map with numDims input dimensions and filtered results using keepDimFilter...
AffineMap replace(AffineExpr expr, AffineExpr replacement, unsigned numResultDims, unsigned numResultSyms) const
Sparse replace method.
AffineMap dropZeroResults()
Returns the AffineMap resulting from removing "zero" results (constant values == 0) from this map.
static AffineMap getPermutationMap(ArrayRef< unsigned > permutation, MLIRContext *context)
Returns an AffineMap representing a permutation.
SmallVector< unsigned > getBroadcastDims() const
Returns the list of broadcast dimensions (i.e.
void walkExprs(llvm::function_ref< void(AffineExpr)> callback) const
Walk all of the AffineExpr's in this mapping.
AffineMap partialConstantFold(ArrayRef< Attribute > operandConstants, SmallVectorImpl< int64_t > *results=nullptr, bool *hasPoison=nullptr) const
Propagates the constant operands into this affine map.
static AffineMap getConstantMap(int64_t val, MLIRContext *context)
Returns a single constant result affine map.
static AffineMap getMultiDimMapWithTargets(unsigned numDims, ArrayRef< unsigned > targets, MLIRContext *context)
Returns an affine map with numDims input dimensions and results specified by targets.
AffineMap getSubMap(ArrayRef< unsigned > resultPos) const
Returns the map consisting of the resultPos subset.
LogicalResult constantFold(ArrayRef< Attribute > operandConstants, SmallVectorImpl< Attribute > &results, bool *hasPoison=nullptr) const
Folds the results of the application of an affine map on the provided operands to a constant if possi...
AffineMap compose(AffineMap map) const
Returns the AffineMap resulting from composing this with map.
bool isIdentity() const
Returns true if this affine map is an identity affine map.
bool isPermutation() const
Returns true if the AffineMap represents a symbol-less permutation map.
A symbolic identifier appearing in an affine expression.
This class is a general helper class for creating context-global objects like types,...
MLIRContext is the top-level object for a collection of MLIR operations.
Include the generated interface declarations.
AffineMap simplifyAffineMap(AffineMap map)
Simplifies an affine map by simplifying its underlying AffineExpr results.
AffineMap concatAffineMaps(ArrayRef< AffineMap > maps, MLIRContext *context)
Concatenates a list of maps into a single AffineMap, stepping over potentially empty maps.
AffineMap expandDimsToRank(AffineMap map, int64_t rank, const llvm::SmallBitVector &projectedDimensions)
Expand map to operate on rank dims while projecting out the dims in projectedDimensions.
AffineMap removeDuplicateExprs(AffineMap map)
Returns a map with the same dimension and symbol count as map, but whose results are the unique affin...
llvm::SmallBitVector getUnusedSymbolsBitVector(ArrayRef< AffineMap > maps)
AffineMap inverseAndBroadcastProjectedPermutation(AffineMap map)
Return the reverse map of a projected permutation where the projected dimensions are transformed into...
AffineMap inversePermutation(AffineMap map)
Returns a map of codomain to domain dimensions such that the first codomain dimension for a particula...
AffineMap compressSymbols(AffineMap map, const llvm::SmallBitVector &unusedSymbols)
Drop the symbols that are listed in unusedSymbols.
static void getMaxDimAndSymbol(ArrayRef< AffineExprContainer > exprsList, int64_t &maxDim, int64_t &maxSym)
Calculates maximum dimension and symbol positions from the expressions in exprsLists and stores them ...
AffineMap compressUnusedDims(AffineMap map)
Drop the dims that are not used.
AffineMap compressDims(AffineMap map, const llvm::SmallBitVector &unusedDims)
Drop the dims that are listed in unusedDims.
AffineExpr getAffineConstantExpr(int64_t constant, MLIRContext *context)
AffineMap getProjectedMap(AffineMap map, const llvm::SmallBitVector &projectedDimensions, bool compressDimsFlag=true, bool compressSymbolsFlag=true)
Calls projectDims(map, projectedDimensions, compressDimsFlag).
llvm::DenseMap< KeyT, ValueT, KeyInfoT, BucketT > DenseMap
llvm::SmallBitVector getUnusedDimsBitVector(ArrayRef< AffineMap > maps)
AffineExpr simplifyAffineExpr(AffineExpr expr, unsigned numDims, unsigned numSymbols)
Simplify an affine expression by flattening and some amount of simple analysis.
AffineExpr getAffineDimExpr(unsigned position, MLIRContext *context)
These free functions allow clients of the API to not use classes in detail.
AffineMap projectDims(AffineMap map, const llvm::SmallBitVector &projectedDimensions, bool compressDimsFlag=false)
Returns the map that results from projecting out the dimensions specified in projectedDimensions.
AffineMap compressUnusedSymbols(AffineMap map)
Drop the symbols that are not used.
AffineMap projectSymbols(AffineMap map, const llvm::SmallBitVector &projectedSymbols, bool compressSymbolsFlag=false)
Symbol counterpart of projectDims.
AffineMap foldAttributesIntoMap(Builder &b, AffineMap map, ArrayRef< OpFoldResult > operands, SmallVector< Value > &remainingValues)
Fold all attributes among the given operands into the affine map.
AffineExpr getAffineSymbolExpr(unsigned position, MLIRContext *context)
void reset(AffineMap map)
Resets this MutableAffineMap with 'map'.
MutableAffineMap()=default
MLIRContext * getContext() const
AffineMap getAffineMap() const
Get the AffineMap corresponding to this MutableAffineMap.
AffineExpr getResult(unsigned idx) const
unsigned getNumSymbols() const
bool isMultipleOf(unsigned idx, int64_t factor) const
Returns true if the idx'th result expression is a multiple of factor.
ArrayRef< AffineExpr > getResults() const
unsigned getNumResults() const
unsigned getNumDims() const
void simplify()
Simplify the (result) expressions in this map using analysis (used by.