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;
27using llvm::divideSignedWouldOverflow;
36class AffineExprConstantFolder {
38 AffineExprConstantFolder(
unsigned numDims, ArrayRef<Attribute> operandConsts)
39 : numDims(numDims), operandConsts(operandConsts) {}
43 IntegerAttr constantFold(AffineExpr expr) {
44 if (
auto result = constantFoldImpl(expr))
49 bool hasPoison()
const {
return hasPoison_; }
52 std::optional<int64_t> constantFoldImpl(AffineExpr expr) {
54 case AffineExprKind::Add:
55 return constantFoldBinExpr(
56 expr, [](int64_t
lhs, int64_t
rhs) -> std::optional<int64_t> {
58 if (llvm::AddOverflow(
lhs,
rhs, sum))
62 case AffineExprKind::Mul:
63 return constantFoldBinExpr(
64 expr, [](int64_t
lhs, int64_t
rhs) -> std::optional<int64_t> {
70 case AffineExprKind::Mod:
71 return constantFoldBinExpr(
72 expr, [
this](int64_t
lhs, int64_t
rhs) -> std::optional<int64_t> {
79 case AffineExprKind::FloorDiv:
80 return constantFoldBinExpr(
81 expr, [
this](int64_t
lhs, int64_t
rhs) -> std::optional<int64_t> {
86 if (divideSignedWouldOverflow(
lhs,
rhs))
88 return divideFloorSigned(
lhs,
rhs);
90 case AffineExprKind::CeilDiv:
91 return constantFoldBinExpr(
92 expr, [
this](int64_t
lhs, int64_t
rhs) -> std::optional<int64_t> {
97 if (divideSignedWouldOverflow(
lhs,
rhs))
99 return divideCeilSigned(
lhs,
rhs);
101 case AffineExprKind::Constant:
102 return cast<AffineConstantExpr>(expr).getValue();
103 case AffineExprKind::DimId:
104 if (
auto attr = llvm::dyn_cast_or_null<IntegerAttr>(
105 operandConsts[cast<AffineDimExpr>(expr).getPosition()]))
106 return attr.getInt();
108 case AffineExprKind::SymbolId:
109 if (
auto attr = llvm::dyn_cast_or_null<IntegerAttr>(
110 operandConsts[numDims +
111 cast<AffineSymbolExpr>(expr).getPosition()]))
112 return attr.getInt();
115 llvm_unreachable(
"Unknown AffineExpr");
119 std::optional<int64_t> constantFoldBinExpr(
121 llvm::function_ref<std::optional<int64_t>(int64_t, int64_t)> op) {
122 auto binOpExpr = cast<AffineBinaryOpExpr>(expr);
123 if (
auto lhs = constantFoldImpl(binOpExpr.getLHS()))
124 if (
auto rhs = constantFoldImpl(binOpExpr.getRHS()))
132 ArrayRef<Attribute> operandConsts;
133 bool hasPoison_{
false};
148 assert(dims >= results &&
"Dimension mismatch");
159 llvm::SmallBitVector dropDimResults(numDims);
160 for (
auto [idx, resultExpr] : llvm::enumerate(identityMap.getResults()))
161 dropDimResults[idx] = !keepDimFilter(cast<AffineDimExpr>(resultExpr));
163 return identityMap.dropResults(dropDimResults);
174 for (
const auto &[resIdx, expr] : llvm::enumerate(
getResults())) {
175 if (
auto constExpr = dyn_cast<AffineConstantExpr>(expr)) {
176 if (constExpr.getValue() != 0)
178 broadcastedDims.push_back(resIdx);
182 return broadcastedDims;
190 broadcastedDims->clear();
194 for (
const auto &idxAndExpr : llvm::enumerate(
getResults())) {
195 unsigned resIdx = idxAndExpr.index();
197 if (
auto constExpr = dyn_cast<AffineConstantExpr>(expr)) {
199 if (constExpr.getValue() != 0)
202 broadcastedDims->push_back(resIdx);
203 }
else if (
auto dimExpr = dyn_cast<AffineDimExpr>(expr)) {
205 if (dimExpr.getPosition() != suffixStart + resIdx)
229 unsigned projectionStart =
231 permutedDims.clear();
237 unsigned leadingBroadcast =
241 for (
const auto &idxAndExpr : llvm::enumerate(
getResults())) {
242 unsigned resIdx = idxAndExpr.index();
246 if (
auto constExpr = dyn_cast<AffineConstantExpr>(expr)) {
247 if (constExpr.getValue() != 0)
249 broadcastDims.push_back(resIdx);
250 }
else if (
auto dimExpr = dyn_cast<AffineDimExpr>(expr)) {
251 if (dimExpr.getPosition() < projectionStart)
253 unsigned newPosition =
254 dimExpr.getPosition() - projectionStart + leadingBroadcast;
255 permutedDims[resIdx] = newPosition;
256 dimFound[newPosition] =
true;
265 for (
auto dim : broadcastDims) {
266 while (pos < dimFound.size() && dimFound[pos]) {
269 permutedDims[dim] = pos++;
277 assert(!permutation.empty() &&
278 "Cannot create permutation map from empty permutation vector");
279 const auto *m = llvm::max_element(permutation);
281 assert(permutationMap.isPermutation() &&
"Invalid permutation vector");
282 return permutationMap;
287 permutation, [](
int64_t i) {
return static_cast<unsigned>(i); });
297 for (
unsigned t : targets)
308template <
typename AffineExprContainer>
312 if (exprsList.empty())
314 int64_t maxDim = -1, maxSym = -1;
317 maps.reserve(exprsList.size());
318 for (
const auto &exprs : exprsList)
320 maxSym + 1, exprs, context));
327 return ::inferFromExprList(exprsList, context);
333 return ::inferFromExprList(exprsList, context);
339 uint64_t thisGcd = resultExpr.getLargestKnownDivisor();
340 gcd = std::gcd(gcd, thisGcd);
343 gcd = std::numeric_limits<uint64_t>::max();
350 dimExprs.reserve(numDims);
351 for (
unsigned i = 0; i < numDims; ++i)
353 return get(numDims, 0, dimExprs, context);
362 for (
unsigned i = 0, numDims =
getNumDims(); i < numDims; ++i) {
363 auto expr = dyn_cast<AffineDimExpr>(results[i]);
364 if (!expr || expr.getPosition() != i)
374 for (
unsigned i = 0, numSymbols =
getNumSymbols(); i < numSymbols; ++i) {
375 auto expr = dyn_cast<AffineDimExpr>(results[i]);
376 if (!expr || expr.getPosition() != i)
391 return llvm::all_of(
getResults(), llvm::IsaPred<AffineConstantExpr>);
396 return cast<AffineConstantExpr>(
getResult(0)).getValue();
400 assert(
isConstant() &&
"map must have only constant results");
403 result.emplace_back(cast<AffineConstantExpr>(expr).getValue());
408 assert(map &&
"uninitialized map storage");
412 assert(map &&
"uninitialized map storage");
413 return map->numSymbols;
417 assert(map &&
"uninitialized map storage");
418 return map->numDims + map->numSymbols;
421 assert(map &&
"uninitialized map storage");
422 return map->results();
429 return cast<AffineDimExpr>(
getResult(idx)).getPosition();
433 if (!isa<AffineDimExpr>(input))
436 for (
unsigned i = 0, numResults =
getNumResults(); i < numResults; i++) {
449 bool *hasPoison)
const {
456 if (integers.empty())
459 auto range = llvm::map_range(integers, [
this](
int64_t i) {
460 return IntegerAttr::get(IndexType::get(
getContext()), i);
462 results.append(range.begin(), range.end());
468 bool *hasPoison)
const {
472 AffineExprConstantFolder exprFolder(
getNumDims(), operandConstants);
477 auto folded = exprFolder.constantFold(expr);
478 if (exprFolder.hasPoison() && hasPoison) {
488 results->push_back(folded.getInt());
490 exprs.push_back(expr);
515 unsigned numResultDims,
516 unsigned numResultSyms)
const {
522 return get(numResultDims, numResultSyms, results,
getContext());
529 unsigned numResultDims,
530 unsigned numResultSyms)
const {
534 newResults.push_back(e.replace(expr,
replacement));
542 unsigned numResultDims,
543 unsigned numResultSyms)
const {
547 newResults.push_back(e.replace(map));
556 newResults.push_back(e.replace(map));
561 auto exprs = llvm::to_vector<4>(
getResults());
563 for (
auto pos = positions.find_last(); pos != -1;
564 pos = positions.find_prev(pos))
565 exprs.erase(exprs.begin() + pos);
570 assert(
getNumDims() == map.getNumResults() &&
"Number of results mismatch");
572 unsigned numDims = map.getNumDims();
574 unsigned numSymbols = numSymbolsThisMap + map.getNumSymbols();
576 for (
unsigned idx = 0; idx < numDims; ++idx) {
580 for (
unsigned idx = numSymbolsThisMap; idx < numSymbols; ++idx) {
581 newSymbols[idx - numSymbolsThisMap] =
585 map.replaceDimsAndSymbols(newDims, newSymbols, numDims, numSymbols);
589 exprs.push_back(expr.
compose(newMap));
590 return AffineMap::get(numDims, numSymbols, exprs, map.getContext());
604 res.push_back(cast<AffineConstantExpr>(e.replaceDims(exprs)).getValue());
611 auto constExpr = dyn_cast<AffineConstantExpr>(expr);
612 if (constExpr && constExpr.getValue() == 0)
623 auto constExpr = dyn_cast<AffineConstantExpr>(expr);
624 if (!constExpr || constExpr.getValue() != 0)
625 newExprs.push_back(expr);
645 if (
auto dim = dyn_cast<AffineDimExpr>(expr)) {
646 if (seen[dim.getPosition()])
648 seen[dim.getPosition()] =
true;
650 auto constExpr = dyn_cast<AffineConstantExpr>(expr);
651 if (!allowZeroInResults || !constExpr || constExpr.getValue() != 0)
668 exprs.reserve(resultPos.size());
669 for (
auto idx : resultPos)
705 allExprs.reserve(maps.size() * maps.front().getNumResults());
706 unsigned numDims = maps.front().getNumDims(),
707 numSymbols = maps.front().getNumSymbols();
708 for (
auto m : maps) {
709 assert(numDims == m.getNumDims() && numSymbols == m.getNumSymbols() &&
710 "expected maps with same num dims and symbols");
711 llvm::append_range(allExprs, m.getResults());
714 AffineMap::get(numDims, numSymbols, allExprs, maps.front().getContext()));
715 unsigned unifiedNumDims = unifiedMap.
getNumDims(),
719 res.reserve(maps.size());
720 for (
auto m : maps) {
722 unifiedResults.take_front(m.getNumResults()),
724 unifiedResults = unifiedResults.drop_front(m.getNumResults());
730 const llvm::SmallBitVector &unusedDims) {
744 const llvm::SmallBitVector &unusedSymbols) {
763 if (
auto attr = dyn_cast<Attribute>(operands[i])) {
764 dimReplacements.push_back(
765 b.getAffineConstantExpr(cast<IntegerAttr>(attr).getInt()));
767 dimReplacements.push_back(
b.getAffineDimExpr(numDims++));
768 remainingValues.push_back(cast<Value>(operands[i]));
773 if (
auto attr = dyn_cast<Attribute>(operands[i + map.
getNumDims()])) {
774 symReplacements.push_back(
775 b.getAffineConstantExpr(cast<IntegerAttr>(attr).getInt()));
777 symReplacements.push_back(
b.getAffineSymbolExpr(numSymbols++));
778 remainingValues.push_back(cast<Value>(operands[i + map.
getNumDims()]));
798 uniqueExprs.erase(llvm::unique(uniqueExprs), uniqueExprs.end());
806 assert(map.
getNumSymbols() == 0 &&
"expected map without symbols");
808 for (
const auto &en : llvm::enumerate(map.
getResults())) {
809 auto expr = en.value();
811 if (
auto d = dyn_cast<AffineDimExpr>(expr)) {
812 if (exprs[d.getPosition()])
819 for (
auto expr : exprs)
821 seenExprs.push_back(expr);
833 for (
unsigned i : llvm::seq(
unsigned(0), map.
getNumResults())) {
835 if (
auto constExpr = dyn_cast<AffineConstantExpr>(map.
getResult(i))) {
836 assert(constExpr.getValue() == 0 &&
837 "Unexpected constant in projected permutation");
852 unsigned numResults = 0, numDims = 0, numSymbols = 0;
854 numResults += m.getNumResults();
856 results.reserve(numResults);
857 for (
auto m : maps) {
858 for (
auto res : m.getResults())
859 results.push_back(res.shiftSymbols(m.getNumSymbols(), numSymbols));
861 numSymbols += m.getNumSymbols();
862 numDims = std::max(m.getNumDims(), numDims);
871template <
typename AffineDimOrSymExpr>
873 const llvm::SmallBitVector &toProject,
875 static_assert(llvm::is_one_of<AffineDimOrSymExpr,
AffineDimExpr,
877 "expected AffineDimExpr or AffineSymbolExpr");
879 constexpr bool isDim = std::is_same<AffineDimOrSymExpr, AffineDimExpr>::value;
882 replacements.reserve(numDimOrSym);
886 using replace_fn_ty =
892 replace_fn_ty replaceSymbols = [](
AffineExpr e,
896 replace_fn_ty replaceNewDimOrSym = (isDim) ? replaceDims : replaceSymbols;
900 for (
unsigned dimOrSym = 0; dimOrSym < numDimOrSym; ++dimOrSym) {
901 if (toProject.test(dimOrSym)) {
905 int64_t newPos = compress ? newNumDimOrSym++ : dimOrSym;
906 replacements.push_back(createNewDimOrSym(newPos, context));
911 resultExprs.push_back(replaceNewDimOrSym(e, replacements));
919 const llvm::SmallBitVector &projectedDimensions,
920 bool compressDimsFlag) {
926 const llvm::SmallBitVector &projectedSymbols,
927 bool compressSymbolsFlag) {
929 compressSymbolsFlag);
933 const llvm::SmallBitVector &projectedDimensions,
934 bool compressDimsFlag,
935 bool compressSymbolsFlag) {
936 map =
projectDims(map, projectedDimensions, compressDimsFlag);
937 if (compressSymbolsFlag)
943 unsigned numDims = maps[0].getNumDims();
944 llvm::SmallBitVector numDimsBitVector(numDims,
true);
946 for (
unsigned i = 0; i < numDims; ++i) {
947 if (m.isFunctionOfDim(i))
948 numDimsBitVector.reset(i);
951 return numDimsBitVector;
955 unsigned numSymbols = maps[0].getNumSymbols();
956 llvm::SmallBitVector numSymbolsBitVector(numSymbols,
true);
958 for (
unsigned i = 0; i < numSymbols; ++i) {
959 if (m.isFunctionOfSymbol(i))
960 numSymbolsBitVector.reset(i);
963 return numSymbolsBitVector;
968 const llvm::SmallBitVector &projectedDimensions) {
987 llvm::append_range(results, map.
getResults());
991 return results[idx].isMultipleOf(factor);
static int64_t product(ArrayRef< int64_t > vals)
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`
static SmallVector< Value > slice(OpBuilder &b, Location loc, Value value, VectorType nativeType)
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...
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 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.
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.