Skip to content

[SPIR-V] Broken translation of some struct types in opaque pointer mode #260

@michalpaszkowski

Description

@michalpaszkowski

During the work on the patch D149679 , I noticed several potential issues with generating struct types in opaque pointer mode.

The problem is visible in block_w_struct_return.ll test. The SPIR-V backend generates the following code in opaque pointer mode:

	OpCapability Kernel
	OpCapability Int8
	OpCapability GenericPointer
	OpCapability Linkage
	OpExtension "SPV_KHR_no_integer_wrap_decoration"
	%1 = OpExtInstImport "OpenCL.std"
	OpMemoryModel Physical32 OpenCL
	OpEntryPoint Kernel %29 "block_ret_struct" %27 %25
	OpExecutionMode %29 ContractionOff
	OpExecutionMode %52 ContractionOff
	OpSource Unknown 0
	OpName %28 "res"
	OpName %29 "block_ret_struct"
	OpName %27 "__block_literal_global"
	OpName %30 "res.addr"
	OpName %31 "kernelBlock"
	OpName %32 "tid"
	OpName %33 "aa"
	OpName %34 "tmp"
	OpName %25 "__spirv_BuiltInGlobalInvocationId"
	OpName %37 "call"
	OpName %45 "sub"
	OpName %49 "agg.result"
	OpName %50 ".block_descriptor"
	OpName %51 "a"
	OpName %52 "__block_ret_struct_block_invoke"
	OpName %53 ".block_descriptor.addr"
	OpName %54 "block"
	OpDecorate %27 Constant
	OpDecorate %27 Alignment 4
	OpDecorate %25 Constant
	OpDecorate %25 LinkageAttributes "__spirv_BuiltInGlobalInvocationId" Import
	OpDecorate %25 BuiltIn GlobalInvocationId
	OpDecorate %45 NoSignedWrap
	OpDecorate %49 Alignment 4
	OpDecorate %49 FuncParamAttr NoAlias
	OpDecorate %51 Alignment 4
	%2 = OpTypeInt 8 0
	%3 = OpTypePointer CrossWorkgroup %2
	%4 = OpTypeVoid
	%5 = OpTypeFunction %4 %3
	%6 = OpTypeInt 32 0
	%7 = OpTypeVector %6 3
	%8 = OpTypePointer Input %2
	%9 = OpTypePointer Function %2
	%10 = OpTypePointer Generic %2
	%11 = OpTypeStruct %6 %6 %10
	%12 = OpTypeFunction %4 %9 %10 %9
	%13 = OpConstant %6 12 
	%14 = OpConstant %6 4 
	%15 = OpTypePointer Generic %2
	%16 = OpTypePointer Function %12
	%17 = OpConstantNull %16
	%18 = OpSpecConstantOp %15 121 %17
	%19 = OpConstantComposite %11 %13 %14 %18
	%20 = OpConstant %6 0 
	%21 = OpConstant %6 4294967295 
	%22 = OpConstant %6 5 
	%23 = OpConstant %6 6 
	%24 = OpTypePointer Function %8
	%25 = OpVariable %8 Input 
	%26 = OpTypePointer CrossWorkgroup %11
	%27 = OpVariable %26 CrossWorkgroup %19
	%29 = OpFunction %4 None %5             ; -- Begin function block_ret_struct
	%28 = OpFunctionParameter %3
	%58 = OpLabel
	%30 = OpVariable %9 Function 
	%31 = OpVariable %9 Function 
	%32 = OpVariable %9 Function 
	%33 = OpVariable %9 Function 
	%34 = OpVariable %9 Function 
	OpStore %30 %28 Aligned 4
	%35 = OpPtrCastToGeneric %10 %27
	OpStore %31 %35 Aligned 4
	%36 = OpLoad %7 %25 Aligned 1
	%37 = OpCompositeExtract %6 %36 0
	OpStore %32 %37 Aligned 4
	%38 = OpLoad %3 %30 Aligned 4
	%39 = OpLoad %6 %32 Aligned 4
	%40 = OpInBoundsPtrAccessChain %3 %38 %39
	OpStore %40 %21 Aligned 4
	%41 = OpInBoundsPtrAccessChain %9 %33 %20 %20
	OpStore %41 %22 Aligned 4
	%42 = OpFunctionCall %4 %52 %34 %35 %33
	%43 = OpInBoundsPtrAccessChain %9 %34 %20 %20
	%44 = OpLoad %6 %43 Aligned 4
	%45 = OpISub %6 %44 %23
	%46 = OpLoad %3 %30 Aligned 4
	%47 = OpLoad %6 %32 Aligned 4
	%48 = OpInBoundsPtrAccessChain %3 %46 %47
	OpStore %48 %45 Aligned 4
	OpReturn
	OpFunctionEnd
                                        ; -- End function
	%52 = OpFunction %4 None %12            ; -- Begin function __block_ret_struct_block_invoke
	%49 = OpFunctionParameter %9
	%50 = OpFunctionParameter %10
	%51 = OpFunctionParameter %9
	%59 = OpLabel
	%53 = OpVariable %9 Function 
	OpStore %53 %50 Aligned 4
	%54 = OpBitcast %10 %50
	%55 = OpInBoundsPtrAccessChain %9 %51 %20 %20
	OpStore %55 %23 Aligned 4
	%56 = OpBitcast %9 %49
	%57 = OpBitcast %9 %51
	OpCopyMemorySized %56 %57 %14 Aligned 4
	OpReturn
	OpFunctionEnd
                                        ; -- End function

