
Pointers and GEP are untyped. SPIR-V required structured OpAccessChain. This means the backend will have to determine a good way to retrieve the structured access from an untyped GEP. This is not a trivial problem, and needs to be addressed to have a robust compiler. The issue is other workstreams relies on the access chain deduction to work. So we have 2 options: - pause all dependent work until we have a good chain deduction. - submit this limited fix to we can work on both this and other features in parallel. Choice we want to make is #2: submitting this **knowing this is not a good** fix. It only increase the number of patterns we can work with, thus allowing others to continue working on other parts of the backend. This patch as-is has many limitations: - If cannot robustly determine the depth of the structured access from a GEP. Fixing this would require looking ahead at the full GEP chain. - It cannot always figure out the correct access indices, especially with dynamic indices. This will require frontend collaboration. Because we know this is a temporary hack, this patch only impacts the logical SPIR-V target. Physical SPIR-V, which can rely on pointer cast remains on the old method. Related to #145002
76 lines
3.8 KiB
LLVM
76 lines
3.8 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
|
|
; RUN: llc -verify-machineinstrs -O3 -mtriple=spirv1.6-unknown-vulkan1.3-compute %s -o - | FileCheck %s
|
|
; RUN: %if spirv-tools %{ llc -O3 -mtriple=spirv1.6-unknown-vulkan1.3-compute %s -o - -filetype=obj | spirv-val %}
|
|
|
|
; struct S1 {
|
|
; int4 i;
|
|
; float4 f;
|
|
; };
|
|
; struct S2 {
|
|
; float4 f;
|
|
; int4 i;
|
|
; };
|
|
;
|
|
; StructuredBuffer<S1> In : register(t1);
|
|
; RWStructuredBuffer<S2> Out : register(u0);
|
|
;
|
|
; [numthreads(1,1,1)]
|
|
; void main(uint GI : SV_GroupIndex) {
|
|
; Out[GI].f = In[GI].f;
|
|
; Out[GI].i = In[GI].i;
|
|
; }
|
|
|
|
%struct.S1 = type { <4 x i32>, <4 x float> }
|
|
%struct.S2 = type { <4 x float>, <4 x i32> }
|
|
|
|
@.str = private unnamed_addr constant [3 x i8] c"In\00", align 1
|
|
@.str.2 = private unnamed_addr constant [4 x i8] c"Out\00", align 1
|
|
|
|
define void @main() local_unnamed_addr #0 {
|
|
; CHECK-LABEL: main
|
|
; CHECK: %43 = OpFunction %2 None %3 ; -- Begin function main
|
|
; CHECK-NEXT: %1 = OpLabel
|
|
; CHECK-NEXT: %44 = OpVariable %28 Function %38
|
|
; CHECK-NEXT: %45 = OpVariable %27 Function %39
|
|
; CHECK-NEXT: %46 = OpCopyObject %19 %40
|
|
; CHECK-NEXT: %47 = OpCopyObject %16 %41
|
|
; CHECK-NEXT: %48 = OpLoad %4 %42
|
|
; CHECK-NEXT: %49 = OpAccessChain %13 %46 %29 %48
|
|
; CHECK-NEXT: %50 = OpInBoundsAccessChain %9 %49 %31
|
|
; CHECK-NEXT: %51 = OpLoad %8 %50 Aligned 1
|
|
; CHECK-NEXT: %52 = OpAccessChain %11 %47 %29 %48
|
|
; CHECK-NEXT: %53 = OpInBoundsAccessChain %9 %52 %29
|
|
; CHECK-NEXT: OpStore %53 %51 Aligned 1
|
|
; CHECK-NEXT: %54 = OpAccessChain %6 %49 %29
|
|
; CHECK-NEXT: %55 = OpLoad %5 %54 Aligned 1
|
|
; CHECK-NEXT: %56 = OpInBoundsAccessChain %6 %52 %31
|
|
; CHECK-NEXT: OpStore %56 %55 Aligned 1
|
|
; CHECK-NEXT: OpReturn
|
|
; CHECK-NEXT: OpFunctionEnd
|
|
entry:
|
|
%0 = tail call target("spirv.VulkanBuffer", [0 x %struct.S1], 12, 0) @llvm.spv.resource.handlefrombinding.tspirv.VulkanBuffer_a0s_struct.S1s_12_0t(i32 0, i32 1, i32 1, i32 0, i1 false, ptr nonnull @.str)
|
|
%1 = tail call target("spirv.VulkanBuffer", [0 x %struct.S2], 12, 1) @llvm.spv.resource.handlefrombinding.tspirv.VulkanBuffer_a0s_struct.S2s_12_1t(i32 0, i32 0, i32 1, i32 0, i1 false, ptr nonnull @.str.2)
|
|
%2 = tail call i32 @llvm.spv.flattened.thread.id.in.group()
|
|
%3 = tail call noundef align 1 dereferenceable(32) ptr addrspace(11) @llvm.spv.resource.getpointer.p11.tspirv.VulkanBuffer_a0s_struct.S1s_12_0t(target("spirv.VulkanBuffer", [0 x %struct.S1], 12, 0) %0, i32 %2)
|
|
%f.i = getelementptr inbounds nuw i8, ptr addrspace(11) %3, i64 16
|
|
%4 = load <4 x float>, ptr addrspace(11) %f.i, align 1
|
|
%5 = tail call noundef align 1 dereferenceable(32) ptr addrspace(11) @llvm.spv.resource.getpointer.p11.tspirv.VulkanBuffer_a0s_struct.S2s_12_1t(target("spirv.VulkanBuffer", [0 x %struct.S2], 12, 1) %1, i32 %2)
|
|
store <4 x float> %4, ptr addrspace(11) %5, align 1
|
|
%6 = load <4 x i32>, ptr addrspace(11) %3, align 1
|
|
%i6.i = getelementptr inbounds nuw i8, ptr addrspace(11) %5, i64 16
|
|
store <4 x i32> %6, ptr addrspace(11) %i6.i, align 1
|
|
ret void
|
|
}
|
|
|
|
declare i32 @llvm.spv.flattened.thread.id.in.group()
|
|
|
|
declare target("spirv.VulkanBuffer", [0 x %struct.S1], 12, 0) @llvm.spv.resource.handlefrombinding.tspirv.VulkanBuffer_a0s_struct.S1s_12_0t(i32, i32, i32, i32, i1, ptr)
|
|
|
|
declare target("spirv.VulkanBuffer", [0 x %struct.S2], 12, 1) @llvm.spv.resource.handlefrombinding.tspirv.VulkanBuffer_a0s_struct.S2s_12_1t(i32, i32, i32, i32, i1, ptr)
|
|
|
|
declare ptr addrspace(11) @llvm.spv.resource.getpointer.p11.tspirv.VulkanBuffer_a0s_struct.S2s_12_1t(target("spirv.VulkanBuffer", [0 x %struct.S2], 12, 1), i32)
|
|
|
|
declare ptr addrspace(11) @llvm.spv.resource.getpointer.p11.tspirv.VulkanBuffer_a0s_struct.S1s_12_0t(target("spirv.VulkanBuffer", [0 x %struct.S1], 12, 0), i32)
|
|
|
|
attributes #0 = { "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" }
|