clspv icon indicating copy to clipboard operation
clspv copied to clipboard

Invalid SPIR-V generated with load/store on some struct members

Open mantognini opened this issue 4 years ago • 1 comments

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.

mantognini avatar Apr 08 '21 11:04 mantognini

This is fixed with #846 (might already be fixed in main)

rjodinchr avatar May 18 '22 14:05 rjodinchr