MLIR 22.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>(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 identityVals.push_back(
234 arith::getIdentityValue(reductionOpValue, resultType, rewriter, loc));
235 }
236 parOp = scf::ParallelOp::create(rewriter, loc, lowerBoundTuple,
237 upperBoundTuple, steps, identityVals,
238 /*bodyBuilderFn=*/nullptr);
239
240 // Copy the body of the affine.parallel op.
241 rewriter.eraseBlock(parOp.getBody());
242 rewriter.inlineRegionBefore(op.getRegion(), parOp.getRegion(),
243 parOp.getRegion().end());
244 assert(reductions.size() == affineParOpTerminator->getNumOperands() &&
245 "Unequal number of reductions and operands.");
246
247 // Emit new "scf.reduce" terminator.
248 rewriter.setInsertionPoint(affineParOpTerminator);
249 auto reduceOp = rewriter.replaceOpWithNewOp<scf::ReduceOp>(
250 affineParOpTerminator, affineParOpTerminator->getOperands());
251 for (unsigned i = 0, end = reductions.size(); i < end; i++) {
252 // For each of the reduction operations get the respective mlir::Value.
253 std::optional<arith::AtomicRMWKind> reductionOp =
254 arith::symbolizeAtomicRMWKind(
255 cast<IntegerAttr>(reductions[i]).getInt());
256 assert(reductionOp && "Reduction Operation cannot be of None Type");
257 arith::AtomicRMWKind reductionOpValue = *reductionOp;
258 rewriter.setInsertionPoint(&parOp.getBody()->back());
259 Block &reductionBody = reduceOp.getReductions()[i].front();
260 rewriter.setInsertionPointToEnd(&reductionBody);
261 Value reductionResult = arith::getReductionOp(
262 reductionOpValue, rewriter, loc, reductionBody.getArgument(0),
263 reductionBody.getArgument(1));
264 scf::ReduceReturnOp::create(rewriter, loc, reductionResult);
265 }
266 rewriter.replaceOp(op, parOp.getResults());
267 return success();
268 }
269};
270
271class AffineIfLowering : public OpRewritePattern<AffineIfOp> {
272public:
273 using OpRewritePattern<AffineIfOp>::OpRewritePattern;
274
275 LogicalResult matchAndRewrite(AffineIfOp op,
276 PatternRewriter &rewriter) const override {
277 auto loc = op.getLoc();
278
279 // Now we just have to handle the condition logic.
280 auto integerSet = op.getIntegerSet();
281 Value zeroConstant = arith::ConstantIndexOp::create(rewriter, loc, 0);
282 SmallVector<Value, 8> operands(op.getOperands());
283 auto operandsRef = llvm::ArrayRef(operands);
284
285 // Calculate cond as a conjunction without short-circuiting.
286 Value cond = nullptr;
287 for (unsigned i = 0, e = integerSet.getNumConstraints(); i < e; ++i) {
288 AffineExpr constraintExpr = integerSet.getConstraint(i);
289 bool isEquality = integerSet.isEq(i);
290
291 // Build and apply an affine expression
292 auto numDims = integerSet.getNumDims();
293 Value affResult = expandAffineExpr(rewriter, loc, constraintExpr,
294 operandsRef.take_front(numDims),
295 operandsRef.drop_front(numDims));
296 if (!affResult)
297 return failure();
298 auto pred =
299 isEquality ? arith::CmpIPredicate::eq : arith::CmpIPredicate::sge;
300 Value cmpVal =
301 arith::CmpIOp::create(rewriter, loc, pred, affResult, zeroConstant);
302 cond =
303 cond ? arith::AndIOp::create(rewriter, loc, cond, cmpVal).getResult()
304 : cmpVal;
305 }
306 cond = cond ? cond
307 : arith::ConstantIntOp::create(rewriter, loc, /*value=*/1,
308 /*width=*/1);
309
310 bool hasElseRegion = !op.getElseRegion().empty();
311 auto ifOp = scf::IfOp::create(rewriter, loc, op.getResultTypes(), cond,
312 hasElseRegion);
313 rewriter.inlineRegionBefore(op.getThenRegion(),
314 &ifOp.getThenRegion().back());
315 rewriter.eraseBlock(&ifOp.getThenRegion().back());
316 if (hasElseRegion) {
317 rewriter.inlineRegionBefore(op.getElseRegion(),
318 &ifOp.getElseRegion().back());
319 rewriter.eraseBlock(&ifOp.getElseRegion().back());
320 }
321
322 // Replace the Affine IfOp finally.
323 rewriter.replaceOp(op, ifOp.getResults());
324 return success();
325 }
326};
327
328/// Convert an "affine.apply" operation into a sequence of arithmetic
329/// operations using the StandardOps dialect.
330class AffineApplyLowering : public OpRewritePattern<AffineApplyOp> {
331public:
332 using OpRewritePattern<AffineApplyOp>::OpRewritePattern;
333
334 LogicalResult matchAndRewrite(AffineApplyOp op,
335 PatternRewriter &rewriter) const override {
336 auto maybeExpandedMap =
337 expandAffineMap(rewriter, op.getLoc(), op.getAffineMap(),
338 llvm::to_vector<8>(op.getOperands()));
339 if (!maybeExpandedMap)
340 return failure();
341 rewriter.replaceOp(op, *maybeExpandedMap);
342 return success();
343 }
344};
345
346/// Apply the affine map from an 'affine.load' operation to its operands, and
347/// feed the results to a newly created 'memref.load' operation (which replaces
348/// the original 'affine.load').
349class AffineLoadLowering : public OpRewritePattern<AffineLoadOp> {
350public:
351 using OpRewritePattern<AffineLoadOp>::OpRewritePattern;
352
353 LogicalResult matchAndRewrite(AffineLoadOp op,
354 PatternRewriter &rewriter) const override {
355 // Expand affine map from 'affineLoadOp'.
356 SmallVector<Value, 8> indices(op.getMapOperands());
357 auto resultOperands =
358 expandAffineMap(rewriter, op.getLoc(), op.getAffineMap(), indices);
359 if (!resultOperands)
360 return failure();
361
362 // Build vector.load memref[expandedMap.results].
363 rewriter.replaceOpWithNewOp<memref::LoadOp>(op, op.getMemRef(),
364 *resultOperands);
365 return success();
366 }
367};
368
369/// Apply the affine map from an 'affine.prefetch' operation to its operands,
370/// and feed the results to a newly created 'memref.prefetch' operation (which
371/// replaces the original 'affine.prefetch').
372class AffinePrefetchLowering : public OpRewritePattern<AffinePrefetchOp> {
373public:
374 using OpRewritePattern<AffinePrefetchOp>::OpRewritePattern;
375
376 LogicalResult matchAndRewrite(AffinePrefetchOp op,
377 PatternRewriter &rewriter) const override {
378 // Expand affine map from 'affinePrefetchOp'.
379 SmallVector<Value, 8> indices(op.getMapOperands());
380 auto resultOperands =
381 expandAffineMap(rewriter, op.getLoc(), op.getAffineMap(), indices);
382 if (!resultOperands)
383 return failure();
384
385 // Build memref.prefetch memref[expandedMap.results].
386 rewriter.replaceOpWithNewOp<memref::PrefetchOp>(
387 op, op.getMemref(), *resultOperands, op.getIsWrite(),
388 op.getLocalityHint(), op.getIsDataCache());
389 return success();
390 }
391};
392
393/// Apply the affine map from an 'affine.store' operation to its operands, and
394/// feed the results to a newly created 'memref.store' operation (which replaces
395/// the original 'affine.store').
396class AffineStoreLowering : public OpRewritePattern<AffineStoreOp> {
397public:
398 using OpRewritePattern<AffineStoreOp>::OpRewritePattern;
399
400 LogicalResult matchAndRewrite(AffineStoreOp op,
401 PatternRewriter &rewriter) const override {
402 // Expand affine map from 'affineStoreOp'.
403 SmallVector<Value, 8> indices(op.getMapOperands());
404 auto maybeExpandedMap =
405 expandAffineMap(rewriter, op.getLoc(), op.getAffineMap(), indices);
406 if (!maybeExpandedMap)
407 return failure();
408
409 // Build memref.store valueToStore, memref[expandedMap.results].
410 rewriter.replaceOpWithNewOp<memref::StoreOp>(
411 op, op.getValueToStore(), op.getMemRef(), *maybeExpandedMap);
412 return success();
413 }
414};
415
416/// Apply the affine maps from an 'affine.dma_start' operation to each of their
417/// respective map operands, and feed the results to a newly created
418/// 'memref.dma_start' operation (which replaces the original
419/// 'affine.dma_start').
420class AffineDmaStartLowering : public OpRewritePattern<AffineDmaStartOp> {
421public:
422 using OpRewritePattern<AffineDmaStartOp>::OpRewritePattern;
423
424 LogicalResult matchAndRewrite(AffineDmaStartOp op,
425 PatternRewriter &rewriter) const override {
426 SmallVector<Value, 8> operands(op.getOperands());
427 auto operandsRef = llvm::ArrayRef(operands);
428
429 // Expand affine map for DMA source memref.
430 auto maybeExpandedSrcMap = expandAffineMap(
431 rewriter, op.getLoc(), op.getSrcMap(),
432 operandsRef.drop_front(op.getSrcMemRefOperandIndex() + 1));
433 if (!maybeExpandedSrcMap)
434 return failure();
435 // Expand affine map for DMA destination memref.
436 auto maybeExpandedDstMap = expandAffineMap(
437 rewriter, op.getLoc(), op.getDstMap(),
438 operandsRef.drop_front(op.getDstMemRefOperandIndex() + 1));
439 if (!maybeExpandedDstMap)
440 return failure();
441 // Expand affine map for DMA tag memref.
442 auto maybeExpandedTagMap = expandAffineMap(
443 rewriter, op.getLoc(), op.getTagMap(),
444 operandsRef.drop_front(op.getTagMemRefOperandIndex() + 1));
445 if (!maybeExpandedTagMap)
446 return failure();
447
448 // Build memref.dma_start operation with affine map results.
449 rewriter.replaceOpWithNewOp<memref::DmaStartOp>(
450 op, op.getSrcMemRef(), *maybeExpandedSrcMap, op.getDstMemRef(),
451 *maybeExpandedDstMap, op.getNumElements(), op.getTagMemRef(),
452 *maybeExpandedTagMap, op.getStride(), op.getNumElementsPerStride());
453 return success();
454 }
455};
456
457/// Apply the affine map from an 'affine.dma_wait' operation tag memref,
458/// and feed the results to a newly created 'memref.dma_wait' operation (which
459/// replaces the original 'affine.dma_wait').
460class AffineDmaWaitLowering : public OpRewritePattern<AffineDmaWaitOp> {
461public:
462 using OpRewritePattern<AffineDmaWaitOp>::OpRewritePattern;
463
464 LogicalResult matchAndRewrite(AffineDmaWaitOp op,
465 PatternRewriter &rewriter) const override {
466 // Expand affine map for DMA tag memref.
467 SmallVector<Value, 8> indices(op.getTagIndices());
468 auto maybeExpandedTagMap =
469 expandAffineMap(rewriter, op.getLoc(), op.getTagMap(), indices);
470 if (!maybeExpandedTagMap)
471 return failure();
472
473 // Build memref.dma_wait operation with affine map results.
474 rewriter.replaceOpWithNewOp<memref::DmaWaitOp>(
475 op, op.getTagMemRef(), *maybeExpandedTagMap, op.getNumElements());
476 return success();
477 }
478};
479
480/// Apply the affine map from an 'affine.vector_load' operation to its operands,
481/// and feed the results to a newly created 'vector.load' operation (which
482/// replaces the original 'affine.vector_load').
483class AffineVectorLoadLowering : public OpRewritePattern<AffineVectorLoadOp> {
484public:
485 using OpRewritePattern<AffineVectorLoadOp>::OpRewritePattern;
486
487 LogicalResult matchAndRewrite(AffineVectorLoadOp op,
488 PatternRewriter &rewriter) const override {
489 // Expand affine map from 'affineVectorLoadOp'.
490 SmallVector<Value, 8> indices(op.getMapOperands());
491 auto resultOperands =
492 expandAffineMap(rewriter, op.getLoc(), op.getAffineMap(), indices);
493 if (!resultOperands)
494 return failure();
495
496 // Build vector.load memref[expandedMap.results].
497 rewriter.replaceOpWithNewOp<vector::LoadOp>(
498 op, op.getVectorType(), op.getMemRef(), *resultOperands);
499 return success();
500 }
501};
502
503/// Apply the affine map from an 'affine.vector_store' operation to its
504/// operands, and feed the results to a newly created 'vector.store' operation
505/// (which replaces the original 'affine.vector_store').
506class AffineVectorStoreLowering : public OpRewritePattern<AffineVectorStoreOp> {
507public:
508 using OpRewritePattern<AffineVectorStoreOp>::OpRewritePattern;
509
510 LogicalResult matchAndRewrite(AffineVectorStoreOp op,
511 PatternRewriter &rewriter) const override {
512 // Expand affine map from 'affineVectorStoreOp'.
513 SmallVector<Value, 8> indices(op.getMapOperands());
514 auto maybeExpandedMap =
515 expandAffineMap(rewriter, op.getLoc(), op.getAffineMap(), indices);
516 if (!maybeExpandedMap)
517 return failure();
518
519 rewriter.replaceOpWithNewOp<vector::StoreOp>(
520 op, op.getValueToStore(), op.getMemRef(), *maybeExpandedMap);
521 return success();
522 }
523};
524
525} // namespace
526
528 // clang-format off
529 patterns.add<
530 AffineApplyLowering,
531 AffineDmaStartLowering,
532 AffineDmaWaitLowering,
533 AffineLoadLowering,
534 AffineMinLowering,
535 AffineMaxLowering,
536 AffineParallelLowering,
537 AffinePrefetchLowering,
538 AffineStoreLowering,
539 AffineForLowering,
540 AffineIfLowering,
541 AffineYieldOpLowering>(patterns.getContext());
542 // clang-format on
543}
544
547 // clang-format off
548 patterns.add<
549 AffineVectorLoadLowering,
550 AffineVectorStoreLowering>(patterns.getContext());
551 // clang-format on
552}
553
554namespace {
555class LowerAffine : public impl::LowerAffinePassBase<LowerAffine> {
556 void runOnOperation() override {
562 target.addLegalDialect<arith::ArithDialect, memref::MemRefDialect,
563 scf::SCFDialect, VectorDialect>();
564 if (failed(applyPartialConversion(getOperation(), target,
565 std::move(patterns))))
566 signalPassFailure();
567 }
568};
569} // 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:129
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:207
void setInsertionPoint(Block *block, Block::iterator insertPoint)
Set the insertion point to the specified location.
Definition Builders.h:398
void setInsertionPointToEnd(Block *block)
Sets the insertion point to the end of the specified block.
Definition Builders.h:436
Location getLoc()
The source location the operation was defined or derived from.
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
AffineMap getDstMap()
Returns the affine map used to access the destination memref.
Definition AffineOps.h:191
unsigned getSrcMemRefOperandIndex()
Returns the operand index of the source memref.
Definition AffineOps.h:133
unsigned getTagMemRefOperandIndex()
Returns the operand index of the tag memref.
Definition AffineOps.h:205
AffineMap getSrcMap()
Returns the affine map used to access the source memref.
Definition AffineOps.h:148
AffineMap getTagMap()
Returns the affine map used to access the tag memref.
Definition AffineOps.h:224
unsigned getDstMemRefOperandIndex()
Returns the operand index of the destination memref.
Definition AffineOps.h:167
Value getSrcMemRef()
Returns the source MemRefType for this DMA operation.
Definition AffineOps.h:136
Value getTagMemRef()
Returns the Tag MemRef associated with the DMA operation being waited on.
Definition AffineOps.h:347
AffineMap getTagMap()
Returns the affine map used to access the tag memref.
Definition AffineOps.h:354
operand_range getTagIndices()
Returns the tag memref index for this DMA operation.
Definition AffineOps.h:361
static ConstantIndexOp create(OpBuilder &builder, Location location, int64_t value)
Definition ArithOps.cpp:359
static ConstantIntOp create(OpBuilder &builder, Location location, int64_t value, unsigned width)
Definition ArithOps.cpp:258
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...
const FrozenRewritePatternSet & patterns
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...