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"
25 #include "mlir/Transforms/Passes.h"
26 
27 namespace mlir {
28 #define GEN_PASS_DEF_LOWERAFFINEPASS
29 #include "mlir/Conversion/Passes.h.inc"
30 } // namespace mlir
31 
32 using namespace mlir;
33 using namespace mlir::affine;
34 using 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 = builder.create<arith::MaxSIOp>(loc, value, *valueIt);
54  else
55  value = builder.create<arith::MinSIOp>(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.
84 Value 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.
92 Value mlir::lowerAffineLowerBound(AffineForOp op, OpBuilder &builder) {
93  return lowerAffineMapMax(builder, op.getLoc(), op.getLowerBoundMap(),
94  op.getLowerBoundOperands());
95 }
96 
97 namespace {
98 class AffineMinLowering : public OpRewritePattern<AffineMinOp> {
99 public:
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 
114 class AffineMaxLowering : public OpRewritePattern<AffineMaxOp> {
115 public:
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.
131 class AffineYieldOpLowering : public OpRewritePattern<AffineYieldOp> {
132 public:
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 
147 class AffineForLowering : public OpRewritePattern<AffineForOp> {
148 public:
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  rewriter.create<arith::ConstantIndexOp>(loc, op.getStepAsInt());
158  auto scfForOp = rewriter.create<scf::ForOp>(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.
170 class AffineParallelLowering : public OpRewritePattern<AffineParallelOp> {
171 public:
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(rewriter.create<arith::ConstantIndexOp>(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 = 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  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 = rewriter.create<scf::ParallelOp>(
237  loc, lowerBoundTuple, 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  rewriter.create<scf::ReduceReturnOp>(loc, reductionResult);
265  }
266  rewriter.replaceOp(op, parOp.getResults());
267  return success();
268  }
269 };
270 
271 class AffineIfLowering : public OpRewritePattern<AffineIfOp> {
272 public:
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 = rewriter.create<arith::ConstantIndexOp>(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  rewriter.create<arith::CmpIOp>(loc, pred, affResult, zeroConstant);
302  cond = cond
303  ? rewriter.create<arith::AndIOp>(loc, cond, cmpVal).getResult()
304  : cmpVal;
305  }
306  cond = cond ? cond
307  : rewriter.create<arith::ConstantIntOp>(loc, /*value=*/1,
308  /*width=*/1);
309 
310  bool hasElseRegion = !op.getElseRegion().empty();
311  auto ifOp = rewriter.create<scf::IfOp>(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.
330 class AffineApplyLowering : public OpRewritePattern<AffineApplyOp> {
331 public:
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').
349 class AffineLoadLowering : public OpRewritePattern<AffineLoadOp> {
350 public:
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').
372 class AffinePrefetchLowering : public OpRewritePattern<AffinePrefetchOp> {
373 public:
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').
396 class AffineStoreLowering : public OpRewritePattern<AffineStoreOp> {
397 public:
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').
420 class AffineDmaStartLowering : public OpRewritePattern<AffineDmaStartOp> {
421 public:
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').
460 class AffineDmaWaitLowering : public OpRewritePattern<AffineDmaWaitOp> {
461 public:
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').
483 class AffineVectorLoadLowering : public OpRewritePattern<AffineVectorLoadOp> {
484 public:
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').
506 class AffineVectorStoreLowering : public OpRewritePattern<AffineVectorStoreOp> {
507 public:
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 
554 namespace {
555 class LowerAffine : public impl::LowerAffinePassBase<LowerAffine> {
556  void runOnOperation() override {
561  ConversionTarget target(getContext());
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
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 MLIRContext * getContext(OpFoldResult val)
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:46
Attributes are known-constant values of operations.
Definition: Attributes.h:25
Block represents an ordered list of Operations.
Definition: Block.h:33
BlockArgument getArgument(unsigned i)
Definition: Block.h:129
Operation & front()
Definition: Block.h:153
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:76
This class helps build Operations.
Definition: Builders.h:205
void setInsertionPoint(Block *block, Block::iterator insertPoint)
Set the insertion point to the specified location.
Definition: Builders.h:396
void setInsertionPointToEnd(Block *block)
Sets the insertion point to the end of the specified block.
Definition: Builders.h:434
Operation * create(const OperationState &state)
Creates an operation given the fields represented as an OperationState.
Definition: Builders.cpp:452
Location getLoc()
The source location the operation was defined or derived from.
Definition: OpDefinition.h:129
A special type of RewriterBase that coordinates the application of a rewrite pattern on the current I...
Definition: PatternMatch.h:769
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,...
Definition: PatternMatch.h:702
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...
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...
Definition: PatternMatch.h:519
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:387
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition: Value.h:96
AffineDmaStartOp starts a non-blocking DMA operation that transfers data from a source memref to a de...
Definition: AffineOps.h:106
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
AffineDmaWaitOp blocks until the completion of a DMA operation associated with the tag element 'tag[i...
Definition: AffineOps.h:330
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
std::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:228
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:218
void populateAffineExpandIndexOpsPatterns(RewritePatternSet &patterns)
Populate patterns that expand affine index operations into more fundamental operations (not necessari...
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:2778
Value getIdentityValue(AtomicRMWKind op, Type resultType, OpBuilder &builder, Location loc, bool useOnlyFiniteValue=false)
Returns the identity value associated with an AtomicRMWKind op.
Definition: ArithOps.cpp:2768
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.
LogicalResult applyPartialConversion(ArrayRef< Operation * > ops, const ConversionTarget &target, const FrozenRewritePatternSet &patterns, ConversionConfig config=ConversionConfig())
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,...
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...
Definition: PatternMatch.h:314