-
Notifications
You must be signed in to change notification settings - Fork 12.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[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]>
- Loading branch information
Showing
14 changed files
with
1,459 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
; RUN: %if spirv-tools %{ spirv-as %s -o - | spirv-val - %} | ||
; RUN: spirv-sim --function=simple --wave=3 --expects=5,6,6 -i %s | ||
OpCapability Shader | ||
OpCapability GroupNonUniform | ||
OpMemoryModel Logical GLSL450 | ||
OpEntryPoint GLCompute %main "main" %WaveIndex | ||
OpExecutionMode %main LocalSize 1 1 1 | ||
OpSource HLSL 670 | ||
OpName %simple "simple" | ||
OpName %main "main" | ||
OpDecorate %WaveIndex BuiltIn SubgroupLocalInvocationId | ||
%int = OpTypeInt 32 1 | ||
%uint = OpTypeInt 32 0 | ||
%bool = OpTypeBool | ||
%int_2 = OpConstant %int 2 | ||
%int_5 = OpConstant %int 5 | ||
%int_6 = OpConstant %int 6 | ||
%uint_0 = OpConstant %uint 0 | ||
%void = OpTypeVoid | ||
%main_type = OpTypeFunction %void | ||
%simple_type = OpTypeFunction %int | ||
%uint_iptr = OpTypePointer Input %uint | ||
%WaveIndex = OpVariable %uint_iptr Input | ||
%main = OpFunction %void None %main_type | ||
%entry = OpLabel | ||
OpReturn | ||
OpFunctionEnd | ||
%simple = OpFunction %int None %simple_type | ||
%1 = OpLabel | ||
%2 = OpLoad %uint %WaveIndex | ||
%3 = OpIEqual %bool %uint_0 %2 | ||
OpSelectionMerge %merge None | ||
OpBranchConditional %3 %true %false | ||
%true = OpLabel | ||
OpBranch %merge | ||
%false = OpLabel | ||
OpBranch %merge | ||
%merge = OpLabel | ||
%4 = OpPhi %int %int_5 %true %int_6 %false | ||
OpReturnValue %4 | ||
OpFunctionEnd | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
; RUN: %if spirv-tools %{ spirv-as %s -o - | spirv-val - %} | ||
; RUN: spirv-sim --function=simple --wave=1 --expects=2 -i %s | ||
OpCapability Shader | ||
OpCapability GroupNonUniform | ||
OpMemoryModel Logical GLSL450 | ||
OpEntryPoint GLCompute %main "main" %WaveIndex | ||
OpExecutionMode %main LocalSize 1 1 1 | ||
OpSource HLSL 670 | ||
OpName %simple "simple" | ||
OpName %main "main" | ||
OpDecorate %WaveIndex BuiltIn SubgroupLocalInvocationId | ||
%int = OpTypeInt 32 1 | ||
%uint = OpTypeInt 32 0 | ||
%uint_2 = OpConstant %uint 2 | ||
%void = OpTypeVoid | ||
%main_type = OpTypeFunction %void | ||
%simple_type = OpTypeFunction %int | ||
%sub_type = OpTypeFunction %uint | ||
%uint_iptr = OpTypePointer Input %uint | ||
%WaveIndex = OpVariable %uint_iptr Input | ||
%main = OpFunction %void None %main_type | ||
%entry = OpLabel | ||
OpReturn | ||
OpFunctionEnd | ||
%sub = OpFunction %uint None %sub_type | ||
%a = OpLabel | ||
OpReturnValue %uint_2 | ||
OpFunctionEnd | ||
%simple = OpFunction %int None %simple_type | ||
%1 = OpLabel | ||
%2 = OpFunctionCall %uint %sub | ||
%3 = OpBitcast %int %2 | ||
OpReturnValue %3 | ||
OpFunctionEnd | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
; RUN: %if spirv-tools %{ spirv-as %s -o - | spirv-val - %} | ||
; RUN: spirv-sim --function=a --wave=1 --expects=2 -i %s | ||
; RUN: spirv-sim --function=b --wave=1 --expects=1 -i %s | ||
OpCapability Shader | ||
OpMemoryModel Logical GLSL450 | ||
OpEntryPoint GLCompute %main "main" | ||
OpExecutionMode %main LocalSize 1 1 1 | ||
OpSource HLSL 670 | ||
OpName %a "a" | ||
OpName %b "b" | ||
OpName %main "main" | ||
%int = OpTypeInt 32 1 | ||
%s1 = OpTypeStruct %int %int %int | ||
%s2 = OpTypeStruct %s1 | ||
%int_1 = OpConstant %int 1 | ||
%int_2 = OpConstant %int 2 | ||
%s1_1_2 = OpConstantComposite %s1 %int_1 %int_2 %int_1 | ||
%s2_s1 = OpConstantComposite %s2 %s1_1_2 | ||
%void = OpTypeVoid | ||
%main_type = OpTypeFunction %void | ||
%simple_type = OpTypeFunction %int | ||
%main = OpFunction %void None %main_type | ||
%entry = OpLabel | ||
OpReturn | ||
OpFunctionEnd | ||
%a = OpFunction %int None %simple_type | ||
%1 = OpLabel | ||
%2 = OpCompositeExtract %int %s1_1_2 1 | ||
OpReturnValue %2 | ||
OpFunctionEnd | ||
%b = OpFunction %int None %simple_type | ||
%3 = OpLabel | ||
%4 = OpCompositeExtract %int %s2_s1 0 2 | ||
OpReturnValue %4 | ||
OpFunctionEnd | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
spirv_sim_root = os.path.join(config.llvm_src_root, "utils", "spirv-sim") | ||
config.substitutions.append( | ||
( | ||
"spirv-sim", | ||
"'%s' %s" | ||
% (config.python_executable, os.path.join(spirv_sim_root, "spirv-sim.py")), | ||
) | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
; RUN: %if spirv-tools %{ spirv-as %s -o - | spirv-val - %} | ||
; RUN: spirv-sim --function=simple --wave=4 --expects=0,2,2,4 -i %s | ||
OpCapability Shader | ||
OpCapability GroupNonUniform | ||
OpMemoryModel Logical GLSL450 | ||
OpEntryPoint GLCompute %main "main" %WaveIndex | ||
OpExecutionMode %main LocalSize 1 1 1 | ||
OpSource HLSL 670 | ||
OpName %simple "simple" | ||
OpName %main "main" | ||
OpDecorate %WaveIndex BuiltIn SubgroupLocalInvocationId | ||
%int = OpTypeInt 32 1 | ||
%uint = OpTypeInt 32 0 | ||
%bool = OpTypeBool | ||
%int_2 = OpConstant %int 2 | ||
%int_5 = OpConstant %int 5 | ||
%int_6 = OpConstant %int 6 | ||
%uint_0 = OpConstant %uint 0 | ||
%uint_2 = OpConstant %uint 2 | ||
%void = OpTypeVoid | ||
%main_type = OpTypeFunction %void | ||
%simple_type = OpTypeFunction %int | ||
%uint_iptr = OpTypePointer Input %uint | ||
%uint_fptr = OpTypePointer Function %uint | ||
%WaveIndex = OpVariable %uint_iptr Input | ||
%main = OpFunction %void None %main_type | ||
%unused = OpLabel | ||
OpReturn | ||
OpFunctionEnd | ||
%simple = OpFunction %int None %simple_type | ||
%entry = OpLabel | ||
; uint i = 0; | ||
%i = OpVariable %uint_fptr Function | ||
%1 = OpLoad %uint %WaveIndex | ||
OpStore %i %uint_0 | ||
OpBranch %header | ||
%header = OpLabel | ||
%2 = OpLoad %uint %i | ||
%3 = OpULessThan %bool %2 %1 | ||
OpLoopMerge %merge %continue None | ||
OpBranchConditional %3 %body %merge | ||
; while (i < WaveGetLaneIndex()) { | ||
; i += 2; | ||
; } | ||
%body = OpLabel | ||
OpBranch %continue | ||
%continue = OpLabel | ||
%4 = OpIAdd %uint %2 %uint_2 | ||
OpStore %i %4 | ||
OpBranch %header | ||
%merge = OpLabel | ||
; return (int) i; | ||
%5 = OpLoad %uint %i | ||
%6 = OpBitcast %int %5 | ||
OpReturnValue %6 | ||
OpFunctionEnd | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
; RUN: %if spirv-tools %{ spirv-as %s -o - | spirv-val - %} | ||
; RUN: not spirv-sim --function=simple --wave=1 --expects=1 -i %s 2>&1 | FileCheck %s | ||
|
||
; CHECK: Expected != Observed | ||
; CHECK: [1] != [2] | ||
OpCapability Shader | ||
OpMemoryModel Logical GLSL450 | ||
OpEntryPoint GLCompute %main "main" | ||
OpExecutionMode %main LocalSize 1 1 1 | ||
OpSource HLSL 670 | ||
OpName %simple "simple" | ||
OpName %main "main" | ||
%int = OpTypeInt 32 1 | ||
%int_2 = OpConstant %int 2 | ||
%void = OpTypeVoid | ||
%main_type = OpTypeFunction %void | ||
%simple_type = OpTypeFunction %int | ||
%main = OpFunction %void None %main_type | ||
%entry = OpLabel | ||
OpReturn | ||
OpFunctionEnd | ||
%simple = OpFunction %int None %simple_type | ||
%1 = OpLabel | ||
OpReturnValue %int_2 | ||
OpFunctionEnd | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
; RUN: %if spirv-tools %{ spirv-as %s -o - | spirv-val - %} | ||
; RUN: spirv-sim --function=simple --wave=1 --expects=2 -i %s | ||
OpCapability Shader | ||
OpMemoryModel Logical GLSL450 | ||
OpEntryPoint GLCompute %main "main" | ||
OpExecutionMode %main LocalSize 1 1 1 | ||
OpSource HLSL 670 | ||
OpName %simple "simple" | ||
OpName %main "main" | ||
%int = OpTypeInt 32 1 | ||
%int_2 = OpConstant %int 2 | ||
%void = OpTypeVoid | ||
%main_type = OpTypeFunction %void | ||
%simple_type = OpTypeFunction %int | ||
%main = OpFunction %void None %main_type | ||
%entry = OpLabel | ||
OpReturn | ||
OpFunctionEnd | ||
%simple = OpFunction %int None %simple_type | ||
%1 = OpLabel | ||
OpReturnValue %int_2 | ||
OpFunctionEnd |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
; RUN: not spirv-sim --function=simple --wave=a --expects=2 -i %s 2>&1 | FileCheck %s --check-prefixes=CHECK-WAVE | ||
; RUN: not spirv-sim --function=simple --wave=1 --expects=a -i %s 2>&1 | FileCheck %s --check-prefixes=CHECK-EXPECT | ||
; RUN: not spirv-sim --function=simple --wave=1 --expects=1, -i %s 2>&1 | FileCheck %s --check-prefixes=CHECK-EXPECT | ||
; RUN: not spirv-sim --function=simple --wave=2 --expects=1 -i %s 2>&1 | FileCheck %s --check-prefixes=CHECK-SIZE | ||
; RUN: not spirv-sim --function=foo --wave=1 --expects=1 -i %s 2>&1 | FileCheck %s --check-prefixes=CHECK-NAME | ||
|
||
; CHECK-WAVE: Invalid format for --wave/-w flag. | ||
|
||
; CHECK-EXPECT: Invalid format for --expects/-e flag. | ||
|
||
; CHECK-SIZE: Wave size != expected result array size | ||
|
||
; CHECK-NAME: 'foo' function not found. Known functions are: | ||
; CHECK-NAME-NEXT: - main | ||
; CHECK-NAME-NEXT: - simple | ||
; CHECK-NANE-NOT-NEXT: - | ||
OpCapability Shader | ||
OpMemoryModel Logical GLSL450 | ||
OpEntryPoint GLCompute %main "main" | ||
OpExecutionMode %main LocalSize 1 1 1 | ||
OpSource HLSL 670 | ||
OpName %simple "simple" | ||
OpName %main "main" | ||
%int = OpTypeInt 32 1 | ||
%int_2 = OpConstant %int 2 | ||
%void = OpTypeVoid | ||
%main_type = OpTypeFunction %void | ||
%simple_type = OpTypeFunction %int | ||
%main = OpFunction %void None %main_type | ||
%entry = OpLabel | ||
OpReturn | ||
OpFunctionEnd | ||
%simple = OpFunction %int None %simple_type | ||
%1 = OpLabel | ||
OpReturnValue %int_2 | ||
OpFunctionEnd |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
; RUN: %if spirv-tools %{ spirv-as %s -o - | spirv-val - %} | ||
; RUN: spirv-sim --function=simple --wave=4 --expects=0,1,2,0 -i %s | ||
OpCapability Shader | ||
OpCapability GroupNonUniform | ||
OpMemoryModel Logical GLSL450 | ||
OpEntryPoint GLCompute %main "main" %WaveIndex | ||
OpExecutionMode %main LocalSize 1 1 1 | ||
OpSource HLSL 670 | ||
OpName %simple "simple" | ||
OpName %main "main" | ||
OpDecorate %WaveIndex BuiltIn SubgroupLocalInvocationId | ||
%int = OpTypeInt 32 1 | ||
%uint = OpTypeInt 32 0 | ||
%bool = OpTypeBool | ||
%int_0 = OpConstant %int 0 | ||
%int_1 = OpConstant %int 1 | ||
%int_2 = OpConstant %int 2 | ||
%uint_0 = OpConstant %uint 0 | ||
%void = OpTypeVoid | ||
%main_type = OpTypeFunction %void | ||
%simple_type = OpTypeFunction %int | ||
%uint_iptr = OpTypePointer Input %uint | ||
%WaveIndex = OpVariable %uint_iptr Input | ||
%main = OpFunction %void None %main_type | ||
%entry = OpLabel | ||
OpReturn | ||
OpFunctionEnd | ||
%simple = OpFunction %int None %simple_type | ||
%1 = OpLabel | ||
%2 = OpLoad %uint %WaveIndex | ||
OpSelectionMerge %merge None | ||
OpSwitch %2 %default 1 %case_1 2 %case_2 | ||
%default = OpLabel | ||
OpBranch %merge | ||
%case_1 = OpLabel | ||
OpBranch %merge | ||
%case_2 = OpLabel | ||
OpBranch %merge | ||
%merge = OpLabel | ||
%4 = OpPhi %int %int_0 %default %int_1 %case_1 %int_2 %case_2 | ||
OpReturnValue %4 | ||
OpFunctionEnd |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
; RUN: %if spirv-tools %{ spirv-as %s -o - | spirv-val - %} | ||
; RUN: spirv-sim --function=simple --wave=4 --expects=0,1,2,3 -i %s | ||
OpCapability Shader | ||
OpCapability GroupNonUniform | ||
OpMemoryModel Logical GLSL450 | ||
OpEntryPoint GLCompute %main "main" %WaveIndex | ||
OpExecutionMode %main LocalSize 1 1 1 | ||
OpSource HLSL 670 | ||
OpName %simple "simple" | ||
OpName %main "main" | ||
OpDecorate %WaveIndex BuiltIn SubgroupLocalInvocationId | ||
%int = OpTypeInt 32 1 | ||
%uint = OpTypeInt 32 0 | ||
%int_2 = OpConstant %int 2 | ||
%void = OpTypeVoid | ||
%main_type = OpTypeFunction %void | ||
%simple_type = OpTypeFunction %int | ||
%uint_iptr = OpTypePointer Input %uint | ||
%WaveIndex = OpVariable %uint_iptr Input | ||
%main = OpFunction %void None %main_type | ||
%entry = OpLabel | ||
OpReturn | ||
OpFunctionEnd | ||
%simple = OpFunction %int None %simple_type | ||
%1 = OpLabel | ||
%2 = OpLoad %uint %WaveIndex | ||
%3 = OpBitcast %int %2 | ||
OpReturnValue %3 | ||
OpFunctionEnd | ||
|
Oops, something went wrong.
5914566
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Keenuts Interesting commit you have here. After reading the commit message, it seems like you have a different use case, but if you do want to use a more fully-fledged SPIR-V interpreter/simulator, I am working on one here: https://github.com/mmoult/SPIRV-Interpreter
Also thought it might be helpful to point out that
.spv
files are typically binary, and.spvasm
is used for assembly like you have.Cheers!
5914566
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi! Thanks, yes the goal was really here just to test cross-wave synchronization in a more suited way than FileCheck.
From the comment I just received on the PR seems at some don't agree with my approach, so I'll open an RFC to gather a broader feedback.
During the backend meetings, some folks at Intel mentioned they might be interested in expending the simulator, so I'll bring up your project as they might not know about it.