MLIR  17.0.0git
Bufferize.cpp
Go to the documentation of this file.
1 //===- Bufferize.cpp - Bufferization utilities ----------------------------===//
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 
10 
19 #include "mlir/IR/Operation.h"
21 #include "mlir/Pass/PassManager.h"
23 #include "mlir/Transforms/Passes.h"
24 #include <optional>
25 
26 namespace mlir {
27 namespace bufferization {
28 #define GEN_PASS_DEF_FINALIZINGBUFFERIZE
29 #define GEN_PASS_DEF_BUFFERIZATIONBUFFERIZE
30 #define GEN_PASS_DEF_ONESHOTBUFFERIZE
31 #include "mlir/Dialect/Bufferization/Transforms/Passes.h.inc"
32 } // namespace bufferization
33 } // namespace mlir
34 
35 #define DEBUG_TYPE "bufferize"
36 
37 using namespace mlir;
38 using namespace mlir::bufferization;
39 
40 //===----------------------------------------------------------------------===//
41 // BufferizeTypeConverter
42 //===----------------------------------------------------------------------===//
43 
45  ValueRange inputs, Location loc) {
46  assert(inputs.size() == 1);
47  assert(inputs[0].getType().isa<BaseMemRefType>());
48  return builder.create<bufferization::ToTensorOp>(loc, type, inputs[0]);
49 }
50 
51 /// Registers conversions into BufferizeTypeConverter
53  // Keep all types unchanged.
54  addConversion([](Type type) { return type; });
55  // Convert RankedTensorType to MemRefType.
56  addConversion([](RankedTensorType type) -> Type {
57  return MemRefType::get(type.getShape(), type.getElementType());
58  });
59  // Convert UnrankedTensorType to UnrankedMemRefType.
60  addConversion([](UnrankedTensorType type) -> Type {
61  return UnrankedMemRefType::get(type.getElementType(), 0);
62  });
66  ValueRange inputs, Location loc) -> Value {
67  assert(inputs.size() == 1 && "expected exactly one input");
68 
69  if (auto inputType = inputs[0].getType().dyn_cast<MemRefType>()) {
70  // MemRef to MemRef cast.
71  assert(inputType != type && "expected different types");
72  // Unranked to ranked and ranked to unranked casts must be explicit.
73  auto rankedDestType = type.dyn_cast<MemRefType>();
74  if (!rankedDestType)
75  return nullptr;
76  FailureOr<Value> replacement =
77  castOrReallocMemRefValue(builder, inputs[0], rankedDestType);
78  if (failed(replacement))
79  return nullptr;
80  return *replacement;
81  }
82 
83  if (inputs[0].getType().isa<TensorType>()) {
84  // Tensor to MemRef cast.
85  return builder.create<bufferization::ToMemrefOp>(loc, type, inputs[0]);
86  }
87 
88  llvm_unreachable("only tensor/memref input types supported");
89  });
90 }
91 
93  ConversionTarget &target) {
94  target.addLegalOp<bufferization::ToTensorOp, bufferization::ToMemrefOp>();
95 }
96 
97 namespace {
98 // In a finalizing bufferize conversion, we know that all tensors have been
99 // converted to memrefs, thus, this op becomes an identity.
100 class BufferizeToTensorOp
101  : public OpConversionPattern<bufferization::ToTensorOp> {
102 public:
105  matchAndRewrite(bufferization::ToTensorOp op, OpAdaptor adaptor,
106  ConversionPatternRewriter &rewriter) const override {
107  rewriter.replaceOp(op, adaptor.getMemref());
108  return success();
109  }
110 };
111 } // namespace
112 
113 namespace {
114 // In a finalizing bufferize conversion, we know that all tensors have been
115 // converted to memrefs, thus, this op becomes an identity.
116 class BufferizeToMemrefOp
117  : public OpConversionPattern<bufferization::ToMemrefOp> {
118 public:
121  matchAndRewrite(bufferization::ToMemrefOp op, OpAdaptor adaptor,
122  ConversionPatternRewriter &rewriter) const override {
123  rewriter.replaceOp(op, adaptor.getTensor());
124  return success();
125  }
126 };
127 } // namespace
128 
130  BufferizeTypeConverter &typeConverter, RewritePatternSet &patterns) {
131  patterns.add<BufferizeToTensorOp, BufferizeToMemrefOp>(typeConverter,
132  patterns.getContext());
133 }
134 
135 namespace {
136 struct FinalizingBufferizePass
137  : public bufferization::impl::FinalizingBufferizeBase<
138  FinalizingBufferizePass> {
139  using FinalizingBufferizeBase<
140  FinalizingBufferizePass>::FinalizingBufferizeBase;
141 
142  void runOnOperation() override {
143  auto func = getOperation();
144  auto *context = &getContext();
145 
146  BufferizeTypeConverter typeConverter;
147  RewritePatternSet patterns(context);
148  ConversionTarget target(*context);
149 
151 
152  // If all result types are legal, and all block arguments are legal (ensured
153  // by func conversion above), then all types in the program are legal.
154  //
155  // We also check that the operand types are legal to avoid creating invalid
156  // IR. For example, this prevents
157  // populateEliminateBufferizeMaterializationsPatterns from updating the
158  // types of the operands to a return op without updating the enclosing
159  // function.
160  target.markUnknownOpDynamicallyLegal(
161  [&](Operation *op) { return typeConverter.isLegal(op); });
162 
163  if (failed(applyFullConversion(func, target, std::move(patterns))))
164  signalPassFailure();
165  }
166 };
167 
168 static LayoutMapOption parseLayoutMapOption(const std::string &s) {
169  if (s == "fully-dynamic-layout-map")
170  return LayoutMapOption::FullyDynamicLayoutMap;
171  if (s == "identity-layout-map")
172  return LayoutMapOption::IdentityLayoutMap;
173  if (s == "infer-layout-map")
174  return LayoutMapOption::InferLayoutMap;
175  llvm_unreachable("invalid layout map option");
176 }
177 
179 parseHeuristicOption(const std::string &s) {
180  if (s == "bottom-up")
182  if (s == "top-down")
184  llvm_unreachable("invalid analysisheuristic option");
185 }
186 
187 struct OneShotBufferizePass
188  : public bufferization::impl::OneShotBufferizeBase<OneShotBufferizePass> {
189  OneShotBufferizePass() = default;
190 
191  explicit OneShotBufferizePass(const OneShotBufferizationOptions &options)
192  : options(options) {}
193 
194  void getDependentDialects(DialectRegistry &registry) const override {
195  registry
196  .insert<bufferization::BufferizationDialect, memref::MemRefDialect>();
198  }
199 
200  void runOnOperation() override {
202  if (!options) {
203  // Make new bufferization options if none were provided when creating the
204  // pass.
205  opt.allowReturnAllocs = allowReturnAllocs;
206  opt.allowUnknownOps = allowUnknownOps;
207  opt.analysisFuzzerSeed = analysisFuzzerSeed;
208  opt.analysisHeuristic = parseHeuristicOption(analysisHeuristic);
209  opt.copyBeforeWrite = copyBeforeWrite;
210  opt.createDeallocs = createDeallocs;
212  parseLayoutMapOption(functionBoundaryTypeConversion);
213  if (mustInferMemorySpace)
214  opt.defaultMemorySpace = std::nullopt;
215  opt.printConflicts = printConflicts;
216  opt.testAnalysisOnly = testAnalysisOnly;
217  opt.bufferizeFunctionBoundaries = bufferizeFunctionBoundaries;
218  opt.noAnalysisFuncFilter = noAnalysisFuncFilter;
219 
220  // Configure type converter.
221  LayoutMapOption unknownTypeConversionOption =
222  parseLayoutMapOption(unknownTypeConversion);
223  opt.unknownTypeConverterFn = [=](Value value, Attribute memorySpace,
224  const BufferizationOptions &options) {
225  auto tensorType = value.getType().cast<TensorType>();
226  if (unknownTypeConversionOption == LayoutMapOption::IdentityLayoutMap)
228  tensorType, memorySpace);
229  assert(unknownTypeConversionOption ==
230  LayoutMapOption::FullyDynamicLayoutMap &&
231  "invalid layout map option");
233  memorySpace);
234  };
235 
236  // Configure op filter.
237  OpFilter::Entry::FilterFn filterFn = [&](Operation *op) {
238  // Filter may be specified via options.
239  if (this->dialectFilter.hasValue())
240  return llvm::is_contained(this->dialectFilter,
241  op->getDialect()->getNamespace());
242  // No filter specified: All other ops are allowed.
243  return true;
244  };
245  opt.opFilter.allowOperation(filterFn);
246  } else {
247  opt = *options;
248  }
249 
250  BufferizationStatistics statistics;
251  ModuleOp moduleOp = getOperation();
252  if (opt.bufferizeFunctionBoundaries) {
253  if (failed(runOneShotModuleBufferize(moduleOp, opt, &statistics))) {
254  signalPassFailure();
255  return;
256  }
257  } else {
258  assert(opt.noAnalysisFuncFilter.empty() &&
259  "invalid combination of bufferization flags");
260  if (failed(runOneShotBufferize(moduleOp, opt, &statistics))) {
261  signalPassFailure();
262  return;
263  }
264  }
265 
266  // Set pass statistics.
267  this->numBufferAlloc = statistics.numBufferAlloc;
268  this->numBufferDealloc = statistics.numBufferDealloc;
269  this->numTensorInPlace = statistics.numTensorInPlace;
270  this->numTensorOutOfPlace = statistics.numTensorOutOfPlace;
271 
272  if (opt.testAnalysisOnly)
273  return;
274 
275  OpPassManager cleanupPipeline("builtin.module");
276  cleanupPipeline.addPass(createCanonicalizerPass());
277  cleanupPipeline.addPass(createCSEPass());
278  cleanupPipeline.addPass(createLoopInvariantCodeMotionPass());
279  (void)runPipeline(cleanupPipeline, moduleOp);
280  }
281 
282 private:
283  std::optional<OneShotBufferizationOptions> options;
284 };
285 } // namespace
286 
287 namespace {
288 struct BufferizationBufferizePass
289  : public bufferization::impl::BufferizationBufferizeBase<
290  BufferizationBufferizePass> {
291  void runOnOperation() override {
293  options.opFilter.allowDialect<BufferizationDialect>();
294 
295  if (failed(bufferizeOp(getOperation(), options)))
296  signalPassFailure();
297  }
298 
299  void getDependentDialects(DialectRegistry &registry) const override {
300  registry
301  .insert<bufferization::BufferizationDialect, memref::MemRefDialect>();
302  }
303 };
304 } // namespace
305 
307  return std::make_unique<BufferizationBufferizePass>();
308 }
309 
311  return std::make_unique<OneShotBufferizePass>();
312 }
313 
316  return std::make_unique<OneShotBufferizePass>(options);
317 }
318 
319 std::unique_ptr<OperationPass<func::FuncOp>>
321  return std::make_unique<FinalizingBufferizePass>();
322 }
323 
324 //===----------------------------------------------------------------------===//
325 // BufferizableOpInterface-based Bufferization
326 //===----------------------------------------------------------------------===//
327 
328 static bool isaTensor(Type t) { return t.isa<TensorType>(); }
329 
330 /// Return true if the given op has a tensor result or a tensor operand.
331 static bool hasTensorSemantics(Operation *op) {
332  if (auto funcOp = dyn_cast<FunctionOpInterface>(op)) {
333  bool hasTensorArg = any_of(funcOp.getArgumentTypes(), isaTensor);
334  bool hasTensorResult = any_of(funcOp.getResultTypes(), isaTensor);
335  return hasTensorArg || hasTensorResult;
336  }
337 
338  bool hasTensorResult = any_of(op->getResultTypes(), isaTensor);
339  bool hasTensorOperand = any_of(op->getOperandTypes(), isaTensor);
340  return hasTensorResult || hasTensorOperand;
341 }
342 
343 namespace {
344 /// A rewriter that keeps track of extra information during bufferization.
345 class BufferizationRewriter : public IRRewriter {
346 public:
347  BufferizationRewriter(MLIRContext *ctx, DenseSet<Operation *> &erasedOps,
348  DenseSet<Operation *> &toMemrefOps,
349  SmallVector<Operation *> &worklist,
351  const OpFilter *opFilter,
352  BufferizationStatistics *statistics)
353  : IRRewriter(ctx), erasedOps(erasedOps), toMemrefOps(toMemrefOps),
354  worklist(worklist), analysisState(options), opFilter(opFilter),
355  statistics(statistics) {}
356 
357 protected:
358  void notifyOperationRemoved(Operation *op) override {
360  erasedOps.insert(op);
361  // Erase if present.
362  toMemrefOps.erase(op);
363  }
364 
365  void notifyOperationInserted(Operation *op) override {
367  erasedOps.erase(op);
368 
369  // Gather statistics about allocs and deallocs.
370  if (statistics) {
371  if (auto sideEffectingOp = dyn_cast<MemoryEffectOpInterface>(op)) {
372  statistics->numBufferAlloc += static_cast<int64_t>(
373  sideEffectingOp.hasEffect<MemoryEffects::Allocate>());
374  statistics->numBufferDealloc += static_cast<int64_t>(
375  sideEffectingOp.hasEffect<MemoryEffects::Free>());
376  }
377  }
378 
379  // Keep track of to_memref ops.
380  if (isa<ToMemrefOp>(op)) {
381  toMemrefOps.insert(op);
382  return;
383  }
384 
385  // Skip to_tensor ops.
386  if (isa<ToTensorOp>(op))
387  return;
388 
389  // Skip non-tensor ops.
390  if (!hasTensorSemantics(op))
391  return;
392 
393  // Skip ops that are not allowed to be bufferized.
394  auto const &options = analysisState.getOptions();
395  if (!options.isOpAllowed(op) || (opFilter && !opFilter->isOpAllowed(op)))
396  return;
397 
398  // Add op to worklist.
399  worklist.push_back(op);
400  }
401 
402 private:
403  /// A set of all erased ops.
404  DenseSet<Operation *> &erasedOps;
405 
406  /// A set of all to_memref ops.
407  DenseSet<Operation *> &toMemrefOps;
408 
409  /// The worklist of ops to be bufferized.
410  SmallVector<Operation *> &worklist;
411 
412  /// The analysis state. Used for debug assertions and access to the
413  /// bufferization options.
414  const AnalysisState analysisState;
415 
416  /// An extra op filter for bufferization.
417  const OpFilter *opFilter;
418 
419  /// Bufferization statistics for debugging.
420  BufferizationStatistics *statistics;
421 };
422 } // namespace
423 
426  bool copyBeforeWrite,
427  const OpFilter *opFilter,
428  BufferizationStatistics *statistics) {
429  if (copyBeforeWrite) {
430  AnalysisState state(options);
431  if (failed(insertTensorCopies(op, state)))
432  return failure();
433  }
434 
435  // Keep track of to_memref ops.
436  DenseSet<Operation *> toMemrefOps;
437  op->walk([&](ToMemrefOp toMemrefOp) { toMemrefOps.insert(toMemrefOp); });
438 
439  // Gather all bufferizable ops in top-to-bottom order.
440  //
441  // We should ideally know the exact memref type of all operands when
442  // bufferizing an op. (This is the case when bufferizing top-to-bottom.)
443  // Otherwise, we have to use a memref type with a fully dynamic layout map to
444  // avoid copies. We are currently missing patterns for layout maps to
445  // canonicalize away (or canonicalize to more precise layouts).
446  //
447  // FuncOps must be bufferized before their bodies, so add them to the worklist
448  // first.
449  SmallVector<Operation *> worklist;
450  op->walk([&](func::FuncOp funcOp) {
451  if (hasTensorSemantics(funcOp))
452  worklist.push_back(funcOp);
453  });
454  op->walk<WalkOrder::PostOrder>([&](Operation *op) {
455  if (hasTensorSemantics(op) && !isa<func::FuncOp>(op))
456  worklist.push_back(op);
457  });
458 
459  // Keep track of all erased ops.
460  DenseSet<Operation *> erasedOps;
461 
462  // Bufferize all ops.
463  BufferizationRewriter rewriter(op->getContext(), erasedOps, toMemrefOps,
464  worklist, options, opFilter, statistics);
465  for (unsigned i = 0; i < worklist.size(); ++i) {
466  Operation *nextOp = worklist[i];
467  // Skip ops that were erased.
468  if (erasedOps.contains(nextOp))
469  continue;
470  // Skip ops that are not bufferizable or not allowed.
471  auto bufferizableOp = options.dynCastBufferizableOp(nextOp);
472  if (!bufferizableOp)
473  continue;
474  if (opFilter && !opFilter->isOpAllowed(nextOp))
475  continue;
476  // Skip ops that no longer have tensor semantics.
477  if (!hasTensorSemantics(nextOp))
478  continue;
479  // Bufferize the op.
480  LLVM_DEBUG(llvm::dbgs()
481  << "//===-------------------------------------------===//\n"
482  << "IR after bufferizing: " << nextOp->getName() << "\n");
483  rewriter.setInsertionPoint(nextOp);
484  if (failed(bufferizableOp.bufferize(rewriter, options))) {
485  LLVM_DEBUG(llvm::dbgs()
486  << "failed to bufferize\n"
487  << "//===-------------------------------------------===//\n");
488  return nextOp->emitError("failed to bufferize op");
489  }
490  LLVM_DEBUG(llvm::dbgs()
491  << *op
492  << "\n//===-------------------------------------------===//\n");
493  }
494 
495  // Fold all to_memref(to_tensor(x)) pairs.
496  for (Operation *op : toMemrefOps) {
497  rewriter.setInsertionPoint(op);
499  cast<ToMemrefOp>(op));
500  }
501 
502  // Remove all dead to_tensor ops.
503  op->walk<WalkOrder::PostOrder>([&](ToTensorOp toTensorOp) {
504  if (toTensorOp->getUses().empty()) {
505  rewriter.eraseOp(toTensorOp);
506  return WalkResult::skip();
507  }
508  return WalkResult::advance();
509  });
510 
511  /// Check the result of bufferization. Return an error if an op was not
512  /// bufferized, unless partial bufferization is allowed.
513  if (options.allowUnknownOps)
514  return success();
515 
516  for (Operation *op : worklist) {
517  // Skip ops that are entirely gone.
518  if (erasedOps.contains(op))
519  continue;
520  // Ops that no longer have tensor semantics (because they were updated
521  // in-place) are allowed.
522  if (!hasTensorSemantics(op))
523  continue;
524  // Continue ops that are not allowed.
525  if (!options.isOpAllowed(op))
526  continue;
527  if (opFilter && !opFilter->isOpAllowed(op))
528  continue;
529  // Ops without any uses and no side effects will fold away.
530  if (op->getUses().empty() && isMemoryEffectFree(op))
531  continue;
532  // ToTensorOps/ToMemrefOps are allowed in the output.
533  if (isa<ToTensorOp, ToMemrefOp>(op))
534  continue;
535  return op->emitError("op was not bufferized");
536  }
537 
538  return success();
539 }
540 
543  options.allowUnknownOps = true;
544  options.createDeallocs = false;
545  options.enforceAliasingInvariants = false;
546  options.unknownTypeConverterFn = [](Value value, Attribute memorySpace,
547  const BufferizationOptions &options) {
549  value.getType().cast<TensorType>(), memorySpace);
550  };
551  options.opFilter.allowDialect<BufferizationDialect>();
552  return options;
553 }
static Value materializeToTensor(OpBuilder &builder, TensorType type, ValueRange inputs, Location loc)
Definition: Bufferize.cpp:44
static bool isaTensor(Type t)
Definition: Bufferize.cpp:328
static bool hasTensorSemantics(Operation *op)
Return true if the given op has a tensor result or a tensor operand.
Definition: Bufferize.cpp:331
static llvm::ManagedStatic< PassManagerOptions > options
Base class for generic analysis states.
Attributes are known-constant values of operations.
Definition: Attributes.h:25
This class provides a shared interface for ranked and unranked memref types.
Definition: BuiltinTypes.h:113
This class implements a pattern rewriter for use with ConversionPatterns.
void replaceOp(Operation *op, ValueRange newValues) override
PatternRewriter hook for replacing the results of an operation.
This class describes a specific conversion target.
void addLegalOp(OperationName op)
Register the given operations as legal.
The DialectRegistry maps a dialect namespace to a constructor for the matching dialect.
StringRef getNamespace() const
Definition: Dialect.h:57
This class provides support for representing a failure result, or a valid value of type T.
Definition: LogicalResult.h:78
This class coordinates rewriting a piece of IR outside of a pattern rewrite, providing a way to keep ...
Definition: PatternMatch.h:605
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition: Location.h:63
MLIRContext is the top-level object for a collection of MLIR operations.
Definition: MLIRContext.h:56
This class helps build Operations.
Definition: Builders.h:199
Operation * create(const OperationState &state)
Creates an operation given the fields represented as an OperationState.
Definition: Builders.cpp:422
OpConversionPattern is a wrapper around ConversionPattern that allows for matching and rewriting agai...
OpConversionPattern(MLIRContext *context, PatternBenefit benefit=1)
This class represents a pass manager that runs passes on either a specific operation type,...
Definition: PassManager.h:52
Operation is the basic unit of execution within MLIR.
Definition: Operation.h:75
Dialect * getDialect()
Return the dialect this operation is associated with, or nullptr if the associated dialect is not loa...
Definition: Operation.h:195
MLIRContext * getContext()
Return the context this operation is associated with.
Definition: Operation.h:191
InFlightDiagnostic emitError(const Twine &message={})
Emit an error about fatal conditions with this operation, reporting up to any diagnostic handlers tha...
Definition: Operation.cpp:224
OperationName getName()
The name of an operation is the key identifier for it.
Definition: Operation.h:94
operand_type_range getOperandTypes()
Definition: Operation.h:358
result_type_range getResultTypes()
Definition: Operation.h:389
use_range getUses()
Returns a range of all uses, which is useful for iterating over all uses.
Definition: Operation.h:669
std::enable_if_t< llvm::function_traits< std::decay_t< FnT > >::num_args==1, RetT > walk(FnT &&callback)
Walk the operation by calling the callback for each nested operation (including this one),...
Definition: Operation.h:620
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.
virtual void notifyOperationRemoved(Operation *op)
This is called on an operation that a rewrite is removing, right before the operation is deleted.
Definition: PatternMatch.h:576
Tensor types represent multi-dimensional arrays, and have two variants: RankedTensorType and Unranked...
Definition: BuiltinTypes.h:77
void addConversion(FnT &&callback)
Register a conversion function.
void addArgumentMaterialization(FnT &&callback)
Register a materialization function, which must be convertible to the following form: std::optional<V...
bool isLegal(Type type)
Return true if the given type is legal for this type converter, i.e.
void addSourceMaterialization(FnT &&callback)
This method registers a materialization that will be called when converting a legal type to an illega...
void addTargetMaterialization(FnT &&callback)
This method registers a materialization that will be called when converting type from an illegal,...
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition: Types.h:74
U cast() const
Definition: Types.h:318
U dyn_cast() const
Definition: Types.h:308
bool isa() const
Definition: Types.h:298
This class provides an abstraction over the different types of ranges over Values.
Definition: ValueRange.h:350
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition: Value.h:93
Type getType() const
Return the type of this value.
Definition: Value.h:122
static WalkResult skip()
Definition: Visitors.h:53
static WalkResult advance()
Definition: Visitors.h:52
AnalysisState provides a variety of helper functions for dealing with tensor values.
A helper type converter class that automatically populates the relevant materializations and type con...
Definition: Bufferize.h:43
BufferizeTypeConverter()
Registers conversions into BufferizeTypeConverter.
Definition: Bufferize.cpp:52
bool isOpAllowed(Operation *op) const
Return whether the op is allowed or not.
void allowOperation()
Allow the given ops.
LogicalResult runOneShotBufferize(Operation *op, const OneShotBufferizationOptions &options, BufferizationStatistics *statistics=nullptr)
Run One-Shot Bufferize on the given op: Analysis + Bufferization.
BaseMemRefType getMemRefTypeWithStaticIdentityLayout(TensorType tensorType, Attribute memorySpace=nullptr)
Return a MemRef type with a static identity layout (i.e., no layout map).
void populateEliminateBufferizeMaterializationsPatterns(BufferizeTypeConverter &typeConverter, RewritePatternSet &patterns)
Populate patterns to eliminate bufferize materializations.
Definition: Bufferize.cpp:129
LogicalResult runOneShotModuleBufferize(ModuleOp moduleOp, const bufferization::OneShotBufferizationOptions &options, BufferizationStatistics *statistics=nullptr)
Run One-Shot Module Bufferization on the given module.
void populateBufferizeMaterializationLegality(ConversionTarget &target)
Marks ops used by bufferization for type conversion materializations as "legal" in the given Conversi...
Definition: Bufferize.cpp:92
LogicalResult foldToMemrefToTensorPair(RewriterBase &rewriter, ToMemrefOp toMemref)
Try to fold to_memref(to_tensor(x)).
LogicalResult bufferizeOp(Operation *op, const BufferizationOptions &options, bool copyBeforeWrite=true, const OpFilter *opFilter=nullptr, BufferizationStatistics *statistics=nullptr)
Bufferize op and its nested ops that implement BufferizableOpInterface.
Definition: Bufferize.cpp:424
void registerAllocationOpInterfaceExternalModels(DialectRegistry &registry)
Register external models for AllocationOpInterface.
LogicalResult insertTensorCopies(Operation *op, const OneShotBufferizationOptions &options, BufferizationStatistics *statistics=nullptr)
Resolve RaW and other conflicts by inserting bufferization.alloc_tensor ops.
std::unique_ptr< OperationPass< func::FuncOp > > createFinalizingBufferizePass()
Creates a pass that finalizes a partial bufferization by removing remaining bufferization....
Definition: Bufferize.cpp:320
std::unique_ptr< Pass > createOneShotBufferizePass()
Create a pass that bufferizes all ops that implement BufferizableOpInterface with One-Shot Bufferize.
Definition: Bufferize.cpp:310
BufferizationOptions getPartialBufferizationOptions()
Definition: Bufferize.cpp:541
FailureOr< Value > castOrReallocMemRefValue(OpBuilder &b, Value value, MemRefType type)
Try to cast the given ranked MemRef-typed value to the given ranked MemRef type.
std::unique_ptr< Pass > createBufferizationBufferizePass()
Create a pass that bufferizes ops from the bufferization dialect.
Definition: Bufferize.cpp:306
BaseMemRefType getMemRefTypeWithFullyDynamicLayout(TensorType tensorType, Attribute memorySpace=nullptr)
Return a MemRef type with fully dynamic layout.
Include the generated interface declarations.
LogicalResult failure(bool isFailure=true)
Utility function to generate a LogicalResult.
Definition: LogicalResult.h:62
std::unique_ptr< Pass > createCSEPass()
Creates a pass to perform common sub expression elimination.
Definition: CSE.cpp:353
std::unique_ptr< Pass > createLoopInvariantCodeMotionPass()
Creates a loop invariant code motion pass that hoists loop invariant instructions out of the loop.
bool isMemoryEffectFree(Operation *op)
Returns true if the given operation is free of memory effects.
LogicalResult success(bool isSuccess=true)
Utility function to generate a LogicalResult.
Definition: LogicalResult.h:56
LogicalResult applyFullConversion(ArrayRef< Operation * > ops, ConversionTarget &target, const FrozenRewritePatternSet &patterns)
Apply a complete conversion on the given operations, and all nested operations.
std::unique_ptr< Pass > createCanonicalizerPass()
Creates an instance of the Canonicalizer pass, configured with default settings (which can be overrid...
bool failed(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a failure value.
Definition: LogicalResult.h:72
This class represents an efficient way to signal success or failure.
Definition: LogicalResult.h:26
The following effect indicates that the operation allocates from some resource.
The following effect indicates that the operation frees some resource that has been allocated.
virtual void notifyOperationInserted(Operation *op)
Notification handler for when an operation is inserted into the builder.
Definition: Builders.h:261
Options for BufferizableOpInterface-based bufferization.
bool createDeallocs
Specifies whether dealloc ops should be generated along with alloc ops.
bool copyBeforeWrite
If set to true, the analysis is skipped.
unsigned analysisFuzzerSeed
Seed for the analysis fuzzer.
bool allowUnknownOps
Specifies whether not bufferizable ops are allowed in the input.
LayoutMapOption functionBoundaryTypeConversion
This flag controls buffer types on function signatures.
bool printConflicts
If set to true, the IR is annotated with details about RaW conflicts.
bool testAnalysisOnly
If set to true, does not modify the IR apart from adding attributes (for checking the results of the ...
OpFilter opFilter
A filter that specifies which ops should be bufferized and which ops should be ignored.
std::optional< Attribute > defaultMemorySpace
The default memory space that should be used when it cannot be inferred from the context.
UnknownTypeConverterFn unknownTypeConverterFn
Type converter from tensors to memrefs.
bool bufferizeFunctionBoundaries
Specifies whether function boundaries (ops in the func dialect) should be bufferized or not.
Bufferization statistics for debugging.
Definition: Bufferize.h:34
Options for analysis-enabled bufferization.
AnalysisHeuristic analysisHeuristic
The heuristic controls the order in which ops are traversed during the analysis.
bool allowReturnAllocs
Specifies whether returning newly allocated memrefs should be allowed.
llvm::ArrayRef< std::string > noAnalysisFuncFilter
Specify the functions that should not be analyzed.
std::function< bool(Operation *)> FilterFn
If the filter function evaluates to true, the filter matches.