forked from OSchip/llvm-project
[mlir] Move the Buffer related source files out of Transforms/
Transforms/ should only contain dialect-independent transformations, and these files are a much better fit for the bufferization dialect anyways. Differential Revision: https://reviews.llvm.org/D117839
This commit is contained in:
parent
e01e4c9115
commit
0e9a4a3b65
|
@ -11,13 +11,12 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef MLIR_TRANSFORMS_BUFFERUTILS_H
|
||||
#define MLIR_TRANSFORMS_BUFFERUTILS_H
|
||||
#ifndef MLIR_DIALECT_BUFFERIZATION_TRANSFORMS_BUFFERUTILS_H
|
||||
#define MLIR_DIALECT_BUFFERIZATION_TRANSFORMS_BUFFERUTILS_H
|
||||
|
||||
#include "mlir/Analysis/BufferViewFlowAnalysis.h"
|
||||
#include "mlir/Analysis/Liveness.h"
|
||||
#include "mlir/Dialect/Arithmetic/IR/Arithmetic.h"
|
||||
#include "mlir/Dialect/StandardOps/IR/Ops.h"
|
||||
#include "mlir/IR/Builders.h"
|
||||
#include "mlir/IR/BuiltinOps.h"
|
||||
#include "mlir/IR/Dominance.h"
|
||||
|
@ -25,6 +24,11 @@
|
|||
#include "mlir/Transforms/DialectConversion.h"
|
||||
|
||||
namespace mlir {
|
||||
namespace memref {
|
||||
class GlobalOp;
|
||||
} // namespace memref
|
||||
|
||||
namespace bufferization {
|
||||
|
||||
/// A simple analysis that detects allocation operations.
|
||||
class BufferPlacementAllocs {
|
||||
|
@ -117,10 +121,6 @@ protected:
|
|||
Liveness liveness;
|
||||
};
|
||||
|
||||
namespace memref {
|
||||
class GlobalOp;
|
||||
} // namespace memref
|
||||
|
||||
// Support class to create global ops for tensor-valued constants in the
|
||||
// program. Globals are created lazily at the top of the `moduleOp` with pretty
|
||||
// names. Duplicates are avoided.
|
||||
|
@ -137,6 +137,7 @@ private:
|
|||
// dependence to the memref dialect for this.
|
||||
DenseMap<Attribute, Operation *> globals;
|
||||
};
|
||||
} // namespace bufferization
|
||||
} // namespace mlir
|
||||
|
||||
#endif // MLIR_TRANSFORMS_BUFFERUTILS_H
|
||||
#endif // MLIR_DIALECT_BUFFERIZATION_TRANSFORMS_BUFFERUTILS_H
|
|
@ -14,10 +14,34 @@ namespace bufferization {
|
|||
/// buffers.
|
||||
std::unique_ptr<Pass> createBufferDeallocationPass();
|
||||
|
||||
/// Creates a pass that moves allocations upwards to reduce the number of
|
||||
/// required copies that are inserted during the BufferDeallocation pass.
|
||||
std::unique_ptr<Pass> createBufferHoistingPass();
|
||||
|
||||
/// Creates a pass that moves allocations upwards out of loops. This avoids
|
||||
/// reallocations inside of loops.
|
||||
std::unique_ptr<Pass> createBufferLoopHoistingPass();
|
||||
|
||||
/// Creates a pass that converts memref function results to out-params.
|
||||
std::unique_ptr<Pass> createBufferResultsToOutParamsPass();
|
||||
|
||||
/// Creates a pass that finalizes a partial bufferization by removing remaining
|
||||
/// bufferization.to_tensor and bufferization.to_memref operations.
|
||||
std::unique_ptr<OperationPass<FuncOp>> createFinalizingBufferizePass();
|
||||
|
||||
/// Creates a pass that promotes heap-based allocations to stack-based ones.
|
||||
/// Only buffers smaller than the provided size are promoted.
|
||||
/// Dynamic shaped buffers are promoted up to the given rank.
|
||||
std::unique_ptr<Pass>
|
||||
createPromoteBuffersToStackPass(unsigned maxAllocSizeInBytes = 1024,
|
||||
unsigned bitwidthOfIndexType = 64,
|
||||
unsigned maxRankOfAllocatedMemRef = 1);
|
||||
|
||||
/// Creates a pass that promotes heap-based allocations to stack-based ones.
|
||||
/// Only buffers smaller with `isSmallAlloc(alloc) == true` are promoted.
|
||||
std::unique_ptr<Pass>
|
||||
createPromoteBuffersToStackPass(std::function<bool(Value)> isSmallAlloc);
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Registration
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -88,6 +88,51 @@ def BufferDeallocation : Pass<"buffer-deallocation", "FuncOp"> {
|
|||
let constructor = "mlir::bufferization::createBufferDeallocationPass()";
|
||||
}
|
||||
|
||||
def BufferHoisting : Pass<"buffer-hoisting", "FuncOp"> {
|
||||
let summary = "Optimizes placement of allocation operations by moving them "
|
||||
"into common dominators and out of nested regions";
|
||||
let description = [{
|
||||
This pass implements an approach to aggressively move allocations upwards
|
||||
into common dominators and out of nested regions.
|
||||
}];
|
||||
let constructor = "mlir::bufferization::createBufferHoistingPass()";
|
||||
}
|
||||
|
||||
def BufferLoopHoisting : Pass<"buffer-loop-hoisting", "FuncOp"> {
|
||||
let summary = "Optimizes placement of allocation operations by moving them "
|
||||
"out of loop nests";
|
||||
let description = [{
|
||||
This pass implements an approach to aggressively move allocations upwards
|
||||
out of loop nests. It does not move allocations into common dominators.
|
||||
}];
|
||||
let constructor = "mlir::bufferization::createBufferLoopHoistingPass()";
|
||||
}
|
||||
|
||||
def BufferResultsToOutParams : Pass<"buffer-results-to-out-params", "ModuleOp"> {
|
||||
let summary = "Converts memref-typed function results to out-params";
|
||||
let description = [{
|
||||
Some calling conventions prefer to pass output memrefs as "out params". The
|
||||
conversion to this calling convention must be done as an atomic
|
||||
transformation of the entire program (hence this is a module pass).
|
||||
|
||||
For example, if a call is rewritten, the callee needs to be rewritten
|
||||
otherwise the IR will end up invalid. Thus, this transformation
|
||||
require an atomic change to the entire program (e.g. the whole module).
|
||||
|
||||
This pass is expected to run immediately after bufferization is finished.
|
||||
At that point, tensor-typed results will have been converted to memref-typed
|
||||
results, and can be consistently converted to out params.
|
||||
|
||||
All memref-typed results are appended to the function argument list.
|
||||
|
||||
The main issue with this pass (and the out-param calling convention) is that
|
||||
buffers for results need to be allocated in the caller. This currently only
|
||||
works for static shaped memrefs.
|
||||
}];
|
||||
let constructor = "mlir::bufferization::createBufferResultsToOutParamsPass()";
|
||||
let dependentDialects = ["memref::MemRefDialect"];
|
||||
}
|
||||
|
||||
def FinalizingBufferize : Pass<"finalizing-bufferize", "FuncOp"> {
|
||||
let summary = "Finalize a partial bufferization";
|
||||
let description = [{
|
||||
|
@ -104,4 +149,28 @@ def FinalizingBufferize : Pass<"finalizing-bufferize", "FuncOp"> {
|
|||
let constructor = "mlir::bufferization::createFinalizingBufferizePass()";
|
||||
}
|
||||
|
||||
def PromoteBuffersToStack : Pass<"promote-buffers-to-stack", "FuncOp"> {
|
||||
let summary = "Promotes heap-based allocations to automatically managed "
|
||||
"stack-based allocations";
|
||||
let description = [{
|
||||
This pass implements a simple algorithm to convert heap-based memory
|
||||
allocations to stack-based ones. It uses a built-in heuristic to decide
|
||||
whether it makes sense to convert an allocation. Furthermore, dynamic
|
||||
shaped buffers that are limited by the rank of the tensor can be
|
||||
converted. They are only transformed if they are considered to be small.
|
||||
}];
|
||||
let constructor = "mlir::bufferization::createPromoteBuffersToStackPass()";
|
||||
let options = [
|
||||
Option<"maxAllocSizeInBytes", "max-alloc-size-in-bytes", "unsigned",
|
||||
/*default=*/"1024",
|
||||
"Maximal size in bytes to promote allocations to stack.">,
|
||||
Option<"bitwidthOfIndexType", "bitwidth-of-index-type", "unsigned",
|
||||
/*default=*/"64",
|
||||
"Bitwidth of the index type. Used for size estimation.">,
|
||||
Option<"maxRankOfAllocatedMemRef", "max-rank-of-allocated-memref", "unsigned",
|
||||
/*default=*/"1",
|
||||
"Maximal memref rank to promote dynamic buffers.">,
|
||||
];
|
||||
}
|
||||
|
||||
#endif // MLIR_DIALECT_BUFFERIZATION_TRANSFORMS_PASSES
|
||||
|
|
|
@ -19,9 +19,9 @@
|
|||
namespace mlir {
|
||||
namespace bufferization {
|
||||
class BufferizeTypeConverter;
|
||||
class GlobalCreator;
|
||||
} // namespace bufferization
|
||||
|
||||
class GlobalCreator;
|
||||
class RewritePatternSet;
|
||||
using OwningRewritePatternList = RewritePatternSet;
|
||||
|
||||
|
@ -38,7 +38,7 @@ std::unique_ptr<Pass> createFuncBufferizePass();
|
|||
/// Add patterns to bufferize tensor constants into global memrefs to the given
|
||||
/// pattern list.
|
||||
void populateTensorConstantBufferizePatterns(
|
||||
GlobalCreator &globalCreator,
|
||||
bufferization::GlobalCreator &globalCreator,
|
||||
bufferization::BufferizeTypeConverter &typeConverter,
|
||||
RewritePatternSet &patterns);
|
||||
|
||||
|
|
|
@ -33,30 +33,6 @@ enum FusionMode { Greedy, ProducerConsumer, Sibling };
|
|||
// Passes
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// Creates a pass that moves allocations upwards to reduce the number of
|
||||
/// required copies that are inserted during the BufferDeallocation pass.
|
||||
std::unique_ptr<Pass> createBufferHoistingPass();
|
||||
|
||||
/// Creates a pass that moves allocations upwards out of loops. This avoids
|
||||
/// reallocations inside of loops.
|
||||
std::unique_ptr<Pass> createBufferLoopHoistingPass();
|
||||
|
||||
/// Creates a pass that promotes heap-based allocations to stack-based ones.
|
||||
/// Only buffers smaller than the provided size are promoted.
|
||||
/// Dynamic shaped buffers are promoted up to the given rank.
|
||||
std::unique_ptr<Pass>
|
||||
createPromoteBuffersToStackPass(unsigned maxAllocSizeInBytes = 1024,
|
||||
unsigned bitwidthOfIndexType = 64,
|
||||
unsigned maxRankOfAllocatedMemRef = 1);
|
||||
|
||||
/// Creates a pass that promotes heap-based allocations to stack-based ones.
|
||||
/// Only buffers smaller with `isSmallAlloc(alloc) == true` are promoted.
|
||||
std::unique_ptr<Pass>
|
||||
createPromoteBuffersToStackPass(std::function<bool(Value)> isSmallAlloc);
|
||||
|
||||
/// Creates a pass that converts memref function results to out-params.
|
||||
std::unique_ptr<Pass> createBufferResultsToOutParamsPass();
|
||||
|
||||
/// Creates an instance of the Canonicalizer pass, configured with default
|
||||
/// settings (which can be overridden by pass options on the command line).
|
||||
std::unique_ptr<Pass> createCanonicalizerPass();
|
||||
|
|
|
@ -217,75 +217,6 @@ def AffinePipelineDataTransfer
|
|||
let constructor = "mlir::createPipelineDataTransferPass()";
|
||||
}
|
||||
|
||||
def BufferHoisting : Pass<"buffer-hoisting", "FuncOp"> {
|
||||
let summary = "Optimizes placement of allocation operations by moving them "
|
||||
"into common dominators and out of nested regions";
|
||||
let description = [{
|
||||
This pass implements an approach to aggressively move allocations upwards
|
||||
into common dominators and out of nested regions.
|
||||
}];
|
||||
let constructor = "mlir::createBufferHoistingPass()";
|
||||
}
|
||||
|
||||
def BufferLoopHoisting : Pass<"buffer-loop-hoisting", "FuncOp"> {
|
||||
let summary = "Optimizes placement of allocation operations by moving them "
|
||||
"out of loop nests";
|
||||
let description = [{
|
||||
This pass implements an approach to aggressively move allocations upwards
|
||||
out of loop nests. It does not move allocations into common dominators.
|
||||
}];
|
||||
let constructor = "mlir::createBufferLoopHoistingPass()";
|
||||
}
|
||||
|
||||
def PromoteBuffersToStack : Pass<"promote-buffers-to-stack", "FuncOp"> {
|
||||
let summary = "Promotes heap-based allocations to automatically managed "
|
||||
"stack-based allocations";
|
||||
let description = [{
|
||||
This pass implements a simple algorithm to convert heap-based memory
|
||||
allocations to stack-based ones. It uses a built-in heuristic to decide
|
||||
whether it makes sense to convert an allocation. Furthermore, dynamic
|
||||
shaped buffers that are limited by the rank of the tensor can be
|
||||
converted. They are only transformed if they are considered to be small.
|
||||
}];
|
||||
let constructor = "mlir::createPromoteBuffersToStackPass()";
|
||||
let options = [
|
||||
Option<"maxAllocSizeInBytes", "max-alloc-size-in-bytes", "unsigned",
|
||||
/*default=*/"1024",
|
||||
"Maximal size in bytes to promote allocations to stack.">,
|
||||
Option<"bitwidthOfIndexType", "bitwidth-of-index-type", "unsigned",
|
||||
/*default=*/"64",
|
||||
"Bitwidth of the index type. Used for size estimation.">,
|
||||
Option<"maxRankOfAllocatedMemRef", "max-rank-of-allocated-memref", "unsigned",
|
||||
/*default=*/"1",
|
||||
"Maximal memref rank to promote dynamic buffers.">,
|
||||
];
|
||||
}
|
||||
|
||||
def BufferResultsToOutParams : Pass<"buffer-results-to-out-params", "ModuleOp"> {
|
||||
let summary = "Converts memref-typed function results to out-params";
|
||||
let description = [{
|
||||
Some calling conventions prefer to pass output memrefs as "out params". The
|
||||
conversion to this calling convention must be done as an atomic
|
||||
transformation of the entire program (hence this is a module pass).
|
||||
|
||||
For example, if a call is rewritten, the callee needs to be rewritten
|
||||
otherwise the IR will end up invalid. Thus, this transformation
|
||||
require an atomic change to the entire program (e.g. the whole module).
|
||||
|
||||
This pass is expected to run immediately after bufferization is finished.
|
||||
At that point, tensor-typed results will have been converted to memref-typed
|
||||
results, and can be consistently converted to out params.
|
||||
|
||||
All memref-typed results are appended to the function argument list.
|
||||
|
||||
The main issue with this pass (and the out-param calling convention) is that
|
||||
buffers for results need to be allocated in the caller. This currently only
|
||||
works for static shaped memrefs.
|
||||
}];
|
||||
let constructor = "mlir::createBufferResultsToOutParamsPass()";
|
||||
let dependentDialects = ["memref::MemRefDialect"];
|
||||
}
|
||||
|
||||
def Canonicalizer : Pass<"canonicalize"> {
|
||||
let summary = "Canonicalize operations";
|
||||
let description = [{
|
||||
|
|
|
@ -54,12 +54,13 @@
|
|||
|
||||
#include "mlir/Dialect/Bufferization/IR/AllocationOpInterface.h"
|
||||
#include "mlir/Dialect/Bufferization/IR/Bufferization.h"
|
||||
#include "mlir/Dialect/Bufferization/Transforms/BufferUtils.h"
|
||||
#include "mlir/Dialect/Bufferization/Transforms/Passes.h"
|
||||
#include "mlir/Dialect/MemRef/IR/MemRef.h"
|
||||
#include "mlir/Transforms/BufferUtils.h"
|
||||
#include "llvm/ADT/SetOperations.h"
|
||||
|
||||
using namespace mlir;
|
||||
using namespace mlir::bufferization;
|
||||
|
||||
/// Walks over all immediate return-like terminators in the given region.
|
||||
static LogicalResult
|
||||
|
|
|
@ -12,14 +12,15 @@
|
|||
// convert heap-based allocations to stack-based allocations, if possible.
|
||||
|
||||
#include "PassDetail.h"
|
||||
#include "mlir/Dialect/Bufferization/Transforms/BufferUtils.h"
|
||||
#include "mlir/Dialect/Bufferization/Transforms/Passes.h"
|
||||
#include "mlir/Dialect/MemRef/IR/MemRef.h"
|
||||
#include "mlir/IR/Operation.h"
|
||||
#include "mlir/Interfaces/LoopLikeInterface.h"
|
||||
#include "mlir/Pass/Pass.h"
|
||||
#include "mlir/Transforms/BufferUtils.h"
|
||||
#include "mlir/Transforms/Passes.h"
|
||||
|
||||
using namespace mlir;
|
||||
using namespace mlir::bufferization;
|
||||
|
||||
/// Returns true if the given operation implements a known high-level region-
|
||||
/// based control-flow interface.
|
||||
|
@ -422,23 +423,22 @@ private:
|
|||
|
||||
} // namespace
|
||||
|
||||
std::unique_ptr<Pass> mlir::createBufferHoistingPass() {
|
||||
std::unique_ptr<Pass> mlir::bufferization::createBufferHoistingPass() {
|
||||
return std::make_unique<BufferHoistingPass>();
|
||||
}
|
||||
|
||||
std::unique_ptr<Pass> mlir::createBufferLoopHoistingPass() {
|
||||
std::unique_ptr<Pass> mlir::bufferization::createBufferLoopHoistingPass() {
|
||||
return std::make_unique<BufferLoopHoistingPass>();
|
||||
}
|
||||
|
||||
std::unique_ptr<Pass>
|
||||
mlir::createPromoteBuffersToStackPass(unsigned maxAllocSizeInBytes,
|
||||
unsigned bitwidthOfIndexType,
|
||||
unsigned maxRankOfAllocatedMemRef) {
|
||||
std::unique_ptr<Pass> mlir::bufferization::createPromoteBuffersToStackPass(
|
||||
unsigned maxAllocSizeInBytes, unsigned bitwidthOfIndexType,
|
||||
unsigned maxRankOfAllocatedMemRef) {
|
||||
return std::make_unique<PromoteBuffersToStackPass>(
|
||||
maxAllocSizeInBytes, bitwidthOfIndexType, maxRankOfAllocatedMemRef);
|
||||
}
|
||||
|
||||
std::unique_ptr<Pass>
|
||||
mlir::createPromoteBuffersToStackPass(std::function<bool(Value)> isSmallAlloc) {
|
||||
std::unique_ptr<Pass> mlir::bufferization::createPromoteBuffersToStackPass(
|
||||
std::function<bool(Value)> isSmallAlloc) {
|
||||
return std::make_unique<PromoteBuffersToStackPass>(std::move(isSmallAlloc));
|
||||
}
|
|
@ -7,11 +7,11 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "PassDetail.h"
|
||||
#include "mlir/Dialect/Bufferization/Transforms/Passes.h"
|
||||
#include "mlir/Dialect/MemRef/IR/MemRef.h"
|
||||
#include "mlir/Dialect/StandardOps/IR/Ops.h"
|
||||
#include "mlir/IR/Operation.h"
|
||||
#include "mlir/Pass/Pass.h"
|
||||
#include "mlir/Transforms/Passes.h"
|
||||
|
||||
using namespace mlir;
|
||||
|
||||
|
@ -139,6 +139,7 @@ struct BufferResultsToOutParamsPass
|
|||
};
|
||||
} // namespace
|
||||
|
||||
std::unique_ptr<Pass> mlir::createBufferResultsToOutParamsPass() {
|
||||
std::unique_ptr<Pass>
|
||||
mlir::bufferization::createBufferResultsToOutParamsPass() {
|
||||
return std::make_unique<BufferResultsToOutParamsPass>();
|
||||
}
|
|
@ -10,18 +10,18 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "mlir/Transforms/BufferUtils.h"
|
||||
#include "PassDetail.h"
|
||||
#include "mlir/Dialect/Bufferization/Transforms/BufferUtils.h"
|
||||
#include "mlir/Dialect/Bufferization/Transforms/Bufferize.h"
|
||||
#include "mlir/Dialect/MemRef/IR/MemRef.h"
|
||||
#include "mlir/Dialect/MemRef/Utils/MemRefUtils.h"
|
||||
#include "mlir/Dialect/StandardOps/IR/Ops.h"
|
||||
#include "mlir/IR/Operation.h"
|
||||
#include "mlir/Interfaces/ControlFlowInterfaces.h"
|
||||
#include "mlir/Interfaces/LoopLikeInterface.h"
|
||||
#include "mlir/Pass/Pass.h"
|
||||
#include "mlir/Transforms/Passes.h"
|
||||
#include "llvm/ADT/SetOperations.h"
|
||||
|
||||
using namespace mlir;
|
||||
using namespace mlir::bufferization;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// BufferPlacementAllocs
|
||||
|
@ -139,3 +139,49 @@ bool BufferPlacementTransformationBase::isLoop(Operation *op) {
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// BufferPlacementTransformationBase
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
memref::GlobalOp GlobalCreator::getGlobalFor(arith::ConstantOp constantOp) {
|
||||
auto type = constantOp.getType().cast<RankedTensorType>();
|
||||
|
||||
BufferizeTypeConverter typeConverter;
|
||||
|
||||
// If we already have a global for this constant value, no need to do
|
||||
// anything else.
|
||||
auto it = globals.find(constantOp.getValue());
|
||||
if (it != globals.end())
|
||||
return cast<memref::GlobalOp>(it->second);
|
||||
|
||||
// Create a builder without an insertion point. We will insert using the
|
||||
// symbol table to guarantee unique names.
|
||||
OpBuilder globalBuilder(moduleOp.getContext());
|
||||
SymbolTable symbolTable(moduleOp);
|
||||
|
||||
// Create a pretty name.
|
||||
SmallString<64> buf;
|
||||
llvm::raw_svector_ostream os(buf);
|
||||
interleave(type.getShape(), os, "x");
|
||||
os << "x" << type.getElementType();
|
||||
|
||||
// Add an optional alignment to the global memref.
|
||||
IntegerAttr memrefAlignment =
|
||||
alignment > 0 ? IntegerAttr::get(globalBuilder.getI64Type(), alignment)
|
||||
: IntegerAttr();
|
||||
|
||||
auto global = globalBuilder.create<memref::GlobalOp>(
|
||||
constantOp.getLoc(), (Twine("__constant_") + os.str()).str(),
|
||||
/*sym_visibility=*/globalBuilder.getStringAttr("private"),
|
||||
/*type=*/typeConverter.convertType(type).cast<MemRefType>(),
|
||||
/*initial_value=*/constantOp.getValue().cast<ElementsAttr>(),
|
||||
/*constant=*/true,
|
||||
/*alignment=*/memrefAlignment);
|
||||
symbolTable.insert(global);
|
||||
// The symbol table inserts at the end of the module, but globals are a bit
|
||||
// nicer if they are at the beginning.
|
||||
global->moveBefore(&moduleOp.front());
|
||||
globals[constantOp.getValue()] = global;
|
||||
return global;
|
||||
}
|
|
@ -1,6 +1,9 @@
|
|||
add_mlir_dialect_library(MLIRBufferizationTransforms
|
||||
Bufferize.cpp
|
||||
BufferDeallocation.cpp
|
||||
BufferOptimizations.cpp
|
||||
BufferResultsToOutParams.cpp
|
||||
BufferUtils.cpp
|
||||
OneShotAnalysis.cpp
|
||||
|
||||
ADDITIONAL_HEADER_DIRS
|
||||
|
|
|
@ -10,10 +10,10 @@
|
|||
|
||||
#include "mlir/Dialect/Arithmetic/IR/Arithmetic.h"
|
||||
#include "mlir/Dialect/Bufferization/IR/BufferizableOpInterface.h"
|
||||
#include "mlir/Dialect/Bufferization/Transforms/BufferUtils.h"
|
||||
#include "mlir/Dialect/MemRef/IR/MemRef.h"
|
||||
#include "mlir/IR/Dialect.h"
|
||||
#include "mlir/IR/Operation.h"
|
||||
#include "mlir/Transforms/BufferUtils.h"
|
||||
|
||||
using namespace mlir::bufferization;
|
||||
|
||||
|
|
|
@ -12,57 +12,16 @@
|
|||
|
||||
#include "PassDetail.h"
|
||||
#include "mlir/Dialect/Bufferization/IR/Bufferization.h"
|
||||
#include "mlir/Dialect/Bufferization/Transforms/BufferUtils.h"
|
||||
#include "mlir/Dialect/Bufferization/Transforms/Bufferize.h"
|
||||
#include "mlir/Dialect/MemRef/IR/MemRef.h"
|
||||
#include "mlir/Dialect/StandardOps/IR/Ops.h"
|
||||
#include "mlir/Dialect/StandardOps/Transforms/Passes.h"
|
||||
#include "mlir/IR/BlockAndValueMapping.h"
|
||||
#include "mlir/Transforms/BufferUtils.h"
|
||||
#include "mlir/Transforms/DialectConversion.h"
|
||||
|
||||
using namespace mlir;
|
||||
|
||||
memref::GlobalOp GlobalCreator::getGlobalFor(arith::ConstantOp constantOp) {
|
||||
auto type = constantOp.getType().cast<RankedTensorType>();
|
||||
|
||||
bufferization::BufferizeTypeConverter typeConverter;
|
||||
|
||||
// If we already have a global for this constant value, no need to do
|
||||
// anything else.
|
||||
auto it = globals.find(constantOp.getValue());
|
||||
if (it != globals.end())
|
||||
return cast<memref::GlobalOp>(it->second);
|
||||
|
||||
// Create a builder without an insertion point. We will insert using the
|
||||
// symbol table to guarantee unique names.
|
||||
OpBuilder globalBuilder(moduleOp.getContext());
|
||||
SymbolTable symbolTable(moduleOp);
|
||||
|
||||
// Create a pretty name.
|
||||
SmallString<64> buf;
|
||||
llvm::raw_svector_ostream os(buf);
|
||||
interleave(type.getShape(), os, "x");
|
||||
os << "x" << type.getElementType();
|
||||
|
||||
// Add an optional alignment to the global memref.
|
||||
IntegerAttr memrefAlignment =
|
||||
alignment > 0 ? IntegerAttr::get(globalBuilder.getI64Type(), alignment)
|
||||
: IntegerAttr();
|
||||
|
||||
auto global = globalBuilder.create<memref::GlobalOp>(
|
||||
constantOp.getLoc(), (Twine("__constant_") + os.str()).str(),
|
||||
/*sym_visibility=*/globalBuilder.getStringAttr("private"),
|
||||
/*type=*/typeConverter.convertType(type).cast<MemRefType>(),
|
||||
/*initial_value=*/constantOp.getValue().cast<ElementsAttr>(),
|
||||
/*constant=*/true,
|
||||
/*alignment=*/memrefAlignment);
|
||||
symbolTable.insert(global);
|
||||
// The symbol table inserts at the end of the module, but globals are a bit
|
||||
// nicer if they are at the beginning.
|
||||
global->moveBefore(&moduleOp.front());
|
||||
globals[constantOp.getValue()] = global;
|
||||
return global;
|
||||
}
|
||||
using namespace mlir::bufferization;
|
||||
|
||||
namespace {
|
||||
class BufferizeTensorConstantOp
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
add_subdirectory(Utils)
|
||||
|
||||
add_mlir_library(MLIRTransforms
|
||||
BufferOptimizations.cpp
|
||||
BufferResultsToOutParams.cpp
|
||||
BufferUtils.cpp
|
||||
Canonicalizer.cpp
|
||||
ControlFlowSink.cpp
|
||||
CSE.cpp
|
||||
|
@ -31,7 +28,6 @@ add_mlir_library(MLIRTransforms
|
|||
LINK_LIBS PUBLIC
|
||||
MLIRAffine
|
||||
MLIRAnalysis
|
||||
MLIRBufferization
|
||||
MLIRCopyOpInterface
|
||||
MLIRLoopLikeInterface
|
||||
MLIRMemRef
|
||||
|
|
|
@ -27,10 +27,6 @@ namespace memref {
|
|||
class MemRefDialect;
|
||||
} // namespace memref
|
||||
|
||||
namespace bufferization {
|
||||
class BufferizationDialect;
|
||||
} // namespace bufferization
|
||||
|
||||
#define GEN_PASS_CLASSES
|
||||
#include "mlir/Transforms/Passes.h.inc"
|
||||
|
||||
|
|
Loading…
Reference in New Issue