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