Files
Andrei Golubev de348bcd5f [NFC][mlir][bufferization] Align alloc/memcpy/cast options hooks to the rest (#206966)
There are three hooks that have a different, more complicated API than
the other ones: allocationFn, memCpyFn, castFn. All three are called via
"helper" functions that check whether the hooks are set to call them and
fall back to default implementations otherwise.

Other hooks (e.g. unknownTypeConverterFn) in the bufferization options
have a different "API": they are always set to some default
implementation and can be overwritten by the user. This is a simpler API
overall and seems it can be universal.

Note for LLVM integration: BufferizationOptions::{createAlloc,
createMemCpy, createCast} functions are "replaced" with direct calls to
the underlying std::function objects. At any call-site that relied on
any of the removed APIs, a call to the respective hook should now be
used instead. The exception is the `allocationFn` hook which needs an
explicit "bufferAlignment" parameter. Beforehand, it was implicitly
taken from BufferizationOptions::bufferAlignment field, so a
non-functional migration path is to go from
`options.createAlloc(builder, loc, destType, value)` to
`options.allocationFn(builder, loc, destType, value,
options.bufferAlignment)`.
2026-07-07 13:15:54 +02:00

169 lines
5.5 KiB
C++

//===- BufferizableOpInterfaceImpl.cpp - Impl. of BufferizableOpInterface -===//
//
// 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/MLProgram/Transforms/BufferizableOpInterfaceImpl.h"
#include "mlir/Dialect/Bufferization/IR/BufferizableOpInterface.h"
#include "mlir/Dialect/Bufferization/Transforms/BufferUtils.h"
#include "mlir/Dialect/MLProgram/IR/MLProgram.h"
#include "mlir/Dialect/MemRef/IR/MemRef.h"
using namespace mlir;
using namespace mlir::bufferization;
using namespace mlir::ml_program;
namespace mlir {
namespace ml_program {
namespace {
template <typename Interface, typename Op>
struct ExternalModelBase
: public BufferizableOpInterface::ExternalModel<Interface, Op> {
AliasingValueList getAliasingValues(Operation *, OpOperand &,
const AnalysisState &) const {
return {};
}
BufferRelation bufferRelation(Operation *, OpResult,
const AnalysisState &) const {
return BufferRelation::Unknown;
}
};
/// Bufferization of ml_program.global into a memref.global
struct GlobalOpInterface
: public ExternalModelBase<GlobalOpInterface, GlobalOp> {
bool bufferizesToMemoryRead(Operation *, OpOperand &,
const AnalysisState &) const {
return false;
}
bool bufferizesToMemoryWrite(Operation *, OpOperand &,
const AnalysisState &) const {
return false;
}
bool hasTensorSemantics(Operation *) const { return true; }
LogicalResult bufferize(Operation *op, RewriterBase &rewriter,
const BufferizationOptions &,
BufferizationState &state) const {
auto globalOp = cast<GlobalOp>(op);
if (!globalOp.getValue().has_value())
return globalOp.emitError("global op must have a value");
bufferization::removeSymbol(globalOp, state);
auto tensorType = cast<TensorType>(globalOp.getType());
auto memrefType = getMemRefTypeWithStaticIdentityLayout(tensorType);
auto replacement = replaceOpWithNewBufferizedOp<memref::GlobalOp>(
rewriter, globalOp, globalOp.getSymName(),
/*sym_visibility=*/globalOp.getSymVisibilityAttr(),
/*type=*/cast<MemRefType>(memrefType),
/*initial_value=*/globalOp.getValue().value(),
/*constant=*/!globalOp.getIsMutable(),
/*alignment=*/nullptr);
bufferization::insertSymbol(replacement, state);
return success();
}
};
/// Bufferization of ml_program.global_load into a memref.get_global
struct GlobalLoadOpInterface
: public ExternalModelBase<GlobalLoadOpInterface, GlobalLoadOp> {
bool bufferizesToMemoryRead(Operation *, OpOperand &,
const AnalysisState &) const {
return false;
}
bool bufferizesToMemoryWrite(Operation *, OpOperand &,
const AnalysisState &) const {
return false;
}
bool isWritable(Operation *, Value, const AnalysisState &) const {
return false;
}
LogicalResult bufferize(Operation *op, RewriterBase &rewriter,
const BufferizationOptions &,
BufferizationState &state) const {
auto globalLoadOp = cast<GlobalLoadOp>(op);
auto tensorType = cast<TensorType>(globalLoadOp.getType());
auto memrefType = getMemRefTypeWithStaticIdentityLayout(tensorType);
replaceOpWithNewBufferizedOp<memref::GetGlobalOp>(
rewriter, globalLoadOp, memrefType,
globalLoadOp.getGlobalAttr().getLeafReference());
return success();
}
};
/// Bufferization of ml_program.global_store into a memref.get_global and
/// memcpy
struct GlobalStoreOpInterface
: public ExternalModelBase<GlobalStoreOpInterface, GlobalStoreOp> {
bool bufferizesToMemoryRead(Operation *, OpOperand &,
const AnalysisState &) const {
return true;
}
bool bufferizesToMemoryWrite(Operation *, OpOperand &,
const AnalysisState &) const {
return true;
}
LogicalResult bufferize(Operation *op, RewriterBase &rewriter,
const BufferizationOptions &options,
BufferizationState &state) const {
auto globalStoreOp = cast<GlobalStoreOp>(op);
auto tensorType = cast<TensorType>(globalStoreOp.getValue().getType());
auto memrefType = getMemRefTypeWithStaticIdentityLayout(tensorType);
auto loc = globalStoreOp.getLoc();
auto targetMemref = memref::GetGlobalOp::create(
rewriter, loc, memrefType,
globalStoreOp.getGlobalAttr().getLeafReference());
auto sourceMemref =
getBuffer(rewriter, globalStoreOp.getValue(), options, state);
if (failed(sourceMemref)) {
return failure();
}
auto memcpy =
options.memCpyFn(rewriter, loc, sourceMemref.value(), targetMemref);
if (failed(memcpy)) {
return failure();
}
rewriter.eraseOp(globalStoreOp);
return success();
}
};
} // namespace
void registerBufferizableOpInterfaceExternalModels(DialectRegistry &registry) {
registry.addExtension(+[](MLIRContext *ctx, MLProgramDialect *) {
GlobalOp::attachInterface<GlobalOpInterface>(*ctx);
GlobalLoadOp::attachInterface<GlobalLoadOpInterface>(*ctx);
GlobalStoreOp::attachInterface<GlobalStoreOpInterface>(*ctx);
});
}
} // namespace ml_program
} // namespace mlir