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.
This commit is contained in:
parent
dfb9bf35c4
commit
9552a396ed
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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(),
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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")));
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
17
llvm/test/CodeGen/SPIRV/LinkOnceODRFun.ll
Normal file
17
llvm/test/CodeGen/SPIRV/LinkOnceODRFun.ll
Normal file
@ -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
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user