While the Khronos SPIR-V Translator generates:

; SPIR-V
; Version: 1.4
; Generator: Khronos LLVM/SPIR-V Translator; 14
; Bound: 79
; Schema: 0
               OpCapability Addresses
               OpCapability Linkage
               OpCapability Kernel
               OpCapability GenericPointer
               OpCapability Int8
          %1 = OpExtInstImport "OpenCL.std"
               OpMemoryModel Physical32 OpenCL
               OpEntryPoint Kernel %75 "block_ret_struct" %__block_literal_global
               OpExecutionMode %75 ContractionOff
               OpSource Unknown 0
               OpName %__block_literal_global "__block_literal_global"
               OpName %_Z13get_global_idj "_Z13get_global_idj"
               OpName %block_ret_struct "block_ret_struct"
               OpName %res "res"
               OpName %entry "entry"
               OpName %res_addr "res.addr"
               OpName %kernelBlock "kernelBlock"
               OpName %tid "tid"
               OpName %struct_A "struct.A"
               OpName %aa "aa"
               OpName %tmp "tmp"
               OpName %call "call"
               OpName %arrayidx "arrayidx"
               OpName %a "a"
               OpName %__block_ret_struct_block_invoke "__block_ret_struct_block_invoke"
               OpName %agg_result "agg.result"
               OpName %_block_descriptor ".block_descriptor"
               OpName %a_0 "a"
               OpName %a1 "a1"
               OpName %sub "sub"
               OpName %arrayidx2 "arrayidx2"
               OpName %entry_0 "entry"
               OpName %_block_descriptor_addr ".block_descriptor.addr"
               OpName %block "block"
               OpName %a1_0 "a1"
               OpName %res_0 "res"
               OpDecorate %__block_literal_global Constant
               OpDecorate %__block_literal_global Alignment 4
               OpDecorate %_Z13get_global_idj LinkageAttributes "_Z13get_global_idj" Import
               OpDecorate %block_ret_struct LinkageAttributes "block_ret_struct" Export
               OpDecorate %res_addr Alignment 4
               OpDecorate %kernelBlock Alignment 4
               OpDecorate %tid Alignment 4
               OpDecorate %aa Alignment 4
               OpDecorate %tmp Alignment 4
               OpDecorate %agg_result FuncParamAttr NoAlias
               OpDecorate %agg_result FuncParamAttr Sret
               OpDecorate %agg_result Alignment 4
               OpDecorate %a_0 FuncParamAttr ByVal
               OpDecorate %a_0 Alignment 4
               OpDecorate %sub NoSignedWrap
               OpDecorate %_block_descriptor_addr Alignment 4
       %uint = OpTypeInt 32 0
      %uchar = OpTypeInt 8 0
    %uint_12 = OpConstant %uint 12
     %uint_4 = OpConstant %uint 4
     %uint_0 = OpConstant %uint 0
%uint_4294967295 = OpConstant %uint 4294967295
     %uint_5 = OpConstant %uint 5
     %uint_6 = OpConstant %uint 6
%_ptr_Generic_uchar = OpTypePointer Generic %uchar
  %_struct_8 = OpTypeStruct %uint %uint %_ptr_Generic_uchar
%_ptr_CrossWorkgroup__struct_8 = OpTypePointer CrossWorkgroup %_struct_8
         %12 = OpTypeFunction %uint %uint
       %void = OpTypeVoid
%_ptr_CrossWorkgroup_uchar = OpTypePointer CrossWorkgroup %uchar
         %17 = OpTypeFunction %void %_ptr_CrossWorkgroup_uchar
%_ptr_Function__ptr_CrossWorkgroup_uchar = OpTypePointer Function %_ptr_CrossWorkgroup_uchar
%_ptr_Function__ptr_Generic_uchar = OpTypePointer Function %_ptr_Generic_uchar
%_ptr_Function_uint = OpTypePointer Function %uint
   %struct_A = OpTypeStruct %uint
%_ptr_Function_struct_A = OpTypePointer Function %struct_A
%_ptr_Function_uchar = OpTypePointer Function %uchar
%_ptr_Generic__struct_8 = OpTypePointer Generic %_struct_8
%_ptr_Function__ptr_Generic__struct_8 = OpTypePointer Function %_ptr_Generic__struct_8
%_ptr_CrossWorkgroup_uint = OpTypePointer CrossWorkgroup %uint
%_ptr_Function__ptr_CrossWorkgroup_uint = OpTypePointer Function %_ptr_CrossWorkgroup_uint
         %51 = OpTypeFunction %void %_ptr_Function_struct_A %_ptr_Generic__struct_8 %_ptr_Function_struct_A
          %7 = OpConstantNull %_ptr_Generic_uchar
          %9 = OpConstantComposite %_struct_8 %uint_12 %uint_4 %7
