1 // Copyright (c) 2024 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "spirv-tools/optimizer.hpp"
16 #include "test/opt/pass_fixture.h"
17 #include "test/opt/pass_utils.h"
18
19 namespace spvtools {
20 namespace opt {
21 namespace {
22
23 using OpExtInstForwardRefFixupPassTest = PassTest<::testing::Test>;
24
TEST_F(OpExtInstForwardRefFixupPassTest,NoChangeWithougExtendedInstructions)25 TEST_F(OpExtInstForwardRefFixupPassTest, NoChangeWithougExtendedInstructions) {
26 const std::string kTest = R"(
27 ; CHECK-NOT: SomeOpcode
28 OpCapability Shader
29 OpMemoryModel Logical GLSL450
30 OpEntryPoint GLCompute %main "main"
31 OpExecutionMode %main LocalSize 1 1 1
32 %void = OpTypeVoid
33 %3 = OpTypeFunction %void
34 %main = OpFunction %void None %3
35 %6 = OpLabel
36 OpReturn
37 OpFunctionEnd;
38 )";
39 const auto result =
40 SinglePassRunAndMatch<OpExtInstWithForwardReferenceFixupPass>(
41 kTest, /* do_validation= */ true);
42 EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithoutChange);
43 }
44
TEST_F(OpExtInstForwardRefFixupPassTest,NoForwardRef_NoChange)45 TEST_F(OpExtInstForwardRefFixupPassTest, NoForwardRef_NoChange) {
46 const std::string kTest = R"(OpCapability Shader
47 OpExtension "SPV_KHR_non_semantic_info"
48 %1 = OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
49 OpMemoryModel Logical GLSL450
50 OpEntryPoint GLCompute %main "main"
51 OpExecutionMode %main LocalSize 1 1 1
52 %3 = OpString "/usr/local/google/home/nathangauer/projects/DirectXShaderCompiler/repro.hlsl"
53 %4 = OpString "// RUN: %dxc -T cs_6_0 %s -E main -spirv -fspv-target-env=vulkan1.1 -fspv-debug=vulkan-with-source | FileCheck %s
54
55 [numthreads(1, 1, 1)]
56 void main() {
57 }
58 "
59 %5 = OpString "main"
60 %6 = OpString ""
61 %7 = OpString "3f3d3740"
62 %8 = OpString " -E main -T cs_6_0 -spirv -fspv-target-env=vulkan1.1 -fspv-debug=vulkan-with-source -Qembed_debug"
63 OpName %main "main"
64 %void = OpTypeVoid
65 %uint = OpTypeInt 32 0
66 %uint_3 = OpConstant %uint 3
67 %uint_1 = OpConstant %uint 1
68 %uint_4 = OpConstant %uint 4
69 %uint_5 = OpConstant %uint 5
70 %15 = OpTypeFunction %void
71 %16 = OpExtInst %void %1 DebugTypeFunction %uint_3 %void
72 %17 = OpExtInst %void %1 DebugSource %3 %4
73 %18 = OpExtInst %void %1 DebugCompilationUnit %uint_1 %uint_4 %17 %uint_5
74 %19 = OpExtInst %void %1 DebugFunction %5 %16 %17 %uint_4 %uint_1 %18 %6 %uint_3 %uint_4
75 %20 = OpExtInst %void %1 DebugEntryPoint %19 %18 %7 %8
76 %main = OpFunction %void None %15
77 %21 = OpLabel
78 %22 = OpExtInst %void %1 DebugFunctionDefinition %19 %main
79 %23 = OpExtInst %void %1 DebugLine %17 %uint_5 %uint_5 %uint_1 %uint_1
80 OpReturn
81 OpFunctionEnd
82 )";
83 SinglePassRunAndCheck<OpExtInstWithForwardReferenceFixupPass>(
84 kTest, kTest, /* skip_nop= */ false);
85 }
86
TEST_F(OpExtInstForwardRefFixupPassTest,NoForwardRef_ReplaceOpExtInstWithForwardWithOpExtInst)87 TEST_F(OpExtInstForwardRefFixupPassTest,
88 NoForwardRef_ReplaceOpExtInstWithForwardWithOpExtInst) {
89 const std::string kTest = R"(
90 OpCapability Shader
91 OpExtension "SPV_KHR_non_semantic_info"
92 OpExtension "SPV_KHR_relaxed_extended_instruction"
93 ; CHECK-NOT: OpExtension "SPV_KHR_relaxed_extended_instruction"
94 %1 = OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
95 OpMemoryModel Logical GLSL450
96 OpEntryPoint GLCompute %main "main"
97 OpExecutionMode %main LocalSize 1 1 1
98 %3 = OpString "/usr/local/google/home/nathangauer/projects/DirectXShaderCompiler/repro.hlsl"
99 %4 = OpString "// RUN: %dxc -T cs_6_0 %s -E main -spirv -fspv-target-env=vulkan1.1 -fspv-debug=vulkan-with-source | FileCheck %s
100
101 [numthreads(1, 1, 1)]
102 void main() {
103 }
104 "
105 %5 = OpString "main"
106 %6 = OpString ""
107 %7 = OpString "3f3d3740"
108 %8 = OpString " -E main -T cs_6_0 -spirv -fspv-target-env=vulkan1.1 -fspv-debug=vulkan-with-source -Qembed_debug"
109 OpName %main "main"
110 %void = OpTypeVoid
111 %uint = OpTypeInt 32 0
112 %uint_3 = OpConstant %uint 3
113 %uint_1 = OpConstant %uint 1
114 %uint_4 = OpConstant %uint 4
115 %uint_5 = OpConstant %uint 5
116 %20 = OpTypeFunction %void
117 %10 = OpExtInstWithForwardRefsKHR %void %1 DebugTypeFunction %uint_3 %void
118 %12 = OpExtInstWithForwardRefsKHR %void %1 DebugSource %3 %4
119 %13 = OpExtInstWithForwardRefsKHR %void %1 DebugCompilationUnit %uint_1 %uint_4 %12 %uint_5
120 %17 = OpExtInstWithForwardRefsKHR %void %1 DebugFunction %5 %10 %12 %uint_4 %uint_1 %13 %6 %uint_3 %uint_4
121 %18 = OpExtInstWithForwardRefsKHR %void %1 DebugEntryPoint %17 %13 %7 %8
122 ; CHECK-NOT: {{.*}} = OpExtInstWithForwardRefsKHR %void %1 DebugTypeFunction %uint_3 %void
123 ; CHECK-NOT: {{.*}} = OpExtInstWithForwardRefsKHR %void %1 DebugSource {{.*}} {{.*}}
124 ; CHECK-NOT: {{.*}} = OpExtInstWithForwardRefsKHR %void %1 DebugCompilationUnit %uint_1 %uint_4 {{.*}} %uint_5
125 ; CHECK-NOT: {{.*}} = OpExtInstWithForwardRefsKHR %void %1 DebugFunction {{.*}} {{.*}} {{.*}} %uint_4 %uint_1 {{.*}} {{.*}} %uint_3 %uint_4
126 ; CHECK-NOT: {{.*}} = OpExtInstWithForwardRefsKHR %void %1 DebugEntryPoint {{.*}} {{.*}} {{.*}} {{.*}}
127 ; CHECK: {{.*}} = OpExtInst %void %1 DebugTypeFunction %uint_3 %void
128 ; CHECK: {{.*}} = OpExtInst %void %1 DebugSource {{.*}} {{.*}}
129 ; CHECK: {{.*}} = OpExtInst %void %1 DebugCompilationUnit %uint_1 %uint_4 {{.*}} %uint_5
130 ; CHECK: {{.*}} = OpExtInst %void %1 DebugFunction {{.*}} {{.*}} {{.*}} %uint_4 %uint_1 {{.*}} {{.*}} %uint_3 %uint_4
131 ; CHECK: {{.*}} = OpExtInst %void %1 DebugEntryPoint {{.*}} {{.*}} {{.*}} {{.*}}
132 %main = OpFunction %void None %20
133 %21 = OpLabel
134 %22 = OpExtInst %void %1 DebugFunctionDefinition %17 %main
135 %23 = OpExtInst %void %1 DebugLine %12 %uint_5 %uint_5 %uint_1 %uint_1
136 ; CHECK: {{.*}} = OpExtInst %void %1 DebugFunctionDefinition {{.*}} %main
137 ; CHECK: {{.*}} = OpExtInst %void %1 DebugLine {{.*}} %uint_5 %uint_5 %uint_1 %uint_1
138 OpReturn
139 OpFunctionEnd
140 )";
141 const auto result =
142 SinglePassRunAndMatch<OpExtInstWithForwardReferenceFixupPass>(
143 kTest, /* do_validation= */ true);
144 EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange);
145 }
146
TEST_F(OpExtInstForwardRefFixupPassTest,ForwardRefs_NoChange)147 TEST_F(OpExtInstForwardRefFixupPassTest, ForwardRefs_NoChange) {
148 const std::string kTest = R"(OpCapability Shader
149 OpExtension "SPV_KHR_non_semantic_info"
150 OpExtension "SPV_KHR_relaxed_extended_instruction"
151 %1 = OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
152 OpMemoryModel Logical GLSL450
153 OpEntryPoint GLCompute %main "main"
154 OpExecutionMode %main LocalSize 1 1 1
155 %3 = OpString "/usr/local/google/home/nathangauer/projects/DirectXShaderCompiler/repro.hlsl"
156 %4 = OpString "// RUN: %dxc -T cs_6_0 %s -E main -spirv -fspv-target-env=vulkan1.1 -fspv-debug=vulkan-with-source | FileCheck %s
157
158 class A {
159 void foo() {
160 }
161 };
162
163 [numthreads(1, 1, 1)]
164 void main() {
165 A a;
166 a.foo();
167 }
168 "
169 %5 = OpString "A"
170 %6 = OpString "A.foo"
171 %7 = OpString ""
172 %8 = OpString "this"
173 %9 = OpString "main"
174 %10 = OpString "a"
175 %11 = OpString "d59ae9c2"
176 %12 = OpString " -E main -T cs_6_0 -spirv -fspv-target-env=vulkan1.1 -fspv-debug=vulkan-with-source -Vd -Qembed_debug"
177 OpName %main "main"
178 OpName %A "A"
179 %void = OpTypeVoid
180 %uint = OpTypeInt 32 0
181 %uint_1 = OpConstant %uint 1
182 %uint_4 = OpConstant %uint 4
183 %uint_5 = OpConstant %uint 5
184 %uint_0 = OpConstant %uint 0
185 %uint_3 = OpConstant %uint 3
186 %uint_7 = OpConstant %uint 7
187 %uint_288 = OpConstant %uint 288
188 %uint_9 = OpConstant %uint 9
189 %uint_13 = OpConstant %uint 13
190 %uint_10 = OpConstant %uint 10
191 %26 = OpTypeFunction %void
192 %uint_12 = OpConstant %uint 12
193 %A = OpTypeStruct
194 %_ptr_Function_A = OpTypePointer Function %A
195 %uint_11 = OpConstant %uint 11
196 %30 = OpExtInst %void %1 DebugExpression
197 %31 = OpExtInst %void %1 DebugSource %3 %4
198 %32 = OpExtInst %void %1 DebugCompilationUnit %uint_1 %uint_4 %31 %uint_5
199 %33 = OpExtInstWithForwardRefsKHR %void %1 DebugTypeComposite %5 %uint_0 %31 %uint_3 %uint_7 %32 %5 %uint_0 %uint_3 %34
200 %35 = OpExtInst %void %1 DebugTypeFunction %uint_3 %void %33
201 %34 = OpExtInst %void %1 DebugFunction %6 %35 %31 %uint_4 %uint_3 %33 %7 %uint_3 %uint_4
202 %36 = OpExtInst %void %1 DebugLocalVariable %8 %33 %31 %uint_4 %uint_3 %34 %uint_288 %uint_1
203 %37 = OpExtInst %void %1 DebugTypeFunction %uint_3 %void
204 %38 = OpExtInst %void %1 DebugFunction %9 %37 %31 %uint_9 %uint_1 %32 %7 %uint_3 %uint_9
205 %39 = OpExtInst %void %1 DebugLexicalBlock %31 %uint_9 %uint_13 %38
206 %40 = OpExtInst %void %1 DebugLocalVariable %10 %33 %31 %uint_10 %uint_5 %39 %uint_4
207 %41 = OpExtInst %void %1 DebugEntryPoint %38 %32 %11 %12
208 %42 = OpExtInst %void %1 DebugInlinedAt %uint_11 %39
209 %main = OpFunction %void None %26
210 %43 = OpLabel
211 %44 = OpVariable %_ptr_Function_A Function
212 %45 = OpExtInst %void %1 DebugFunctionDefinition %38 %main
213 %57 = OpExtInst %void %1 DebugScope %39
214 %47 = OpExtInst %void %1 DebugLine %31 %uint_10 %uint_10 %uint_3 %uint_5
215 %48 = OpExtInst %void %1 DebugDeclare %40 %44 %30
216 %58 = OpExtInst %void %1 DebugScope %34 %42
217 %50 = OpExtInst %void %1 DebugLine %31 %uint_4 %uint_5 %uint_3 %uint_3
218 %51 = OpExtInst %void %1 DebugDeclare %36 %44 %30
219 %59 = OpExtInst %void %1 DebugNoScope
220 %53 = OpExtInst %void %1 DebugLine %31 %uint_12 %uint_12 %uint_1 %uint_1
221 OpReturn
222 OpFunctionEnd
223 )";
224 SinglePassRunAndCheck<OpExtInstWithForwardReferenceFixupPass>(
225 kTest, kTest, /* skip_nop= */ false);
226 }
227
TEST_F(OpExtInstForwardRefFixupPassTest,ForwardRefs_ReplaceOpExtInstWithOpExtInstWithForwardRefs)228 TEST_F(OpExtInstForwardRefFixupPassTest,
229 ForwardRefs_ReplaceOpExtInstWithOpExtInstWithForwardRefs) {
230 const std::string kTest = R"(
231 OpCapability Shader
232 OpExtension "SPV_KHR_non_semantic_info"
233 ; CHECK: OpExtension "SPV_KHR_relaxed_extended_instruction"
234 %1 = OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
235 OpMemoryModel Logical GLSL450
236 OpEntryPoint GLCompute %main "main"
237 OpExecutionMode %main LocalSize 1 1 1
238 %3 = OpString "/usr/local/google/home/nathangauer/projects/DirectXShaderCompiler/repro.hlsl"
239 %4 = OpString "// RUN: %dxc -T cs_6_0 %s -E main -spirv -fspv-target-env=vulkan1.1 -fspv-debug=vulkan-with-source | FileCheck %s
240
241 class A {
242 void foo() {
243 }
244 };
245
246 [numthreads(1, 1, 1)]
247 void main() {
248 A a;
249 a.foo();
250 }
251 "
252 %5 = OpString "A"
253 %6 = OpString "A.foo"
254 %7 = OpString ""
255 %8 = OpString "this"
256 %9 = OpString "main"
257 %10 = OpString "a"
258 %11 = OpString "d59ae9c2"
259 %12 = OpString " -E main -T cs_6_0 -spirv -fspv-target-env=vulkan1.1 -fspv-debug=vulkan-with-source -Vd -Qembed_debug"
260 OpName %main "main"
261 OpName %A "A"
262 %void = OpTypeVoid
263 %uint = OpTypeInt 32 0
264 %uint_1 = OpConstant %uint 1
265 %uint_4 = OpConstant %uint 4
266 %uint_5 = OpConstant %uint 5
267 %uint_0 = OpConstant %uint 0
268 %uint_3 = OpConstant %uint 3
269 %uint_7 = OpConstant %uint 7
270 %uint_288 = OpConstant %uint 288
271 %uint_9 = OpConstant %uint 9
272 %uint_13 = OpConstant %uint 13
273 %uint_10 = OpConstant %uint 10
274 %40 = OpTypeFunction %void
275 %uint_12 = OpConstant %uint 12
276 %A = OpTypeStruct
277 %_ptr_Function_A = OpTypePointer Function %A
278 %uint_11 = OpConstant %uint 11
279 %15 = OpExtInst %void %1 DebugExpression
280 %16 = OpExtInst %void %1 DebugSource %3 %4
281 %17 = OpExtInst %void %1 DebugCompilationUnit %uint_1 %uint_4 %16 %uint_5
282 %21 = OpExtInst %void %1 DebugTypeComposite %5 %uint_0 %16 %uint_3 %uint_7 %17 %5 %uint_0 %uint_3 %25
283 %26 = OpExtInst %void %1 DebugTypeFunction %uint_3 %void %21
284 %25 = OpExtInst %void %1 DebugFunction %6 %26 %16 %uint_4 %uint_3 %21 %7 %uint_3 %uint_4
285 %27 = OpExtInst %void %1 DebugLocalVariable %8 %21 %16 %uint_4 %uint_3 %25 %uint_288 %uint_1
286 %29 = OpExtInst %void %1 DebugTypeFunction %uint_3 %void
287 %30 = OpExtInst %void %1 DebugFunction %9 %29 %16 %uint_9 %uint_1 %17 %7 %uint_3 %uint_9
288 %32 = OpExtInst %void %1 DebugLexicalBlock %16 %uint_9 %uint_13 %30
289 %34 = OpExtInst %void %1 DebugLocalVariable %10 %21 %16 %uint_10 %uint_5 %32 %uint_4
290 %36 = OpExtInst %void %1 DebugEntryPoint %30 %17 %11 %12
291 %37 = OpExtInst %void %1 DebugInlinedAt %uint_11 %32
292 ; CHECK: {{.*}} = OpExtInst %void %1 DebugExpression
293 ; CHECK: {{.*}} = OpExtInst %void %1 DebugSource
294 ; CHECK: {{.*}} = OpExtInst %void %1 DebugCompilationUnit
295 ; CHECK: {{.*}} = OpExtInstWithForwardRefsKHR %void {{.*}} DebugTypeComposite
296 ; CHECK-NOT: {{.*}} = OpExtInst %void {{.*}} DebugTypeComposite
297 ; CHECK: {{.*}} = OpExtInst %void %1 DebugTypeFunction
298 ; CHECK: {{.*}} = OpExtInst %void %1 DebugFunction
299 ; CHECK: {{.*}} = OpExtInst %void %1 DebugLocalVariable
300 ; CHECK: {{.*}} = OpExtInst %void %1 DebugTypeFunction
301 ; CHECK: {{.*}} = OpExtInst %void %1 DebugFunction
302 ; CHECK: {{.*}} = OpExtInst %void %1 DebugLexicalBlock
303 ; CHECK: {{.*}} = OpExtInst %void %1 DebugLocalVariable
304 ; CHECK: {{.*}} = OpExtInst %void %1 DebugEntryPoint
305 ; CHECK: {{.*}} = OpExtInst %void %1 DebugInlinedAt
306 %main = OpFunction %void None %40
307 %43 = OpLabel
308 %44 = OpVariable %_ptr_Function_A Function
309 %45 = OpExtInst %void %1 DebugFunctionDefinition %30 %main
310 %51 = OpExtInst %void %1 DebugScope %32
311 %46 = OpExtInst %void %1 DebugLine %16 %uint_10 %uint_10 %uint_3 %uint_5
312 %47 = OpExtInst %void %1 DebugDeclare %34 %44 %15
313 %52 = OpExtInst %void %1 DebugScope %25 %37
314 %48 = OpExtInst %void %1 DebugLine %16 %uint_4 %uint_5 %uint_3 %uint_3
315 %49 = OpExtInst %void %1 DebugDeclare %27 %44 %15
316 %53 = OpExtInst %void %1 DebugNoScope
317 %50 = OpExtInst %void %1 DebugLine %16 %uint_12 %uint_12 %uint_1 %uint_1
318 ; CHECK: {{.*}} = OpExtInst %void %1 DebugFunctionDefinition
319 ; CHECK: {{.*}} = OpExtInst %void %1 DebugScope
320 ; CHECK: {{.*}} = OpExtInst %void %1 DebugLine
321 ; CHECK: {{.*}} = OpExtInst %void %1 DebugDeclare
322 ; CHECK: {{.*}} = OpExtInst %void %1 DebugScope
323 ; CHECK: {{.*}} = OpExtInst %void %1 DebugLine
324 ; CHECK: {{.*}} = OpExtInst %void %1 DebugDeclare
325 ; CHECK: {{.*}} = OpExtInst %void %1 DebugNoScope
326 ; CHECK: {{.*}} = OpExtInst %void %1 DebugLine
327 OpReturn
328 OpFunctionEnd
329 )";
330 const auto result =
331 SinglePassRunAndMatch<OpExtInstWithForwardReferenceFixupPass>(
332 kTest, /* do_validation= */ true);
333 EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange);
334 }
335
336 } // namespace
337 } // namespace opt
338 } // namespace spvtools
339