Skip to content

Commit c3d8124

Browse files
authored
[Utils][SPIR-V] Adding spirv-sim to LLVM (#104020)
Currently, the testing infrastructure for SPIR-V is based on FileCheck. Those tests are great to check some level of codegen, but when the test needs check both the CFG layout and the content of each basic-block, things becomes messy. - Because the CHECK/CHECK-DAG/CHECK-NEXT state is limited, it is sometimes hard to catch the good block: if 2 basic blocks have similar instructions, FileCheck can match the wrong one. - Cross-lane interaction can be a bit difficult to understand, and writting a FileCheck test that is strong enough to catch bad CFG transforms while not being broken everytime some unrelated codegen part changes is hard. And lastly, the spirv-val tooling we have checks that the generated SPIR-V respects the spec, not that it is correct in regards to the source IR. For those reasons, I believe the best way to test the structurizer is to: - run spirv-val to make sure the CFG respects the spec. - simulate the function to validate result for each lane, making sure the generated code is correct. This simulator has no other dependencies than core python. It also only supports a very limited set of instructions as we can test most features through control-flow and some basic cross-lane interactions. As-is, the added tests are just a harness for the simulator itself. If this gets merged, the structurizer PR will benefit from this as I'll be able to add extensive testing using this. --------- Signed-off-by: Nathan Gauër <[email protected]>
1 parent fe1a1ee commit c3d8124

File tree

14 files changed

+1459
-1
lines changed

14 files changed

+1459
-1
lines changed

llvm/test/Other/spirv-sim/branch.spv

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
; RUN: %if spirv-tools %{ spirv-as %s -o - | spirv-val - %}
2+
; RUN: spirv-sim --function=simple --wave=3 --expects=5,6,6 -i %s
3+
OpCapability Shader
4+
OpCapability GroupNonUniform
5+
OpMemoryModel Logical GLSL450
6+
OpEntryPoint GLCompute %main "main" %WaveIndex
7+
OpExecutionMode %main LocalSize 1 1 1
8+
OpSource HLSL 670
9+
OpName %simple "simple"
10+
OpName %main "main"
11+
OpDecorate %WaveIndex BuiltIn SubgroupLocalInvocationId
12+
%int = OpTypeInt 32 1
13+
%uint = OpTypeInt 32 0
14+
%bool = OpTypeBool
15+
%int_2 = OpConstant %int 2
16+
%int_5 = OpConstant %int 5
17+
%int_6 = OpConstant %int 6
18+
%uint_0 = OpConstant %uint 0
19+
%void = OpTypeVoid
20+
%main_type = OpTypeFunction %void
21+
%simple_type = OpTypeFunction %int
22+
%uint_iptr = OpTypePointer Input %uint
23+
%WaveIndex = OpVariable %uint_iptr Input
24+
%main = OpFunction %void None %main_type
25+
%entry = OpLabel
26+
OpReturn
27+
OpFunctionEnd
28+
%simple = OpFunction %int None %simple_type
29+
%1 = OpLabel
30+
%2 = OpLoad %uint %WaveIndex
31+
%3 = OpIEqual %bool %uint_0 %2
32+
OpSelectionMerge %merge None
33+
OpBranchConditional %3 %true %false
34+
%true = OpLabel
35+
OpBranch %merge
36+
%false = OpLabel
37+
OpBranch %merge
38+
%merge = OpLabel
39+
%4 = OpPhi %int %int_5 %true %int_6 %false
40+
OpReturnValue %4
41+
OpFunctionEnd
42+

llvm/test/Other/spirv-sim/call.spv

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
; RUN: %if spirv-tools %{ spirv-as %s -o - | spirv-val - %}
2+
; RUN: spirv-sim --function=simple --wave=1 --expects=2 -i %s
3+
OpCapability Shader
4+
OpCapability GroupNonUniform
5+
OpMemoryModel Logical GLSL450
6+
OpEntryPoint GLCompute %main "main" %WaveIndex
7+
OpExecutionMode %main LocalSize 1 1 1
8+
OpSource HLSL 670
9+
OpName %simple "simple"
10+
OpName %main "main"
11+
OpDecorate %WaveIndex BuiltIn SubgroupLocalInvocationId
12+
%int = OpTypeInt 32 1
13+
%uint = OpTypeInt 32 0
14+
%uint_2 = OpConstant %uint 2
15+
%void = OpTypeVoid
16+
%main_type = OpTypeFunction %void
17+
%simple_type = OpTypeFunction %int
18+
%sub_type = OpTypeFunction %uint
19+
%uint_iptr = OpTypePointer Input %uint
20+
%WaveIndex = OpVariable %uint_iptr Input
21+
%main = OpFunction %void None %main_type
22+
%entry = OpLabel
23+
OpReturn
24+
OpFunctionEnd
25+
%sub = OpFunction %uint None %sub_type
26+
%a = OpLabel
27+
OpReturnValue %uint_2
28+
OpFunctionEnd
29+
%simple = OpFunction %int None %simple_type
30+
%1 = OpLabel
31+
%2 = OpFunctionCall %uint %sub
32+
%3 = OpBitcast %int %2
33+
OpReturnValue %3
34+
OpFunctionEnd
35+
36+
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
; RUN: %if spirv-tools %{ spirv-as %s -o - | spirv-val - %}
2+
; RUN: spirv-sim --function=a --wave=1 --expects=2 -i %s
3+
; RUN: spirv-sim --function=b --wave=1 --expects=1 -i %s
4+
OpCapability Shader
5+
OpMemoryModel Logical GLSL450
6+
OpEntryPoint GLCompute %main "main"
7+
OpExecutionMode %main LocalSize 1 1 1
8+
OpSource HLSL 670
9+
OpName %a "a"
10+
OpName %b "b"
11+
OpName %main "main"
12+
%int = OpTypeInt 32 1
13+
%s1 = OpTypeStruct %int %int %int
14+
%s2 = OpTypeStruct %s1
15+
%int_1 = OpConstant %int 1
16+
%int_2 = OpConstant %int 2
17+
%s1_1_2 = OpConstantComposite %s1 %int_1 %int_2 %int_1
18+
%s2_s1 = OpConstantComposite %s2 %s1_1_2
19+
%void = OpTypeVoid
20+
%main_type = OpTypeFunction %void
21+
%simple_type = OpTypeFunction %int
22+
%main = OpFunction %void None %main_type
23+
%entry = OpLabel
24+
OpReturn
25+
OpFunctionEnd
26+
%a = OpFunction %int None %simple_type
27+
%1 = OpLabel
28+
%2 = OpCompositeExtract %int %s1_1_2 1
29+
OpReturnValue %2
30+
OpFunctionEnd
31+
%b = OpFunction %int None %simple_type
32+
%3 = OpLabel
33+
%4 = OpCompositeExtract %int %s2_s1 0 2
34+
OpReturnValue %4
35+
OpFunctionEnd
36+
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
spirv_sim_root = os.path.join(config.llvm_src_root, "utils", "spirv-sim")
2+
config.substitutions.append(
3+
(
4+
"spirv-sim",
5+
"'%s' %s"
6+
% (config.python_executable, os.path.join(spirv_sim_root, "spirv-sim.py")),
7+
)
8+
)

llvm/test/Other/spirv-sim/loop.spv

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
; RUN: %if spirv-tools %{ spirv-as %s -o - | spirv-val - %}
2+
; RUN: spirv-sim --function=simple --wave=4 --expects=0,2,2,4 -i %s
3+
OpCapability Shader
4+
OpCapability GroupNonUniform
5+
OpMemoryModel Logical GLSL450
6+
OpEntryPoint GLCompute %main "main" %WaveIndex
7+
OpExecutionMode %main LocalSize 1 1 1
8+
OpSource HLSL 670
9+
OpName %simple "simple"
10+
OpName %main "main"
11+
OpDecorate %WaveIndex BuiltIn SubgroupLocalInvocationId
12+
%int = OpTypeInt 32 1
13+
%uint = OpTypeInt 32 0
14+
%bool = OpTypeBool
15+
%int_2 = OpConstant %int 2
16+
%int_5 = OpConstant %int 5
17+
%int_6 = OpConstant %int 6
18+
%uint_0 = OpConstant %uint 0
19+
%uint_2 = OpConstant %uint 2
20+
%void = OpTypeVoid
21+
%main_type = OpTypeFunction %void
22+
%simple_type = OpTypeFunction %int
23+
%uint_iptr = OpTypePointer Input %uint
24+
%uint_fptr = OpTypePointer Function %uint
25+
%WaveIndex = OpVariable %uint_iptr Input
26+
%main = OpFunction %void None %main_type
27+
%unused = OpLabel
28+
OpReturn
29+
OpFunctionEnd
30+
%simple = OpFunction %int None %simple_type
31+
%entry = OpLabel
32+
; uint i = 0;
33+
%i = OpVariable %uint_fptr Function
34+
%1 = OpLoad %uint %WaveIndex
35+
OpStore %i %uint_0
36+
OpBranch %header
37+
%header = OpLabel
38+
%2 = OpLoad %uint %i
39+
%3 = OpULessThan %bool %2 %1
40+
OpLoopMerge %merge %continue None
41+
OpBranchConditional %3 %body %merge
42+
; while (i < WaveGetLaneIndex()) {
43+
; i += 2;
44+
; }
45+
%body = OpLabel
46+
OpBranch %continue
47+
%continue = OpLabel
48+
%4 = OpIAdd %uint %2 %uint_2
49+
OpStore %i %4
50+
OpBranch %header
51+
%merge = OpLabel
52+
; return (int) i;
53+
%5 = OpLoad %uint %i
54+
%6 = OpBitcast %int %5
55+
OpReturnValue %6
56+
OpFunctionEnd
57+
58+
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
; RUN: %if spirv-tools %{ spirv-as %s -o - | spirv-val - %}
2+
; RUN: not spirv-sim --function=simple --wave=1 --expects=1 -i %s 2>&1 | FileCheck %s
3+
4+
; CHECK: Expected != Observed
5+
; CHECK: [1] != [2]
6+
OpCapability Shader
7+
OpMemoryModel Logical GLSL450
8+
OpEntryPoint GLCompute %main "main"
9+
OpExecutionMode %main LocalSize 1 1 1
10+
OpSource HLSL 670
11+
OpName %simple "simple"
12+
OpName %main "main"
13+
%int = OpTypeInt 32 1
14+
%int_2 = OpConstant %int 2
15+
%void = OpTypeVoid
16+
%main_type = OpTypeFunction %void
17+
%simple_type = OpTypeFunction %int
18+
%main = OpFunction %void None %main_type
19+
%entry = OpLabel
20+
OpReturn
21+
OpFunctionEnd
22+
%simple = OpFunction %int None %simple_type
23+
%1 = OpLabel
24+
OpReturnValue %int_2
25+
OpFunctionEnd
26+

llvm/test/Other/spirv-sim/simple.spv

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
; RUN: %if spirv-tools %{ spirv-as %s -o - | spirv-val - %}
2+
; RUN: spirv-sim --function=simple --wave=1 --expects=2 -i %s
3+
OpCapability Shader
4+
OpMemoryModel Logical GLSL450
5+
OpEntryPoint GLCompute %main "main"
6+
OpExecutionMode %main LocalSize 1 1 1
7+
OpSource HLSL 670
8+
OpName %simple "simple"
9+
OpName %main "main"
10+
%int = OpTypeInt 32 1
11+
%int_2 = OpConstant %int 2
12+
%void = OpTypeVoid
13+
%main_type = OpTypeFunction %void
14+
%simple_type = OpTypeFunction %int
15+
%main = OpFunction %void None %main_type
16+
%entry = OpLabel
17+
OpReturn
18+
OpFunctionEnd
19+
%simple = OpFunction %int None %simple_type
20+
%1 = OpLabel
21+
OpReturnValue %int_2
22+
OpFunctionEnd
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
; RUN: not spirv-sim --function=simple --wave=a --expects=2 -i %s 2>&1 | FileCheck %s --check-prefixes=CHECK-WAVE
2+
; RUN: not spirv-sim --function=simple --wave=1 --expects=a -i %s 2>&1 | FileCheck %s --check-prefixes=CHECK-EXPECT
3+
; RUN: not spirv-sim --function=simple --wave=1 --expects=1, -i %s 2>&1 | FileCheck %s --check-prefixes=CHECK-EXPECT
4+
; RUN: not spirv-sim --function=simple --wave=2 --expects=1 -i %s 2>&1 | FileCheck %s --check-prefixes=CHECK-SIZE
5+
; RUN: not spirv-sim --function=foo --wave=1 --expects=1 -i %s 2>&1 | FileCheck %s --check-prefixes=CHECK-NAME
6+
7+
; CHECK-WAVE: Invalid format for --wave/-w flag.
8+
9+
; CHECK-EXPECT: Invalid format for --expects/-e flag.
10+
11+
; CHECK-SIZE: Wave size != expected result array size
12+
13+
; CHECK-NAME: 'foo' function not found. Known functions are:
14+
; CHECK-NAME-NEXT: - main
15+
; CHECK-NAME-NEXT: - simple
16+
; CHECK-NANE-NOT-NEXT: -
17+
OpCapability Shader
18+
OpMemoryModel Logical GLSL450
19+
OpEntryPoint GLCompute %main "main"
20+
OpExecutionMode %main LocalSize 1 1 1
21+
OpSource HLSL 670
22+
OpName %simple "simple"
23+
OpName %main "main"
24+
%int = OpTypeInt 32 1
25+
%int_2 = OpConstant %int 2
26+
%void = OpTypeVoid
27+
%main_type = OpTypeFunction %void
28+
%simple_type = OpTypeFunction %int
29+
%main = OpFunction %void None %main_type
30+
%entry = OpLabel
31+
OpReturn
32+
OpFunctionEnd
33+
%simple = OpFunction %int None %simple_type
34+
%1 = OpLabel
35+
OpReturnValue %int_2
36+
OpFunctionEnd

llvm/test/Other/spirv-sim/switch.spv

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
; RUN: %if spirv-tools %{ spirv-as %s -o - | spirv-val - %}
2+
; RUN: spirv-sim --function=simple --wave=4 --expects=0,1,2,0 -i %s
3+
OpCapability Shader
4+
OpCapability GroupNonUniform
5+
OpMemoryModel Logical GLSL450
6+
OpEntryPoint GLCompute %main "main" %WaveIndex
7+
OpExecutionMode %main LocalSize 1 1 1
8+
OpSource HLSL 670
9+
OpName %simple "simple"
10+
OpName %main "main"
11+
OpDecorate %WaveIndex BuiltIn SubgroupLocalInvocationId
12+
%int = OpTypeInt 32 1
13+
%uint = OpTypeInt 32 0
14+
%bool = OpTypeBool
15+
%int_0 = OpConstant %int 0
16+
%int_1 = OpConstant %int 1
17+
%int_2 = OpConstant %int 2
18+
%uint_0 = OpConstant %uint 0
19+
%void = OpTypeVoid
20+
%main_type = OpTypeFunction %void
21+
%simple_type = OpTypeFunction %int
22+
%uint_iptr = OpTypePointer Input %uint
23+
%WaveIndex = OpVariable %uint_iptr Input
24+
%main = OpFunction %void None %main_type
25+
%entry = OpLabel
26+
OpReturn
27+
OpFunctionEnd
28+
%simple = OpFunction %int None %simple_type
29+
%1 = OpLabel
30+
%2 = OpLoad %uint %WaveIndex
31+
OpSelectionMerge %merge None
32+
OpSwitch %2 %default 1 %case_1 2 %case_2
33+
%default = OpLabel
34+
OpBranch %merge
35+
%case_1 = OpLabel
36+
OpBranch %merge
37+
%case_2 = OpLabel
38+
OpBranch %merge
39+
%merge = OpLabel
40+
%4 = OpPhi %int %int_0 %default %int_1 %case_1 %int_2 %case_2
41+
OpReturnValue %4
42+
OpFunctionEnd
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
; RUN: %if spirv-tools %{ spirv-as %s -o - | spirv-val - %}
2+
; RUN: spirv-sim --function=simple --wave=4 --expects=0,1,2,3 -i %s
3+
OpCapability Shader
4+
OpCapability GroupNonUniform
5+
OpMemoryModel Logical GLSL450
6+
OpEntryPoint GLCompute %main "main" %WaveIndex
7+
OpExecutionMode %main LocalSize 1 1 1
8+
OpSource HLSL 670
9+
OpName %simple "simple"
10+
OpName %main "main"
11+
OpDecorate %WaveIndex BuiltIn SubgroupLocalInvocationId
12+
%int = OpTypeInt 32 1
13+
%uint = OpTypeInt 32 0
14+
%int_2 = OpConstant %int 2
15+
%void = OpTypeVoid
16+
%main_type = OpTypeFunction %void
17+
%simple_type = OpTypeFunction %int
18+
%uint_iptr = OpTypePointer Input %uint
19+
%WaveIndex = OpVariable %uint_iptr Input
20+
%main = OpFunction %void None %main_type
21+
%entry = OpLabel
22+
OpReturn
23+
OpFunctionEnd
24+
%simple = OpFunction %int None %simple_type
25+
%1 = OpLabel
26+
%2 = OpLoad %uint %WaveIndex
27+
%3 = OpBitcast %int %2
28+
OpReturnValue %3
29+
OpFunctionEnd
30+

0 commit comments

Comments
 (0)