Skip to content

Commit f7be667

Browse files
mantogninisvenvh
authored andcommitted
Add default initializer to CrossWorkgroup globals
This patch ensures that OpenCL program-scope variables in the global address space have an appropriate null value by default, following the OpenCL C Specification s6.7.1. This patch is needed to support linked SPIR-V modules. An OpenCL program-scope variable in the global address space such as "int foo;" is represented as follows in LLVM IR: @foo = common dso_local local_unnamed_addr addrspace(1) global i32 0, align 4 Given the above IR, the LLVM to SPIR-V translator produces an exported OpVariable without the default zero initializer, because LLVMToSPIRV::transValueWithoutDecoration knows that variables with common linkage type are initialized to 0 and that they can be represented in SPIR-V as uninitialized variables with the "Export" linkage type as shown: OpDecorate %foo LinkageAttributes "foo" Export %foo = OpVariable %_ptr_CrossWorkgroup_uint CrossWorkgroup When the SPIR-V linker is used to create a program, and not a library, it removes the "Export" decoration. When translating back to LLVM, the SPIR-V reader knows in SPIRVToLLVM::transLinkageType that an exported OpVariable with no initializer corresponds to a global LLVM variable with common linkage type and that, therefore, its initializer is zero (as per the LLVM IR specification). However, after linking, the variable no longer has the export decoration and SPIRVToLLVM::transLinkageType assumes it has an internal linkage type and prior to this patch SPIRVToLLVM::transValueWithoutDecoration no longer knew its default value. This resulted in an invalid LLVM module: @foo = internal addrspace(1) global i32, align 4 ; missing initializer ^ Actually, llvm::verifyModule complains that: Global is external, but doesn't have external or weak linkage! i32 addrspace(1)* @foo Side note: this message might seem a bit confusing at first. The verifier thinks that this LLVM global variable is external because it is a declaration (as it has no initializer). It has internal linkage type, which is not valid for declarations. This patch recovers the lost information, by ensuring that program-scope variables in the global address space have a default value of zero and, therefore, ensures that the translation from LLVM to SPIR-V and back to LLVM is consistent even when the SPIR-V linker is involved. Co-authored-by: Sven van Haastregt <sven.vanhaastregt@arm.com>
1 parent 6bd6416 commit f7be667

File tree

2 files changed

+6
-7
lines changed

2 files changed

+6
-7
lines changed

llvm-spirv/lib/SPIRV/SPIRVReader.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1641,18 +1641,20 @@ Value *SPIRVToLLVM::transValueWithoutDecoration(SPIRVValue *BV, Function *F,
16411641
auto Ty = transType(BVar->getType()->getPointerElementType());
16421642
bool IsConst = BVar->isConstant();
16431643
llvm::GlobalValue::LinkageTypes LinkageTy = transLinkageType(BVar);
1644+
SPIRVStorageClassKind BS = BVar->getStorageClass();
16441645
Constant *Initializer = nullptr;
16451646
SPIRVValue *Init = BVar->getInitializer();
16461647
if (Init)
16471648
Initializer = dyn_cast<Constant>(transValue(Init, F, BB, false));
16481649
else if (LinkageTy == GlobalValue::CommonLinkage)
1649-
// In LLVM variables with common linkage type must be initilized by 0
1650+
// In LLVM, variables with common linkage type must be initialized to 0.
16501651
Initializer = Constant::getNullValue(Ty);
1651-
else if (BVar->getStorageClass() ==
1652-
SPIRVStorageClassKind::StorageClassWorkgroup)
1652+
else if (BS == SPIRVStorageClassKind::StorageClassWorkgroup)
16531653
Initializer = dyn_cast<Constant>(UndefValue::get(Ty));
1654+
else if ((LinkageTy != GlobalValue::ExternalLinkage) &&
1655+
(BS == SPIRVStorageClassKind::StorageClassCrossWorkgroup))
1656+
Initializer = Constant::getNullValue(Ty);
16541657

1655-
SPIRVStorageClassKind BS = BVar->getStorageClass();
16561658
if (BS == StorageClassFunction && !Init) {
16571659
assert(BB && "Invalid BB");
16581660
return mapValue(BV, new AllocaInst(Ty, 0, BV->getName(), BB));

llvm-spirv/test/transcoding/linked-program.ll

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
; REQUIRES: spirv-link
22
;
3-
; FIXME This currently crashes when translating back from SPIR-V.
4-
; XFAIL: *
5-
;
63
; RUN: llvm-as %s -o %t.bc
74
; RUN: llvm-spirv %t.bc -o %t.spv
85
; RUN: spirv-val %t.spv

0 commit comments

Comments
 (0)