%__block_literal_global = OpVariable %_ptr_CrossWorkgroup__struct_8 CrossWorkgroup %9
%_Z13get_global_idj = OpFunction %uint None %12
         %14 = OpFunctionParameter %uint
               OpFunctionEnd
%block_ret_struct = OpFunction %void None %17
        %res = OpFunctionParameter %_ptr_CrossWorkgroup_uchar
      %entry = OpLabel
   %res_addr = OpVariable %_ptr_Function__ptr_CrossWorkgroup_uchar Function
%kernelBlock = OpVariable %_ptr_Function__ptr_Generic_uchar Function
        %tid = OpVariable %_ptr_Function_uint Function
         %aa = OpVariable %_ptr_Function_struct_A Function
        %tmp = OpVariable %_ptr_Function_struct_A Function
         %31 = OpBitcast %_ptr_Function__ptr_CrossWorkgroup_uchar %res_addr
               OpStore %31 %res Aligned 4
         %33 = OpBitcast %_ptr_Function_uchar %kernelBlock
               OpLifetimeStart %33 4
         %35 = OpPtrCastToGeneric %_ptr_Generic__struct_8 %__block_literal_global
         %37 = OpBitcast %_ptr_Function__ptr_Generic__struct_8 %kernelBlock
               OpStore %37 %35 Aligned 4
         %38 = OpBitcast %_ptr_Function_uchar %tid
               OpLifetimeStart %38 4
       %call = OpFunctionCall %uint %_Z13get_global_idj %uint_0
               OpStore %tid %call Aligned 4
         %43 = OpBitcast %_ptr_Function__ptr_CrossWorkgroup_uint %res_addr
         %44 = OpLoad %_ptr_CrossWorkgroup_uint %43 Aligned 4
         %45 = OpLoad %uint %tid Aligned 4
   %arrayidx = OpInBoundsPtrAccessChain %_ptr_CrossWorkgroup_uint %44 %45
               OpStore %arrayidx %uint_4294967295 Aligned 4
         %48 = OpBitcast %_ptr_Function_uchar %aa
               OpLifetimeStart %48 4
          %a = OpInBoundsPtrAccessChain %_ptr_Function_uint %aa %uint_0 %uint_0
               OpStore %a %uint_5 Aligned 4
         %56 = OpFunctionCall %void %__block_ret_struct_block_invoke %tmp %35 %aa
         %a1 = OpInBoundsPtrAccessChain %_ptr_Function_uint %tmp %uint_0 %uint_0
         %58 = OpLoad %uint %a1 Aligned 4
        %sub = OpISub %uint %58 %uint_6
         %61 = OpBitcast %_ptr_Function__ptr_CrossWorkgroup_uint %res_addr
         %62 = OpLoad %_ptr_CrossWorkgroup_uint %61 Aligned 4
         %63 = OpLoad %uint %tid Aligned 4
  %arrayidx2 = OpInBoundsPtrAccessChain %_ptr_CrossWorkgroup_uint %62 %63
               OpStore %arrayidx2 %sub Aligned 4
         %65 = OpBitcast %_ptr_Function_uchar %aa
               OpLifetimeStop %65 4
         %66 = OpBitcast %_ptr_Function_uchar %tid
               OpLifetimeStop %66 4
         %67 = OpBitcast %_ptr_Function_uchar %kernelBlock
               OpLifetimeStop %67 4
               OpReturn
               OpFunctionEnd
%__block_ret_struct_block_invoke = OpFunction %void None %51
 %agg_result = OpFunctionParameter %_ptr_Function_struct_A
%_block_descriptor = OpFunctionParameter %_ptr_Generic__struct_8
        %a_0 = OpFunctionParameter %_ptr_Function_struct_A
    %entry_0 = OpLabel
%_block_descriptor_addr = OpVariable %_ptr_Function__ptr_Generic_uchar Function
         %70 = OpBitcast %_ptr_Function__ptr_Generic__struct_8 %_block_descriptor_addr
               OpStore %70 %_block_descriptor Aligned 4
      %block = OpBitcast %_ptr_Generic_uchar %_block_descriptor
       %a1_0 = OpInBoundsPtrAccessChain %_ptr_Function_uint %a_0 %uint_0 %uint_0
               OpStore %a1_0 %uint_6 Aligned 4
         %73 = OpBitcast %_ptr_Function_uchar %agg_result
         %74 = OpBitcast %_ptr_Function_uchar %a_0
               OpCopyMemorySized %73 %74 %uint_4 Aligned 4
               OpReturn
               OpFunctionEnd
         %75 = OpFunction %void None %17
      %res_0 = OpFunctionParameter %_ptr_CrossWorkgroup_uchar
         %77 = OpLabel
         %78 = OpFunctionCall %void %block_ret_struct %res_0
               OpReturn
               OpFunctionEnd

Notice missing OpTypeStruct for %struct.A = type { i32 }. The issue will need to be narrowed down. There are also big differences in the typed pointer mode between the backend and the translator on this test case.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions