Skip to content

Commit 1f6a5a2

Browse files
svenvhjsji
authored andcommitted
Emit alloca for all OpVariables with Function storage (#2986)
A Function storage class variable needs storage for each dynamic execution instance, so emit an alloca instead of a global. The SPIR-V Reader was already doing so for OpVariables without an initializer, but when an initializer is present it would still emit a global. Co-authored-by: Ben Watkins <[email protected]> Original commit: KhronosGroup/SPIRV-LLVM-Translator@648654da1d135e5
1 parent 1703841 commit 1f6a5a2

File tree

3 files changed

+49
-6
lines changed

3 files changed

+49
-6
lines changed

llvm-spirv/lib/SPIRV/SPIRVReader.cpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1660,9 +1660,18 @@ Value *SPIRVToLLVM::transValueWithoutDecoration(SPIRVValue *BV, Function *F,
16601660
return transValue(Init, F, BB);
16611661
}
16621662

1663-
if (BS == StorageClassFunction && !Init) {
1664-
assert(BB && "Invalid BB");
1665-
return mapValue(BV, new AllocaInst(Ty, 0, BV->getName(), BB));
1663+
if (BS == StorageClassFunction) {
1664+
// A Function storage class variable needs storage for each dynamic
1665+
// execution instance, so emit an alloca instead of a global.
1666+
assert(BB && "OpVariable with Function storage class requires BB");
1667+
IRBuilder<> Builder(BB);
1668+
AllocaInst *AI = Builder.CreateAlloca(Ty, 0, BV->getName());
1669+
if (Init) {
1670+
auto *Src = transValue(Init, F, BB);
1671+
const bool IsVolatile = BVar->hasDecorate(DecorationVolatile);
1672+
Builder.CreateStore(Src, AI, IsVolatile);
1673+
}
1674+
return mapValue(BV, AI);
16661675
}
16671676

16681677
SPIRAddressSpace AddrSpace;

llvm-spirv/test/OpCopyMemory.spvasm

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,6 @@
4646
OpFunctionEnd
4747

4848
; CHECK-LABEL: define spir_kernel void @copymemory(ptr addrspace(1) %dstShort, ptr addrspace(1) %dstInt, ptr addrspace(1) %dstStruct)
49-
; CHECK: call void @llvm.memcpy.p1.p0.i64(ptr addrspace(1) %dstShort, ptr @pShort, i64 2, i1 false)
50-
; CHECK: call void @llvm.memcpy.p1.p0.i64(ptr addrspace(1) %dstInt, ptr @pInt, i64 4, i1 false)
51-
; CHECK: call void @llvm.memcpy.p1.p0.i64(ptr addrspace(1) %dstStruct, ptr @pStruct, i64 12, i1 false)
49+
; CHECK: call void @llvm.memcpy.p1.p0.i64(ptr addrspace(1) %dstShort, ptr %pShort, i64 2, i1 false)
50+
; CHECK: call void @llvm.memcpy.p1.p0.i64(ptr addrspace(1) %dstInt, ptr %pInt, i64 4, i1 false)
51+
; CHECK: call void @llvm.memcpy.p1.p0.i64(ptr addrspace(1) %dstStruct, ptr %pStruct, i64 12, i1 false)
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
; Check translation of OpVariable with Function storage and initializer.
2+
3+
; REQUIRES: spirv-as
4+
; RUN: spirv-as --target-env spv1.0 -o %t.spv %s
5+
; RUN: spirv-val %t.spv
6+
; RUN: llvm-spirv -r %t.spv -o %t.rev.bc
7+
; RUN: llvm-dis %t.rev.bc -o - | FileCheck %s
8+
9+
OpCapability Addresses
10+
OpCapability Kernel
11+
OpCapability Int64
12+
OpMemoryModel Physical64 OpenCL
13+
OpEntryPoint Kernel %kernel "test"
14+
OpName %pvalue "pvalue"
15+
%uint = OpTypeInt 32 0
16+
%ulong = OpTypeInt 64 0
17+
%void = OpTypeVoid
18+
%gptr_int = OpTypePointer CrossWorkgroup %uint
19+
%pptr_int = OpTypePointer Function %uint
20+
%kernel_sig = OpTypeFunction %void %gptr_int
21+
%uint_42 = OpConstant %uint 42
22+
%ulong_4 = OpConstant %ulong 4
23+
%kernel = OpFunction %void None %kernel_sig
24+
%dst = OpFunctionParameter %gptr_int
25+
%entry = OpLabel
26+
%pvalue = OpVariable %pptr_int Function %uint_42
27+
OpCopyMemorySized %dst %pvalue %ulong_4 Volatile
28+
OpReturn
29+
OpFunctionEnd
30+
31+
; CHECK-LABEL: define spir_kernel void @test
32+
; CHECK: %pvalue = alloca i32, align 4
33+
; CHECK: store i32 42, ptr %pvalue, align 4
34+
; CHECK: call void @llvm.memcpy.p1.p0.i64

0 commit comments

Comments
 (0)