[llvm] 9552a39 - add support for the SPV_KHR_linkonce_odr extension (#81512)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Feb 15 02:30:21 PST 2024
Author: Vyacheslav Levytskyy
Date: 2024-02-15T11:30:17+01:00
New Revision: 9552a396ed649e499bc4a370ab72ca6972e5b982
URL: https://github.com/llvm/llvm-project/commit/9552a396ed649e499bc4a370ab72ca6972e5b982
DIFF: https://github.com/llvm/llvm-project/commit/9552a396ed649e499bc4a370ab72ca6972e5b982.diff
LOG: add support for the SPV_KHR_linkonce_odr extension (#81512)
This PR adds support for the SPV_KHR_linkonce_odr extension and modifies
existing negative test with a positive check for the extension and
proper linkage type in case when the extension is enabled.
SPV_KHR_linkonce_odr adds a "LinkOnceODR" linkage type, allowing proper
translation of, for example, C++ templates classes merging during
linking from different modules and supporting any other cases when a
global variable/function must be merged with equivalent global
variable(s)/function(s) from other modules during the linking process.
Added:
llvm/test/CodeGen/SPIRV/LinkOnceODRFun.ll
Modified:
llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp
llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
llvm/lib/Target/SPIRV/SPIRVSubtarget.cpp
llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td
llvm/test/CodeGen/SPIRV/LinkOnceODR.ll
Removed:
################################################################################
diff --git a/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp b/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp
index 8ac498e1556bec..baeed2ad895a4b 100644
--- a/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp
@@ -332,6 +332,10 @@ bool SPIRVCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
if (F.hasName())
buildOpName(FuncVReg, F.getName(), MIRBuilder);
+ // Get access to information about available extensions
+ const auto *ST =
+ static_cast<const SPIRVSubtarget *>(&MIRBuilder.getMF().getSubtarget());
+
// Handle entry points and function linkage.
if (isEntryPoint(F)) {
const auto &STI = MIRBuilder.getMF().getSubtarget<SPIRVSubtarget>();
@@ -342,15 +346,19 @@ bool SPIRVCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
addStringImm(F.getName(), MIB);
} else if (F.getLinkage() == GlobalValue::LinkageTypes::ExternalLinkage ||
F.getLinkage() == GlobalValue::LinkOnceODRLinkage) {
- auto LnkTy = F.isDeclaration() ? SPIRV::LinkageType::Import
- : SPIRV::LinkageType::Export;
+ SPIRV::LinkageType::LinkageType LnkTy =
+ F.isDeclaration()
+ ? SPIRV::LinkageType::Import
+ : (F.getLinkage() == GlobalValue::LinkOnceODRLinkage &&
+ ST->canUseExtension(
+ SPIRV::Extension::SPV_KHR_linkonce_odr)
+ ? SPIRV::LinkageType::LinkOnceODR
+ : SPIRV::LinkageType::Export);
buildOpDecorate(FuncVReg, MIRBuilder, SPIRV::Decoration::LinkageAttributes,
{static_cast<uint32_t>(LnkTy)}, F.getGlobalIdentifier());
}
// Handle function pointers decoration
- const auto *ST =
- static_cast<const SPIRVSubtarget *>(&MIRBuilder.getMF().getSubtarget());
bool hasFunctionPointers =
ST->canUseExtension(SPIRV::Extension::SPV_INTEL_function_pointers);
if (hasFunctionPointers) {
@@ -393,7 +401,7 @@ void SPIRVCallLowering::produceIndirectPtrTypes(
// SPIR-V pointer to function type:
SPIRVType *IndirectFuncPtrTy = GR->getOrCreateSPIRVPointerType(
SpirvFuncTy, MIRBuilder, SPIRV::StorageClass::Function);
- // Correct the Calee type
+ // Correct the Callee type
GR->assignSPIRVTypeToVReg(IndirectFuncPtrTy, IC.Callee, MF);
}
}
diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
index 52eeb8a523e6f6..ed2c9ab4d4362a 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
@@ -1601,7 +1601,10 @@ bool SPIRVInstructionSelector::selectGlobalValue(
SPIRV::LinkageType::LinkageType LnkType =
(GV->isDeclaration() || GV->hasAvailableExternallyLinkage())
? SPIRV::LinkageType::Import
- : SPIRV::LinkageType::Export;
+ : (GV->getLinkage() == GlobalValue::LinkOnceODRLinkage &&
+ STI.canUseExtension(SPIRV::Extension::SPV_KHR_linkonce_odr)
+ ? SPIRV::LinkageType::LinkOnceODR
+ : SPIRV::LinkageType::Export);
Register Reg = GR.buildGlobalVariable(ResVReg, ResType, GlobalIdent, GV,
Storage, Init, GlobalVar->isConstant(),
diff --git a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
index 9f14ea5dbe19b3..688b98ffa67477 100644
--- a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
@@ -679,6 +679,12 @@ static void addOpDecorateReqs(const MachineInstr &MI, unsigned DecIndex,
auto BuiltIn = static_cast<SPIRV::BuiltIn::BuiltIn>(BuiltInOp);
Reqs.addRequirements(getSymbolicOperandRequirements(
SPIRV::OperandCategory::BuiltInOperand, BuiltIn, ST, Reqs));
+ } else if (Dec == SPIRV::Decoration::LinkageAttributes) {
+ int64_t LinkageOp = MI.getOperand(MI.getNumOperands() - 1).getImm();
+ SPIRV::LinkageType::LinkageType LnkType =
+ static_cast<SPIRV::LinkageType::LinkageType>(LinkageOp);
+ if (LnkType == SPIRV::LinkageType::LinkOnceODR)
+ Reqs.addExtension(SPIRV::Extension::SPV_KHR_linkonce_odr);
}
}
diff --git a/llvm/lib/Target/SPIRV/SPIRVSubtarget.cpp b/llvm/lib/Target/SPIRV/SPIRVSubtarget.cpp
index effedc2f17d351..354cd5d9b297e7 100644
--- a/llvm/lib/Target/SPIRV/SPIRVSubtarget.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVSubtarget.cpp
@@ -54,6 +54,11 @@ cl::list<SPIRV::Extension::Extension> Extensions(
"SPV_KHR_bit_instructions",
"This enables bit instructions to be used by SPIR-V modules "
"without requiring the Shader capability"),
+ clEnumValN(
+ SPIRV::Extension::SPV_KHR_linkonce_odr, "SPV_KHR_linkonce_odr",
+ "Allows to use the LinkOnceODR linkage type that is to let "
+ "a function or global variable to be merged with other functions "
+ "or global variables of the same name when linkage occurs."),
clEnumValN(SPIRV::Extension::SPV_INTEL_function_pointers,
"SPV_INTEL_function_pointers",
"Allows translation of function pointers")));
diff --git a/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td b/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td
index 5d252275ac709b..ed05013642ac21 100644
--- a/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td
+++ b/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td
@@ -1040,6 +1040,7 @@ multiclass LinkageTypeOperand<bits<32> value, list<Capability> reqCapabilities>
defm Export : LinkageTypeOperand<0, [Linkage]>;
defm Import : LinkageTypeOperand<1, [Linkage]>;
+defm LinkOnceODR : LinkageTypeOperand<2, [Linkage]>;
//===----------------------------------------------------------------------===//
// Multiclass used to define AccessQualifier enum values and at the same time
diff --git a/llvm/test/CodeGen/SPIRV/LinkOnceODR.ll b/llvm/test/CodeGen/SPIRV/LinkOnceODR.ll
index 3fb49ac241c6e6..3dfdeac7adaa5e 100644
--- a/llvm/test/CodeGen/SPIRV/LinkOnceODR.ll
+++ b/llvm/test/CodeGen/SPIRV/LinkOnceODR.ll
@@ -1,5 +1,14 @@
-;; No extension -> no LinkOnceODR
+; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_KHR_linkonce_odr %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV-EXT
+; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_KHR_linkonce_odr %s -o - -filetype=obj | spirv-val %}
+
+; CHECK-SPIRV-EXT: Capability Linkage
+; CHECK-SPIRV-EXT: Extension "SPV_KHR_linkonce_odr"
+; CHECK-SPIRV-EXT-DAG: OpDecorate %[[#]] LinkageAttributes "GV" LinkOnceODR
+; CHECK-SPIRV-EXT-DAG: OpDecorate %[[#]] LinkageAttributes "square" LinkOnceODR
+
+; No extension -> no LinkOnceODR
; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV
+; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %}
; CHECK-SPIRV-NOT: OpExtension "SPV_KHR_linkonce_odr"
; CHECK-SPIRV-NOT: OpDecorate %[[#]] LinkageAttributes "GV" LinkOnceODR
diff --git a/llvm/test/CodeGen/SPIRV/LinkOnceODRFun.ll b/llvm/test/CodeGen/SPIRV/LinkOnceODRFun.ll
new file mode 100644
index 00000000000000..7505c3fc277e9e
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/LinkOnceODRFun.ll
@@ -0,0 +1,17 @@
+; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_KHR_linkonce_odr %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV-EXT
+; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_KHR_linkonce_odr %s -o - -filetype=obj | spirv-val %}
+
+; CHECK-SPIRV-EXT: Capability Linkage
+; CHECK-SPIRV-EXT: Extension "SPV_KHR_linkonce_odr"
+; CHECK-SPIRV-EXT-DAG: OpDecorate %[[#]] LinkageAttributes "square" LinkOnceODR
+
+define spir_kernel void @k() {
+entry:
+ %call = call spir_func i32 @square(i32 2)
+ ret void
+}
+
+define linkonce_odr dso_local spir_func i32 @square(i32 %in) {
+entry:
+ ret i32 %in
+}
More information about the llvm-commits
mailing list