25 #include "llvm/ADT/STLExtras.h"
26 #include "llvm/ADT/SmallBitVector.h"
31 #define GEN_PASS_DEF_EXPANDSTRIDEDMETADATA
32 #include "mlir/Dialect/MemRef/Transforms/Passes.h.inc"
41 struct StridedMetadata {
59 static FailureOr<StridedMetadata>
61 memref::SubViewOp subview) {
64 Value source = subview.getSource();
65 auto sourceType = cast<MemRefType>(source.
getType());
66 unsigned sourceRank = sourceType.getRank();
68 auto newExtractStridedMetadata =
69 rewriter.
create<memref::ExtractStridedMetadataOp>(origLoc, source);
81 auto origStrides = newExtractStridedMetadata.getStrides();
89 values[0] = ShapedType::isDynamic(sourceOffset)
91 : rewriter.getIndexAttr(sourceOffset);
96 for (
unsigned i = 0; i < sourceRank; ++i) {
99 ShapedType::isDynamic(sourceStrides[i])
103 rewriter, origLoc, s0 * s1, {subStrides[i], origStride}));
106 unsigned baseIdxForDim = 1 + 2 * i;
107 unsigned subOffsetForDim = baseIdxForDim;
108 unsigned origStrideForDim = baseIdxForDim + 1;
109 expr = expr + symbols[subOffsetForDim] * symbols[origStrideForDim];
110 values[subOffsetForDim] = subOffsets[i];
111 values[origStrideForDim] = origStride;
121 if (computedOffset && !ShapedType::isDynamic(resultOffset))
122 assert(*computedOffset == resultOffset &&
123 "mismatch between computed offset and result type offset");
129 auto subType = cast<MemRefType>(subview.getType());
130 unsigned subRank = subType.getRank();
139 llvm::SmallBitVector droppedDims = subview.getDroppedDims();
142 finalSizes.reserve(subRank);
145 finalStrides.reserve(subRank);
151 for (
unsigned i = 0; i < sourceRank; ++i) {
152 if (droppedDims.test(i))
155 finalSizes.push_back(subSizes[i]);
156 finalStrides.push_back(strides[i]);
161 if (computedStride && !ShapedType::isDynamic(resultStrides[
j]))
162 assert(*computedStride == resultStrides[
j] &&
163 "mismatch between computed stride and result type stride");
167 assert(finalSizes.size() == subRank &&
168 "Should have populated all the values at this point");
169 return StridedMetadata{newExtractStridedMetadata.getBaseBuffer(), finalOffset,
170 finalSizes, finalStrides};
191 LogicalResult matchAndRewrite(memref::SubViewOp subview,
193 FailureOr<StridedMetadata> stridedMetadata =
194 resolveSubviewStridedMetadata(rewriter, subview);
195 if (failed(stridedMetadata)) {
197 "failed to resolve subview metadata");
201 subview, subview.getType(), stridedMetadata->basePtr,
202 stridedMetadata->offset, stridedMetadata->sizes,
203 stridedMetadata->strides);
221 struct ExtractStridedMetadataOpSubviewFolder
225 LogicalResult matchAndRewrite(memref::ExtractStridedMetadataOp op,
227 auto subviewOp = op.getSource().getDefiningOp<memref::SubViewOp>();
231 FailureOr<StridedMetadata> stridedMetadata =
232 resolveSubviewStridedMetadata(rewriter, subviewOp);
233 if (failed(stridedMetadata)) {
235 op,
"failed to resolve metadata in terms of source subview op");
239 results.reserve(subviewOp.getType().getRank() * 2 + 2);
240 results.push_back(stridedMetadata->basePtr);
242 stridedMetadata->offset));
246 stridedMetadata->strides));
269 getExpandedSizes(memref::ExpandShapeOp expandShape,
OpBuilder &builder,
272 expandShape.getReassociationIndices()[groupId];
273 assert(!reassocGroup.empty() &&
274 "Reassociation group should have at least one dimension");
276 unsigned groupSize = reassocGroup.size();
279 uint64_t productOfAllStaticSizes = 1;
280 std::optional<unsigned> dynSizeIdx;
281 MemRefType expandShapeType = expandShape.getResultType();
284 for (
unsigned i = 0; i < groupSize; ++i) {
285 uint64_t dimSize = expandShapeType.getDimSize(reassocGroup[i]);
286 if (ShapedType::isDynamic(dimSize)) {
287 assert(!dynSizeIdx &&
"There must be at most one dynamic size per group");
291 productOfAllStaticSizes *= dimSize;
301 builder, expandShape.getLoc(), s0.
floorDiv(productOfAllStaticSizes),
305 return expandedSizes;
338 expandShape.getReassociationIndices()[groupId];
339 assert(!reassocGroup.empty() &&
340 "Reassociation group should have at least one dimension");
342 unsigned groupSize = reassocGroup.size();
343 MemRefType expandShapeType = expandShape.getResultType();
345 std::optional<int64_t> dynSizeIdx;
349 uint64_t currentStride = 1;
351 for (
int i = groupSize - 1; i >= 0; --i) {
352 expandedStrides[i] = builder.
getIndexAttr(currentStride);
353 uint64_t dimSize = expandShapeType.getDimSize(reassocGroup[i]);
354 if (ShapedType::isDynamic(dimSize)) {
355 assert(!dynSizeIdx &&
"There must be at most one dynamic size per group");
360 currentStride *= dimSize;
364 Value source = expandShape.getSrc();
365 auto sourceType = cast<MemRefType>(source.
getType());
368 OpFoldResult origStride = ShapedType::isDynamic(strides[groupId])
369 ? origStrides[groupId]
373 int64_t doneStrideIdx = 0;
377 int64_t productOfAllStaticSizes = currentStride;
378 assert(ShapedType::isDynamic(sourceType.getDimSize(groupId)) &&
379 "We shouldn't be able to change dynamicity");
384 for (; doneStrideIdx < *dynSizeIdx; ++doneStrideIdx) {
385 int64_t baseExpandedStride =
386 cast<IntegerAttr>(expandedStrides[doneStrideIdx].get<Attribute>())
389 builder, expandShape.getLoc(),
390 (s0 * baseExpandedStride).floorDiv(productOfAllStaticSizes) * s1,
391 {origSize, origStride});
397 for (; doneStrideIdx < groupSize; ++doneStrideIdx) {
398 int64_t baseExpandedStride =
399 cast<IntegerAttr>(expandedStrides[doneStrideIdx].get<Attribute>())
402 builder, expandShape.getLoc(), s0 * baseExpandedStride, {origStride});
405 return expandedStrides;
422 unsigned numberOfSymbols = 0;
423 unsigned groupSize = indices.size();
424 for (
unsigned i = 0; i < groupSize; ++i) {
427 unsigned srcIdx = indices[i];
428 int64_t maybeConstant = maybeConstants[srcIdx];
430 inputValues.push_back(isDynamic(maybeConstant)
454 getCollapsedSize(memref::CollapseShapeOp collapseShape,
OpBuilder &builder,
458 MemRefType collapseShapeType = collapseShape.getResultType();
460 uint64_t size = collapseShapeType.getDimSize(groupId);
461 if (!ShapedType::isDynamic(size)) {
463 return collapsedSize;
469 Value source = collapseShape.getSrc();
470 auto sourceType = cast<MemRefType>(source.
getType());
473 collapseShape.getReassociationIndices()[groupId];
475 collapsedSize.push_back(getProductOfValues(
476 reassocGroup, builder, collapseShape.getLoc(), sourceType.getShape(),
477 origSizes, ShapedType::isDynamic));
479 return collapsedSize;
495 getCollapsedStride(memref::CollapseShapeOp collapseShape,
OpBuilder &builder,
499 collapseShape.getReassociationIndices()[groupId];
500 assert(!reassocGroup.empty() &&
501 "Reassociation group should have at least one dimension");
503 Value source = collapseShape.getSrc();
504 auto sourceType = cast<MemRefType>(source.
getType());
510 for (int64_t currentDim : reassocGroup) {
516 if (srcShape[currentDim] == 1)
519 int64_t currentStride = strides[currentDim];
520 groupStrides.push_back(ShapedType::isDynamic(currentStride)
521 ? origStrides[currentDim]
524 if (groupStrides.empty()) {
527 MemRefType collapsedType = collapseShape.getResultType();
528 auto [collapsedStrides, collapsedOffset] =
530 int64_t finalStride = collapsedStrides[groupId];
531 if (ShapedType::isDynamic(finalStride)) {
534 for (int64_t currentDim : reassocGroup) {
535 assert(srcShape[currentDim] == 1 &&
536 "We should be dealing with 1x1x...x1");
538 if (ShapedType::isDynamic(strides[currentDim]))
539 return {origStrides[currentDim]};
541 llvm_unreachable(
"We should have found a dynamic stride");
564 template <
typename ReassociativeReshapeLikeOp>
565 static FailureOr<StridedMetadata> resolveReshapeStridedMetadata(
566 RewriterBase &rewriter, ReassociativeReshapeLikeOp reshape,
575 getReshapedStrides) {
578 Location origLoc = reshape.getLoc();
579 Value source = reshape.getSrc();
580 auto sourceType = cast<MemRefType>(source.
getType());
581 unsigned sourceRank = sourceType.getRank();
583 auto newExtractStridedMetadata =
584 rewriter.
create<memref::ExtractStridedMetadataOp>(origLoc, source);
588 MemRefType reshapeType = reshape.getResultType();
589 unsigned reshapeRank = reshapeType.getRank();
592 ShapedType::isDynamic(offset)
594 : rewriter.getIndexAttr(offset);
597 if (sourceRank == 0) {
599 return StridedMetadata{newExtractStridedMetadata.getBaseBuffer(), offsetOfr,
604 finalSizes.reserve(reshapeRank);
606 finalStrides.reserve(reshapeRank);
613 unsigned idx = 0, endIdx = reshape.getReassociationIndices().size();
614 for (; idx != endIdx; ++idx) {
616 getReshapedSizes(reshape, rewriter, origSizes, idx);
618 reshape, rewriter, origSizes, origStrides, idx);
620 unsigned groupSize = reshapedSizes.size();
621 for (
unsigned i = 0; i < groupSize; ++i) {
622 finalSizes.push_back(reshapedSizes[i]);
623 finalStrides.push_back(reshapedStrides[i]);
626 assert(((isa<memref::ExpandShapeOp>(reshape) && idx == sourceRank) ||
627 (isa<memref::CollapseShapeOp>(reshape) && idx == reshapeRank)) &&
628 "We should have visited all the input dimensions");
629 assert(finalSizes.size() == reshapeRank &&
630 "We should have populated all the values");
632 return StridedMetadata{newExtractStridedMetadata.getBaseBuffer(), offsetOfr,
633 finalSizes, finalStrides};
652 template <
typename ReassociativeReshapeLikeOp,
664 LogicalResult matchAndRewrite(ReassociativeReshapeLikeOp reshape,
666 FailureOr<StridedMetadata> stridedMetadata =
667 resolveReshapeStridedMetadata<ReassociativeReshapeLikeOp>(
668 rewriter, reshape, getReshapedSizes, getReshapedStrides);
669 if (failed(stridedMetadata)) {
671 "failed to resolve reshape metadata");
675 reshape, reshape.getType(), stridedMetadata->basePtr,
676 stridedMetadata->offset, stridedMetadata->sizes,
677 stridedMetadata->strides);
695 struct ExtractStridedMetadataOpCollapseShapeFolder
699 LogicalResult matchAndRewrite(memref::ExtractStridedMetadataOp op,
701 auto collapseShapeOp =
702 op.getSource().getDefiningOp<memref::CollapseShapeOp>();
703 if (!collapseShapeOp)
706 FailureOr<StridedMetadata> stridedMetadata =
707 resolveReshapeStridedMetadata<memref::CollapseShapeOp>(
708 rewriter, collapseShapeOp, getCollapsedSize, getCollapsedStride);
709 if (failed(stridedMetadata)) {
712 "failed to resolve metadata in terms of source collapse_shape op");
715 Location loc = collapseShapeOp.getLoc();
717 results.push_back(stridedMetadata->basePtr);
719 stridedMetadata->offset));
723 stridedMetadata->strides));
743 template <
typename AllocLikeOp>
744 struct ExtractStridedMetadataOpAllocFolder
749 LogicalResult matchAndRewrite(memref::ExtractStridedMetadataOp op,
751 auto allocLikeOp = op.getSource().getDefiningOp<AllocLikeOp>();
755 auto memRefType = cast<MemRefType>(allocLikeOp.getResult().getType());
756 if (!memRefType.getLayout().isIdentity())
758 allocLikeOp,
"alloc-like operations should have been normalized");
761 int rank = memRefType.getRank();
764 ValueRange dynamic = allocLikeOp.getDynamicSizes();
767 unsigned dynamicPos = 0;
768 for (int64_t size : memRefType.getShape()) {
769 if (ShapedType::isDynamic(size))
770 sizes.push_back(dynamic[dynamicPos++]);
778 unsigned symbolNumber = 0;
779 for (
int i = rank - 2; i >= 0; --i) {
781 assert(i + 1 + symbolNumber == sizes.size() &&
782 "The ArrayRef should encompass the last #symbolNumber sizes");
785 sizesInvolvedInStride);
790 results.reserve(rank * 2 + 2);
792 auto baseBufferType = cast<MemRefType>(op.getBaseBuffer().getType());
795 results.push_back(
nullptr);
797 if (allocLikeOp.getType() == baseBufferType)
798 results.push_back(allocLikeOp);
800 results.push_back(rewriter.
create<memref::ReinterpretCastOp>(
801 loc, baseBufferType, allocLikeOp, offset,
807 results.push_back(rewriter.
create<arith::ConstantIndexOp>(loc, offset));
834 struct ExtractStridedMetadataOpGetGlobalFolder
839 LogicalResult matchAndRewrite(memref::ExtractStridedMetadataOp op,
841 auto getGlobalOp = op.getSource().getDefiningOp<memref::GetGlobalOp>();
845 auto memRefType = cast<MemRefType>(getGlobalOp.getResult().getType());
846 if (!memRefType.getLayout().isIdentity()) {
849 "get-global operation result should have been normalized");
853 int rank = memRefType.getRank();
857 assert(!llvm::any_of(sizes, ShapedType::isDynamic) &&
858 "unexpected dynamic shape for result of `memref.get_global` op");
865 results.reserve(rank * 2 + 2);
867 auto baseBufferType = cast<MemRefType>(op.getBaseBuffer().getType());
869 if (getGlobalOp.getType() == baseBufferType)
870 results.push_back(getGlobalOp);
872 results.push_back(rewriter.
create<memref::ReinterpretCastOp>(
873 loc, baseBufferType, getGlobalOp, offset,
878 results.push_back(rewriter.
create<arith::ConstantIndexOp>(loc, offset));
880 for (
auto size : sizes)
881 results.push_back(rewriter.
create<arith::ConstantIndexOp>(loc, size));
883 for (
auto stride : strides)
884 results.push_back(rewriter.
create<arith::ConstantIndexOp>(loc, stride));
893 class RewriteExtractAlignedPointerAsIndexOfViewLikeOp
898 matchAndRewrite(memref::ExtractAlignedPointerAsIndexOp extractOp,
901 extractOp.getSource().getDefiningOp<ViewLikeOpInterface>();
905 extractOp.getSourceMutable().assign(viewLikeOp.getViewSource());
924 class ExtractStridedMetadataOpReinterpretCastFolder
929 matchAndRewrite(memref::ExtractStridedMetadataOp extractStridedMetadataOp,
931 auto reinterpretCastOp = extractStridedMetadataOp.getSource()
932 .getDefiningOp<memref::ReinterpretCastOp>();
933 if (!reinterpretCastOp)
936 Location loc = extractStridedMetadataOp.getLoc();
939 if (failed(extractStridedMetadataOp.inferReturnTypes(
940 rewriter.
getContext(), loc, {reinterpretCastOp.getSource()},
942 inferredReturnTypes)))
944 reinterpretCastOp,
"reinterpret_cast source's type is incompatible");
946 auto memrefType = cast<MemRefType>(reinterpretCastOp.getResult().getType());
947 unsigned rank = memrefType.getRank();
949 results.resize_for_overwrite(rank * 2 + 2);
951 auto newExtractStridedMetadata =
952 rewriter.
create<memref::ExtractStridedMetadataOp>(
953 loc, reinterpretCastOp.getSource());
956 results[0] = newExtractStridedMetadata.getBaseBuffer();
960 rewriter, loc, reinterpretCastOp.getMixedOffsets()[0]);
962 const unsigned sizeStartIdx = 2;
963 const unsigned strideStartIdx = sizeStartIdx + rank;
967 for (
unsigned i = 0; i < rank; ++i) {
968 results[sizeStartIdx + i] = sizes[i];
969 results[strideStartIdx + i] = strides[i];
971 rewriter.
replaceOp(extractStridedMetadataOp,
998 class ExtractStridedMetadataOpCastFolder
1003 matchAndRewrite(memref::ExtractStridedMetadataOp extractStridedMetadataOp,
1005 Value source = extractStridedMetadataOp.getSource();
1010 Location loc = extractStridedMetadataOp.getLoc();
1013 if (failed(extractStridedMetadataOp.inferReturnTypes(
1014 rewriter.
getContext(), loc, {castOp.getSource()},
1016 inferredReturnTypes)))
1018 "cast source's type is incompatible");
1020 auto memrefType = cast<MemRefType>(source.
getType());
1021 unsigned rank = memrefType.getRank();
1023 results.resize_for_overwrite(rank * 2 + 2);
1025 auto newExtractStridedMetadata =
1026 rewriter.
create<memref::ExtractStridedMetadataOp>(loc,
1027 castOp.getSource());
1030 results[0] = newExtractStridedMetadata.getBaseBuffer();
1032 auto getConstantOrValue = [&rewriter](int64_t constant,
1034 return !ShapedType::isDynamic(constant)
1040 assert(sourceStrides.size() == rank &&
"unexpected number of strides");
1044 getConstantOrValue(sourceOffset, newExtractStridedMetadata.getOffset());
1046 const unsigned sizeStartIdx = 2;
1047 const unsigned strideStartIdx = sizeStartIdx + rank;
1052 for (
unsigned i = 0; i < rank; ++i) {
1053 results[sizeStartIdx + i] = getConstantOrValue(sourceSizes[i], sizes[i]);
1054 results[strideStartIdx + i] =
1055 getConstantOrValue(sourceStrides[i], strides[i]);
1057 rewriter.
replaceOp(extractStridedMetadataOp,
1070 class ExtractStridedMetadataOpExtractStridedMetadataFolder
1075 matchAndRewrite(memref::ExtractStridedMetadataOp extractStridedMetadataOp,
1077 auto sourceExtractStridedMetadataOp =
1078 extractStridedMetadataOp.getSource()
1079 .getDefiningOp<memref::ExtractStridedMetadataOp>();
1080 if (!sourceExtractStridedMetadataOp)
1082 Location loc = extractStridedMetadataOp.getLoc();
1083 rewriter.
replaceOp(extractStridedMetadataOp,
1084 {sourceExtractStridedMetadataOp.getBaseBuffer(),
1094 patterns.
add<SubviewFolder,
1095 ReshapeFolder<memref::ExpandShapeOp, getExpandedSizes,
1096 getExpandedStrides>,
1097 ReshapeFolder<memref::CollapseShapeOp, getCollapsedSize,
1098 getCollapsedStride>,
1099 ExtractStridedMetadataOpAllocFolder<memref::AllocOp>,
1100 ExtractStridedMetadataOpAllocFolder<memref::AllocaOp>,
1101 ExtractStridedMetadataOpCollapseShapeFolder,
1102 ExtractStridedMetadataOpGetGlobalFolder,
1103 RewriteExtractAlignedPointerAsIndexOfViewLikeOp,
1104 ExtractStridedMetadataOpReinterpretCastFolder,
1105 ExtractStridedMetadataOpSubviewFolder,
1106 ExtractStridedMetadataOpCastFolder,
1107 ExtractStridedMetadataOpExtractStridedMetadataFolder>(
1113 patterns.
add<ExtractStridedMetadataOpAllocFolder<memref::AllocOp>,
1114 ExtractStridedMetadataOpAllocFolder<memref::AllocaOp>,
1115 ExtractStridedMetadataOpCollapseShapeFolder,
1116 ExtractStridedMetadataOpGetGlobalFolder,
1117 ExtractStridedMetadataOpSubviewFolder,
1118 RewriteExtractAlignedPointerAsIndexOfViewLikeOp,
1119 ExtractStridedMetadataOpReinterpretCastFolder,
1120 ExtractStridedMetadataOpCastFolder,
1121 ExtractStridedMetadataOpExtractStridedMetadataFolder>(
1131 struct ExpandStridedMetadataPass final
1132 :
public memref::impl::ExpandStridedMetadataBase<
1133 ExpandStridedMetadataPass> {
1134 void runOnOperation()
override;
1139 void ExpandStridedMetadataPass::runOnOperation() {
1146 return std::make_unique<ExpandStridedMetadataPass>();
static MLIRContext * getContext(OpFoldResult val)
Base type for affine expression.
AffineExpr floorDiv(uint64_t v) const
static AffineMap getMultiDimIdentityMap(unsigned numDims, MLIRContext *context)
Returns an AffineMap with 'numDims' identity result dim exprs.
IntegerAttr getIndexAttr(int64_t value)
AffineExpr getAffineSymbolExpr(unsigned position)
AffineExpr getAffineConstantExpr(int64_t constant)
MLIRContext * getContext() const
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
This class helps build Operations.
Operation * create(const OperationState &state)
Creates an operation given the fields represented as an OperationState.
This class represents a single result from folding an operation.
bool use_empty()
Returns true if this operation has no uses.
Location getLoc()
The source location the operation was defined or derived from.
A special type of RewriterBase that coordinates the application of a rewrite pattern on the current I...
MLIRContext * getContext() const
RewritePatternSet & add(ConstructorArg &&arg, ConstructorArgs &&...args)
Add an instance of each of the pattern types 'Ts' to the pattern list with the given arguments.
This class coordinates the application of a rewrite on a set of IR, providing a way for clients to tr...
std::enable_if_t<!std::is_convertible< CallbackT, Twine >::value, LogicalResult > notifyMatchFailure(Location loc, CallbackT &&reasonCallback)
Used to notify the listener that the IR failed to be rewritten because of a match failure,...
virtual void replaceOp(Operation *op, ValueRange newValues)
Replace the results of the given (original) operation with the specified list of values (replacements...
void modifyOpInPlace(Operation *root, CallableT &&callable)
This method is a utility wrapper around an in-place modification of an operation.
OpTy replaceOpWithNewOp(Operation *op, Args &&...args)
Replace the results of the given (original) op with a new op that is created without verification (re...
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...
Type getType() const
Return the type of this value.
Operation * getDefiningOp() const
If this value is the result of an operation, return the operation that defines it.
OpFoldResult makeComposedFoldedAffineMin(OpBuilder &b, Location loc, AffineMap map, ArrayRef< OpFoldResult > operands)
Constructs an AffineMinOp that computes a minimum across the results of applying map to operands,...
OpFoldResult makeComposedFoldedAffineApply(OpBuilder &b, Location loc, AffineMap map, ArrayRef< OpFoldResult > operands)
Constructs an AffineApplyOp that applies map to operands after composing the map with the maps of any...
std::unique_ptr< Pass > createExpandStridedMetadataPass()
Creates an operation pass to expand some memref operation into easier to reason about operations.
void populateResolveExtractStridedMetadataPatterns(RewritePatternSet &patterns)
Appends patterns for resolving memref.extract_strided_metadata into memref.extract_strided_metadata o...
void populateExpandStridedMetadataPatterns(RewritePatternSet &patterns)
Appends patterns for expanding memref operations that modify the metadata (sizes, offset,...
Include the generated interface declarations.
std::optional< int64_t > getConstantIntValue(OpFoldResult ofr)
If ofr is a constant integer or an IntegerAttr, return the integer.
LogicalResult getStridesAndOffset(MemRefType t, SmallVectorImpl< int64_t > &strides, int64_t &offset)
Returns the strides of the MemRef if the layout map is in strided form.
SmallVector< int64_t > computeSuffixProduct(ArrayRef< int64_t > sizes)
Given a set of sizes, return the suffix product.
LogicalResult applyPatternsAndFoldGreedily(Region ®ion, const FrozenRewritePatternSet &patterns, GreedyRewriteConfig config=GreedyRewriteConfig(), bool *changed=nullptr)
Rewrite ops in the given region, which must be isolated from above, by repeatedly applying the highes...
Value getValueOrCreateConstantIndexOp(OpBuilder &b, Location loc, OpFoldResult ofr)
Converts an OpFoldResult to a Value.
OpFoldResult getAsOpFoldResult(Value val)
Given a value, try to extract a constant Attribute.
void bindSymbolsList(MLIRContext *ctx, MutableArrayRef< AffineExprTy > exprs)
OpRewritePattern is a wrapper around RewritePattern that allows for matching and rewriting against an...
OpRewritePattern(MLIRContext *context, PatternBenefit benefit=1, ArrayRef< StringRef > generatedNames={})
Patterns must specify the root operation name they match against, and can also specify the benefit of...
Eliminates variable at the specified position using Fourier-Motzkin variable elimination.