MLIR  18.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 
21 #include "mlir/IR/IRMapping.h"
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::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. The predicate defines which
38 /// comparison to perform, "lt" for "min", "gt" for "max" and is used for the
39 /// `cmpi` operation followed by the `select` operation:
40 ///
41 /// %cond = arith.cmpi "predicate" %v0, %v1
42 /// %result = select %cond, %v0, %v1
43 ///
44 /// Multiple values are scanned in a linear sequence. This creates a data
45 /// dependences that wouldn't exist in a tree reduction, but is easier to
46 /// recognize as a reduction by the subsequent passes.
48  arith::CmpIPredicate predicate,
49  ValueRange values, OpBuilder &builder) {
50  assert(!values.empty() && "empty min/max chain");
51 
52  auto valueIt = values.begin();
53  Value value = *valueIt++;
54  for (; valueIt != values.end(); ++valueIt) {
55  auto cmpOp = builder.create<arith::CmpIOp>(loc, predicate, value, *valueIt);
56  value = builder.create<arith::SelectOp>(loc, cmpOp.getResult(), value,
57  *valueIt);
58  }
59 
60  return value;
61 }
62 
63 /// Emit instructions that correspond to computing the maximum value among the
64 /// values of a (potentially) multi-output affine map applied to `operands`.
66  ValueRange operands) {
67  if (auto values = expandAffineMap(builder, loc, map, operands))
68  return buildMinMaxReductionSeq(loc, arith::CmpIPredicate::sgt, *values,
69  builder);
70  return nullptr;
71 }
72 
73 /// Emit instructions that correspond to computing the minimum value among the
74 /// values of a (potentially) multi-output affine map applied to `operands`.
76  ValueRange operands) {
77  if (auto values = expandAffineMap(builder, loc, map, operands))
78  return buildMinMaxReductionSeq(loc, arith::CmpIPredicate::slt, *values,
79  builder);
80  return nullptr;
81 }
82 
83 /// Emit instructions that correspond to the affine map in the upper bound
84 /// applied to the respective operands, and compute the minimum value across
85 /// the results.
86 Value mlir::lowerAffineUpperBound(AffineForOp op, OpBuilder &builder) {
87  return lowerAffineMapMin(builder, op.getLoc(), op.getUpperBoundMap(),
88  op.getUpperBoundOperands());
89 }
90 
91 /// Emit instructions that correspond to the affine map in the lower bound
92 /// applied to the respective operands, and compute the maximum value across
93 /// the results.
94 Value mlir::lowerAffineLowerBound(AffineForOp op, OpBuilder &builder) {
95  return lowerAffineMapMax(builder, op.getLoc(), op.getLowerBoundMap(),
96  op.getLowerBoundOperands());
97 }
98 
99 namespace {
100 class AffineMinLowering : public OpRewritePattern<AffineMinOp> {
101 public:
103 
104  LogicalResult matchAndRewrite(AffineMinOp op,
105  PatternRewriter &rewriter) const override {
106  Value reduced =
107  lowerAffineMapMin(rewriter, op.getLoc(), op.getMap(), op.getOperands());
108  if (!reduced)
109  return failure();
110 
111  rewriter.replaceOp(op, reduced);
112  return success();
113  }
114 };
115 
116 class AffineMaxLowering : public OpRewritePattern<AffineMaxOp> {
117 public:
119 
120  LogicalResult matchAndRewrite(AffineMaxOp op,
121  PatternRewriter &rewriter) const override {
122  Value reduced =
123  lowerAffineMapMax(rewriter, op.getLoc(), op.getMap(), op.getOperands());
124  if (!reduced)
125  return failure();
126 
127  rewriter.replaceOp(op, reduced);
128  return success();
129  }
130 };
131 
132 /// Affine yields ops are removed.
133 class AffineYieldOpLowering : public OpRewritePattern<AffineYieldOp> {
134 public:
136 
137  LogicalResult matchAndRewrite(AffineYieldOp op,
138  PatternRewriter &rewriter) const override {
139  if (isa<scf::ParallelOp>(op->getParentOp())) {
140  // scf.parallel does not yield any values via its terminator scf.yield but
141  // models reductions differently using additional ops in its region.
142  rewriter.replaceOpWithNewOp<scf::YieldOp>(op);
143  return success();
144  }
145  rewriter.replaceOpWithNewOp<scf::YieldOp>(op, op.getOperands());
146  return success();
147  }
148 };
149 
150 class AffineForLowering : public OpRewritePattern<AffineForOp> {
151 public:
153 
154  LogicalResult matchAndRewrite(AffineForOp op,
155  PatternRewriter &rewriter) const override {
156  Location loc = op.getLoc();
157  Value lowerBound = lowerAffineLowerBound(op, rewriter);
158  Value upperBound = lowerAffineUpperBound(op, rewriter);
159  Value step =
160  rewriter.create<arith::ConstantIndexOp>(loc, op.getStepAsInt());
161  auto scfForOp = rewriter.create<scf::ForOp>(loc, lowerBound, upperBound,
162  step, op.getInits());
163  rewriter.eraseBlock(scfForOp.getBody());
164  rewriter.inlineRegionBefore(op.getRegion(), scfForOp.getRegion(),
165  scfForOp.getRegion().end());
166  rewriter.replaceOp(op, scfForOp.getResults());
167  return success();
168  }
169 };
170 
171 /// Convert an `affine.parallel` (loop nest) operation into a `scf.parallel`
172 /// operation.
173 class AffineParallelLowering : public OpRewritePattern<AffineParallelOp> {
174 public:
176 
177  LogicalResult matchAndRewrite(AffineParallelOp op,
178  PatternRewriter &rewriter) const override {
179  Location loc = op.getLoc();
180  SmallVector<Value, 8> steps;
181  SmallVector<Value, 8> upperBoundTuple;
182  SmallVector<Value, 8> lowerBoundTuple;
183  SmallVector<Value, 8> identityVals;
184  // Emit IR computing the lower and upper bound by expanding the map
185  // expression.
186  lowerBoundTuple.reserve(op.getNumDims());
187  upperBoundTuple.reserve(op.getNumDims());
188  for (unsigned i = 0, e = op.getNumDims(); i < e; ++i) {
189  Value lower = lowerAffineMapMax(rewriter, loc, op.getLowerBoundMap(i),
190  op.getLowerBoundsOperands());
191  if (!lower)
192  return rewriter.notifyMatchFailure(op, "couldn't convert lower bounds");
193  lowerBoundTuple.push_back(lower);
194 
195  Value upper = lowerAffineMapMin(rewriter, loc, op.getUpperBoundMap(i),
196  op.getUpperBoundsOperands());
197  if (!upper)
198  return rewriter.notifyMatchFailure(op, "couldn't convert upper bounds");
199  upperBoundTuple.push_back(upper);
200  }
201  steps.reserve(op.getSteps().size());
202  for (int64_t step : op.getSteps())
203  steps.push_back(rewriter.create<arith::ConstantIndexOp>(loc, step));
204 
205  // Get the terminator op.
206  Operation *affineParOpTerminator = op.getBody()->getTerminator();
207  scf::ParallelOp parOp;
208  if (op.getResults().empty()) {
209  // Case with no reduction operations/return values.
210  parOp = rewriter.create<scf::ParallelOp>(loc, lowerBoundTuple,
211  upperBoundTuple, steps,
212  /*bodyBuilderFn=*/nullptr);
213  rewriter.eraseBlock(parOp.getBody());
214  rewriter.inlineRegionBefore(op.getRegion(), parOp.getRegion(),
215  parOp.getRegion().end());
216  rewriter.replaceOp(op, parOp.getResults());
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  for (unsigned i = 0, end = reductions.size(); i < end; i++) {
247  // For each of the reduction operations get the respective mlir::Value.
248  std::optional<arith::AtomicRMWKind> reductionOp =
249  arith::symbolizeAtomicRMWKind(
250  cast<IntegerAttr>(reductions[i]).getInt());
251  assert(reductionOp && "Reduction Operation cannot be of None Type");
252  arith::AtomicRMWKind reductionOpValue = *reductionOp;
253  rewriter.setInsertionPoint(&parOp.getBody()->back());
254  auto reduceOp = rewriter.create<scf::ReduceOp>(
255  loc, affineParOpTerminator->getOperand(i));
256  rewriter.setInsertionPointToEnd(&reduceOp.getReductionOperator().front());
257  Value reductionResult = arith::getReductionOp(
258  reductionOpValue, rewriter, loc,
259  reduceOp.getReductionOperator().front().getArgument(0),
260  reduceOp.getReductionOperator().front().getArgument(1));
261  rewriter.create<scf::ReduceReturnOp>(loc, reductionResult);
262  }
263  rewriter.replaceOp(op, parOp.getResults());
264  return success();
265  }
266 };
267 
268 class AffineIfLowering : public OpRewritePattern<AffineIfOp> {
269 public:
271 
272  LogicalResult matchAndRewrite(AffineIfOp op,
273  PatternRewriter &rewriter) const override {
274  auto loc = op.getLoc();
275 
276  // Now we just have to handle the condition logic.
277  auto integerSet = op.getIntegerSet();
278  Value zeroConstant = rewriter.create<arith::ConstantIndexOp>(loc, 0);
279  SmallVector<Value, 8> operands(op.getOperands());
280  auto operandsRef = llvm::ArrayRef(operands);
281 
282  // Calculate cond as a conjunction without short-circuiting.
283  Value cond = nullptr;
284  for (unsigned i = 0, e = integerSet.getNumConstraints(); i < e; ++i) {
285  AffineExpr constraintExpr = integerSet.getConstraint(i);
286  bool isEquality = integerSet.isEq(i);
287 
288  // Build and apply an affine expression
289  auto numDims = integerSet.getNumDims();
290  Value affResult = expandAffineExpr(rewriter, loc, constraintExpr,
291  operandsRef.take_front(numDims),
292  operandsRef.drop_front(numDims));
293  if (!affResult)
294  return failure();
295  auto pred =
296  isEquality ? arith::CmpIPredicate::eq : arith::CmpIPredicate::sge;
297  Value cmpVal =
298  rewriter.create<arith::CmpIOp>(loc, pred, affResult, zeroConstant);
299  cond = cond
300  ? rewriter.create<arith::AndIOp>(loc, cond, cmpVal).getResult()
301  : cmpVal;
302  }
303  cond = cond ? cond
304  : rewriter.create<arith::ConstantIntOp>(loc, /*value=*/1,
305  /*width=*/1);
306 
307  bool hasElseRegion = !op.getElseRegion().empty();
308  auto ifOp = rewriter.create<scf::IfOp>(loc, op.getResultTypes(), cond,
309  hasElseRegion);
310  rewriter.inlineRegionBefore(op.getThenRegion(),
311  &ifOp.getThenRegion().back());
312  rewriter.eraseBlock(&ifOp.getThenRegion().back());
313  if (hasElseRegion) {
314  rewriter.inlineRegionBefore(op.getElseRegion(),
315  &ifOp.getElseRegion().back());
316  rewriter.eraseBlock(&ifOp.getElseRegion().back());
317  }
318 
319  // Replace the Affine IfOp finally.
320  rewriter.replaceOp(op, ifOp.getResults());
321  return success();
322  }
323 };
324 
325 /// Convert an "affine.apply" operation into a sequence of arithmetic
326 /// operations using the StandardOps dialect.
327 class AffineApplyLowering : public OpRewritePattern<AffineApplyOp> {
328 public:
330 
331  LogicalResult matchAndRewrite(AffineApplyOp op,
332  PatternRewriter &rewriter) const override {
333  auto maybeExpandedMap =
334  expandAffineMap(rewriter, op.getLoc(), op.getAffineMap(),
335  llvm::to_vector<8>(op.getOperands()));
336  if (!maybeExpandedMap)
337  return failure();
338  rewriter.replaceOp(op, *maybeExpandedMap);
339  return success();
340  }
341 };
342 
343 /// Apply the affine map from an 'affine.load' operation to its operands, and
344 /// feed the results to a newly created 'memref.load' operation (which replaces
345 /// the original 'affine.load').
346 class AffineLoadLowering : public OpRewritePattern<AffineLoadOp> {
347 public:
349 
350  LogicalResult matchAndRewrite(AffineLoadOp op,
351  PatternRewriter &rewriter) const override {
352  // Expand affine map from 'affineLoadOp'.
353  SmallVector<Value, 8> indices(op.getMapOperands());
354  auto resultOperands =
355  expandAffineMap(rewriter, op.getLoc(), op.getAffineMap(), indices);
356  if (!resultOperands)
357  return failure();
358 
359  // Build vector.load memref[expandedMap.results].
360  rewriter.replaceOpWithNewOp<memref::LoadOp>(op, op.getMemRef(),
361  *resultOperands);
362  return success();
363  }
364 };
365 
366 /// Apply the affine map from an 'affine.prefetch' operation to its operands,
367 /// and feed the results to a newly created 'memref.prefetch' operation (which
368 /// replaces the original 'affine.prefetch').
369 class AffinePrefetchLowering : public OpRewritePattern<AffinePrefetchOp> {
370 public:
372 
373  LogicalResult matchAndRewrite(AffinePrefetchOp op,
374  PatternRewriter &rewriter) const override {
375  // Expand affine map from 'affinePrefetchOp'.
376  SmallVector<Value, 8> indices(op.getMapOperands());
377  auto resultOperands =
378  expandAffineMap(rewriter, op.getLoc(), op.getAffineMap(), indices);
379  if (!resultOperands)
380  return failure();
381 
382  // Build memref.prefetch memref[expandedMap.results].
383  rewriter.replaceOpWithNewOp<memref::PrefetchOp>(
384  op, op.getMemref(), *resultOperands, op.getIsWrite(),
385  op.getLocalityHint(), op.getIsDataCache());
386  return success();
387  }
388 };
389 
390 /// Apply the affine map from an 'affine.store' operation to its operands, and
391 /// feed the results to a newly created 'memref.store' operation (which replaces
392 /// the original 'affine.store').
393 class AffineStoreLowering : public OpRewritePattern<AffineStoreOp> {
394 public:
396 
397  LogicalResult matchAndRewrite(AffineStoreOp op,
398  PatternRewriter &rewriter) const override {
399  // Expand affine map from 'affineStoreOp'.
400  SmallVector<Value, 8> indices(op.getMapOperands());
401  auto maybeExpandedMap =
402  expandAffineMap(rewriter, op.getLoc(), op.getAffineMap(), indices);
403  if (!maybeExpandedMap)
404  return failure();
405 
406  // Build memref.store valueToStore, memref[expandedMap.results].
407  rewriter.replaceOpWithNewOp<memref::StoreOp>(
408  op, op.getValueToStore(), op.getMemRef(), *maybeExpandedMap);
409  return success();
410  }
411 };
412 
413 /// Apply the affine maps from an 'affine.dma_start' operation to each of their
414 /// respective map operands, and feed the results to a newly created
415 /// 'memref.dma_start' operation (which replaces the original
416 /// 'affine.dma_start').
417 class AffineDmaStartLowering : public OpRewritePattern<AffineDmaStartOp> {
418 public:
420 
421  LogicalResult matchAndRewrite(AffineDmaStartOp op,
422  PatternRewriter &rewriter) const override {
423  SmallVector<Value, 8> operands(op.getOperands());
424  auto operandsRef = llvm::ArrayRef(operands);
425 
426  // Expand affine map for DMA source memref.
427  auto maybeExpandedSrcMap = expandAffineMap(
428  rewriter, op.getLoc(), op.getSrcMap(),
429  operandsRef.drop_front(op.getSrcMemRefOperandIndex() + 1));
430  if (!maybeExpandedSrcMap)
431  return failure();
432  // Expand affine map for DMA destination memref.
433  auto maybeExpandedDstMap = expandAffineMap(
434  rewriter, op.getLoc(), op.getDstMap(),
435  operandsRef.drop_front(op.getDstMemRefOperandIndex() + 1));
436  if (!maybeExpandedDstMap)
437  return failure();
438  // Expand affine map for DMA tag memref.
439  auto maybeExpandedTagMap = expandAffineMap(
440  rewriter, op.getLoc(), op.getTagMap(),
441  operandsRef.drop_front(op.getTagMemRefOperandIndex() + 1));
442  if (!maybeExpandedTagMap)
443  return failure();
444 
445  // Build memref.dma_start operation with affine map results.
446  rewriter.replaceOpWithNewOp<memref::DmaStartOp>(
447  op, op.getSrcMemRef(), *maybeExpandedSrcMap, op.getDstMemRef(),
448  *maybeExpandedDstMap, op.getNumElements(), op.getTagMemRef(),
449  *maybeExpandedTagMap, op.getStride(), op.getNumElementsPerStride());
450  return success();
451  }
452 };
453 
454 /// Apply the affine map from an 'affine.dma_wait' operation tag memref,
455 /// and feed the results to a newly created 'memref.dma_wait' operation (which
456 /// replaces the original 'affine.dma_wait').
457 class AffineDmaWaitLowering : public OpRewritePattern<AffineDmaWaitOp> {
458 public:
460 
461  LogicalResult matchAndRewrite(AffineDmaWaitOp op,
462  PatternRewriter &rewriter) const override {
463  // Expand affine map for DMA tag memref.
464  SmallVector<Value, 8> indices(op.getTagIndices());
465  auto maybeExpandedTagMap =
466  expandAffineMap(rewriter, op.getLoc(), op.getTagMap(), indices);
467  if (!maybeExpandedTagMap)
468  return failure();
469 
470  // Build memref.dma_wait operation with affine map results.
471  rewriter.replaceOpWithNewOp<memref::DmaWaitOp>(
472  op, op.getTagMemRef(), *maybeExpandedTagMap, op.getNumElements());
473  return success();
474  }
475 };
476 
477 /// Apply the affine map from an 'affine.vector_load' operation to its operands,
478 /// and feed the results to a newly created 'vector.load' operation (which
479 /// replaces the original 'affine.vector_load').
480 class AffineVectorLoadLowering : public OpRewritePattern<AffineVectorLoadOp> {
481 public:
483 
484  LogicalResult matchAndRewrite(AffineVectorLoadOp op,
485  PatternRewriter &rewriter) const override {
486  // Expand affine map from 'affineVectorLoadOp'.
487  SmallVector<Value, 8> indices(op.getMapOperands());
488  auto resultOperands =
489  expandAffineMap(rewriter, op.getLoc(), op.getAffineMap(), indices);
490  if (!resultOperands)
491  return failure();
492 
493  // Build vector.load memref[expandedMap.results].
494  rewriter.replaceOpWithNewOp<vector::LoadOp>(
495  op, op.getVectorType(), op.getMemRef(), *resultOperands);
496  return success();
497  }
498 };
499 
500 /// Apply the affine map from an 'affine.vector_store' operation to its
501 /// operands, and feed the results to a newly created 'vector.store' operation
502 /// (which replaces the original 'affine.vector_store').
503 class AffineVectorStoreLowering : public OpRewritePattern<AffineVectorStoreOp> {
504 public:
506 
507  LogicalResult matchAndRewrite(AffineVectorStoreOp op,
508  PatternRewriter &rewriter) const override {
509  // Expand affine map from 'affineVectorStoreOp'.
510  SmallVector<Value, 8> indices(op.getMapOperands());
511  auto maybeExpandedMap =
512  expandAffineMap(rewriter, op.getLoc(), op.getAffineMap(), indices);
513  if (!maybeExpandedMap)
514  return failure();
515 
516  rewriter.replaceOpWithNewOp<vector::StoreOp>(
517  op, op.getValueToStore(), op.getMemRef(), *maybeExpandedMap);
518  return success();
519  }
520 };
521 
522 } // namespace
523 
525  // clang-format off
526  patterns.add<
527  AffineApplyLowering,
528  AffineDmaStartLowering,
529  AffineDmaWaitLowering,
530  AffineLoadLowering,
531  AffineMinLowering,
532  AffineMaxLowering,
533  AffineParallelLowering,
534  AffinePrefetchLowering,
535  AffineStoreLowering,
536  AffineForLowering,
537  AffineIfLowering,
538  AffineYieldOpLowering>(patterns.getContext());
539  // clang-format on
540 }
541 
543  RewritePatternSet &patterns) {
544  // clang-format off
545  patterns.add<
546  AffineVectorLoadLowering,
547  AffineVectorStoreLowering>(patterns.getContext());
548  // clang-format on
549 }
550 
551 namespace {
552 class LowerAffinePass
553  : public impl::ConvertAffineToStandardBase<LowerAffinePass> {
554  void runOnOperation() override {
555  RewritePatternSet patterns(&getContext());
558  ConversionTarget target(getContext());
559  target.addLegalDialect<arith::ArithDialect, memref::MemRefDialect,
560  scf::SCFDialect, VectorDialect>();
561  if (failed(applyPartialConversion(getOperation(), target,
562  std::move(patterns))))
563  signalPassFailure();
564  }
565 };
566 } // namespace
567 
568 /// Lowers If and For operations within a function into their lower level CFG
569 /// equivalent blocks.
570 std::unique_ptr<Pass> mlir::createLowerAffinePass() {
571  return std::make_unique<LowerAffinePass>();
572 }
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:47
Attributes are known-constant values of operations.
Definition: Attributes.h:25
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:63
This class helps build Operations.
Definition: Builders.h:206
void setInsertionPoint(Block *block, Block::iterator insertPoint)
Set the insertion point to the specified location.
Definition: Builders.h:383
void setInsertionPointToEnd(Block *block)
Sets the insertion point to the end of the specified block.
Definition: Builders.h:421
Operation * create(const OperationState &state)
Creates an operation given the fields represented as an OperationState.
Definition: Builders.cpp:446
Operation is the basic unit of execution within MLIR.
Definition: Operation.h:88
Value getOperand(unsigned idx)
Definition: Operation.h:345
Location getLoc()
The source location the operation was defined or derived from.
Definition: Operation.h:223
unsigned getNumOperands()
Definition: Operation.h:341
Operation * getParentOp()
Returns the closest surrounding operation that contains this operation or nullptr if this is a top-le...
Definition: Operation.h:234
Region & getRegion(unsigned index)
Returns the region held by this operation at position 'index'.
Definition: Operation.h:665
result_type_range getResultTypes()
Definition: Operation.h:423
operand_range getOperands()
Returns an iterator on the underlying Value's.
Definition: Operation.h:373
result_range getResults()
Definition: Operation.h:410
A special type of RewriterBase that coordinates the application of a rewrite pattern on the current I...
Definition: PatternMatch.h:727
iterator end()
Definition: Region.h:56
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:660
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:539
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:378
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:94
AffineDmaWaitOp blocks until the completion of a DMA operation associated with the tag element 'tag[i...
Definition: AffineOps.h:291
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:223
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:213
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:2513
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:2503
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, const ConversionTarget &target, const FrozenRewritePatternSet &patterns, DenseSet< Operation * > *unconvertedOps=nullptr)
Below we define several entry points for operation conversion.
Value lowerAffineUpperBound(affine::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
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...
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(affine::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:357