Invalid SPIR-V generated with load/store on some struct members
This one was quite hard to reduce, even with the help of bugpoint. Hence why the snippet is not as short as I'd liked.
target datalayout = "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024"
target triple = "spir-unknown-unknown"
; vstore8(half8 value, int offset, half* ptr)
declare spir_func void @_Z7vstore8Dv8_DhjPU3AS1Dh(<8 x half>, i32, half addrspace(1)*)
%TYPE = type { i8 addrspace(1)*, i32 }
define spir_func void @foo(%TYPE* noalias sret(%TYPE) align 4 %x) {
entry:
%y = getelementptr inbounds %TYPE, %TYPE* %x, i32 0, i32 1 ; critical
ret void
}
define spir_kernel void @test() {
entry:
%dst = alloca %TYPE, align 4
call spir_func void @foo(%TYPE* sret(%TYPE) align 4 %dst)
%ptr = getelementptr inbounds %TYPE, %TYPE* %dst, i32 0, i32 0; ptr = i8**
%i8ptr = load i8 addrspace(1)*, i8 addrspace(1)** %ptr, align 4
%hptr = bitcast i8 addrspace(1)* %i8ptr to half addrspace(1)*
call spir_func void @_Z7vstore8Dv8_DhjPU3AS1Dh(<8 x half> zeroinitializer, i32 0, half addrspace(1)* %hptr)
ret void
}
Slight variations of this input result in different issues. The dead GEP in @foo is actually necessary to trigger a validation issue.
$ clspv -x ir validation-issue.ll -o - | spirv-val --target-env vulkan1.0
error: line 57: OpStore Pointer <id> '21[%21]' is not a logical pointer.
OpStore %21 %uchar_0
Using --print-after-all --print-module-scope I could see the final IR looks like this:
define spir_kernel void @test() local_unnamed_addr #1 !clspv.pod_args_impl !3 {
entry:
%0 = tail call spir_func %TYPE @foo()
%.elt = extractvalue %TYPE %0, 0
; no GEP!
store i8 0, i8 addrspace(1)* %.elt, align 1
%1 = getelementptr i8, i8 addrspace(1)* %.elt, i32 1
store i8 0, i8 addrspace(1)* %1, align 1
%2 = getelementptr i8, i8 addrspace(1)* %.elt, i32 2
store i8 0, i8 addrspace(1)* %2, align 1
[...]
Unfortunately, this final IR cannot be consumed by clspv -- it results in a unrelated crash.
If I hack the final module right before SPIR-V generation to replace this pattern:
%ptr = extractvalue %TYPE %x, 0
store i8 0, i8 addrspace(1)* %ptr
with
%tmp = extractvalue %TYPE %x, 0
%ptr = getelementptr i8, i8 addrspace(1)* %tmp, i32 0
store i8 0, i8 addrspace(1)* %ptr
the validation issue is gone. This essentially inserts a GEP 0 before the store, which does not modify the computed memory location but results in a pointer of a different type.
Note I've also seen this issue with load/OpLoad instructions. The pattern is the same.
This is fixed with #846 (might already be fixed in main)