Skip to content

[mlir][bufferization] Define a pipeline for buffer deallocation #66352

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions mlir/include/mlir/Dialect/Bufferization/Pipelines/Passes.h
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions mlir/include/mlir/InitAllPasses.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -81,6 +82,7 @@ inline void registerAllPasses() {
arm_sme::registerArmSMEPasses();

// Dialect pipelines
bufferization::registerBufferizationPipelines();
sparse_tensor::registerSparseTensorPipelines();
}

Expand Down
1 change: 1 addition & 0 deletions mlir/lib/Dialect/Bufferization/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
add_subdirectory(IR)
add_subdirectory(Pipelines)
add_subdirectory(TransformOps)
add_subdirectory(Transforms)
Original file line number Diff line number Diff line change
@@ -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 changes: 13 additions & 0 deletions mlir/lib/Dialect/Bufferization/Pipelines/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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
)
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand Down Expand Up @@ -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);
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
// / \
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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>
}
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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>>
Expand Down
16 changes: 16 additions & 0 deletions utils/bazel/llvm-project-overlay/mlir/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -8249,6 +8249,7 @@ cc_library(
":AsyncToLLVM",
":AsyncTransforms",
":BufferizationDialect",
":BufferizationPipelines",
":BufferizationTransformOps",
":BufferizationTransforms",
":CastInterfaces",
Expand Down Expand Up @@ -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 = [
Expand Down