From 41b1ca1263ac2afe8cd4298be6fd6561c4cfa382 Mon Sep 17 00:00:00 2001 From: "Levytskyy, Vyacheslav" Date: Mon, 12 Feb 2024 10:35:20 -0800 Subject: [PATCH 1/4] add support for the SPV_KHR_linkonce_odr extension --- llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp | 17 ++++++++++++----- .../Target/SPIRV/SPIRVInstructionSelector.cpp | 5 ++++- llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp | 6 ++++++ llvm/lib/Target/SPIRV/SPIRVSubtarget.cpp | 5 +++++ llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td | 1 + llvm/test/CodeGen/SPIRV/LinkOnceODR.ll | 11 ++++++++++- 6 files changed, 38 insertions(+), 7 deletions(-) diff --git a/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp b/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp index 8ac498e1556be..fd287f2a944d3 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(&MIRBuilder.getMF().getSubtarget()); + // Handle entry points and function linkage. if (isEntryPoint(F)) { const auto &STI = MIRBuilder.getMF().getSubtarget(); @@ -342,15 +346,18 @@ 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(LnkTy)}, F.getGlobalIdentifier()); } // Handle function pointers decoration - const auto *ST = - static_cast(&MIRBuilder.getMF().getSubtarget()); bool hasFunctionPointers = ST->canUseExtension(SPIRV::Extension::SPV_INTEL_function_pointers); if (hasFunctionPointers) { @@ -393,7 +400,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 52eeb8a523e6f..ed2c9ab4d4362 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 a18aae1761c83..cb2320a98b344 100644 --- a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp @@ -647,6 +647,12 @@ static void addOpDecorateReqs(const MachineInstr &MI, unsigned DecIndex, auto BuiltIn = static_cast(BuiltInOp); Reqs.addRequirements(getSymbolicOperandRequirements( SPIRV::OperandCategory::BuiltInOperand, BuiltIn, ST, Reqs)); + } else if (Dec == SPIRV::Decoration::LinkageAttributes) { + int64_t LinkageOp = MI.getOperand(DecIndex + 2).getImm(); + SPIRV::LinkageType::LinkageType LnkType = + static_cast(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 effedc2f17d35..6bcd8d4d51418 100644 --- a/llvm/lib/Target/SPIRV/SPIRVSubtarget.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVSubtarget.cpp @@ -54,6 +54,11 @@ cl::list 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 5d252275ac709..ed05013642ac2 100644 --- a/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td +++ b/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td @@ -1040,6 +1040,7 @@ multiclass LinkageTypeOperand value, list 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 3fb49ac241c6e..1ea6f62f3ba04 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 +; RUN: %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 +; RUN: %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 From df2a57dd4c613bd750981332f2514138ca357c7c Mon Sep 17 00:00:00 2001 From: "Levytskyy, Vyacheslav" Date: Mon, 12 Feb 2024 10:48:50 -0800 Subject: [PATCH 2/4] apply clang-format suggestions --- llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp | 15 ++++++++------- llvm/lib/Target/SPIRV/SPIRVSubtarget.cpp | 10 +++++----- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp b/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp index fd287f2a944d3..baeed2ad895a4 100644 --- a/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp @@ -346,13 +346,14 @@ bool SPIRVCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder, addStringImm(F.getName(), MIB); } else if (F.getLinkage() == GlobalValue::LinkageTypes::ExternalLinkage || F.getLinkage() == GlobalValue::LinkOnceODRLinkage) { - 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); + 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(LnkTy)}, F.getGlobalIdentifier()); } diff --git a/llvm/lib/Target/SPIRV/SPIRVSubtarget.cpp b/llvm/lib/Target/SPIRV/SPIRVSubtarget.cpp index 6bcd8d4d51418..354cd5d9b297e 100644 --- a/llvm/lib/Target/SPIRV/SPIRVSubtarget.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVSubtarget.cpp @@ -54,11 +54,11 @@ cl::list 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_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"))); From 639deba2b767acd69897121a85060d5aad386f24 Mon Sep 17 00:00:00 2001 From: "Levytskyy, Vyacheslav" Date: Mon, 12 Feb 2024 11:46:19 -0800 Subject: [PATCH 3/4] revert to don't using spirv-val --- llvm/test/CodeGen/SPIRV/LinkOnceODR.ll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm/test/CodeGen/SPIRV/LinkOnceODR.ll b/llvm/test/CodeGen/SPIRV/LinkOnceODR.ll index 1ea6f62f3ba04..3dfdeac7adaa5 100644 --- a/llvm/test/CodeGen/SPIRV/LinkOnceODR.ll +++ b/llvm/test/CodeGen/SPIRV/LinkOnceODR.ll @@ -1,5 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_KHR_linkonce_odr %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV-EXT -; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_KHR_linkonce_odr %s -o - -filetype=obj | spirv-val %} +; 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" @@ -8,7 +8,7 @@ ; No extension -> no LinkOnceODR ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV -; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} +; 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 From 81ca0c52b75507b41a6e3ea21e3415b90836ea13 Mon Sep 17 00:00:00 2001 From: "Levytskyy, Vyacheslav" Date: Wed, 14 Feb 2024 09:00:22 -0800 Subject: [PATCH 4/4] fix access to linkage type operand --- llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp | 2 +- llvm/test/CodeGen/SPIRV/LinkOnceODRFun.ll | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 llvm/test/CodeGen/SPIRV/LinkOnceODRFun.ll diff --git a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp index cb2320a98b344..0412d98345524 100644 --- a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp @@ -648,7 +648,7 @@ static void addOpDecorateReqs(const MachineInstr &MI, unsigned DecIndex, Reqs.addRequirements(getSymbolicOperandRequirements( SPIRV::OperandCategory::BuiltInOperand, BuiltIn, ST, Reqs)); } else if (Dec == SPIRV::Decoration::LinkageAttributes) { - int64_t LinkageOp = MI.getOperand(DecIndex + 2).getImm(); + int64_t LinkageOp = MI.getOperand(MI.getNumOperands() - 1).getImm(); SPIRV::LinkageType::LinkageType LnkType = static_cast(LinkageOp); if (LnkType == SPIRV::LinkageType::LinkOnceODR) diff --git a/llvm/test/CodeGen/SPIRV/LinkOnceODRFun.ll b/llvm/test/CodeGen/SPIRV/LinkOnceODRFun.ll new file mode 100644 index 0000000000000..7505c3fc277e9 --- /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 +}