Skip to content

Commit 9552a39

Browse files
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.
1 parent dfb9bf3 commit 9552a39

7 files changed

+56
-7
lines changed

llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp

+13-5
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,10 @@ bool SPIRVCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
332332
if (F.hasName())
333333
buildOpName(FuncVReg, F.getName(), MIRBuilder);
334334

335+
// Get access to information about available extensions
336+
const auto *ST =
337+
static_cast<const SPIRVSubtarget *>(&MIRBuilder.getMF().getSubtarget());
338+
335339
// Handle entry points and function linkage.
336340
if (isEntryPoint(F)) {
337341
const auto &STI = MIRBuilder.getMF().getSubtarget<SPIRVSubtarget>();
@@ -342,15 +346,19 @@ bool SPIRVCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
342346
addStringImm(F.getName(), MIB);
343347
} else if (F.getLinkage() == GlobalValue::LinkageTypes::ExternalLinkage ||
344348
F.getLinkage() == GlobalValue::LinkOnceODRLinkage) {
345-
auto LnkTy = F.isDeclaration() ? SPIRV::LinkageType::Import
346-
: SPIRV::LinkageType::Export;
349+
SPIRV::LinkageType::LinkageType LnkTy =
350+
F.isDeclaration()
351+
? SPIRV::LinkageType::Import
352+
: (F.getLinkage() == GlobalValue::LinkOnceODRLinkage &&
353+
ST->canUseExtension(
354+
SPIRV::Extension::SPV_KHR_linkonce_odr)
355+
? SPIRV::LinkageType::LinkOnceODR
356+
: SPIRV::LinkageType::Export);
347357
buildOpDecorate(FuncVReg, MIRBuilder, SPIRV::Decoration::LinkageAttributes,
348358
{static_cast<uint32_t>(LnkTy)}, F.getGlobalIdentifier());
349359
}
350360

351361
// Handle function pointers decoration
352-
const auto *ST =
353-
static_cast<const SPIRVSubtarget *>(&MIRBuilder.getMF().getSubtarget());
354362
bool hasFunctionPointers =
355363
ST->canUseExtension(SPIRV::Extension::SPV_INTEL_function_pointers);
356364
if (hasFunctionPointers) {
@@ -393,7 +401,7 @@ void SPIRVCallLowering::produceIndirectPtrTypes(
393401
// SPIR-V pointer to function type:
394402
SPIRVType *IndirectFuncPtrTy = GR->getOrCreateSPIRVPointerType(
395403
SpirvFuncTy, MIRBuilder, SPIRV::StorageClass::Function);
396-
// Correct the Calee type
404+
// Correct the Callee type
397405
GR->assignSPIRVTypeToVReg(IndirectFuncPtrTy, IC.Callee, MF);
398406
}
399407
}

llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp

