MLIR 23.0.0git
AffineToStandard.cpp
Go to the documentation of this file.
1//===- AffineToStandard.cpp - Lower affine constructs to primitives -------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file lowers affine constructs (If and For statements, AffineApply
10// operations) within a function into their standard If and For equivalent ops.
11//
12//===----------------------------------------------------------------------===//
13
15
22#include "mlir/IR/IntegerSet.h"
23#include "mlir/IR/MLIRContext.h"
26
27namespace mlir {
28#define GEN_PASS_DEF_LOWERAFFINEPASS
29#include "mlir/Conversion/Passes.h.inc"
30} // namespace mlir
31
32using namespace mlir;
33using namespace mlir::affine;
34using namespace mlir::vector;
35
36/// Given a range of values, emit the code that reduces them with "min" or "max"
37/// depending on the provided comparison predicate, sgt for max and slt for min.
38///
39/// Multiple values are scanned in a linear sequence. This creates a data
40/// dependences that wouldn't exist in a tree reduction, but is easier to
41/// recognize as a reduction by the subsequent passes.
43 arith::CmpIPredicate predicate,
44 ValueRange values, OpBuilder &builder) {
45 assert(!values.empty() && "empty min/max chain");
46 assert(predicate == arith::CmpIPredicate::sgt ||
47 predicate == arith::CmpIPredicate::slt);
48
49 auto valueIt = values.begin();
50 Value value = *valueIt++;
51 for (; valueIt != values.end(); ++valueIt) {
52 if (predicate == arith::CmpIPredicate::sgt)
53 value = arith::MaxSIOp::create(builder, loc, value, *valueIt);
54 else
55 value = arith::MinSIOp::create(builder, loc, value, *valueIt);
56 }
57
58 return value;
59}
60
61/// Emit instructions that correspond to computing the maximum value among the
62/// values of a (potentially) multi-output affine map applied to `operands`.
64 ValueRange operands) {
65 if (auto values = expandAffineMap(builder, loc, map, operands))
66 return buildMinMaxReductionSeq(loc, arith::CmpIPredicate::sgt, *values,
67 builder);
68 return nullptr;
69}
70
71/// Emit instructions that correspond to computing the minimum value among the
72/// values of a (potentially) multi-output affine map applied to `operands`.
74 ValueRange operands) {
75 if (auto values = expandAffineMap(builder, loc, map, operands))
76 return buildMinMaxReductionSeq(loc, arith::CmpIPredicate::slt, *values,
77 builder);
78 return nullptr;
79}
80
81/// Emit instructions that correspond to the affine map in the upper bound
82/// applied to the respective operands, and compute the minimum value across
83/// the results.
84Value mlir::lowerAffineUpperBound(AffineForOp op, OpBuilder &builder) {
85 return lowerAffineMapMin(builder, op.getLoc(), op.getUpperBoundMap(),
86 op.getUpperBoundOperands());
87}
88
89/// Emit instructions that correspond to the affine map in the lower bound
90/// applied to the respective operands, and compute the maximum value across
91/// the results.
92Value mlir::lowerAffineLowerBound(AffineForOp op, OpBuilder &builder) {
93 return lowerAffineMapMax(builder, op.getLoc(), op.getLowerBoundMap(),
94 op.getLowerBoundOperands());
95}
96
97namespace {
98class AffineMinLowering : public OpRewritePattern<AffineMinOp> {
99public:
100 using OpRewritePattern<AffineMinOp>::OpRewritePattern;
101
102 LogicalResult matchAndRewrite(AffineMinOp op,
103 PatternRewriter &rewriter) const override {
104 Value reduced =
105 lowerAffineMapMin(rewriter, op.getLoc(), op.getMap(), op.getOperands());
106 if (!reduced)
107 return failure();
108
109 rewriter.replaceOp(op, reduced);
110 return success();
111 }
112};
113
114class AffineMaxLowering : public OpRewritePattern<AffineMaxOp> {
115public:
116 using OpRewritePattern<AffineMaxOp>::OpRewritePattern;
117
118 LogicalResult matchAndRewrite(AffineMaxOp op,
119 PatternRewriter &rewriter) const override {
120 Value reduced =
121 lowerAffineMapMax(rewriter, op.getLoc(), op.getMap(), op.getOperands());
122 if (!reduced)
123 return failure();
124
125 rewriter.replaceOp(op, reduced);
126 return success();
127 }
128};
129
130/// Affine yields ops are removed.
131class AffineYieldOpLowering : public OpRewritePattern<AffineYieldOp> {
132public:
133 using OpRewritePattern<AffineYieldOp>::OpRewritePattern;
134
135 LogicalResult matchAndRewrite(AffineYieldOp op,
136 PatternRewriter &rewriter) const override {
137 if (isa<scf::ParallelOp, AffineParallelOp>(op->getParentOp())) {
138 // Terminator is rewritten as part of the "affine.parallel" lowering
139 // pattern.
140 return failure();
141 }
142 rewriter.replaceOpWithNewOp<scf::YieldOp>(op, op.getOperands());
143 return success();
144 }
145};
146
147class AffineForLowering : public OpRewritePattern<AffineForOp> {
148public:
149 using OpRewritePattern<AffineForOp>::OpRewritePattern;
150
151 LogicalResult matchAndRewrite(AffineForOp op,
152 PatternRewriter &rewriter) const override {
153 Location loc = op.getLoc();
154 Value lowerBound = lowerAffineLowerBound(op, rewriter);
155 Value upperBound = lowerAffineUpperBound(op, rewriter);
156 Value step =
157 arith::ConstantIndexOp::create(rewriter, loc, op.getStepAsInt());
158 auto scfForOp = scf::ForOp::create(rewriter, loc, lowerBound, upperBound,
159 step, op.getInits());
160 rewriter.eraseBlock(scfForOp.getBody());
161 rewriter.inlineRegionBefore(op.getRegion(), scfForOp.getRegion(),
162 scfForOp.getRegion().end());
163 rewriter.replaceOp(op, scfForOp.getResults());
164 return success();
165 }
166};
167
168/// Convert an `affine.parallel` (loop nest) operation into a `scf.parallel`
169/// operation.
170class AffineParallelLowering : public OpRewritePattern<AffineParallelOp> {
171public:
172 using OpRewritePattern<AffineParallelOp>::OpRewritePattern;
173
174 LogicalResult matchAndRewrite(AffineParallelOp op,
175 PatternRewriter &rewriter) const override {
176 Location loc = op.getLoc();
177 SmallVector<Value, 8> steps;
178 SmallVector<Value, 8> upperBoundTuple;
179 SmallVector<Value, 8> lowerBoundTuple;
180 SmallVector<Value, 8> identityVals;
181 // Emit IR computing the lower and upper bound by expanding the map
182 // expression.
183 lowerBoundTuple.reserve(op.getNumDims());
184 upperBoundTuple.reserve(op.getNumDims());
185 for (unsigned i = 0, e = op.getNumDims(); i < e; ++i) {
186 Value lower = lowerAffineMapMax(rewriter, loc, op.getLowerBoundMap(i),
187 op.getLowerBoundsOperands());
188 if (!lower)
189 return rewriter.notifyMatchFailure(op, "couldn't convert lower bounds");
190 lowerBoundTuple.push_back(lower);
191
192 Value upper = lowerAffineMapMin(rewriter, loc, op.getUpperBoundMap(i),
193 op.getUpperBoundsOperands());
194 if (!upper)
195 return rewriter.notifyMatchFailure(op, "couldn't convert upper bounds");
196 upperBoundTuple.push_back(upper);
197 }
198 steps.reserve(op.getSteps().size());
199 for (int64_t step : op.getSteps())
200 steps.push_back(arith::ConstantIndexOp::create(rewriter, loc, step));
201
202 // Get the terminator op.
203 auto affineParOpTerminator =
204 cast<AffineYieldOp>(op.getBody()->getTerminator());
205 scf::ParallelOp parOp;
206 if (op.getResults().empty()) {
207 // Case with no reduction operations/return values.
208 parOp = scf::ParallelOp::create(rewriter, loc, lowerBoundTuple,
209 upperBoundTuple, steps,
210 /*bodyBuilderFn=*/nullptr);
211 rewriter.eraseBlock(parOp.getBody());
212 rewriter.inlineRegionBefore(op.getRegion(), parOp.getRegion(),
213 parOp.getRegion().end());
214 rewriter.replaceOp(op, parOp.getResults());
215 rewriter.setInsertionPoint(affineParOpTerminator);
216 rewriter.replaceOpWithNewOp<scf::ReduceOp>(affineParOpTerminator);
217 return success();
218 }
219 // Case with affine.parallel with reduction operations/return values.
220 // scf.parallel handles the reduction operation differently unlike
221 // affine.parallel.
222 ArrayRef<Attribute> reductions = op.getReductions().getValue();
223 for (auto pair : llvm::zip(reductions, op.getResultTypes())) {
224 // For each of the reduction operations get the identity values for
225 // initialization of the result values.
226 Attribute reduction = std::get<0>(pair);
227 Type resultType = std::get<1>(pair);
228 std::optional<arith::AtomicRMWKind> reductionOp =
229 arith::symbolizeAtomicRMWKind(
230 static_cast<uint64_t>(cast<IntegerAttr>(reduction).getInt()));
231 assert(reductionOp && "Reduction operation cannot be of None Type");
232 arith::AtomicRMWKind reductionOpValue = *reductionOp;
233 Value identityVal =
234 arith::getIdentityValue(reductionOpValue, resultType, rewriter, loc);
235 if (!identityVal)
236 return rewriter.notifyMatchFailure(
237 op, "unsupported reduction kind for identity value");
238 identityVals.push_back(identityVal);
239 }
240 parOp = scf::ParallelOp::create(rewriter, loc, lowerBoundTuple,
241 upperBoundTuple, steps, identityVals,
242 /*bodyBuilderFn=*/nullptr);
243
244 // Copy the body of the affine.parallel op.
245 rewriter.eraseBlock(parOp.getBody());
246 rewriter.inlineRegionBefore(op.getRegion(), parOp.getRegion(),
247 parOp.getRegion().end());
248 assert(reductions.size() == affineParOpTerminator->getNumOperands() &&
249 "Unequal number of reductions and operands.");
250
251 // Emit new "scf.reduce" terminator.
252 rewriter.setInsertionPoint(affineParOpTerminator);
253 auto reduceOp = rewriter.replaceOpWithNewOp<scf::ReduceOp>(
254 affineParOpTerminator, affineParOpTerminator->getOperands());
255 for (unsigned i = 0, end = reductions.size(); i < end; i++) {
256 // For each of the reduction operations get the respective mlir::Value.
257 std::optional<arith::AtomicRMWKind> reductionOp =
258 arith::symbolizeAtomicRMWKind(
259 cast<IntegerAttr>(reductions[i]).getInt());
260 assert(reductionOp && "Reduction Operation cannot be of None Type");
261 arith::AtomicRMWKind reductionOpValue = *reductionOp;
262 rewriter.setInsertionPoint(&parOp.getBody()->back());
263 Block &reductionBody = reduceOp.getReductions()[i].front();
264 rewriter.setInsertionPointToEnd(&reductionBody);
265 Value reductionResult = arith::getReductionOp(
266 reductionOpValue, rewriter, loc, reductionBody.getArgument(0),
267 reductionBody.getArgument(1));
268 scf::ReduceReturnOp::create(rewriter, loc, reductionResult);
269 }
270 rewriter.replaceOp(op, parOp.getResults());
271 return success();
272 }
273};
274
275class AffineIfLowering : public OpRewritePattern<AffineIfOp> {
276public:
277 using OpRewritePattern<AffineIfOp>::OpRewritePattern;
278
279 LogicalResult matchAndRewrite(AffineIfOp op,
280 PatternRewriter &rewriter) const override {
281 auto loc = op.getLoc();
282
283 // Now we just have to handle the condition logic.
284 auto integerSet = op.getIntegerSet();
285 Value zeroConstant = arith::ConstantIndexOp::create(rewriter, loc, 0);
286 SmallVector<Value, 8> operands(op.getOperands());
287 auto operandsRef = llvm::ArrayRef(operands);
288
289 // Calculate cond as a conjunction without short-circuiting.
290 Value cond = nullptr;
291 for (unsigned i = 0, e = integerSet.getNumConstraints(); i < e; ++i) {
292 AffineExpr constraintExpr = integerSet.getConstraint(i);
293 bool isEquality = integerSet.isEq(i);
294
295 // Build and apply an affine expression
296 auto numDims = integerSet.getNumDims();
297 Value affResult = expandAffineExpr(rewriter, loc, constraintExpr,
298 operandsRef.take_front(numDims),
299 operandsRef.drop_front(numDims));
300 if (!affResult)
301 return failure();
302 auto pred =
303 isEquality ? arith::CmpIPredicate::eq : arith::CmpIPredicate::sge;
304 Value cmpVal =
305 arith::CmpIOp::create(rewriter, loc, pred, affResult, zeroConstant);
306 cond =
307 cond ? arith::AndIOp::create(rewriter, loc, cond, cmpVal).getResult()
308 : cmpVal;
309 }
310 cond = cond ? cond
311 : arith::ConstantIntOp::create(rewriter, loc, /*value=*/1,
312 /*width=*/1);
313
314 bool hasElseRegion = !op.getElseRegion().empty();
315 auto ifOp = scf::IfOp::create(rewriter, loc, op.getResultTypes(), cond,
316 hasElseRegion);
317 rewriter.inlineRegionBefore(op.getThenRegion(),
318 &ifOp.getThenRegion().back());
319 rewriter.eraseBlock(&ifOp.getThenRegion().back());
320 if (hasElseRegion) {
321 rewriter.inlineRegionBefore(op.getElseRegion(),
322 &ifOp.getElseRegion().back());
323 rewriter.eraseBlock(&ifOp.getElseRegion().back());
324 }
325
326 // Replace the Affine IfOp finally.
327 rewriter.replaceOp(op, ifOp.getResults());
328 return success();
329 }
330};
331
332/// Convert an "affine.apply" operation into a sequence of arithmetic
333/// operations using the StandardOps dialect.
334class AffineApplyLowering : public OpRewritePattern<AffineApplyOp> {
335public:
336 using OpRewritePattern<AffineApplyOp>::OpRewritePattern;
337
338 LogicalResult matchAndRewrite(AffineApplyOp op,
339 PatternRewriter &rewriter) const override {
340 auto maybeExpandedMap =
341 expandAffineMap(rewriter, op.getLoc(), op.getAffineMap(),
342 llvm::to_vector<8>(op.getOperands()));
343 if (!maybeExpandedMap)
344 return failure();
345 rewriter.replaceOp(op, *maybeExpandedMap);
346 return success();
347 }
348};
349
350/// Apply the affine map from an 'affine.load' operation to its operands, and
351/// feed the results to a newly created 'memref.load' operation (which replaces
352/// the original 'affine.load').
353class AffineLoadLowering : public OpRewritePattern<AffineLoadOp> {
354public:
355 using OpRewritePattern<AffineLoadOp>::OpRewritePattern;
356
357 LogicalResult matchAndRewrite(AffineLoadOp op,
358 PatternRewriter &rewriter) const override {
359 // Expand affine map from 'affineLoadOp'.
360 SmallVector<Value, 8> indices(op.getMapOperands());
361 auto resultOperands =
362 expandAffineMap(rewriter, op.getLoc(), op.getAffineMap(), indices);
363 if (!resultOperands)
364 return failure();
365
366 // Build vector.load memref[expandedMap.results].
367 rewriter.replaceOpWithNewOp<memref::LoadOp>(op, op.getMemRef(),
368 *resultOperands);
369 return success();
370 }
371};
372
373/// Apply the affine map from an 'affine.prefetch' operation to its operands,
374/// and feed the results to a newly created 'memref.prefetch' operation (which
375/// replaces the original 'affine.prefetch').
376class AffinePrefetchLowering : public OpRewritePattern<AffinePrefetchOp> {
377public:
378 using OpRewritePattern<AffinePrefetchOp>::OpRewritePattern;
379
380 LogicalResult matchAndRewrite(AffinePrefetchOp op,
381 PatternRewriter &rewriter) const override {
382 // Expand affine map from 'affinePrefetchOp'.
383 SmallVector<Value, 8> indices(op.getMapOperands());
384 auto resultOperands =
385 expandAffineMap(rewriter, op.getLoc(), op.getAffineMap(), indices);
386 if (!resultOperands)
387 return failure();
388
389 // Build memref.prefetch memref[expandedMap.results].
390 rewriter.replaceOpWithNewOp<memref::PrefetchOp>(
391 op, op.getMemref(), *resultOperands, op.getIsWrite(),
392 op.getLocalityHint(), op.getIsDataCache());
393 return success();
394 }
395};
396
397/// Apply the affine map from an 'affine.store' operation to its operands, and
398/// feed the results to a newly created 'memref.store' operation (which replaces
399/// the original 'affine.store').
400class AffineStoreLowering : public OpRewritePattern<AffineStoreOp> {
401public:
402 using OpRewritePattern<AffineStoreOp>::OpRewritePattern;
403
404 LogicalResult matchAndRewrite(AffineStoreOp op,
405 PatternRewriter &rewriter) const override {
406 // Expand affine map from 'affineStoreOp'.
407 SmallVector<Value, 8> indices(op.getMapOperands());
408 auto maybeExpandedMap =
409 expandAffineMap(rewriter, op.getLoc(), op.getAffineMap(), indices);
410 if (!maybeExpandedMap)
411 return failure();
412
413 // Build memref.store valueToStore, memref[expandedMap.results].
414 rewriter.replaceOpWithNewOp<memref::StoreOp>(
415 op, op.getValueToStore(), op.getMemRef(), *maybeExpandedMap);
416 return success();
417 }
418};
419
420/// Apply the affine maps from an 'affine.dma_start' operation to each of their
421/// respective map operands, and feed the results to a newly created
422/// 'memref.dma_start' operation (which replaces the original
423/// 'affine.dma_start').
424class AffineDmaStartLowering : public OpRewritePattern<AffineDmaStartOp> {
425public:
426 using OpRewritePattern<AffineDmaStartOp>::OpRewritePattern;
427
428 LogicalResult matchAndRewrite(AffineDmaStartOp op,
429 PatternRewriter &rewriter) const override {
430 SmallVector<Value, 8> operands(op.getOperands());
431 auto operandsRef = llvm::ArrayRef(operands);
432
433 // Expand affine map for DMA source memref.
434 auto maybeExpandedSrcMap = expandAffineMap(
435 rewriter, op.getLoc(), op.getSrcMap(),
436 operandsRef.drop_front(op.getSrcMemRefOperandIndex() + 1));
437 if (!maybeExpandedSrcMap)
438 return failure();
439 // Expand affine map for DMA destination memref.
440 auto maybeExpandedDstMap = expandAffineMap(
441 rewriter, op.getLoc(), op.getDstMap(),
442 operandsRef.drop_front(op.getDstMemRefOperandIndex() + 1));
443 if (!maybeExpandedDstMap)
444 return failure();
445 // Expand affine map for DMA tag memref.
446 auto maybeExpandedTagMap = expandAffineMap(
447 rewriter, op.getLoc(), op.getTagMap(),
448 operandsRef.drop_front(op.getTagMemRefOperandIndex() + 1));
449 if (!maybeExpandedTagMap)
450 return failure();
451
452 // Build memref.dma_start operation with affine map results.
453 rewriter.replaceOpWithNewOp<memref::DmaStartOp>(
454 op, op.getSrcMemRef(), *maybeExpandedSrcMap, op.getDstMemRef(),
455 *maybeExpandedDstMap, op.getNumElements(), op.getTagMemRef(),
456 *maybeExpandedTagMap, op.getStride(), op.getNumElementsPerStride());
457 return success();
458 }
459};
460
461/// Apply the affine map from an 'affine.dma_wait' operation tag memref,
462/// and feed the results to a newly created 'memref.dma_wait' operation (which
463/// replaces the original 'affine.dma_wait').
464class AffineDmaWaitLowering : public OpRewritePattern<AffineDmaWaitOp> {
465public:
466 using OpRewritePattern<AffineDmaWaitOp>::OpRewritePattern;
467
468 LogicalResult matchAndRewrite(AffineDmaWaitOp op,
469 PatternRewriter &rewriter) const override {
470 // Expand affine map for DMA tag memref.
471 SmallVector<Value, 8> indices(op.getTagIndices());
472 auto maybeExpandedTagMap =
473 expandAffineMap(rewriter, op.getLoc(), op.getTagMap(), indices);
474 if (!maybeExpandedTagMap)
475 return failure();
476
477 // Build memref.dma_wait operation with affine map results.
478 rewriter.replaceOpWithNewOp<memref::DmaWaitOp>(
479 op, op.getTagMemRef(), *maybeExpandedTagMap, op.getNumElements());
480 return success();
481 }
482};
483
484/// Apply the affine map from an 'affine.vector_load' operation to its operands,
485/// and feed the results to a newly created 'vector.load' operation (which
486/// replaces the original 'affine.vector_load').
487class AffineVectorLoadLowering : public OpRewritePattern<AffineVectorLoadOp> {
488public:
489 using OpRewritePattern<AffineVectorLoadOp>::OpRewritePattern;
490
491 LogicalResult matchAndRewrite(AffineVectorLoadOp op,
492 PatternRewriter &rewriter) const override {
493 // Expand affine map from 'affineVectorLoadOp'.
494 SmallVector<Value, 8> indices(op.getMapOperands());
495 auto resultOperands =
496 expandAffineMap(rewriter, op.getLoc(), op.getAffineMap(), indices);
497 if (!resultOperands)
498 return failure();
499
500 // Build vector.load memref[expandedMap.results].
501 rewriter.replaceOpWithNewOp<vector::LoadOp>(
502 op, op.getVectorType(), op.getMemRef(), *resultOperands);
503 return success();
504 }
505};
506
507/// Apply the affine map from an 'affine.vector_store' operation to its
508/// operands, and feed the results to a newly created 'vector.store' operation
509/// (which replaces the original 'affine.vector_store').
510class AffineVectorStoreLowering : public OpRewritePattern<AffineVectorStoreOp> {
511public:
512 using OpRewritePattern<AffineVectorStoreOp>::OpRewritePattern;
513
514 LogicalResult matchAndRewrite(AffineVectorStoreOp op,
515 PatternRewriter &rewriter) const override {
516 // Expand affine map from 'affineVectorStoreOp'.
517 SmallVector<Value, 8> indices(op.getMapOperands());
518 auto maybeExpandedMap =
519 expandAffineMap(rewriter, op.getLoc(), op.getAffineMap(), indices);
520 if (!maybeExpandedMap)
521 return failure();
522
523 rewriter.replaceOpWithNewOp<vector::StoreOp>(
524 op, op.getValueToStore(), op.getMemRef(), *maybeExpandedMap);
525 return success();
526 }
527};
528
529} // namespace
530
532 // clang-format off
533 patterns.add<
534 AffineApplyLowering,
535 AffineDmaStartLowering,
536 AffineDmaWaitLowering,
537 AffineLoadLowering,
538 AffineMinLowering,
539 AffineMaxLowering,
540 AffineParallelLowering,
541 AffinePrefetchLowering,
542 AffineStoreLowering,
543 AffineForLowering,
544 AffineIfLowering,
545 AffineYieldOpLowering>(patterns.getContext());
546 // clang-format on
547}
548
550 RewritePatternSet &patterns) {
551 // clang-format off
552 patterns.add<
553 AffineVectorLoadLowering,
554 AffineVectorStoreLowering>(patterns.getContext());
555 // clang-format on
556}
557
558namespace {
559class LowerAffine : public impl::LowerAffinePassBase<LowerAffine> {
560 void runOnOperation() override {
561 RewritePatternSet patterns(&getContext());
566 target.addLegalDialect<arith::ArithDialect, memref::MemRefDialect,
567 scf::SCFDialect, VectorDialect>();
568 if (failed(applyPartialConversion(getOperation(), target,
569 std::move(patterns))))
570 signalPassFailure();
571 }
572};
573} // namespace
return success()
static Value lowerAffineMapMax(OpBuilder &builder, Location loc, AffineMap map, ValueRange operands)
Emit instructions that correspond to computing the maximum value among the values of a (potentially) ...
static Value buildMinMaxReductionSeq(Location loc, arith::CmpIPredicate predicate, ValueRange values, OpBuilder &builder)
Given a range of values, emit the code that reduces them with "min" or "max" depending on the provide...
static Value lowerAffineMapMin(OpBuilder &builder, Location loc, AffineMap map, ValueRange operands)
Emit instructions that correspond to computing the minimum value among the values of a (potentially) ...
b getContext())
A multi-dimensional affine map Affine map's are immutable like Type's, and they are uniqued.
Definition AffineMap.h:46
BlockArgument getArgument(unsigned i)
Definition Block.h:139
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition Location.h:76
This class helps build Operations.
Definition Builders.h:209
void setInsertionPoint(Block *block, Block::iterator insertPoint)
Set the insertion point to the specified location.
Definition Builders.h:400
void setInsertionPointToEnd(Block *block)
Sets the insertion point to the end of the specified block.
Definition Builders.h:438
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.
virtual void eraseBlock(Block *block)
This method erases all operations in a block.
virtual void replaceOp(Operation *op, ValueRange newValues)
Replace the results of the given (original) operation with the specified list of values (replacements...
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,...
void inlineRegionBefore(Region &region, Region &parent, Region::iterator before)
Move the blocks that belong to "region" before the given position in another region "parent".
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.
Definition ValueRange.h:387
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition Value.h:96
static ConstantIndexOp create(OpBuilder &builder, Location location, int64_t value)
Definition ArithOps.cpp:363
static ConstantIntOp create(OpBuilder &builder, Location location, int64_t value, unsigned width)
Definition ArithOps.cpp:262
void populateAffineExpandIndexOpsPatterns(RewritePatternSet &patterns)
Populate patterns that expand affine index operations into more fundamental operations (not necessari...
Include the generated interface declarations.
Value lowerAffineUpperBound(affine::AffineForOp op, OpBuilder &builder)
Emit code that computes the upper bound of the given affine loop using standard arithmetic operations...
void populateAffineToVectorConversionPatterns(RewritePatternSet &patterns)
Collect a set of patterns to convert vector-related Affine ops to the Vector dialect.
void populateAffineToStdConversionPatterns(RewritePatternSet &patterns)
Collect a set of patterns to convert from the Affine dialect to the Standard dialect,...
Value lowerAffineLowerBound(affine::AffineForOp op, OpBuilder &builder)
Emit code that computes the lower bound of the given affine loop using standard arithmetic operations...
OpRewritePattern is a wrapper around RewritePattern that allows for matching and rewriting against an...