mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-03-04 08:27:50 +00:00
[mlir][bufferization] Define a pipeline for buffer deallocation (#66352)
Since ownership based buffer deallocation requires a few passes to be run in a somewhat fixed sequence, it makes sense to have a pipeline for convenience (and to reduce the number of transform ops to represent default deallocation).
This commit is contained in:
parent
bdac5de428
commit
08b7a71bcc
50
mlir/include/mlir/Dialect/Bufferization/Pipelines/Passes.h
Normal file
50
mlir/include/mlir/Dialect/Bufferization/Pipelines/Passes.h
Normal file
@ -0,0 +1,50 @@
|
||||
//===- Passes.h - Bufferization pipeline entry points -----------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This header file defines prototypes of all bufferization pipelines.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef MLIR_DIALECT_BUFFERIZATION_PIPELINES_PASSES_H
|
||||
#define MLIR_DIALECT_BUFFERIZATION_PIPELINES_PASSES_H
|
||||
|
||||
#include "mlir/Pass/PassOptions.h"
|
||||
|
||||
namespace mlir {
|
||||
namespace bufferization {
|
||||
|
||||
/// Options for the buffer deallocation pipeline.
|
||||
struct BufferDeallocationPipelineOptions
|
||||
: public PassPipelineOptions<BufferDeallocationPipelineOptions> {
|
||||
PassOptions::Option<bool> privateFunctionDynamicOwnership{
|
||||
*this, "private-function-dynamic-ownership",
|
||||
llvm::cl::desc(
|
||||
"Allows to add additional arguments to private functions to "
|
||||
"dynamically pass ownership of memrefs to callees. This can enable "
|
||||
"earlier deallocations."),
|
||||
llvm::cl::init(false)};
|
||||
};
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Building and Registering.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// Adds the buffer deallocation pipeline to the `OpPassManager`. This
|
||||
/// is the standard pipeline for deallocating the MemRefs introduced by the
|
||||
/// One-Shot bufferization pass.
|
||||
void buildBufferDeallocationPipeline(
|
||||
OpPassManager &pm, const BufferDeallocationPipelineOptions &options);
|
||||
|
||||
/// Registers all pipelines for the `bufferization` dialect. Currently,
|
||||
/// this includes only the "buffer-deallocation-pipeline".
|
||||
void registerBufferizationPipelines();
|
||||
|
||||
} // namespace bufferization
|
||||
} // namespace mlir
|
||||
|
||||
#endif // MLIR_DIALECT_BUFFERIZATION_PIPELINES_PASSES_H
|
@ -30,7 +30,8 @@ std::unique_ptr<Pass> createBufferDeallocationPass();
|
||||
|
||||
/// Creates an instance of the OwnershipBasedBufferDeallocation pass to free all
|
||||
/// allocated buffers.
|
||||
std::unique_ptr<Pass> createOwnershipBasedBufferDeallocationPass();
|
||||
std::unique_ptr<Pass> createOwnershipBasedBufferDeallocationPass(
|
||||
bool privateFuncDynamicOwnership = false);
|
||||
|
||||
/// Creates a pass that optimizes `bufferization.dealloc` operations. For
|
||||
/// example, it reduces the number of alias checks needed at runtime using
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "mlir/Dialect/Arith/Transforms/Passes.h"
|
||||
#include "mlir/Dialect/ArmSME/Transforms/Passes.h"
|
||||
#include "mlir/Dialect/Async/Passes.h"
|
||||
#include "mlir/Dialect/Bufferization/Pipelines/Passes.h"
|
||||
#include "mlir/Dialect/Bufferization/Transforms/Passes.h"
|
||||
#include "mlir/Dialect/Func/Transforms/Passes.h"
|
||||
#include "mlir/Dialect/GPU/Transforms/Passes.h"
|
||||
@ -81,6 +82,7 @@ inline void registerAllPasses() {
|
||||
arm_sme::registerArmSMEPasses();
|
||||
|
||||
// Dialect pipelines
|
||||
bufferization::registerBufferizationPipelines();
|
||||
sparse_tensor::registerSparseTensorPipelines();
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
add_subdirectory(IR)
|
||||
add_subdirectory(Pipelines)
|
||||
add_subdirectory(TransformOps)
|
||||
add_subdirectory(Transforms)
|
||||
|
@ -0,0 +1,46 @@
|
||||
//===- BufferizationPipelines.cpp - Pipelines for bufferization -----------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "mlir/Dialect/Bufferization/Pipelines/Passes.h"
|
||||
|
||||
#include "mlir/Dialect/Bufferization/Transforms/Passes.h"
|
||||
#include "mlir/Dialect/Func/IR/FuncOps.h"
|
||||
#include "mlir/Dialect/MemRef/Transforms/Passes.h"
|
||||
#include "mlir/Pass/PassManager.h"
|
||||
#include "mlir/Transforms/Passes.h"
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Pipeline implementation.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
void mlir::bufferization::buildBufferDeallocationPipeline(
|
||||
OpPassManager &pm, const BufferDeallocationPipelineOptions &options) {
|
||||
pm.addNestedPass<func::FuncOp>(
|
||||
memref::createExpandReallocPass(/*emitDeallocs=*/false));
|
||||
pm.addNestedPass<func::FuncOp>(createCanonicalizerPass());
|
||||
pm.addNestedPass<func::FuncOp>(createOwnershipBasedBufferDeallocationPass(
|
||||
options.privateFunctionDynamicOwnership.getValue()));
|
||||
pm.addNestedPass<func::FuncOp>(createCanonicalizerPass());
|
||||
pm.addNestedPass<func::FuncOp>(createBufferDeallocationSimplificationPass());
|
||||
pm.addPass(createLowerDeallocationsPass());
|
||||
pm.addNestedPass<func::FuncOp>(createCSEPass());
|
||||
pm.addNestedPass<func::FuncOp>(createCanonicalizerPass());
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Pipeline registration.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
void mlir::bufferization::registerBufferizationPipelines() {
|
||||
PassPipelineRegistration<BufferDeallocationPipelineOptions>(
|
||||
"buffer-deallocation-pipeline",
|
||||
"The default pipeline for automatically inserting deallocation "
|
||||
"operations after one-shot bufferization. Deallocation operations "
|
||||
"(except `memref.realloc`) may not be present already.",
|
||||
buildBufferDeallocationPipeline);
|
||||
}
|
13
mlir/lib/Dialect/Bufferization/Pipelines/CMakeLists.txt
Normal file
13
mlir/lib/Dialect/Bufferization/Pipelines/CMakeLists.txt
Normal file
@ -0,0 +1,13 @@
|
||||
add_mlir_dialect_library(MLIRBufferizationPipelines
|
||||
BufferizationPipelines.cpp
|
||||
|
||||
ADDITIONAL_HEADER_DIRS
|
||||
${MLIR_MAIN_INCLUDE_DIR}/mlir/Dialect/Bufferization
|
||||
|
||||
LINK_LIBS PUBLIC
|
||||
MLIRBufferizationTransforms
|
||||
MLIRMemRefTransforms
|
||||
MLIRFuncDialect
|
||||
MLIRPass
|
||||
MLIRTransforms
|
||||
)
|
@ -994,6 +994,11 @@ namespace {
|
||||
struct OwnershipBasedBufferDeallocationPass
|
||||
: public bufferization::impl::OwnershipBasedBufferDeallocationBase<
|
||||
OwnershipBasedBufferDeallocationPass> {
|
||||
OwnershipBasedBufferDeallocationPass() = default;
|
||||
OwnershipBasedBufferDeallocationPass(bool privateFuncDynamicOwnership)
|
||||
: OwnershipBasedBufferDeallocationPass() {
|
||||
this->privateFuncDynamicOwnership.setValue(privateFuncDynamicOwnership);
|
||||
}
|
||||
void runOnOperation() override {
|
||||
func::FuncOp func = getOperation();
|
||||
if (func.isExternal())
|
||||
@ -1025,6 +1030,8 @@ LogicalResult bufferization::deallocateBuffersOwnershipBased(
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
std::unique_ptr<Pass>
|
||||
mlir::bufferization::createOwnershipBasedBufferDeallocationPass() {
|
||||
return std::make_unique<OwnershipBasedBufferDeallocationPass>();
|
||||
mlir::bufferization::createOwnershipBasedBufferDeallocationPass(
|
||||
bool privateFuncDynamicOwnership) {
|
||||
return std::make_unique<OwnershipBasedBufferDeallocationPass>(
|
||||
privateFuncDynamicOwnership);
|
||||
}
|
||||
|
@ -2,6 +2,8 @@
|
||||
// RUN: -buffer-deallocation-simplification -split-input-file %s | FileCheck %s
|
||||
// RUN: mlir-opt -verify-diagnostics -ownership-based-buffer-deallocation=private-function-dynamic-ownership=true -split-input-file %s > /dev/null
|
||||
|
||||
// RUN: mlir-opt %s -buffer-deallocation-pipeline --split-input-file > /dev/null
|
||||
|
||||
// Test Case:
|
||||
// bb0
|
||||
// / \
|
||||
|
@ -3,6 +3,9 @@
|
||||
// RUN: mlir-opt -verify-diagnostics -ownership-based-buffer-deallocation=private-function-dynamic-ownership=true \
|
||||
// RUN: --buffer-deallocation-simplification -split-input-file %s | FileCheck %s --check-prefix=CHECK-DYNAMIC
|
||||
|
||||
// RUN: mlir-opt %s -buffer-deallocation-pipeline --split-input-file > /dev/null
|
||||
// RUN: mlir-opt %s -buffer-deallocation-pipeline=private-function-dynamic-ownership --split-input-file > /dev/null
|
||||
|
||||
func.func private @f(%arg0: memref<f64>) -> memref<f64> {
|
||||
return %arg0 : memref<f64>
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
// RUN: mlir-opt -verify-diagnostics -expand-realloc=emit-deallocs=false -ownership-based-buffer-deallocation \
|
||||
// RUN: --buffer-deallocation-simplification -split-input-file %s | FileCheck %s
|
||||
|
||||
// RUN: mlir-opt %s -buffer-deallocation-pipeline --split-input-file > /dev/null
|
||||
|
||||
func.func @auto_dealloc() {
|
||||
%c10 = arith.constant 10 : index
|
||||
%c100 = arith.constant 100 : index
|
||||
|
@ -3,6 +3,9 @@
|
||||
// RUN: mlir-opt --allow-unregistered-dialect -verify-diagnostics -ownership-based-buffer-deallocation=private-function-dynamic-ownership=true \
|
||||
// RUN: --buffer-deallocation-simplification -split-input-file %s | FileCheck %s --check-prefix=CHECK-DYNAMIC
|
||||
|
||||
// RUN: mlir-opt %s -buffer-deallocation-pipeline --split-input-file > /dev/null
|
||||
// RUN: mlir-opt %s -buffer-deallocation-pipeline=private-function-dynamic-ownership --split-input-file > /dev/null
|
||||
|
||||
// Test Case: Existing AllocOp with no users.
|
||||
// BufferDeallocation expected behavior: It should insert a DeallocOp right
|
||||
// before ReturnOp.
|
||||
|
@ -2,6 +2,8 @@
|
||||
// RUN: --buffer-deallocation-simplification -split-input-file %s | FileCheck %s
|
||||
// RUN: mlir-opt -verify-diagnostics -ownership-based-buffer-deallocation=private-function-dynamic-ownership=true -split-input-file %s > /dev/null
|
||||
|
||||
// RUN: mlir-opt %s -buffer-deallocation-pipeline --split-input-file > /dev/null
|
||||
|
||||
// Test Case: Dead operations in a single block.
|
||||
// BufferDeallocation expected behavior: It only inserts the two missing
|
||||
// DeallocOps after the last BufferBasedOp.
|
||||
|
@ -2,6 +2,8 @@
|
||||
// RUN: --buffer-deallocation-simplification -split-input-file %s | FileCheck %s
|
||||
// RUN: mlir-opt -allow-unregistered-dialect -verify-diagnostics -ownership-based-buffer-deallocation=private-function-dynamic-ownership=true -split-input-file %s > /dev/null
|
||||
|
||||
// RUN: mlir-opt %s -buffer-deallocation-pipeline --split-input-file --verify-diagnostics > /dev/null
|
||||
|
||||
// Test Case: Nested regions - This test defines a BufferBasedOp inside the
|
||||
// region of a RegionBufferBasedOp.
|
||||
// BufferDeallocation expected behavior: The AllocOp for the BufferBasedOp
|
||||
|
@ -2,6 +2,8 @@
|
||||
// RUN: --buffer-deallocation-simplification -split-input-file %s | FileCheck %s
|
||||
// RUN: mlir-opt -verify-diagnostics -ownership-based-buffer-deallocation=private-function-dynamic-ownership=true -split-input-file %s > /dev/null
|
||||
|
||||
// RUN: mlir-opt %s -buffer-deallocation-pipeline --split-input-file > /dev/null
|
||||
|
||||
// CHECK-LABEL: func @subview
|
||||
func.func @subview(%arg0 : index, %arg1 : index, %arg2 : memref<?x?xf32>) {
|
||||
%0 = memref.alloc() : memref<64x4xf32, strided<[4, 1], offset: 0>>
|
||||
|
@ -8249,6 +8249,7 @@ cc_library(
|
||||
":AsyncToLLVM",
|
||||
":AsyncTransforms",
|
||||
":BufferizationDialect",
|
||||
":BufferizationPipelines",
|
||||
":BufferizationTransformOps",
|
||||
":BufferizationTransforms",
|
||||
":CastInterfaces",
|
||||
@ -12214,6 +12215,21 @@ cc_library(
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "BufferizationPipelines",
|
||||
srcs = glob(["lib/Dialect/Bufferization/Pipelines/*.cpp"]),
|
||||
hdrs = ["include/mlir/Dialect/Bufferization/Pipelines/Passes.h"],
|
||||
includes = ["include"],
|
||||
deps = [
|
||||
":BufferizationToMemRef",
|
||||
":BufferizationTransforms",
|
||||
":FuncDialect",
|
||||
":MemRefTransforms",
|
||||
":Pass",
|
||||
":Transforms",
|
||||
],
|
||||
)
|
||||
|
||||
td_library(
|
||||
name = "DLTIDialectTdFiles",
|
||||
srcs = [
|
||||
|
Loading…
x
Reference in New Issue
Block a user