• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2019 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 <string>
16 
17 #include "gmock/gmock.h"
18 #include "test/opt/assembly_builder.h"
19 #include "test/opt/pass_fixture.h"
20 #include "test/opt/pass_utils.h"
21 
22 namespace spvtools {
23 namespace opt {
24 namespace {
25 
26 using FixStorageClassTest = PassTest<::testing::Test>;
27 
TEST_F(FixStorageClassTest,FixAccessChain)28 TEST_F(FixStorageClassTest, FixAccessChain) {
29   const std::string text = R"(
30 ; CHECK: OpAccessChain %_ptr_Workgroup_float
31 ; CHECK: OpAccessChain %_ptr_Uniform_float
32                OpCapability Shader
33                OpMemoryModel Logical GLSL450
34                OpEntryPoint GLCompute %1 "testMain" %gl_GlobalInvocationID %gl_LocalInvocationID %gl_WorkGroupID
35                OpExecutionMode %1 LocalSize 8 8 1
36                OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId
37                OpDecorate %gl_LocalInvocationID BuiltIn LocalInvocationId
38                OpDecorate %gl_WorkGroupID BuiltIn WorkgroupId
39                OpDecorate %8 DescriptorSet 0
40                OpDecorate %8 Binding 0
41                OpDecorate %_runtimearr_float ArrayStride 4
42                OpMemberDecorate %_struct_7 0 Offset 0
43                OpDecorate %_struct_7 BufferBlock
44         %int = OpTypeInt 32 1
45       %int_0 = OpConstant %int 0
46       %float = OpTypeFloat 32
47     %float_2 = OpConstant %float 2
48        %uint = OpTypeInt 32 0
49     %uint_10 = OpConstant %uint 10
50 %_arr_float_uint_10 = OpTypeArray %float %uint_10
51 %ptr = OpTypePointer Function %_arr_float_uint_10
52 %_arr__arr_float_uint_10_uint_10 = OpTypeArray %_arr_float_uint_10 %uint_10
53   %_struct_5 = OpTypeStruct %_arr__arr_float_uint_10_uint_10
54 %_ptr_Workgroup__struct_5 = OpTypePointer Workgroup %_struct_5
55 %_runtimearr_float = OpTypeRuntimeArray %float
56   %_struct_7 = OpTypeStruct %_runtimearr_float
57 %_ptr_Uniform__struct_7 = OpTypePointer Uniform %_struct_7
58      %v3uint = OpTypeVector %uint 3
59 %_ptr_Input_v3uint = OpTypePointer Input %v3uint
60        %void = OpTypeVoid
61          %30 = OpTypeFunction %void
62 %_ptr_Function_float = OpTypePointer Function %float
63 %_ptr_Uniform_float = OpTypePointer Uniform %float
64           %6 = OpVariable %_ptr_Workgroup__struct_5 Workgroup
65           %8 = OpVariable %_ptr_Uniform__struct_7 Uniform
66 %gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input
67 %gl_LocalInvocationID = OpVariable %_ptr_Input_v3uint Input
68 %gl_WorkGroupID = OpVariable %_ptr_Input_v3uint Input
69           %1 = OpFunction %void None %30
70          %38 = OpLabel
71          %44 = OpLoad %v3uint %gl_LocalInvocationID
72          %50 = OpAccessChain %_ptr_Function_float %6 %int_0 %int_0 %int_0
73          %51 = OpLoad %float %50
74          %52 = OpFMul %float %float_2 %51
75                OpStore %50 %52
76          %55 = OpLoad %float %50
77          %59 = OpCompositeExtract %uint %44 0
78          %60 = OpAccessChain %_ptr_Uniform_float %8 %int_0 %59
79                OpStore %60 %55
80                OpReturn
81                OpFunctionEnd
82 )";
83 
84   SinglePassRunAndMatch<FixStorageClass>(text, false);
85 }
86 
TEST_F(FixStorageClassTest,FixLinkedAccessChain)87 TEST_F(FixStorageClassTest, FixLinkedAccessChain) {
88   const std::string text = R"(
89 ; CHECK: OpAccessChain %_ptr_Workgroup__arr_float_uint_10
90 ; CHECK: OpAccessChain %_ptr_Workgroup_float
91 ; CHECK: OpAccessChain %_ptr_Uniform_float
92                OpCapability Shader
93                OpMemoryModel Logical GLSL450
94                OpEntryPoint GLCompute %1 "testMain" %gl_GlobalInvocationID %gl_LocalInvocationID %gl_WorkGroupID
95                OpExecutionMode %1 LocalSize 8 8 1
96                OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId
97                OpDecorate %gl_LocalInvocationID BuiltIn LocalInvocationId
98                OpDecorate %gl_WorkGroupID BuiltIn WorkgroupId
99                OpDecorate %5 DescriptorSet 0
100                OpDecorate %5 Binding 0
101                OpDecorate %_runtimearr_float ArrayStride 4
102                OpMemberDecorate %_struct_7 0 Offset 0
103                OpDecorate %_struct_7 BufferBlock
104         %int = OpTypeInt 32 1
105       %int_0 = OpConstant %int 0
106       %float = OpTypeFloat 32
107     %float_2 = OpConstant %float 2
108        %uint = OpTypeInt 32 0
109     %uint_10 = OpConstant %uint 10
110 %_arr_float_uint_10 = OpTypeArray %float %uint_10
111 %_ptr_Function__arr_float_uint_10 = OpTypePointer Function %_arr_float_uint_10
112 %_ptr = OpTypePointer Function %_arr_float_uint_10
113 %_arr__arr_float_uint_10_uint_10 = OpTypeArray %_arr_float_uint_10 %uint_10
114  %_struct_17 = OpTypeStruct %_arr__arr_float_uint_10_uint_10
115 %_ptr_Workgroup__struct_17 = OpTypePointer Workgroup %_struct_17
116 %_runtimearr_float = OpTypeRuntimeArray %float
117   %_struct_7 = OpTypeStruct %_runtimearr_float
118 %_ptr_Uniform__struct_7 = OpTypePointer Uniform %_struct_7
119      %v3uint = OpTypeVector %uint 3
120 %_ptr_Input_v3uint = OpTypePointer Input %v3uint
121        %void = OpTypeVoid
122          %23 = OpTypeFunction %void
123 %_ptr_Function_float = OpTypePointer Function %float
124 %_ptr_Uniform_float = OpTypePointer Uniform %float
125          %27 = OpVariable %_ptr_Workgroup__struct_17 Workgroup
126           %5 = OpVariable %_ptr_Uniform__struct_7 Uniform
127 %gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input
128 %gl_LocalInvocationID = OpVariable %_ptr_Input_v3uint Input
129 %gl_WorkGroupID = OpVariable %_ptr_Input_v3uint Input
130           %1 = OpFunction %void None %23
131          %28 = OpLabel
132          %29 = OpLoad %v3uint %gl_LocalInvocationID
133          %30 = OpAccessChain %_ptr_Function__arr_float_uint_10 %27 %int_0 %int_0
134          %31 = OpAccessChain %_ptr_Function_float %30 %int_0
135          %32 = OpLoad %float %31
136          %33 = OpFMul %float %float_2 %32
137                OpStore %31 %33
138          %34 = OpLoad %float %31
139          %35 = OpCompositeExtract %uint %29 0
140          %36 = OpAccessChain %_ptr_Uniform_float %5 %int_0 %35
141                OpStore %36 %34
142                OpReturn
143                OpFunctionEnd
144 )";
145 
146   SinglePassRunAndMatch<FixStorageClass>(text, false);
147 }
148 
TEST_F(FixStorageClassTest,FixCopyObject)149 TEST_F(FixStorageClassTest, FixCopyObject) {
150   const std::string text = R"(
151 ; CHECK: OpCopyObject %_ptr_Workgroup__struct_17
152 ; CHECK: OpAccessChain %_ptr_Workgroup_float
153 ; CHECK: OpAccessChain %_ptr_Uniform_float
154                OpCapability Shader
155                OpMemoryModel Logical GLSL450
156                OpEntryPoint GLCompute %1 "testMain" %gl_GlobalInvocationID %gl_LocalInvocationID %gl_WorkGroupID
157                OpExecutionMode %1 LocalSize 8 8 1
158                OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId
159                OpDecorate %gl_LocalInvocationID BuiltIn LocalInvocationId
160                OpDecorate %gl_WorkGroupID BuiltIn WorkgroupId
161                OpDecorate %8 DescriptorSet 0
162                OpDecorate %8 Binding 0
163                OpDecorate %_runtimearr_float ArrayStride 4
164                OpMemberDecorate %_struct_7 0 Offset 0
165                OpDecorate %_struct_7 BufferBlock
166         %int = OpTypeInt 32 1
167       %int_0 = OpConstant %int 0
168       %float = OpTypeFloat 32
169     %float_2 = OpConstant %float 2
170        %uint = OpTypeInt 32 0
171     %uint_10 = OpConstant %uint 10
172 %_arr_float_uint_10 = OpTypeArray %float %uint_10
173 %ptr = OpTypePointer Function %_arr_float_uint_10
174 %_arr__arr_float_uint_10_uint_10 = OpTypeArray %_arr_float_uint_10 %uint_10
175   %_struct_17 = OpTypeStruct %_arr__arr_float_uint_10_uint_10
176 %_ptr_Workgroup__struct_17 = OpTypePointer Workgroup %_struct_17
177 %_ptr_Function__struct_17 = OpTypePointer Function %_struct_17
178 %_runtimearr_float = OpTypeRuntimeArray %float
179   %_struct_7 = OpTypeStruct %_runtimearr_float
180 %_ptr_Uniform__struct_7 = OpTypePointer Uniform %_struct_7
181      %v3uint = OpTypeVector %uint 3
182 %_ptr_Input_v3uint = OpTypePointer Input %v3uint
183        %void = OpTypeVoid
184          %30 = OpTypeFunction %void
185 %_ptr_Function_float = OpTypePointer Function %float
186 %_ptr_Uniform_float = OpTypePointer Uniform %float
187           %6 = OpVariable %_ptr_Workgroup__struct_17 Workgroup
188           %8 = OpVariable %_ptr_Uniform__struct_7 Uniform
189 %gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input
190 %gl_LocalInvocationID = OpVariable %_ptr_Input_v3uint Input
191 %gl_WorkGroupID = OpVariable %_ptr_Input_v3uint Input
192           %1 = OpFunction %void None %30
193          %38 = OpLabel
194          %44 = OpLoad %v3uint %gl_LocalInvocationID
195          %cp = OpCopyObject %_ptr_Function__struct_17 %6
196          %50 = OpAccessChain %_ptr_Function_float %cp %int_0 %int_0 %int_0
197          %51 = OpLoad %float %50
198          %52 = OpFMul %float %float_2 %51
199                OpStore %50 %52
200          %55 = OpLoad %float %50
201          %59 = OpCompositeExtract %uint %44 0
202          %60 = OpAccessChain %_ptr_Uniform_float %8 %int_0 %59
203                OpStore %60 %55
204                OpReturn
205                OpFunctionEnd
206 )";
207 
208   SinglePassRunAndMatch<FixStorageClass>(text, false);
209 }
210 
TEST_F(FixStorageClassTest,FixPhiInSelMerge)211 TEST_F(FixStorageClassTest, FixPhiInSelMerge) {
212   const std::string text = R"(
213 ; CHECK: OpPhi %_ptr_Workgroup__struct_19
214 ; CHECK: OpAccessChain %_ptr_Workgroup_float
215 ; CHECK: OpAccessChain %_ptr_Uniform_float
216                OpCapability Shader
217                OpMemoryModel Logical GLSL450
218                OpEntryPoint GLCompute %1 "testMain" %gl_GlobalInvocationID %gl_LocalInvocationID %gl_WorkGroupID
219                OpExecutionMode %1 LocalSize 8 8 1
220                OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId
221                OpDecorate %gl_LocalInvocationID BuiltIn LocalInvocationId
222                OpDecorate %gl_WorkGroupID BuiltIn WorkgroupId
223                OpDecorate %5 DescriptorSet 0
224                OpDecorate %5 Binding 0
225                OpDecorate %_runtimearr_float ArrayStride 4
226                OpMemberDecorate %_struct_7 0 Offset 0
227                OpDecorate %_struct_7 BufferBlock
228        %bool = OpTypeBool
229        %true = OpConstantTrue %bool
230         %int = OpTypeInt 32 1
231       %int_0 = OpConstant %int 0
232       %float = OpTypeFloat 32
233     %float_2 = OpConstant %float 2
234        %uint = OpTypeInt 32 0
235     %uint_10 = OpConstant %uint 10
236 %_arr_float_uint_10 = OpTypeArray %float %uint_10
237 %_ptr_Function__arr_float_uint_10 = OpTypePointer Function %_arr_float_uint_10
238 %_arr__arr_float_uint_10_uint_10 = OpTypeArray %_arr_float_uint_10 %uint_10
239  %_struct_19 = OpTypeStruct %_arr__arr_float_uint_10_uint_10
240 %_ptr_Workgroup__struct_19 = OpTypePointer Workgroup %_struct_19
241 %_ptr_Function__struct_19 = OpTypePointer Function %_struct_19
242 %_runtimearr_float = OpTypeRuntimeArray %float
243   %_struct_7 = OpTypeStruct %_runtimearr_float
244 %_ptr_Uniform__struct_7 = OpTypePointer Uniform %_struct_7
245      %v3uint = OpTypeVector %uint 3
246 %_ptr_Input_v3uint = OpTypePointer Input %v3uint
247        %void = OpTypeVoid
248          %25 = OpTypeFunction %void
249 %_ptr_Function_float = OpTypePointer Function %float
250 %_ptr_Uniform_float = OpTypePointer Uniform %float
251          %28 = OpVariable %_ptr_Workgroup__struct_19 Workgroup
252          %29 = OpVariable %_ptr_Workgroup__struct_19 Workgroup
253           %5 = OpVariable %_ptr_Uniform__struct_7 Uniform
254 %gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input
255 %gl_LocalInvocationID = OpVariable %_ptr_Input_v3uint Input
256 %gl_WorkGroupID = OpVariable %_ptr_Input_v3uint Input
257           %1 = OpFunction %void None %25
258          %30 = OpLabel
259                OpSelectionMerge %31 None
260                OpBranchConditional %true %32 %31
261          %32 = OpLabel
262                OpBranch %31
263          %31 = OpLabel
264          %33 = OpPhi %_ptr_Function__struct_19 %28 %30 %29 %32
265          %34 = OpLoad %v3uint %gl_LocalInvocationID
266          %35 = OpAccessChain %_ptr_Function_float %33 %int_0 %int_0 %int_0
267          %36 = OpLoad %float %35
268          %37 = OpFMul %float %float_2 %36
269                OpStore %35 %37
270          %38 = OpLoad %float %35
271          %39 = OpCompositeExtract %uint %34 0
272          %40 = OpAccessChain %_ptr_Uniform_float %5 %int_0 %39
273                OpStore %40 %38
274                OpReturn
275                OpFunctionEnd
276 )";
277 
278   SinglePassRunAndMatch<FixStorageClass>(text, false);
279 }
280 
TEST_F(FixStorageClassTest,FixPhiInLoop)281 TEST_F(FixStorageClassTest, FixPhiInLoop) {
282   const std::string text = R"(
283 ; CHECK: OpPhi %_ptr_Workgroup__struct_19
284 ; CHECK: OpAccessChain %_ptr_Workgroup_float
285 ; CHECK: OpAccessChain %_ptr_Uniform_float
286                OpCapability Shader
287                OpMemoryModel Logical GLSL450
288                OpEntryPoint GLCompute %1 "testMain" %gl_GlobalInvocationID %gl_LocalInvocationID %gl_WorkGroupID
289                OpExecutionMode %1 LocalSize 8 8 1
290                OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId
291                OpDecorate %gl_LocalInvocationID BuiltIn LocalInvocationId
292                OpDecorate %gl_WorkGroupID BuiltIn WorkgroupId
293                OpDecorate %5 DescriptorSet 0
294                OpDecorate %5 Binding 0
295                OpDecorate %_runtimearr_float ArrayStride 4
296                OpMemberDecorate %_struct_7 0 Offset 0
297                OpDecorate %_struct_7 BufferBlock
298        %bool = OpTypeBool
299        %true = OpConstantTrue %bool
300         %int = OpTypeInt 32 1
301       %int_0 = OpConstant %int 0
302       %float = OpTypeFloat 32
303     %float_2 = OpConstant %float 2
304        %uint = OpTypeInt 32 0
305     %uint_10 = OpConstant %uint 10
306 %_arr_float_uint_10 = OpTypeArray %float %uint_10
307 %_ptr_Function__arr_float_uint_10 = OpTypePointer Function %_arr_float_uint_10
308 %_arr__arr_float_uint_10_uint_10 = OpTypeArray %_arr_float_uint_10 %uint_10
309  %_struct_19 = OpTypeStruct %_arr__arr_float_uint_10_uint_10
310 %_ptr_Workgroup__struct_19 = OpTypePointer Workgroup %_struct_19
311 %_ptr_Function__struct_19 = OpTypePointer Function %_struct_19
312 %_runtimearr_float = OpTypeRuntimeArray %float
313   %_struct_7 = OpTypeStruct %_runtimearr_float
314 %_ptr_Uniform__struct_7 = OpTypePointer Uniform %_struct_7
315      %v3uint = OpTypeVector %uint 3
316 %_ptr_Input_v3uint = OpTypePointer Input %v3uint
317        %void = OpTypeVoid
318          %25 = OpTypeFunction %void
319 %_ptr_Function_float = OpTypePointer Function %float
320 %_ptr_Uniform_float = OpTypePointer Uniform %float
321          %28 = OpVariable %_ptr_Workgroup__struct_19 Workgroup
322          %29 = OpVariable %_ptr_Workgroup__struct_19 Workgroup
323           %5 = OpVariable %_ptr_Uniform__struct_7 Uniform
324 %gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input
325 %gl_LocalInvocationID = OpVariable %_ptr_Input_v3uint Input
326 %gl_WorkGroupID = OpVariable %_ptr_Input_v3uint Input
327           %1 = OpFunction %void None %25
328          %30 = OpLabel
329                OpSelectionMerge %31 None
330                OpBranchConditional %true %32 %31
331          %32 = OpLabel
332                OpBranch %31
333          %31 = OpLabel
334          %33 = OpPhi %_ptr_Function__struct_19 %28 %30 %29 %32
335          %34 = OpLoad %v3uint %gl_LocalInvocationID
336          %35 = OpAccessChain %_ptr_Function_float %33 %int_0 %int_0 %int_0
337          %36 = OpLoad %float %35
338          %37 = OpFMul %float %float_2 %36
339                OpStore %35 %37
340          %38 = OpLoad %float %35
341          %39 = OpCompositeExtract %uint %34 0
342          %40 = OpAccessChain %_ptr_Uniform_float %5 %int_0 %39
343                OpStore %40 %38
344                OpReturn
345                OpFunctionEnd
346 )";
347 
348   SinglePassRunAndMatch<FixStorageClass>(text, false);
349 }
350 
TEST_F(FixStorageClassTest,DontChangeFunctionCalls)351 TEST_F(FixStorageClassTest, DontChangeFunctionCalls) {
352   const std::string text = R"(OpCapability Shader
353 OpMemoryModel Logical GLSL450
354 OpEntryPoint GLCompute %1 "testMain"
355 OpExecutionMode %1 LocalSize 8 8 1
356 OpDecorate %2 DescriptorSet 0
357 OpDecorate %2 Binding 0
358 %int = OpTypeInt 32 1
359 %_ptr_Function_int = OpTypePointer Function %int
360 %_ptr_Workgroup_int = OpTypePointer Workgroup %int
361 %_ptr_Uniform_int = OpTypePointer Uniform %int
362 %void = OpTypeVoid
363 %8 = OpTypeFunction %void
364 %9 = OpTypeFunction %_ptr_Uniform_int %_ptr_Function_int
365 %10 = OpVariable %_ptr_Workgroup_int Workgroup
366 %2 = OpVariable %_ptr_Uniform_int Uniform
367 %1 = OpFunction %void None %8
368 %11 = OpLabel
369 %12 = OpFunctionCall %_ptr_Uniform_int %13 %10
370 OpReturn
371 OpFunctionEnd
372 %13 = OpFunction %_ptr_Uniform_int None %9
373 %14 = OpFunctionParameter %_ptr_Function_int
374 %15 = OpLabel
375 OpReturnValue %2
376 OpFunctionEnd
377 )";
378 
379   SinglePassRunAndCheck<FixStorageClass>(text, text, false, false);
380 }
381 
TEST_F(FixStorageClassTest,FixSelect)382 TEST_F(FixStorageClassTest, FixSelect) {
383   const std::string text = R"(
384 ; CHECK: OpSelect %_ptr_Workgroup__struct_19
385 ; CHECK: OpAccessChain %_ptr_Workgroup_float
386 ; CHECK: OpAccessChain %_ptr_Uniform_float
387                OpCapability Shader
388                OpMemoryModel Logical GLSL450
389                OpEntryPoint GLCompute %1 "testMain" %gl_GlobalInvocationID %gl_LocalInvocationID %gl_WorkGroupID
390                OpExecutionMode %1 LocalSize 8 8 1
391                OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId
392                OpDecorate %gl_LocalInvocationID BuiltIn LocalInvocationId
393                OpDecorate %gl_WorkGroupID BuiltIn WorkgroupId
394                OpDecorate %5 DescriptorSet 0
395                OpDecorate %5 Binding 0
396                OpDecorate %_runtimearr_float ArrayStride 4
397                OpMemberDecorate %_struct_7 0 Offset 0
398                OpDecorate %_struct_7 BufferBlock
399        %bool = OpTypeBool
400        %true = OpConstantTrue %bool
401         %int = OpTypeInt 32 1
402       %int_0 = OpConstant %int 0
403       %float = OpTypeFloat 32
404     %float_2 = OpConstant %float 2
405        %uint = OpTypeInt 32 0
406     %uint_10 = OpConstant %uint 10
407 %_arr_float_uint_10 = OpTypeArray %float %uint_10
408 %_ptr_Function__arr_float_uint_10 = OpTypePointer Function %_arr_float_uint_10
409 %_arr__arr_float_uint_10_uint_10 = OpTypeArray %_arr_float_uint_10 %uint_10
410  %_struct_19 = OpTypeStruct %_arr__arr_float_uint_10_uint_10
411 %_ptr_Workgroup__struct_19 = OpTypePointer Workgroup %_struct_19
412 %_ptr_Function__struct_19 = OpTypePointer Function %_struct_19
413 %_runtimearr_float = OpTypeRuntimeArray %float
414   %_struct_7 = OpTypeStruct %_runtimearr_float
415 %_ptr_Uniform__struct_7 = OpTypePointer Uniform %_struct_7
416      %v3uint = OpTypeVector %uint 3
417 %_ptr_Input_v3uint = OpTypePointer Input %v3uint
418        %void = OpTypeVoid
419          %25 = OpTypeFunction %void
420 %_ptr_Function_float = OpTypePointer Function %float
421 %_ptr_Uniform_float = OpTypePointer Uniform %float
422          %28 = OpVariable %_ptr_Workgroup__struct_19 Workgroup
423          %29 = OpVariable %_ptr_Workgroup__struct_19 Workgroup
424           %5 = OpVariable %_ptr_Uniform__struct_7 Uniform
425 %gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input
426 %gl_LocalInvocationID = OpVariable %_ptr_Input_v3uint Input
427 %gl_WorkGroupID = OpVariable %_ptr_Input_v3uint Input
428           %1 = OpFunction %void None %25
429          %30 = OpLabel
430          %33 = OpSelect %_ptr_Function__struct_19 %true %28 %29
431          %34 = OpLoad %v3uint %gl_LocalInvocationID
432          %35 = OpAccessChain %_ptr_Function_float %33 %int_0 %int_0 %int_0
433          %36 = OpLoad %float %35
434          %37 = OpFMul %float %float_2 %36
435                OpStore %35 %37
436          %38 = OpLoad %float %35
437          %39 = OpCompositeExtract %uint %34 0
438          %40 = OpAccessChain %_ptr_Uniform_float %5 %int_0 %39
439                OpStore %40 %38
440                OpReturn
441                OpFunctionEnd
442 )";
443 
444   SinglePassRunAndMatch<FixStorageClass>(text, false);
445 }
446 
TEST_F(FixStorageClassTest,BitCast)447 TEST_F(FixStorageClassTest, BitCast) {
448   const std::string text = R"(OpCapability VariablePointersStorageBuffer
449 OpMemoryModel Logical GLSL450
450 OpEntryPoint GLCompute %1 "main"
451 %void = OpTypeVoid
452 %3 = OpTypeFunction %void
453 %_ptr_Output_void = OpTypePointer Output %void
454 %_ptr_Private__ptr_Output_void = OpTypePointer Private %_ptr_Output_void
455 %6 = OpVariable %_ptr_Private__ptr_Output_void Private
456 %1 = OpFunction %void Inline %3
457 %7 = OpLabel
458 %8 = OpBitcast %_ptr_Output_void %6
459 OpReturn
460 OpFunctionEnd
461 )";
462 
463   SinglePassRunAndCheck<FixStorageClass>(text, text, false);
464 }
465 
TEST_F(FixStorageClassTest,FixLinkedAccessChain2)466 TEST_F(FixStorageClassTest, FixLinkedAccessChain2) {
467   // This case is similar to FixLinkedAccessChain.  The difference is that the
468   // first OpAccessChain instruction starts as workgroup storage class.  Only
469   // the second one needs to change.
470   const std::string text = R"(
471 ; CHECK: OpAccessChain %_ptr_Workgroup__arr_float_uint_10
472 ; CHECK: OpAccessChain %_ptr_Workgroup_float
473 ; CHECK: OpAccessChain %_ptr_Uniform_float
474                OpCapability Shader
475                OpMemoryModel Logical GLSL450
476                OpEntryPoint GLCompute %1 "testMain" %gl_GlobalInvocationID %gl_LocalInvocationID %gl_WorkGroupID
477                OpExecutionMode %1 LocalSize 8 8 1
478                OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId
479                OpDecorate %gl_LocalInvocationID BuiltIn LocalInvocationId
480                OpDecorate %gl_WorkGroupID BuiltIn WorkgroupId
481                OpDecorate %5 DescriptorSet 0
482                OpDecorate %5 Binding 0
483                OpDecorate %_runtimearr_float ArrayStride 4
484                OpMemberDecorate %_struct_7 0 Offset 0
485                OpDecorate %_struct_7 BufferBlock
486         %int = OpTypeInt 32 1
487       %int_0 = OpConstant %int 0
488       %float = OpTypeFloat 32
489     %float_2 = OpConstant %float 2
490        %uint = OpTypeInt 32 0
491     %uint_10 = OpConstant %uint 10
492 %_arr_float_uint_10 = OpTypeArray %float %uint_10
493 %_ptr_Workgroup__arr_float_uint_10 = OpTypePointer Workgroup %_arr_float_uint_10
494 %_ptr = OpTypePointer Function %_arr_float_uint_10
495 %_arr__arr_float_uint_10_uint_10 = OpTypeArray %_arr_float_uint_10 %uint_10
496  %_struct_17 = OpTypeStruct %_arr__arr_float_uint_10_uint_10
497 %_ptr_Workgroup__struct_17 = OpTypePointer Workgroup %_struct_17
498 %_runtimearr_float = OpTypeRuntimeArray %float
499   %_struct_7 = OpTypeStruct %_runtimearr_float
500 %_ptr_Uniform__struct_7 = OpTypePointer Uniform %_struct_7
501      %v3uint = OpTypeVector %uint 3
502 %_ptr_Input_v3uint = OpTypePointer Input %v3uint
503        %void = OpTypeVoid
504          %23 = OpTypeFunction %void
505 %_ptr_Function_float = OpTypePointer Function %float
506 %_ptr_Uniform_float = OpTypePointer Uniform %float
507          %27 = OpVariable %_ptr_Workgroup__struct_17 Workgroup
508           %5 = OpVariable %_ptr_Uniform__struct_7 Uniform
509 %gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input
510 %gl_LocalInvocationID = OpVariable %_ptr_Input_v3uint Input
511 %gl_WorkGroupID = OpVariable %_ptr_Input_v3uint Input
512           %1 = OpFunction %void None %23
513          %28 = OpLabel
514          %29 = OpLoad %v3uint %gl_LocalInvocationID
515          %30 = OpAccessChain %_ptr_Workgroup__arr_float_uint_10 %27 %int_0 %int_0
516          %31 = OpAccessChain %_ptr_Function_float %30 %int_0
517          %32 = OpLoad %float %31
518          %33 = OpFMul %float %float_2 %32
519                OpStore %31 %33
520          %34 = OpLoad %float %31
521          %35 = OpCompositeExtract %uint %29 0
522          %36 = OpAccessChain %_ptr_Uniform_float %5 %int_0 %35
523                OpStore %36 %34
524                OpReturn
525                OpFunctionEnd
526 )";
527 
528   SinglePassRunAndMatch<FixStorageClass>(text, false);
529 }
530 
TEST_F(FixStorageClassTest,AllowImageFormatMismatch)531 TEST_F(FixStorageClassTest, AllowImageFormatMismatch) {
532   const std::string text = R"(OpCapability Shader
533 OpCapability SampledBuffer
534 OpCapability ImageBuffer
535 OpMemoryModel Logical GLSL450
536 OpEntryPoint GLCompute %main "main"
537 OpExecutionMode %main LocalSize 1 1 1
538 OpSource HLSL 600
539 OpName %type_buffer_image "type.buffer.image"
540 OpName %Buf "Buf"
541 OpName %main "main"
542 OpName %src_main "src.main"
543 OpName %bb_entry "bb.entry"
544 OpName %type_buffer_image_0 "type.buffer.image"
545 OpName %b "b"
546 OpDecorate %Buf DescriptorSet 0
547 OpDecorate %Buf Binding 0
548 %float = OpTypeFloat 32
549 %type_buffer_image = OpTypeImage %float Buffer 2 0 0 2 Rgba16f
550 %_ptr_UniformConstant_type_buffer_image = OpTypePointer UniformConstant %type_buffer_image
551 %void = OpTypeVoid
552 %11 = OpTypeFunction %void
553 %type_buffer_image_0 = OpTypeImage %float Buffer 2 0 0 2 Rgba32f
554 %_ptr_Function_type_buffer_image_0 = OpTypePointer Function %type_buffer_image_0
555 %Buf = OpVariable %_ptr_UniformConstant_type_buffer_image UniformConstant
556 %main = OpFunction %void None %11
557 %13 = OpLabel
558 %14 = OpFunctionCall %void %src_main
559 OpReturn
560 OpFunctionEnd
561 %src_main = OpFunction %void None %11
562 %bb_entry = OpLabel
563 %b = OpVariable %_ptr_Function_type_buffer_image_0 Function
564 %15 = OpLoad %type_buffer_image %Buf
565 OpStore %b %15
566 OpReturn
567 OpFunctionEnd
568 )";
569 
570   SinglePassRunAndCheck<FixStorageClass>(text, text, false, false);
571 }
572 
573 using FixTypeTest = PassTest<::testing::Test>;
574 
TEST_F(FixTypeTest,FixAccessChain)575 TEST_F(FixTypeTest, FixAccessChain) {
576   const std::string text = R"(
577 ; CHECK: [[ac1:%\w+]] = OpAccessChain %_ptr_Uniform_S %A %int_0 %uint_0
578 ; CHECK: [[ac2:%\w+]] = OpAccessChain %_ptr_Uniform_T [[ac1]] %int_0
579                OpCapability Shader
580                OpMemoryModel Logical GLSL450
581                OpEntryPoint GLCompute %main "main"
582                OpExecutionMode %main LocalSize 1 1 1
583                OpSource HLSL 600
584                OpName %type_RWStructuredBuffer_S "type.RWStructuredBuffer.S"
585                OpName %S "S"
586                OpMemberName %S 0 "t"
587                OpName %T "T"
588                OpMemberName %T 0 "a"
589                OpName %A "A"
590                OpName %type_ACSBuffer_counter "type.ACSBuffer.counter"
591                OpMemberName %type_ACSBuffer_counter 0 "counter"
592                OpName %counter_var_A "counter.var.A"
593                OpName %main "main"
594                OpName %S_0 "S"
595                OpMemberName %S_0 0 "t"
596                OpName %T_0 "T"
597                OpMemberName %T_0 0 "a"
598                OpDecorate %A DescriptorSet 0
599                OpDecorate %A Binding 0
600                OpDecorate %counter_var_A DescriptorSet 0
601                OpDecorate %counter_var_A Binding 1
602                OpMemberDecorate %T 0 Offset 0
603                OpMemberDecorate %S 0 Offset 0
604                OpDecorate %_runtimearr_S ArrayStride 4
605                OpMemberDecorate %type_RWStructuredBuffer_S 0 Offset 0
606                OpDecorate %type_RWStructuredBuffer_S BufferBlock
607                OpMemberDecorate %type_ACSBuffer_counter 0 Offset 0
608                OpDecorate %type_ACSBuffer_counter BufferBlock
609         %int = OpTypeInt 32 1
610       %int_0 = OpConstant %int 0
611        %uint = OpTypeInt 32 0
612      %uint_0 = OpConstant %uint 0
613           %T = OpTypeStruct %int
614           %S = OpTypeStruct %T
615 %_runtimearr_S = OpTypeRuntimeArray %S
616 %type_RWStructuredBuffer_S = OpTypeStruct %_runtimearr_S
617 %_ptr_Uniform_type_RWStructuredBuffer_S = OpTypePointer Uniform %type_RWStructuredBuffer_S
618 %type_ACSBuffer_counter = OpTypeStruct %int
619 %_ptr_Uniform_type_ACSBuffer_counter = OpTypePointer Uniform %type_ACSBuffer_counter
620        %void = OpTypeVoid
621          %18 = OpTypeFunction %void
622         %T_0 = OpTypeStruct %int
623         %S_0 = OpTypeStruct %T_0
624 %_ptr_Function_S_0 = OpTypePointer Function %S_0
625 %_ptr_Uniform_S = OpTypePointer Uniform %S
626 %_ptr_Uniform_T = OpTypePointer Uniform %T
627          %22 = OpTypeFunction %T_0 %_ptr_Function_S_0
628 %_ptr_Function_T_0 = OpTypePointer Function %T_0
629           %A = OpVariable %_ptr_Uniform_type_RWStructuredBuffer_S Uniform
630 %counter_var_A = OpVariable %_ptr_Uniform_type_ACSBuffer_counter Uniform
631        %main = OpFunction %void None %18
632          %24 = OpLabel
633          %25 = OpVariable %_ptr_Function_T_0 Function
634          %26 = OpVariable %_ptr_Function_S_0 Function
635          %27 = OpAccessChain %_ptr_Uniform_S %A %int_0 %uint_0
636          %28 = OpAccessChain %_ptr_Function_T_0 %27 %int_0
637                OpReturn
638                OpFunctionEnd
639 )";
640 
641   SinglePassRunAndMatch<FixStorageClass>(text, false);
642 }
643 
TEST_F(FixTypeTest,FixLoad)644 TEST_F(FixTypeTest, FixLoad) {
645   const std::string text = R"(
646 ; CHECK: [[ac1:%\w+]] = OpAccessChain %_ptr_Uniform_S %A %int_0 %uint_0
647 ; CHECK: [[ac2:%\w+]] = OpAccessChain %_ptr_Uniform_T [[ac1]] %int_0
648 ; CHECK: [[ld:%\w+]] = OpLoad %T [[ac2]]
649                OpCapability Shader
650                OpMemoryModel Logical GLSL450
651                OpEntryPoint GLCompute %main "main"
652                OpExecutionMode %main LocalSize 1 1 1
653                OpSource HLSL 600
654                OpName %type_RWStructuredBuffer_S "type.RWStructuredBuffer.S"
655                OpName %S "S"
656                OpMemberName %S 0 "t"
657                OpName %T "T"
658                OpMemberName %T 0 "a"
659                OpName %A "A"
660                OpName %type_ACSBuffer_counter "type.ACSBuffer.counter"
661                OpMemberName %type_ACSBuffer_counter 0 "counter"
662                OpName %counter_var_A "counter.var.A"
663                OpName %main "main"
664                OpName %S_0 "S"
665                OpMemberName %S_0 0 "t"
666                OpName %T_0 "T"
667                OpMemberName %T_0 0 "a"
668                OpDecorate %A DescriptorSet 0
669                OpDecorate %A Binding 0
670                OpDecorate %counter_var_A DescriptorSet 0
671                OpDecorate %counter_var_A Binding 1
672                OpMemberDecorate %T 0 Offset 0
673                OpMemberDecorate %S 0 Offset 0
674                OpDecorate %_runtimearr_S ArrayStride 4
675                OpMemberDecorate %type_RWStructuredBuffer_S 0 Offset 0
676                OpDecorate %type_RWStructuredBuffer_S BufferBlock
677                OpMemberDecorate %type_ACSBuffer_counter 0 Offset 0
678                OpDecorate %type_ACSBuffer_counter BufferBlock
679         %int = OpTypeInt 32 1
680       %int_0 = OpConstant %int 0
681        %uint = OpTypeInt 32 0
682      %uint_0 = OpConstant %uint 0
683           %T = OpTypeStruct %int
684           %S = OpTypeStruct %T
685 %_runtimearr_S = OpTypeRuntimeArray %S
686 %type_RWStructuredBuffer_S = OpTypeStruct %_runtimearr_S
687 %_ptr_Uniform_type_RWStructuredBuffer_S = OpTypePointer Uniform %type_RWStructuredBuffer_S
688 %type_ACSBuffer_counter = OpTypeStruct %int
689 %_ptr_Uniform_type_ACSBuffer_counter = OpTypePointer Uniform %type_ACSBuffer_counter
690        %void = OpTypeVoid
691          %18 = OpTypeFunction %void
692         %T_0 = OpTypeStruct %int
693         %S_0 = OpTypeStruct %T_0
694 %_ptr_Function_S_0 = OpTypePointer Function %S_0
695 %_ptr_Uniform_S = OpTypePointer Uniform %S
696 %_ptr_Uniform_T = OpTypePointer Uniform %T
697          %22 = OpTypeFunction %T_0 %_ptr_Function_S_0
698 %_ptr_Function_T_0 = OpTypePointer Function %T_0
699           %A = OpVariable %_ptr_Uniform_type_RWStructuredBuffer_S Uniform
700 %counter_var_A = OpVariable %_ptr_Uniform_type_ACSBuffer_counter Uniform
701        %main = OpFunction %void None %18
702          %24 = OpLabel
703          %25 = OpVariable %_ptr_Function_T_0 Function
704          %26 = OpVariable %_ptr_Function_S_0 Function
705          %27 = OpAccessChain %_ptr_Uniform_S %A %int_0 %uint_0
706          %28 = OpAccessChain %_ptr_Uniform_T %27 %int_0
707          %29 = OpLoad %T_0 %28
708                OpReturn
709                OpFunctionEnd
710 )";
711 
712   SinglePassRunAndMatch<FixStorageClass>(text, false);
713 }
714 
TEST_F(FixTypeTest,FixStore)715 TEST_F(FixTypeTest, FixStore) {
716   const std::string text = R"(
717 ; CHECK: [[ld:%\w+]] = OpLoad %T
718 ; CHECK: OpStore
719                OpCapability Shader
720                OpMemoryModel Logical GLSL450
721                OpEntryPoint GLCompute %main "main"
722                OpExecutionMode %main LocalSize 1 1 1
723                OpSource HLSL 600
724                OpName %type_RWStructuredBuffer_S "type.RWStructuredBuffer.S"
725                OpName %S "S"
726                OpMemberName %S 0 "t"
727                OpName %T "T"
728                OpMemberName %T 0 "a"
729                OpName %A "A"
730                OpName %type_ACSBuffer_counter "type.ACSBuffer.counter"
731                OpMemberName %type_ACSBuffer_counter 0 "counter"
732                OpName %counter_var_A "counter.var.A"
733                OpName %main "main"
734                OpName %S_0 "S"
735                OpMemberName %S_0 0 "t"
736                OpName %T_0 "T"
737                OpMemberName %T_0 0 "a"
738                OpDecorate %A DescriptorSet 0
739                OpDecorate %A Binding 0
740                OpDecorate %counter_var_A DescriptorSet 0
741                OpDecorate %counter_var_A Binding 1
742                OpMemberDecorate %T 0 Offset 0
743                OpMemberDecorate %S 0 Offset 0
744                OpDecorate %_runtimearr_S ArrayStride 4
745                OpMemberDecorate %type_RWStructuredBuffer_S 0 Offset 0
746                OpDecorate %type_RWStructuredBuffer_S BufferBlock
747                OpMemberDecorate %type_ACSBuffer_counter 0 Offset 0
748                OpDecorate %type_ACSBuffer_counter BufferBlock
749         %int = OpTypeInt 32 1
750       %int_0 = OpConstant %int 0
751        %uint = OpTypeInt 32 0
752      %uint_0 = OpConstant %uint 0
753           %T = OpTypeStruct %int
754           %S = OpTypeStruct %T
755 %_runtimearr_S = OpTypeRuntimeArray %S
756 %type_RWStructuredBuffer_S = OpTypeStruct %_runtimearr_S
757 %_ptr_Uniform_type_RWStructuredBuffer_S = OpTypePointer Uniform %type_RWStructuredBuffer_S
758 %type_ACSBuffer_counter = OpTypeStruct %int
759 %_ptr_Uniform_type_ACSBuffer_counter = OpTypePointer Uniform %type_ACSBuffer_counter
760        %void = OpTypeVoid
761          %18 = OpTypeFunction %void
762         %T_0 = OpTypeStruct %int
763         %S_0 = OpTypeStruct %T_0
764 %_ptr_Function_S_0 = OpTypePointer Function %S_0
765 %_ptr_Uniform_S = OpTypePointer Uniform %S
766 %_ptr_Uniform_T = OpTypePointer Uniform %T
767          %22 = OpTypeFunction %T_0 %_ptr_Function_S_0
768 %_ptr_Function_T_0 = OpTypePointer Function %T_0
769           %A = OpVariable %_ptr_Uniform_type_RWStructuredBuffer_S Uniform
770 %counter_var_A = OpVariable %_ptr_Uniform_type_ACSBuffer_counter Uniform
771        %main = OpFunction %void None %18
772          %24 = OpLabel
773          %25 = OpVariable %_ptr_Function_T_0 Function
774          %26 = OpVariable %_ptr_Function_S_0 Function
775          %27 = OpAccessChain %_ptr_Uniform_S %A %int_0 %uint_0
776          %28 = OpAccessChain %_ptr_Uniform_T %27 %int_0
777          %29 = OpLoad %T %28
778                OpStore %25 %29
779                OpReturn
780                OpFunctionEnd
781 )";
782 
783   SinglePassRunAndMatch<FixStorageClass>(text, false);
784 }
785 
TEST_F(FixTypeTest,FixSelect)786 TEST_F(FixTypeTest, FixSelect) {
787   const std::string text = R"(
788 ; CHECK: OpSelect %_ptr_Uniform__struct_3
789                OpCapability Shader
790                OpMemoryModel Logical GLSL450
791                OpEntryPoint GLCompute %1 "main"
792                OpExecutionMode %1 LocalSize 1 1 1
793                OpSource HLSL 600
794                OpDecorate %2 DescriptorSet 0
795                OpDecorate %2 Binding 0
796                OpMemberDecorate %_struct_3 0 Offset 0
797                OpDecorate %_runtimearr__struct_3 ArrayStride 4
798                OpMemberDecorate %_struct_5 0 Offset 0
799                OpDecorate %_struct_5 BufferBlock
800        %uint = OpTypeInt 32 0
801      %uint_0 = OpConstant %uint 0
802      %uint_1 = OpConstant %uint 1
803   %_struct_3 = OpTypeStruct %uint
804 %_runtimearr__struct_3 = OpTypeRuntimeArray %_struct_3
805   %_struct_5 = OpTypeStruct %_runtimearr__struct_3
806 %_ptr_Uniform__struct_5 = OpTypePointer Uniform %_struct_5
807        %void = OpTypeVoid
808          %11 = OpTypeFunction %void
809  %_struct_12 = OpTypeStruct %uint
810 %_ptr_Function__struct_12 = OpTypePointer Function %_struct_12
811 %_ptr_Uniform_uint = OpTypePointer Uniform %uint
812        %bool = OpTypeBool
813 %_ptr_Uniform__struct_3 = OpTypePointer Uniform %_struct_3
814           %2 = OpVariable %_ptr_Uniform__struct_5 Uniform
815           %1 = OpFunction %void None %11
816          %17 = OpLabel
817          %18 = OpAccessChain %_ptr_Uniform_uint %2 %uint_0 %uint_0 %uint_0
818          %19 = OpLoad %uint %18
819          %20 = OpSGreaterThan %bool %19 %uint_0
820          %21 = OpAccessChain %_ptr_Uniform__struct_3 %2 %uint_0 %uint_0
821          %22 = OpAccessChain %_ptr_Uniform__struct_3 %2 %uint_0 %uint_1
822          %23 = OpSelect %_ptr_Function__struct_12 %20 %21 %22
823                OpReturn
824                OpFunctionEnd
825 )";
826 
827   SinglePassRunAndMatch<FixStorageClass>(text, false);
828 }
829 
TEST_F(FixTypeTest,FixPhiInLoop)830 TEST_F(FixTypeTest, FixPhiInLoop) {
831   const std::string text = R"(
832 ; CHECK: [[ac_init:%\w+]] = OpAccessChain %_ptr_Uniform__struct_3
833 ; CHECK: [[ac_phi:%\w+]] = OpPhi %_ptr_Uniform__struct_3 [[ac_init]] {{%\w+}} [[ac_update:%\w+]] {{%\w+}}
834 ; CHECK: [[ac_update]] = OpPtrAccessChain %_ptr_Uniform__struct_3 [[ac_phi]] %int_1
835                OpCapability Shader
836                OpMemoryModel Logical GLSL450
837                OpEntryPoint GLCompute %1 "main"
838                OpExecutionMode %1 LocalSize 1 1 1
839                OpSource HLSL 600
840                OpDecorate %2 DescriptorSet 0
841                OpDecorate %2 Binding 0
842                OpMemberDecorate %_struct_3 0 Offset 0
843                OpDecorate %_runtimearr__struct_3 ArrayStride 4
844                OpMemberDecorate %_struct_5 0 Offset 0
845                OpDecorate %_struct_5 BufferBlock
846         %int = OpTypeInt 32 1
847       %int_0 = OpConstant %int 0
848       %int_1 = OpConstant %int 1
849   %_struct_3 = OpTypeStruct %int
850   %_struct_9 = OpTypeStruct %int
851 %_runtimearr__struct_3 = OpTypeRuntimeArray %_struct_3
852   %_struct_5 = OpTypeStruct %_runtimearr__struct_3
853 %_ptr_Uniform__struct_5 = OpTypePointer Uniform %_struct_5
854        %void = OpTypeVoid
855          %12 = OpTypeFunction %void
856        %bool = OpTypeBool
857 %_ptr_Uniform__struct_3 = OpTypePointer Uniform %_struct_3
858 %_ptr_Function__struct_9 = OpTypePointer Function %_struct_9
859           %2 = OpVariable %_ptr_Uniform__struct_5 Uniform
860           %1 = OpFunction %void None %12
861          %16 = OpLabel
862          %17 = OpAccessChain %_ptr_Uniform__struct_3 %2 %int_0 %int_0
863                OpBranch %18
864          %18 = OpLabel
865          %20 = OpPhi %_ptr_Function__struct_9 %17 %16 %21 %22
866          %23 = OpUndef %bool
867                OpLoopMerge %24 %22 None
868                OpBranchConditional %23 %22 %24
869          %22 = OpLabel
870          %21 = OpPtrAccessChain %_ptr_Function__struct_9 %20 %int_1
871                OpBranch %18
872          %24 = OpLabel
873                OpReturn
874                OpFunctionEnd
875 )";
876 
877   SinglePassRunAndMatch<FixStorageClass>(text, false);
878 }
879 
880 }  // namespace
881 }  // namespace opt
882 }  // namespace spvtools
883