MLIR  16.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"
25 #include "mlir/Transforms/Passes.h"
26 
27 namespace mlir {
28 #define GEN_PASS_DEF_CONVERTAFFINETOSTANDARD
29 #include "mlir/Conversion/Passes.h.inc"
30 } // namespace mlir
31 
32 using namespace mlir;
33 using namespace mlir::vector;
34 
35 /// Given a range of values, emit the code that reduces them with "min" or "max"
36 /// depending on the provided comparison predicate. The predicate defines which
37 /// comparison to perform, "lt" for "min", "gt" for "max" and is used for the
38 /// `cmpi` operation followed by the `select` operation:
39 ///
40 /// %cond = arith.cmpi "predicate" %v0, %v1
41 /// %result = select %cond, %v0, %v1
42 ///
43 /// Multiple values are scanned in a linear sequence. This creates a data
44 /// dependences that wouldn't exist in a tree reduction, but is easier to
45 /// recognize as a reduction by the subsequent passes.
47  arith::CmpIPredicate predicate,
48  ValueRange values, OpBuilder &builder) {
49  assert(!values.empty() && "empty min/max chain");
50 
51  auto valueIt = values.begin();
52  Value value = *valueIt++;
53  for (; valueIt != values.end(); ++valueIt) {
54  auto cmpOp = builder.create<arith::CmpIOp>(loc, predicate, value, *valueIt);
55  value = builder.create<arith::SelectOp>(loc, cmpOp.getResult(), value,
56  *valueIt);
57  }
58 
59  return value;
60 }
61 
62 /// Emit instructions that correspond to computing the maximum value among the
63 /// values of a (potentially) multi-output affine map applied to `operands`.
65  ValueRange operands) {
66  if (auto values = expandAffineMap(builder, loc, map, operands))
67  return buildMinMaxReductionSeq(loc, arith::CmpIPredicate::sgt, *values,
68  builder);
69  return nullptr;
70 }
71 
72 /// Emit instructions that correspond to computing the minimum value among the
73 /// values of a (potentially) multi-output affine map applied to `operands`.
75  ValueRange operands) {
76  if (auto values = expandAffineMap(builder, loc, map, operands))
77  return buildMinMaxReductionSeq(loc, arith::CmpIPredicate::slt, *values,
78  builder);
79  return nullptr;
80 }
81 
82 /// Emit instructions that correspond to the affine map in the upper bound
83 /// applied to the respective operands, and compute the minimum value across
84 /// the results.
85 Value mlir::lowerAffineUpperBound(AffineForOp op, OpBuilder &builder) {
86  return lowerAffineMapMin(builder, op.getLoc(), op.getUpperBoundMap(),
87  op.getUpperBoundOperands());
88 }
89 
90 /// Emit instructions that correspond to the affine map in the lower bound
91 /// applied to the respective operands, and compute the maximum value across
92 /// the results.
93 Value mlir::lowerAffineLowerBound(AffineForOp op, OpBuilder &builder) {
94  return lowerAffineMapMax(builder, op.getLoc(), op.getLowerBoundMap(),
95  op.getLowerBoundOperands());
96 }
97 
98 namespace {
99 class AffineMinLowering : public OpRewritePattern<AffineMinOp> {
100 public:
102 
103  LogicalResult matchAndRewrite(AffineMinOp op,
104  PatternRewriter &rewriter) const override {
105  Value reduced =
106  lowerAffineMapMin(rewriter, op.getLoc(), op.getMap(), op.getOperands());
107  if (!reduced)
108  return failure();
109 
110  rewriter.replaceOp(op, reduced);
111  return success();
112  }
113 };
114 
115 class AffineMaxLowering : public OpRewritePattern<AffineMaxOp> {
116 public:
118 
119  LogicalResult matchAndRewrite(AffineMaxOp op,
120  PatternRewriter &rewriter) const override {
121  Value reduced =
122  lowerAffineMapMax(rewriter, op.getLoc(), op.getMap(), op.getOperands());
123  if (!reduced)
124  return failure();
125 
126  rewriter.replaceOp(op, reduced);
127  return success();
128  }
129 };
130 
131 /// Affine yields ops are removed.
132 class AffineYieldOpLowering : public OpRewritePattern<AffineYieldOp> {
133 public:
135 
136  LogicalResult matchAndRewrite(AffineYieldOp op,
137  PatternRewriter &rewriter) const override {
138  if (isa<scf::ParallelOp>(op->getParentOp())) {
139  // scf.parallel does not yield any values via its terminator scf.yield but
140  // models reductions differently using additional ops in its region.
141  rewriter.replaceOpWithNewOp<scf::YieldOp>(op);
142  return success();
143  }
144  rewriter.replaceOpWithNewOp<scf::YieldOp>(op, op.getOperands());
145  return success();
146  }
147 };
148 
149 class AffineForLowering : public OpRewritePattern<AffineForOp> {
150 public:
152 
153  LogicalResult matchAndRewrite(AffineForOp op,
154  PatternRewriter &rewriter) const override {
155  Location loc = op.getLoc();
156  Value lowerBound = lowerAffineLowerBound(op, rewriter);
157  Value upperBound = lowerAffineUpperBound(op, rewriter);
158  Value step = rewriter.create<arith::ConstantIndexOp>(loc, op.getStep());
159  auto scfForOp = rewriter.create<scf::ForOp>(loc, lowerBound, upperBound,
160  step, op.getIterOperands());
161  rewriter.eraseBlock(scfForOp.getBody());
162  rewriter.inlineRegionBefore(op.getRegion(), scfForOp.getRegion(),
163  scfForOp.getRegion().end());
164  rewriter.replaceOp(op, scfForOp.getResults());
165  return success();
166  }
167 };
168 
169 /// Convert an `affine.parallel` (loop nest) operation into a `scf.parallel`
170 /// operation.
171 class AffineParallelLowering : public OpRewritePattern<AffineParallelOp> {
172 public:
174 
175  LogicalResult matchAndRewrite(AffineParallelOp op,
176  PatternRewriter &rewriter) const override {
177  Location loc = op.getLoc();
178  SmallVector<Value, 8> steps;
179  SmallVector<Value, 8> upperBoundTuple;
180  SmallVector<Value, 8> lowerBoundTuple;
181  SmallVector<Value, 8> identityVals;
182  // Emit IR computing the lower and upper bound by expanding the map
183  // expression.
184  lowerBoundTuple.reserve(op.getNumDims());
185  upperBoundTuple.reserve(op.getNumDims());
186  for (unsigned i = 0, e = op.getNumDims(); i < e; ++i) {
187  Value lower = lowerAffineMapMax(rewriter, loc, op.getLowerBoundMap(i),
188  op.getLowerBoundsOperands());
189  if (!lower)
190  return rewriter.notifyMatchFailure(op, "couldn't convert lower bounds");
191  lowerBoundTuple.push_back(lower);
192 
193  Value upper = lowerAffineMapMin(rewriter, loc, op.getUpperBoundMap(i),
194  op.getUpperBoundsOperands());
195  if (!upper)
196  return rewriter.notifyMatchFailure(op, "couldn't convert upper bounds");
197  upperBoundTuple.push_back(upper);
198  }
199  steps.reserve(op.getSteps().size());
200  for (int64_t step : op.getSteps())
201  steps.push_back(rewriter.create<arith::ConstantIndexOp>(loc, step));
202 
203  // Get the terminator op.
204  Operation *affineParOpTerminator = op.getBody()->getTerminator();
205  scf::ParallelOp parOp;
206  if (op.getResults().empty()) {
207  // Case with no reduction operations/return values.
208  parOp = rewriter.create<scf::ParallelOp>(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  return success();
216  }
217  // Case with affine.parallel with reduction operations/return values.
218  // scf.parallel handles the reduction operation differently unlike
219  // affine.parallel.
220  ArrayRef<Attribute> reductions = op.getReductions().getValue();
221  for (auto pair : llvm::zip(reductions, op.getResultTypes())) {
222  // For each of the reduction operations get the identity values for
223  // initialization of the result values.
224  Attribute reduction = std::get<0>(pair);
225  Type resultType = std::get<1>(pair);
226  Optional<arith::AtomicRMWKind> reductionOp =
227  arith::symbolizeAtomicRMWKind(
228  static_cast<uint64_t>(reduction.cast<IntegerAttr>().getInt()));
229  assert(reductionOp && "Reduction operation cannot be of None Type");
230  arith::AtomicRMWKind reductionOpValue = *reductionOp;
231  identityVals.push_back(
232  arith::getIdentityValue(reductionOpValue, resultType, rewriter, loc));
233  }
234  parOp = rewriter.create<scf::ParallelOp>(
235  loc, lowerBoundTuple, upperBoundTuple, steps, identityVals,
236  /*bodyBuilderFn=*/nullptr);
237 
238  // Copy the body of the affine.parallel op.
239  rewriter.eraseBlock(parOp.getBody());
240  rewriter.inlineRegionBefore(op.getRegion(), parOp.getRegion(),
241  parOp.getRegion().end());
242  assert(reductions.size() == affineParOpTerminator->getNumOperands() &&
243  "Unequal number of reductions and operands.");
244  for (unsigned i = 0, end = reductions.size(); i < end; i++) {
245  // For each of the reduction operations get the respective mlir::Value.
246  Optional<arith::AtomicRMWKind> reductionOp =
247  arith::symbolizeAtomicRMWKind(
248  reductions[i].cast<IntegerAttr>().getInt());
249  assert(reductionOp && "Reduction Operation cannot be of None Type");
250  arith::AtomicRMWKind reductionOpValue = *reductionOp;
251  rewriter.setInsertionPoint(&parOp.getBody()->back());
252  auto reduceOp = rewriter.create<scf::ReduceOp>(
253  loc, affineParOpTerminator->getOperand(i));
254  rewriter.setInsertionPointToEnd(&reduceOp.getReductionOperator().front());
255  Value reductionResult = arith::getReductionOp(
256  reductionOpValue, rewriter, loc,
257  reduceOp.getReductionOperator().front().getArgument(0),
258  reduceOp.getReductionOperator().front().getArgument(1));
259  rewriter.create<scf::ReduceReturnOp>(loc, reductionResult);
260  }
261  rewriter.replaceOp(op, parOp.getResults());
262  return success();
263  }
264 };
265 
266 class AffineIfLowering : public OpRewritePattern<AffineIfOp> {
267 public:
269 
270  LogicalResult matchAndRewrite(AffineIfOp op,
271  PatternRewriter &rewriter) const override {
272  auto loc = op.getLoc();
273 
274  // Now we just have to handle the condition logic.
275  auto integerSet = op.getIntegerSet();
276  Value zeroConstant = rewriter.create<arith::ConstantIndexOp>(loc, 0);
277  SmallVector<Value, 8> operands(op.getOperands());
278  auto operandsRef = llvm::makeArrayRef(operands);
279 
280  // Calculate cond as a conjunction without short-circuiting.
281  Value cond = nullptr;
282  for (unsigned i = 0, e = integerSet.getNumConstraints(); i < e; ++i) {
283  AffineExpr constraintExpr = integerSet.getConstraint(i);
284  bool isEquality = integerSet.isEq(i);
285 
286  // Build and apply an affine expression
287  auto numDims = integerSet.getNumDims();
288  Value affResult = expandAffineExpr(rewriter, loc, constraintExpr,
289  operandsRef.take_front(numDims),
290  operandsRef.drop_front(numDims));
291  if (!affResult)
292  return failure();
293  auto pred =
294  isEquality ? arith::CmpIPredicate::eq : arith::CmpIPredicate::sge;
295  Value cmpVal =
296  rewriter.create<arith::CmpIOp>(loc, pred, affResult, zeroConstant);
297  cond = cond
298  ? rewriter.create<arith::AndIOp>(loc, cond, cmpVal).getResult()
299  : cmpVal;
300  }
301  cond = cond ? cond
302  : rewriter.create<arith::ConstantIntOp>(loc, /*value=*/1,
303  /*width=*/1);
304 
305  bool hasElseRegion = !op.getElseRegion().empty();
306  auto ifOp = rewriter.create<scf::IfOp>(loc, op.getResultTypes(), cond,
307  hasElseRegion);
308  rewriter.inlineRegionBefore(op.getThenRegion(),
309  &ifOp.getThenRegion().back());
310  rewriter.eraseBlock(&ifOp.getThenRegion().back());
311  if (hasElseRegion) {
312  rewriter.inlineRegionBefore(op.getElseRegion(),
313  &ifOp.getElseRegion().back());
314  rewriter.eraseBlock(&ifOp.getElseRegion().back());
315  }
316 
317  // Replace the Affine IfOp finally.
318  rewriter.replaceOp(op, ifOp.getResults());
319  return success();
320  }
321 };
322 
323 /// Convert an "affine.apply" operation into a sequence of arithmetic
324 /// operations using the StandardOps dialect.
325 class AffineApplyLowering : public OpRewritePattern<AffineApplyOp> {
326 public:
328 
329  LogicalResult matchAndRewrite(AffineApplyOp op,
330  PatternRewriter &rewriter) const override {
331  auto maybeExpandedMap =
332  expandAffineMap(rewriter, op.getLoc(), op.getAffineMap(),
333  llvm::to_vector<8>(op.getOperands()));
334  if (!maybeExpandedMap)
335  return failure();
336  rewriter.replaceOp(op, *maybeExpandedMap);
337  return success();
338  }
339 };
340 
341 /// Apply the affine map from an 'affine.load' operation to its operands, and
342 /// feed the results to a newly created 'memref.load' operation (which replaces
343 /// the original 'affine.load').
344 class AffineLoadLowering : public OpRewritePattern<AffineLoadOp> {
345 public:
347 
348  LogicalResult matchAndRewrite(AffineLoadOp op,
349  PatternRewriter &rewriter) const override {
350  // Expand affine map from 'affineLoadOp'.
351  SmallVector<Value, 8> indices(op.getMapOperands());
352  auto resultOperands =
353  expandAffineMap(rewriter, op.getLoc(), op.getAffineMap(), indices);
354  if (!resultOperands)
355  return failure();
356 
357  // Build vector.load memref[expandedMap.results].
358  rewriter.replaceOpWithNewOp<memref::LoadOp>(op, op.getMemRef(),
359  *resultOperands);
360  return success();
361  }
362 };
363 
364 /// Apply the affine map from an 'affine.prefetch' operation to its operands,
365 /// and feed the results to a newly created 'memref.prefetch' operation (which
366 /// replaces the original 'affine.prefetch').
367 class AffinePrefetchLowering : public OpRewritePattern<AffinePrefetchOp> {
368 public:
370 
371  LogicalResult matchAndRewrite(AffinePrefetchOp op,
372  PatternRewriter &rewriter) const override {
373  // Expand affine map from 'affinePrefetchOp'.
374  SmallVector<Value, 8> indices(op.getMapOperands());
375  auto resultOperands =
376  expandAffineMap(rewriter, op.getLoc(), op.getAffineMap(), indices);
377  if (!resultOperands)
378  return failure();
379 
380  // Build memref.prefetch memref[expandedMap.results].
381  rewriter.replaceOpWithNewOp<memref::PrefetchOp>(
382  op, op.getMemref(), *resultOperands, op.getIsWrite(),
383  op.getLocalityHint(), op.getIsDataCache());
384  return success();
385  }
386 };
387 
388 /// Apply the affine map from an 'affine.store' operation to its operands, and
389 /// feed the results to a newly created 'memref.store' operation (which replaces
390 /// the original 'affine.store').
391 class AffineStoreLowering : public OpRewritePattern<AffineStoreOp> {
392 public:
394 
395  LogicalResult matchAndRewrite(AffineStoreOp op,
396  PatternRewriter &rewriter) const override {
397  // Expand affine map from 'affineStoreOp'.
398  SmallVector<Value, 8> indices(op.getMapOperands());
399  auto maybeExpandedMap =
400  expandAffineMap(rewriter, op.getLoc(), op.getAffineMap(), indices);
401  if (!maybeExpandedMap)
402  return failure();
403 
404  // Build memref.store valueToStore, memref[expandedMap.results].
405  rewriter.replaceOpWithNewOp<memref::StoreOp>(
406  op, op.getValueToStore(), op.getMemRef(), *maybeExpandedMap);
407  return success();
408  }
409 };
410 
411 /// Apply the affine maps from an 'affine.dma_start' operation to each of their
412 /// respective map operands, and feed the results to a newly created
413 /// 'memref.dma_start' operation (which replaces the original
414 /// 'affine.dma_start').
415 class AffineDmaStartLowering : public OpRewritePattern<AffineDmaStartOp> {
416 public:
418 
419  LogicalResult matchAndRewrite(AffineDmaStartOp op,
420  PatternRewriter &rewriter) const override {
421  SmallVector<Value, 8> operands(op.getOperands());
422  auto operandsRef = llvm::makeArrayRef(operands);
423 
424  // Expand affine map for DMA source memref.
425  auto maybeExpandedSrcMap = expandAffineMap(
426  rewriter, op.getLoc(), op.getSrcMap(),
427  operandsRef.drop_front(op.getSrcMemRefOperandIndex() + 1));
428  if (!maybeExpandedSrcMap)
429  return failure();
430  // Expand affine map for DMA destination memref.
431  auto maybeExpandedDstMap = expandAffineMap(
432  rewriter, op.getLoc(), op.getDstMap(),
433  operandsRef.drop_front(op.getDstMemRefOperandIndex() + 1));
434  if (!maybeExpandedDstMap)
435  return failure();
436  // Expand affine map for DMA tag memref.
437  auto maybeExpandedTagMap = expandAffineMap(
438  rewriter, op.getLoc(), op.getTagMap(),
439  operandsRef.drop_front(op.getTagMemRefOperandIndex() + 1));
440  if (!maybeExpandedTagMap)
441  return failure();
442 
443  // Build memref.dma_start operation with affine map results.
444  rewriter.replaceOpWithNewOp<memref::DmaStartOp>(
445  op, op.getSrcMemRef(), *maybeExpandedSrcMap, op.getDstMemRef(),
446  *maybeExpandedDstMap, op.getNumElements(), op.getTagMemRef(),
447  *maybeExpandedTagMap, op.getStride(), op.getNumElementsPerStride());
448  return success();
449  }
450 };
451 
452 /// Apply the affine map from an 'affine.dma_wait' operation tag memref,
453 /// and feed the results to a newly created 'memref.dma_wait' operation (which
454 /// replaces the original 'affine.dma_wait').
455 class AffineDmaWaitLowering : public OpRewritePattern<AffineDmaWaitOp> {
456 public:
458 
459  LogicalResult matchAndRewrite(AffineDmaWaitOp op,
460  PatternRewriter &rewriter) const override {
461  // Expand affine map for DMA tag memref.
462  SmallVector<Value, 8> indices(op.getTagIndices());
463  auto maybeExpandedTagMap =
464  expandAffineMap(rewriter, op.getLoc(), op.getTagMap(), indices);
465  if (!maybeExpandedTagMap)
466  return failure();
467 
468  // Build memref.dma_wait operation with affine map results.
469  rewriter.replaceOpWithNewOp<memref::DmaWaitOp>(
470  op, op.getTagMemRef(), *maybeExpandedTagMap, op.getNumElements());
471  return success();
472  }
473 };
474 
475 /// Apply the affine map from an 'affine.vector_load' operation to its operands,
476 /// and feed the results to a newly created 'vector.load' operation (which
477 /// replaces the original 'affine.vector_load').
478 class AffineVectorLoadLowering : public OpRewritePattern<AffineVectorLoadOp> {
479 public:
481 
482  LogicalResult matchAndRewrite(AffineVectorLoadOp op,
483  PatternRewriter &rewriter) const override {
484  // Expand affine map from 'affineVectorLoadOp'.
485  SmallVector<Value, 8> indices(op.getMapOperands());
486  auto resultOperands =
487  expandAffineMap(rewriter, op.getLoc(), op.getAffineMap(), indices);
488  if (!resultOperands)
489  return failure();
490 
491  // Build vector.load memref[expandedMap.results].
492  rewriter.replaceOpWithNewOp<vector::LoadOp>(
493  op, op.getVectorType(), op.getMemRef(), *resultOperands);
494  return success();
495  }
496 };
497 
498 /// Apply the affine map from an 'affine.vector_store' operation to its
499 /// operands, and feed the results to a newly created 'vector.store' operation
500 /// (which replaces the original 'affine.vector_store').
501 class AffineVectorStoreLowering : public OpRewritePattern<AffineVectorStoreOp> {
502 public:
504 
505  LogicalResult matchAndRewrite(AffineVectorStoreOp op,
506  PatternRewriter &rewriter) const override {
507  // Expand affine map from 'affineVectorStoreOp'.
508  SmallVector<Value, 8> indices(op.getMapOperands());
509  auto maybeExpandedMap =
510  expandAffineMap(rewriter, op.getLoc(), op.getAffineMap(), indices);
511  if (!maybeExpandedMap)
512  return failure();
513 
514  rewriter.replaceOpWithNewOp<vector::StoreOp>(
515  op, op.getValueToStore(), op.getMemRef(), *maybeExpandedMap);
516  return success();
517  }
518 };
519 
520 } // namespace
521 
523  // clang-format off
524  patterns.add<
525  AffineApplyLowering,
526  AffineDmaStartLowering,
527  AffineDmaWaitLowering,
528  AffineLoadLowering,
529  AffineMinLowering,
530  AffineMaxLowering,
531  AffineParallelLowering,
532  AffinePrefetchLowering,
533  AffineStoreLowering,
534  AffineForLowering,
535  AffineIfLowering,
536  AffineYieldOpLowering>(patterns.getContext());
537  // clang-format on
538 }
539 
541  RewritePatternSet &patterns) {
542  // clang-format off
543  patterns.add<
544  AffineVectorLoadLowering,
545  AffineVectorStoreLowering>(patterns.getContext());
546  // clang-format on
547 }
548 
549 namespace {
550 class LowerAffinePass
551  : public impl::ConvertAffineToStandardBase<LowerAffinePass> {
552  void runOnOperation() override {
553  RewritePatternSet patterns(&getContext());
556  ConversionTarget target(getContext());
557  target.addLegalDialect<arith::ArithDialect, memref::MemRefDialect,
558  scf::SCFDialect, VectorDialect>();
559  if (failed(applyPartialConversion(getOperation(), target,
560  std::move(patterns))))
561  signalPassFailure();
562  }
563 };
564 } // namespace
565 
566 /// Lowers If and For operations within a function into their lower level CFG
567 /// equivalent blocks.
568 std::unique_ptr<Pass> mlir::createLowerAffinePass() {
569  return std::make_unique<LowerAffinePass>();
570 }
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) ...
static constexpr const bool value
AffineDmaStartOp starts a non-blocking DMA operation that transfers data from a source memref to a de...
Definition: AffineOps.h:92
unsigned getSrcMemRefOperandIndex()
Returns the operand index of the source memref.
Definition: AffineOps.h:104
unsigned getTagMemRefOperandIndex()
Returns the operand index of the tag memref.
Definition: AffineOps.h:168
AffineMap getTagMap()
Returns the affine map used to access the tag memref.
Definition: AffineOps.h:184
Value getSrcMemRef()
Returns the source MemRefType for this DMA operation.
Definition: AffineOps.h:107
unsigned getDstMemRefOperandIndex()
Returns the operand index of the destination memref.
Definition: AffineOps.h:134
AffineMap getSrcMap()
Returns the affine map used to access the source memref.
Definition: AffineOps.h:116
AffineMap getDstMap()
Returns the affine map used to access the destination memref.
Definition: AffineOps.h:155
AffineDmaWaitOp blocks until the completion of a DMA operation associated with the tag element 'tag[i...
Definition: AffineOps.h:285
operand_range getTagIndices()
Returns the tag memref index for this DMA operation.
Definition: AffineOps.h:308
Value getTagMemRef()
Returns the Tag MemRef associated with the DMA operation being waited on.
Definition: AffineOps.h:296
AffineMap getTagMap()
Returns the affine map used to access the tag memref.
Definition: AffineOps.h:302
Base type for affine expression.
Definition: AffineExpr.h:68
A multi-dimensional affine map Affine map's are immutable like Type's, and they are uniqued.
Definition: AffineMap.h:42
Attributes are known-constant values of operations.
Definition: Attributes.h:25
U cast() const
Definition: Attributes.h:137
This class describes a specific conversion target.
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition: Location.h:64
This class helps build Operations.
Definition: Builders.h:198
void setInsertionPoint(Block *block, Block::iterator insertPoint)
Set the insertion point to the specified location.
Definition: Builders.h:350
void setInsertionPointToEnd(Block *block)
Sets the insertion point to the end of the specified block.
Definition: Builders.h:388
Operation * create(const OperationState &state)
Creates an operation given the fields represented as an OperationState.
Definition: Builders.cpp:422
Location getLoc()
The source location the operation was defined or derived from.
Definition: OpDefinition.h:108
Operation is a basic unit of execution within MLIR.
Definition: Operation.h:31
Value getOperand(unsigned idx)
Definition: Operation.h:267
unsigned getNumOperands()
Definition: Operation.h:263
A special type of RewriterBase that coordinates the application of a rewrite pattern on the current I...
Definition: PatternMatch.h:605
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.
std::enable_if_t<!std::is_convertible< CallbackT, Twine >::value, LogicalResult > notifyMatchFailure(Location loc, CallbackT &&reasonCallback)
Used to notify the rewriter that the IR failed to be rewritten because of a match failure,...
Definition: PatternMatch.h:517
virtual void eraseBlock(Block *block)
This method erases all operations in a block.
virtual void replaceOp(Operation *op, ValueRange newValues)
This method replaces the results of the operation with the specified list of values.
virtual 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)
Replaces the result op with a new op that is created without verification.
Definition: PatternMatch.h:451
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition: Types.h:74
This class provides an abstraction over the different types of ranges over Values.
Definition: ValueRange.h:349
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition: Value.h:85
Value getIdentityValue(AtomicRMWKind op, Type resultType, OpBuilder &builder, Location loc)
Returns the identity value associated with an AtomicRMWKind op.
Definition: ArithOps.cpp:2208
Value getReductionOp(AtomicRMWKind op, OpBuilder &builder, Location loc, Value lhs, Value rhs)
Returns the value obtained by applying the reduction operation kind associated with a binary AtomicRM...
Definition: ArithOps.cpp:2216
Include the generated interface declarations.
LogicalResult failure(bool isFailure=true)
Utility function to generate a LogicalResult.
Definition: LogicalResult.h:62
LogicalResult applyPartialConversion(ArrayRef< Operation * > ops, ConversionTarget &target, const FrozenRewritePatternSet &patterns, DenseSet< Operation * > *unconvertedOps=nullptr)
Below we define several entry points for operation conversion.
Value lowerAffineUpperBound(AffineForOp op, OpBuilder &builder)
Emit code that computes the upper bound of the given affine loop using standard arithmetic operations...
LogicalResult success(bool isSuccess=true)
Utility function to generate a LogicalResult.
Definition: LogicalResult.h:56
Value expandAffineExpr(OpBuilder &builder, Location loc, AffineExpr expr, ValueRange dimValues, ValueRange symbolValues)
Emit code that computes the given affine expression using standard arithmetic operations applied to t...
Definition: Utils.cpp:216
void populateAffineToVectorConversionPatterns(RewritePatternSet &patterns)
Collect a set of patterns to convert vector-related Affine ops to the Vector dialect.
std::unique_ptr< Pass > createLowerAffinePass()
Lowers affine control flow operations (ForStmt, IfStmt and AffineApplyOp) to equivalent lower-level c...
Optional< SmallVector< Value, 8 > > expandAffineMap(OpBuilder &builder, Location loc, AffineMap affineMap, ValueRange operands)
Create a sequence of operations that implement the affineMap applied to the given operands (as it it ...
Definition: Utils.cpp:224
void populateAffineToStdConversionPatterns(RewritePatternSet &patterns)
Collect a set of patterns to convert from the Affine dialect to the Standard dialect,...
bool failed(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a failure value.
Definition: LogicalResult.h:72
Value lowerAffineLowerBound(AffineForOp op, OpBuilder &builder)
Emit code that computes the lower bound of the given affine loop using standard arithmetic operations...
This class represents an efficient way to signal success or failure.
Definition: LogicalResult.h:26
OpRewritePattern is a wrapper around RewritePattern that allows for matching and rewriting against an...
Definition: PatternMatch.h:356