[mlir] Add support for LLVM's dso_local attr

This patch brings support for setting runtime preemption specifiers of
LLVM's GlobalValues. In LLVM semantics, if the `dso_local` attribute
is not explicitly requested, then it is inferred based on linkage and
visibility. We model this same behavior with a UnitAttribute: if it is
present, then we explicitly request the GlobalValue to marked as
`dso_local`, otherwise we rely on the GlobalValue itself to make this
decision.

Reviewed By: ftynse

Differential Revision: https://reviews.llvm.org/D104983
This commit is contained in:
Felipe de Azevedo Piovezan 2021-06-29 14:57:16 +02:00 committed by Alex Zinenko
parent 355216380b
commit 8ca04b0513
6 changed files with 41 additions and 6 deletions

View File

@ -907,6 +907,7 @@ def LLVM_GlobalOp : LLVM_Op<"mlir.global",
UnitAttr:$constant,
StrAttr:$sym_name,
Linkage:$linkage,
UnitAttr:$dso_local,
OptionalAttr<AnyAttr>:$value,
OptionalAttr<I64Attr>:$alignment,
DefaultValuedAttr<Confined<I32Attr, [IntNonNegative]>, "0">:$addr_space,
@ -1017,6 +1018,7 @@ def LLVM_GlobalOp : LLVM_Op<"mlir.global",
"StringRef":$name, "Attribute":$value,
CArg<"uint64_t", "0">:$alignment,
CArg<"unsigned", "0">:$addrSpace,
CArg<"bool", "false">:$dsoLocal,
CArg<"ArrayRef<NamedAttribute>", "{}">:$attrs)>
];
@ -1081,6 +1083,7 @@ def LLVM_LLVMFuncOp : LLVM_Op<"func",
}];
let arguments = (ins DefaultValuedAttr<Linkage, "Linkage::External">:$linkage,
UnitAttr:$dso_local,
OptionalAttr<FlatSymbolRefAttr>:$personality,
OptionalAttr<ArrayAttr>:$passthrough);
@ -1091,6 +1094,7 @@ def LLVM_LLVMFuncOp : LLVM_Op<"func",
let builders = [
OpBuilder<(ins "StringRef":$name, "Type":$type,
CArg<"Linkage", "Linkage::External">:$linkage,
CArg<"bool", "false">:$dsoLocal,
CArg<"ArrayRef<NamedAttribute>", "{}">:$attrs,
CArg<"ArrayRef<DictionaryAttr>", "{}">:$argAttrs)>
];

View File

