From 8ca04b05133b9fc1b891585e9dfd6e30790998ba Mon Sep 17 00:00:00 2001 From: Felipe de Azevedo Piovezan Date: Tue, 29 Jun 2021 14:57:16 +0200 Subject: [PATCH] [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 --- mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td | 4 ++++ mlir/lib/Conversion/GPUCommon/GPUOpsLowering.cpp | 2 +- mlir/lib/Conversion/StandardToLLVM/StandardToLLVM.cpp | 6 +++--- mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp | 8 ++++++-- mlir/lib/Target/LLVMIR/ModuleTranslation.cpp | 11 +++++++++++ mlir/test/Target/LLVMIR/llvmir.mlir | 16 ++++++++++++++++ 6 files changed, 41 insertions(+), 6 deletions(-) diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td index f714126..ed5f74c 100644 --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td @@ -907,6 +907,7 @@ def LLVM_GlobalOp : LLVM_Op<"mlir.global", UnitAttr:$constant, StrAttr:$sym_name, Linkage:$linkage, + UnitAttr:$dso_local, OptionalAttr:$value, OptionalAttr:$alignment, DefaultValuedAttr, "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", "{}">:$attrs)> ]; @@ -1081,6 +1083,7 @@ def LLVM_LLVMFuncOp : LLVM_Op<"func", }]; let arguments = (ins DefaultValuedAttr:$linkage, + UnitAttr:$dso_local, OptionalAttr:$personality, OptionalAttr:$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", "{}">:$attrs, CArg<"ArrayRef", "{}">:$argAttrs)> ]; diff --git a/mlir/lib/Conversion/GPUCommon/GPUOpsLowering.cpp b/mlir/lib/Conversion/GPUCommon/GPUOpsLowering.cpp index 912f58d..98aa0e0 100644 --- a/mlir/lib/Conversion/GPUCommon/GPUOpsLowering.cpp +++ b/mlir/lib/Conversion/GPUCommon/GPUOpsLowering.cpp @@ -70,7 +70,7 @@ GPUFuncOpLowering::matchAndRewrite(gpu::GPUFuncOp gpuFuncOp, attributes.emplace_back(kernelAttributeName, rewriter.getUnitAttr()); auto llvmFuncOp = rewriter.create( gpuFuncOp.getLoc(), gpuFuncOp.getName(), funcType, - LLVM::Linkage::External, attributes); + LLVM::Linkage::External, /*dsoLocal*/ false, attributes); { // Insert operations that correspond to converted workgroup and private diff --git a/mlir/lib/Conversion/StandardToLLVM/StandardToLLVM.cpp b/mlir/lib/Conversion/StandardToLLVM/StandardToLLVM.cpp index eb390bf..f09f2a0 100644 --- a/mlir/lib/Conversion/StandardToLLVM/StandardToLLVM.cpp +++ b/mlir/lib/Conversion/StandardToLLVM/StandardToLLVM.cpp @@ -1266,7 +1266,7 @@ static void wrapForExternalCallers(OpBuilder &rewriter, Location loc, typeConverter.convertFunctionTypeCWrapper(type); auto wrapperFuncOp = rewriter.create( 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( 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( 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, diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp index 95f3460..8b9a8fa 100644 --- a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp +++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp @@ -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 attrs) { + bool dsoLocal, ArrayRef 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 attrs, + bool dsoLocal, ArrayRef attrs, ArrayRef 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(linkage))); result.attributes.append(attrs.begin(), attrs.end()); + if (dsoLocal) + result.addAttribute("dso_local", builder.getUnitAttr()); if (argAttrs.empty()) return; diff --git a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp index 0d1ae3f..bbff0b0 100644 --- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp +++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp @@ -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 alignment = op.alignment(); if (alignment.hasValue()) var->setAlignment(llvm::MaybeAlign(alignment.getValue())); @@ -687,6 +697,7 @@ LogicalResult ModuleTranslation::convertFunctionSignatures() { llvm::Function *llvmFunc = cast(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(), diff --git a/mlir/test/Target/LLVMIR/llvmir.mlir b/mlir/test/Target/LLVMIR/llvmir.mlir index cb5358f..551fa7e 100644 --- a/mlir/test/Target/LLVMIR/llvmir.mlir +++ b/mlir/test/Target/LLVMIR/llvmir.mlir @@ -80,6 +80,13 @@ llvm.mlir.global private local_unnamed_addr constant @local_unnamed_addr(42 : i6 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. // @@ -429,6 +436,15 @@ llvm.func internal @func_internal() { } // +// 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. // -- 2.7.4