24#define GEN_PASS_DEF_AFFINEEXPANDINDEXOPS
25#include "mlir/Dialect/Affine/Transforms/Passes.h.inc"
44 bool knownNonNegative) {
45 if (staticBasis.empty())
49 result.reserve(staticBasis.size());
50 size_t dynamicIndex = dynamicBasis.size();
51 Value dynamicPart =
nullptr;
55 arith::IntegerOverflowFlags ovflags = arith::IntegerOverflowFlags::nsw;
57 ovflags = ovflags | arith::IntegerOverflowFlags::nuw;
58 for (
int64_t elem : llvm::reverse(staticBasis)) {
59 if (ShapedType::isDynamic(elem)) {
64 arith::MulIOp::create(rewriter, loc, dynamicPart,
65 dynamicBasis[dynamicIndex - 1], ovflags);
67 dynamicPart = dynamicBasis[dynamicIndex - 1];
73 if (dynamicPart && staticPart == 1) {
74 result.push_back(dynamicPart);
80 arith::MulIOp::create(rewriter, loc, dynamicPart, stride, ovflags);
92 if (value.
getType() == targetType)
94 return vector::BroadcastOp::create(rewriter, loc, targetType, value);
99 AffineDelinearizeIndexOp op) {
101 Value linearIdx = op.getLinearIndex();
102 unsigned numResults = op.getNumResults();
104 if (numResults == staticBasis.size())
105 staticBasis = staticBasis.drop_front();
107 if (numResults == 1) {
113 results.reserve(numResults);
121 for (
Value &stride : strides)
125 arith::ConstantOp::create(rewriter, loc, rewriter.
getZeroAttr(indexType));
128 arith::FloorDivSIOp::create(rewriter, loc, linearIdx, strides.front());
129 results.push_back(initialPart);
131 auto emitModTerm = [&](
Value stride) ->
Value {
132 Value remainder = arith::RemSIOp::create(rewriter, loc, linearIdx, stride);
133 Value remainderNegative = arith::CmpIOp::create(
134 rewriter, loc, arith::CmpIPredicate::slt, remainder, zero);
138 Value corrected = arith::AddIOp::create(rewriter, loc, remainder, stride,
139 arith::IntegerOverflowFlags::nsw);
140 Value mod = arith::SelectOp::create(rewriter, loc, remainderNegative,
141 corrected, remainder);
146 for (
size_t i = 0, e = strides.size() - 1; i < e; ++i) {
147 Value thisStride = strides[i];
148 Value nextStride = strides[i + 1];
149 Value modulus = emitModTerm(thisStride);
153 Value divided = arith::DivSIOp::create(rewriter, loc, modulus, nextStride);
154 results.push_back(divided);
157 results.push_back(emitModTerm(strides.back()));
164 AffineLinearizeIndexOp op) {
166 if (op.getMultiIndex().empty()) {
168 op, rewriter.
getZeroAttr(op.getLinearIndex().getType()));
174 Type indexType = op.getLinearIndex().getType();
175 size_t numIndexes = multiIndex.size();
177 if (numIndexes == staticBasis.size())
178 staticBasis = staticBasis.drop_front();
185 for (
Value &stride : strides)
189 scaledValues.reserve(numIndexes);
194 for (
auto [stride, idxOp] :
195 llvm::zip_equal(strides, llvm::drop_end(op.getMultiIndexMutable()))) {
196 Value scaledIdx = arith::MulIOp::create(rewriter, loc, idxOp.get(), stride,
197 arith::IntegerOverflowFlags::nsw);
199 scaledValues.emplace_back(scaledIdx, numHoistableLoops);
201 scaledValues.emplace_back(
207 llvm::stable_sort(scaledValues,
208 [&](
auto l,
auto r) {
return l.second > r.second; });
211 for (
auto [scaledValue, numHoistableLoops] : llvm::drop_begin(scaledValues)) {
212 std::ignore = numHoistableLoops;
213 result = arith::AddIOp::create(rewriter, loc,
result, scaledValue,
214 arith::IntegerOverflowFlags::nsw);
221struct LowerDelinearizeIndexOps
224 LogicalResult matchAndRewrite(AffineDelinearizeIndexOp op,
230struct LowerLinearizeIndexOps final :
OpRewritePattern<AffineLinearizeIndexOp> {
232 LogicalResult matchAndRewrite(AffineLinearizeIndexOp op,
233 PatternRewriter &rewriter)
const override {
234 return affine::lowerAffineLinearizeIndexOp(rewriter, op);
238class ExpandAffineIndexOpsPass
239 :
public affine::impl::AffineExpandIndexOpsBase<ExpandAffineIndexOpsPass> {
241 ExpandAffineIndexOpsPass() =
default;
243 void runOnOperation()
override {
245 RewritePatternSet patterns(context);
248 return signalPassFailure();
256 patterns.
insert<LowerDelinearizeIndexOps, LowerLinearizeIndexOps>(
261 return std::make_unique<ExpandAffineIndexOpsPass>();
static Value broadcastToMatchType(RewriterBase &rewriter, Location loc, Value value, Type targetType)
Broadcast a scalar value to match the given type.
TypedAttr getZeroAttr(Type type)
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
void createOrFold(SmallVectorImpl< Value > &results, Location location, Args &&...args)
Create an operation of specific op type at the current insertion point, and immediately try to fold i...
A special type of RewriterBase that coordinates the application of a rewrite pattern on the current I...
RewritePatternSet & insert(ConstructorArg &&arg, ConstructorArgs &&...args)
Add an instance of each of the pattern types 'Ts' to the pattern list with the given arguments.
MLIRContext * getContext() const
This class coordinates the application of a rewrite on a set of IR, providing a way for clients to tr...
virtual void replaceOp(Operation *op, ValueRange newValues)
Replace the results of the given (original) operation with the specified list of values (replacements...
OpTy replaceOpWithNewOp(Operation *op, Args &&...args)
Replace the results of the given (original) op with a new op that is created without verification (re...
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
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.
Specialization of arith.constant op that returns an integer of index type.
LogicalResult lowerAffineDelinearizeIndexOp(RewriterBase &rewriter, AffineDelinearizeIndexOp op)
Lowers affine.delinearize_index into a sequence of division and remainder operations.
LogicalResult lowerAffineLinearizeIndexOp(RewriterBase &rewriter, AffineLinearizeIndexOp op)
Lowers affine.linearize_index into a sequence of multiplications and additions.
std::unique_ptr< Pass > createAffineExpandIndexOpsPass()
Creates a pass to expand affine index operations into more fundamental operations (not necessarily re...
int64_t numEnclosingInvariantLoops(OpOperand &operand)
Performs explicit copying for the contiguous sequence of operations in the block iterator range [‘beg...
void populateAffineExpandIndexOpsPatterns(RewritePatternSet &patterns)
Populate patterns that expand affine index operations into more fundamental operations (not necessari...
Include the generated interface declarations.
SmallVector< int64_t > computeStrides(ArrayRef< int64_t > sizes)
LogicalResult applyPatternsGreedily(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...
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...