@ -70,7 +70,7 @@ GPUFuncOpLowering::matchAndRewrite(gpu::GPUFuncOp gpuFuncOp,
attributes.emplace_back(kernelAttributeName, rewriter.getUnitAttr());
auto llvmFuncOp = rewriter.create<LLVM::LLVMFuncOp>(
gpuFuncOp.getLoc(), gpuFuncOp.getName(), funcType,
LLVM::Linkage::External, attributes);
LLVM::Linkage::External, /*dsoLocal*/ false, attributes);
{
// Insert operations that correspond to converted workgroup and private

View File

@ -1266,7 +1266,7 @@ static void wrapForExternalCallers(OpBuilder &rewriter, Location loc,
typeConverter.convertFunctionTypeCWrapper(type);
auto wrapperFuncOp = rewriter.create<LLVM::LLVMFuncOp>(
loc, llvm::formatv("_mlir_ciface_{0}", funcOp.getName()).str(),
wrapperFuncType, LLVM::Linkage::External, attributes);
wrapperFuncType, LLVM::Linkage::External, /*dsoLocal*/ false, attributes);
OpBuilder::InsertionGuard guard(rewriter);
rewriter.setInsertionPointToStart(wrapperFuncOp.addEntryBlock());
@ -1330,7 +1330,7 @@ static void wrapExternalFunction(OpBuilder &builder, Location loc,
// Create the auxiliary function.
auto wrapperFunc = builder.create<LLVM::LLVMFuncOp>(
loc, llvm::formatv("_mlir_ciface_{0}", funcOp.getName()).str(),
wrapperType, LLVM::Linkage::External, attributes);
wrapperType, LLVM::Linkage::External, /*dsoLocal*/ false, attributes);
builder.setInsertionPointToStart(newFuncOp.addEntryBlock());
@ -1441,7 +1441,7 @@ protected:
// functions have linkage.
auto newFuncOp = rewriter.create<LLVM::LLVMFuncOp>(
funcOp.getLoc(), funcOp.getName(), llvmType, LLVM::Linkage::External,
attributes);
/*dsoLocal*/ false, attributes);
rewriter.inlineRegionBefore(funcOp.getBody(), newFuncOp.getBody(),
newFuncOp.end());
if (failed(rewriter.convertRegionTypes(&newFuncOp.getBody(), *typeConverter,

View File

@ -1267,7 +1267,7 @@ static StringRef getUnnamedAddrAttrName() { return "unnamed_addr"; }
void GlobalOp::build(OpBuilder &builder, OperationState &result, Type type,
bool isConstant, Linkage linkage, StringRef name,
Attribute value, uint64_t alignment, unsigned addrSpace,
ArrayRef<NamedAttribute> attrs) {
bool dsoLocal, ArrayRef<NamedAttribute> attrs) {
result.addAttribute(SymbolTable::getSymbolAttrName(),
builder.getStringAttr(name));
result.addAttribute("type", TypeAttr::get(type));
@ -1275,6 +1275,8 @@ void GlobalOp::build(OpBuilder &builder, OperationState &result, Type type,
result.addAttribute("constant", builder.getUnitAttr());
if (value)
result.addAttribute("value", value);
if (dsoLocal)
result.addAttribute("dso_local", builder.getUnitAttr());
// Only add an alignment attribute if the "alignment" input
// is different from 0. The value must also be a power of two, but
@ -1756,7 +1758,7 @@ Block *LLVMFuncOp::addEntryBlock() {
void LLVMFuncOp::build(OpBuilder &builder, OperationState &result,
StringRef name, Type type, LLVM::Linkage linkage,
ArrayRef<NamedAttribute> attrs,
bool dsoLocal, ArrayRef<NamedAttribute> attrs,
ArrayRef<DictionaryAttr> argAttrs) {
result.addRegion();
result.addAttribute(SymbolTable::getSymbolAttrName(),
@ -1765,6 +1767,8 @@ void LLVMFuncOp::build(OpBuilder &builder, OperationState &result,
result.addAttribute(getLinkageAttrName(),
builder.getI64IntegerAttr(static_cast<int64_t>(linkage)));
result.attributes.append(attrs.begin(), attrs.end());
if (dsoLocal)
result.addAttribute("dso_local", builder.getUnitAttr());
if (argAttrs.empty())
return;

View File

@ -425,6 +425,14 @@ static bool shouldDropGlobalInitializer(llvm::GlobalValue::LinkageTypes linkage,
linkage == llvm::GlobalVariable::ExternalWeakLinkage;
}
/// Sets the runtime preemption specifier of `gv` to dso_local if
/// `dsoLocalRequested` is true, otherwise it is left unchanged.
static void addRuntimePreemptionSpecifier(bool dsoLocalRequested,
llvm::GlobalValue *gv) {
if (dsoLocalRequested)
gv->setDSOLocal(true);
}
/// Create named global variables that correspond to llvm.mlir.global
/// definitions.
LogicalResult ModuleTranslation::convertGlobals() {
@ -458,6 +466,8 @@ LogicalResult ModuleTranslation::convertGlobals() {
if (op.section().hasValue())
var->setSection(*op.section());
addRuntimePreemptionSpecifier(op.dso_local(), var);
Optional<uint64_t> alignment = op.alignment();
if (alignment.hasValue())
var->setAlignment(llvm::MaybeAlign(alignment.getValue()));
@ -687,6 +697,7 @@ LogicalResult ModuleTranslation::convertFunctionSignatures() {
llvm::Function *llvmFunc = cast<llvm::Function>(llvmFuncCst.getCallee());
llvmFunc->setLinkage(convertLinkageToLLVM(function.linkage()));
mapFunction(function.getName(), llvmFunc);
addRuntimePreemptionSpecifier(function.dso_local(), llvmFunc);
// Forward the pass-through attributes to LLVM.
if (failed(forwardPassthroughAttributes(function.getLoc(),

View File

@ -79,6 +79,13 @@ llvm.mlir.global private local_unnamed_addr constant @local_unnamed_addr(42 : i6
// CHECK: @unnamed_addr = private unnamed_addr constant i64 42
llvm.mlir.global private unnamed_addr constant @unnamed_addr(42 : i64) : i64
//
// dso_local attribute.
//
llvm.mlir.global @has_dso_local(42 : i64) {dso_local} : i64
// CHECK: @has_dso_local = dso_local global i64 42
//
// Section attribute.
//
@ -428,6 +435,15 @@ llvm.func internal @func_internal() {
llvm.return
}
//
// dso_local attribute.
//
// CHECK: define dso_local void @dso_local_func
llvm.func @dso_local_func() attributes {dso_local} {
llvm.return
}
//
// MemRef type conversion, allocation and communication with functions.
//