Skip to content

Commit 5914566

Browse files
authored
[Utils][SPIR-V] Adding spirv-sim to LLVM (#107094)
### 2nd submission The buildbots are using python 3.8, and some type annotations I was using are only available starting 3.9. The last commit on the pile is the additional changes compared to the original submission #104020. ### Original text: 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 9e08db7 commit 5914566

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)