+4-1
Original file line numberDiff line numberDiff line change
@@ -1601,7 +1601,10 @@ bool SPIRVInstructionSelector::selectGlobalValue(
16011601
SPIRV::LinkageType::LinkageType LnkType =
16021602
(GV->isDeclaration() || GV->hasAvailableExternallyLinkage())
16031603
? SPIRV::LinkageType::Import
1604-
: SPIRV::LinkageType::Export;
1604+
: (GV->getLinkage() == GlobalValue::LinkOnceODRLinkage &&
1605+
STI.canUseExtension(SPIRV::Extension::SPV_KHR_linkonce_odr)
1606+
? SPIRV::LinkageType::LinkOnceODR
1607+
: SPIRV::LinkageType::Export);
16051608

16061609
Register Reg = GR.buildGlobalVariable(ResVReg, ResType, GlobalIdent, GV,
16071610
Storage, Init, GlobalVar->isConstant(),

llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -679,6 +679,12 @@ static void addOpDecorateReqs(const MachineInstr &MI, unsigned DecIndex,
679679
auto BuiltIn = static_cast<SPIRV::BuiltIn::BuiltIn>(BuiltInOp);
680680
Reqs.addRequirements(getSymbolicOperandRequirements(
681681
SPIRV::OperandCategory::BuiltInOperand, BuiltIn, ST, Reqs));
682+
} else if (Dec == SPIRV::Decoration::LinkageAttributes) {
683+
int64_t LinkageOp = MI.getOperand(MI.getNumOperands() - 1).getImm();
684+
SPIRV::LinkageType::LinkageType LnkType =
685+
static_cast<SPIRV::LinkageType::LinkageType>(LinkageOp);
686+
if (LnkType == SPIRV::LinkageType::LinkOnceODR)
687+
Reqs.addExtension(SPIRV::Extension::SPV_KHR_linkonce_odr);
682688
}
683689
}
684690

llvm/lib/Target/SPIRV/SPIRVSubtarget.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,11 @@ cl::list<SPIRV::Extension::Extension> Extensions(
5454
"SPV_KHR_bit_instructions",
5555
"This enables bit instructions to be used by SPIR-V modules "
5656
"without requiring the Shader capability"),
57+
clEnumValN(
58+
SPIRV::Extension::SPV_KHR_linkonce_odr, "SPV_KHR_linkonce_odr",
59+
"Allows to use the LinkOnceODR linkage type that is to let "
60+
"a function or global variable to be merged with other functions "
61+
"or global variables of the same name when linkage occurs."),
5762
clEnumValN(SPIRV::Extension::SPV_INTEL_function_pointers,
5863
"SPV_INTEL_function_pointers",
5964
"Allows translation of function pointers")));

llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td

+1
Original file line numberDiff line numberDiff line change
@@ -1040,6 +1040,7 @@ multiclass LinkageTypeOperand<bits<32> value, list<Capability> reqCapabilities>
10401040

10411041
defm Export : LinkageTypeOperand<0, [Linkage]>;
10421042
defm Import : LinkageTypeOperand<1, [Linkage]>;
1043+
defm LinkOnceODR : LinkageTypeOperand<2, [Linkage]>;
10431044

10441045
//===----------------------------------------------------------------------===//
10451046
// Multiclass used to define AccessQualifier enum values and at the same time

llvm/test/CodeGen/SPIRV/LinkOnceODR.ll

+10-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
1-
;; No extension -> no LinkOnceODR
1+
; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_KHR_linkonce_odr %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV-EXT
2+
; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_KHR_linkonce_odr %s -o - -filetype=obj | spirv-val %}
3+
4+
; CHECK-SPIRV-EXT: Capability Linkage
5+
; CHECK-SPIRV-EXT: Extension "SPV_KHR_linkonce_odr"
6+
; CHECK-SPIRV-EXT-DAG: OpDecorate %[[#]] LinkageAttributes "GV" LinkOnceODR
7+
; CHECK-SPIRV-EXT-DAG: OpDecorate %[[#]] LinkageAttributes "square" LinkOnceODR
8+
9+
; No extension -> no LinkOnceODR
210
; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV
11+
; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %}
312

413
; CHECK-SPIRV-NOT: OpExtension "SPV_KHR_linkonce_odr"
514
; CHECK-SPIRV-NOT: OpDecorate %[[#]] LinkageAttributes "GV" LinkOnceODR
+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_KHR_linkonce_odr %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV-EXT
2+
; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_KHR_linkonce_odr %s -o - -filetype=obj | spirv-val %}
3+
4+
; CHECK-SPIRV-EXT: Capability Linkage
5+
; CHECK-SPIRV-EXT: Extension "SPV_KHR_linkonce_odr"
6+
; CHECK-SPIRV-EXT-DAG: OpDecorate %[[#]] LinkageAttributes "square" LinkOnceODR
7+
8+
define spir_kernel void @k() {
9+
entry:
10+
%call = call spir_func i32 @square(i32 2)
11+
ret void
12+
}
13+
14+
define linkonce_odr dso_local spir_func i32 @square(i32 %in) {
15+
entry:
16+
ret i32 %in
17+
}

0 commit comments

Comments
 (0)