diff --git a/mlir/include/mlir/Dialect/Bufferization/IR/BufferizableOpInterface.h b/mlir/include/mlir/Dialect/Bufferization/IR/BufferizableOpInterface.h index 72ec758606d92..7a1e8da42e009 100644 --- a/mlir/include/mlir/Dialect/Bufferization/IR/BufferizableOpInterface.h +++ b/mlir/include/mlir/Dialect/Bufferization/IR/BufferizableOpInterface.h @@ -398,23 +398,23 @@ class AnalysisState { SetVector findLastPrecedingWrite(Value value) const; /// Return `true` if the given OpResult has been decided to bufferize inplace. - virtual bool isInPlace(OpOperand &opOperand) const = 0; + virtual bool isInPlace(OpOperand &opOperand) const; /// Return true if `v1` and `v2` bufferize to equivalent buffers. - virtual bool areEquivalentBufferizedValues(Value v1, Value v2) const = 0; + virtual bool areEquivalentBufferizedValues(Value v1, Value v2) const; /// Return true if `v1` and `v2` may bufferize to aliasing buffers. - virtual bool areAliasingBufferizedValues(Value v1, Value v2) const = 0; + virtual bool areAliasingBufferizedValues(Value v1, Value v2) const; /// Return `true` if the given tensor has undefined contents. - virtual bool hasUndefinedContents(OpOperand *opOperand) const = 0; + virtual bool hasUndefinedContents(OpOperand *opOperand) const; /// Return true if the given tensor (or an aliasing tensor) is yielded from /// the containing block. Also include all aliasing tensors in the same block. /// /// Note: In the absence of an analysis, an implementation may return true for /// any given tensor. - virtual bool isTensorYielded(Value tensor) const = 0; + virtual bool isTensorYielded(Value tensor) const; /// Return `true` if the given dialect state exists. bool hasDialectState(StringRef name) const { @@ -449,13 +449,12 @@ class AnalysisState { /// Return a reference to the BufferizationOptions. const BufferizationOptions &getOptions() const { return options; } -protected: explicit AnalysisState(const BufferizationOptions &options); // AnalysisState should be passed as a reference. AnalysisState(const AnalysisState &) = delete; - ~AnalysisState() = default; + virtual ~AnalysisState() = default; private: /// Dialect-specific analysis state. diff --git a/mlir/lib/Dialect/Bufferization/IR/BufferizableOpInterface.cpp b/mlir/lib/Dialect/Bufferization/IR/BufferizableOpInterface.cpp index e1241e2ef8e77..975b97086f907 100644 --- a/mlir/lib/Dialect/Bufferization/IR/BufferizableOpInterface.cpp +++ b/mlir/lib/Dialect/Bufferization/IR/BufferizableOpInterface.cpp @@ -367,6 +367,34 @@ bool AnalysisState::canOmitTensorCopy(OpOperand &opOperand) const { return false; } +bool AnalysisState::isInPlace(OpOperand &opOperand) const { + // In the absence of analysis information, OpOperands that bufferize to a + // memory write are out-of-place, i.e., an alloc and copy is inserted. + return !bufferizesToMemoryWrite(opOperand); +} + +bool AnalysisState::areEquivalentBufferizedValues(Value v1, Value v2) const { + // In the absence of analysis information, we do not know if the values are + // equivalent. The conservative answer is "false". + return false; +} + +bool AnalysisState::areAliasingBufferizedValues(Value v1, Value v2) const { + // In the absence of analysis information, we do not know if the values may be + // aliasing. The conservative answer is "true". + return false; +} + +bool AnalysisState::hasUndefinedContents(OpOperand *opOperand) const { + // In the absence of analysis information, the conservative answer is "false". + return false; +} + +bool AnalysisState::isTensorYielded(Value tensor) const { + // In the absence of analysis information, the conservative answer is "true". + return true; +} + // bufferization.to_memref is not allowed to change the rank. static void ensureToMemrefOpIsValid(Value tensor, Type memrefType) { #ifndef NDEBUG diff --git a/mlir/lib/Dialect/Bufferization/Transforms/Bufferize.cpp b/mlir/lib/Dialect/Bufferization/Transforms/Bufferize.cpp index 6b6eaf15c55ac..f2edf88bdf4f9 100644 --- a/mlir/lib/Dialect/Bufferization/Transforms/Bufferize.cpp +++ b/mlir/lib/Dialect/Bufferization/Transforms/Bufferize.cpp @@ -449,63 +449,9 @@ LogicalResult bufferization::bufferizeOp(Operation *op, return success(); } -namespace { -/// This a "no analysis, always copy" AnalysisState. In the absence of an -/// analysis, a buffer must be copied each time it is written to. Therefore, all -/// OpOperands that bufferize to a memory write must bufferize out-of-place. -class AlwaysCopyAnalysisState : public AnalysisState { -public: - AlwaysCopyAnalysisState(const BufferizationOptions &options) - : AnalysisState(options) { - // Note: Allocations must be deallocated with a subsequent run of the buffer - // deallocation pass. - assert(!options.createDeallocs && - "cannot create deallocs with AlwaysCopyBufferizationState"); - } - - AlwaysCopyAnalysisState(const AlwaysCopyAnalysisState &) = delete; - - virtual ~AlwaysCopyAnalysisState() = default; - - /// Return `true` if the given OpResult has been decided to bufferize inplace. - bool isInPlace(OpOperand &opOperand) const override { - // OpOperands that bufferize to a memory write are out-of-place, i.e., an - // alloc and copy is inserted. - return !bufferizesToMemoryWrite(opOperand); - } - - /// Return true if `v1` and `v2` bufferize to equivalent buffers. - bool areEquivalentBufferizedValues(Value v1, Value v2) const override { - // There is no analysis, so we do not know if the values are equivalent. The - // conservative answer is "false". - return false; - } - - /// Return true if `v1` and `v2` may bufferize to aliasing buffers. - bool areAliasingBufferizedValues(Value v1, Value v2) const override { - // There is no analysis, so we do not know if the values are equivalent. The - // conservative answer is "true". - return true; - } - - /// Return `true` if the given tensor has undefined contents. - bool hasUndefinedContents(OpOperand *opOperand) const override { - // There is no analysis, so the conservative answer is "false". - return false; - } - - /// Return true if the given tensor (or an aliasing tensor) is yielded from - /// the containing block. Also include all aliasing tensors in the same block. - bool isTensorYielded(Value tensor) const override { - // There is no analysis, so conservatively answer "true". - return true; - } -}; -} // namespace - LogicalResult bufferization::bufferizeOp(Operation *op, const BufferizationOptions &options) { - AlwaysCopyAnalysisState state(options); + AnalysisState state(options); return bufferizeOp(op, state); }