1 // Copyright (c) 2017 Google Inc.
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 "source/opt/value_number_table.h"
19 #include "test/opt/assembly_builder.h"
20 #include "test/opt/pass_fixture.h"
21 #include "test/opt/pass_utils.h"
22
23 namespace spvtools {
24 namespace opt {
25 namespace {
26
27 using ::testing::HasSubstr;
28 using ::testing::MatchesRegex;
29 using PrivateToLocalTest = PassTest<::testing::Test>;
30
TEST_F(PrivateToLocalTest,ChangeToLocal)31 TEST_F(PrivateToLocalTest, ChangeToLocal) {
32 // Change the private variable to a local, and change the types accordingly.
33 const std::string text = R"(
34 OpCapability Shader
35 %1 = OpExtInstImport "GLSL.std.450"
36 OpMemoryModel Logical GLSL450
37 OpEntryPoint Fragment %2 "main"
38 OpExecutionMode %2 OriginUpperLeft
39 OpSource GLSL 430
40 %3 = OpTypeVoid
41 %4 = OpTypeFunction %3
42 ; CHECK: [[float:%[a-zA-Z_\d]+]] = OpTypeFloat 32
43 %5 = OpTypeFloat 32
44 ; CHECK: [[newtype:%[a-zA-Z_\d]+]] = OpTypePointer Function [[float]]
45 %6 = OpTypePointer Private %5
46 ; CHECK-NOT: OpVariable [[.+]] Private
47 %8 = OpVariable %6 Private
48 ; CHECK: OpFunction
49 %2 = OpFunction %3 None %4
50 ; CHECK: OpLabel
51 %7 = OpLabel
52 ; CHECK-NEXT: [[newvar:%[a-zA-Z_\d]+]] = OpVariable [[newtype]] Function
53 ; CHECK: OpLoad [[float]] [[newvar]]
54 %9 = OpLoad %5 %8
55 OpReturn
56 OpFunctionEnd
57 )";
58 SinglePassRunAndMatch<PrivateToLocalPass>(text, false);
59 }
60
TEST_F(PrivateToLocalTest,ReuseExistingType)61 TEST_F(PrivateToLocalTest, ReuseExistingType) {
62 // Change the private variable to a local, and change the types accordingly.
63 const std::string text = R"(
64 OpCapability Shader
65 %1 = OpExtInstImport "GLSL.std.450"
66 OpMemoryModel Logical GLSL450
67 OpEntryPoint Fragment %2 "main"
68 OpExecutionMode %2 OriginUpperLeft
69 OpSource GLSL 430
70 %3 = OpTypeVoid
71 %4 = OpTypeFunction %3
72 ; CHECK: [[float:%[a-zA-Z_\d]+]] = OpTypeFloat 32
73 %5 = OpTypeFloat 32
74 %func_ptr = OpTypePointer Function %5
75 ; CHECK: [[newtype:%[a-zA-Z_\d]+]] = OpTypePointer Function [[float]]
76 ; CHECK-NOT: [[%[a-zA-Z_\d]+]] = OpTypePointer Function [[float]]
77 %6 = OpTypePointer Private %5
78 ; CHECK-NOT: OpVariable [[.+]] Private
79 %8 = OpVariable %6 Private
80 ; CHECK: OpFunction
81 %2 = OpFunction %3 None %4
82 ; CHECK: OpLabel
83 %7 = OpLabel
84 ; CHECK-NEXT: [[newvar:%[a-zA-Z_\d]+]] = OpVariable [[newtype]] Function
85 ; CHECK: OpLoad [[float]] [[newvar]]
86 %9 = OpLoad %5 %8
87 OpReturn
88 OpFunctionEnd
89 )";
90 SinglePassRunAndMatch<PrivateToLocalPass>(text, false);
91 }
92
TEST_F(PrivateToLocalTest,UpdateAccessChain)93 TEST_F(PrivateToLocalTest, UpdateAccessChain) {
94 // Change the private variable to a local, and change the AccessChain.
95 const std::string text = R"(
96 OpCapability Shader
97 %1 = OpExtInstImport "GLSL.std.450"
98 OpMemoryModel Logical GLSL450
99 OpEntryPoint Fragment %2 "main"
100 OpExecutionMode %2 OriginUpperLeft
101 OpSource GLSL 430
102 %uint = OpTypeInt 32 0
103 %uint_0 = OpConstant %uint 0
104 %void = OpTypeVoid
105 %6 = OpTypeFunction %void
106 ; CHECK: [[float:%[a-zA-Z_\d]+]] = OpTypeFloat
107 %float = OpTypeFloat 32
108 ; CHECK: [[struct:%[a-zA-Z_\d]+]] = OpTypeStruct
109 %_struct_8 = OpTypeStruct %float
110 %_ptr_Private_float = OpTypePointer Private %float
111 ; CHECK: [[new_struct_type:%[a-zA-Z_\d]+]] = OpTypePointer Function [[struct]]
112 ; CHECK: [[new_float_type:%[a-zA-Z_\d]+]] = OpTypePointer Function [[float]]
113 %_ptr_Private__struct_8 = OpTypePointer Private %_struct_8
114 ; CHECK-NOT: OpVariable [[.+]] Private
115 %11 = OpVariable %_ptr_Private__struct_8 Private
116 ; CHECK: OpFunction
117 %2 = OpFunction %void None %6
118 ; CHECK: OpLabel
119 %12 = OpLabel
120 ; CHECK-NEXT: [[newvar:%[a-zA-Z_\d]+]] = OpVariable [[new_struct_type]] Function
121 ; CHECK: [[member:%[a-zA-Z_\d]+]] = OpAccessChain [[new_float_type]] [[newvar]]
122 %13 = OpAccessChain %_ptr_Private_float %11 %uint_0
123 ; CHECK: OpLoad [[float]] [[member]]
124 %14 = OpLoad %float %13
125 OpReturn
126 OpFunctionEnd
127 )";
128 SinglePassRunAndMatch<PrivateToLocalPass>(text, false);
129 }
130
TEST_F(PrivateToLocalTest,UseTexelPointer)131 TEST_F(PrivateToLocalTest, UseTexelPointer) {
132 // Change the private variable to a local, and change the OpImageTexelPointer.
133 const std::string text = R"(
134 OpCapability SampledBuffer
135 OpCapability StorageImageExtendedFormats
136 OpCapability ImageBuffer
137 OpCapability Shader
138 %1 = OpExtInstImport "GLSL.std.450"
139 OpMemoryModel Logical GLSL450
140 OpEntryPoint GLCompute %2 "min" %gl_GlobalInvocationID
141 OpExecutionMode %2 LocalSize 64 1 1
142 OpSource HLSL 600
143 OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId
144 OpDecorate %4 DescriptorSet 4
145 OpDecorate %4 Binding 70
146 %uint = OpTypeInt 32 0
147 %6 = OpTypeImage %uint Buffer 0 0 0 2 R32ui
148 %_ptr_UniformConstant_6 = OpTypePointer UniformConstant %6
149 %_ptr_Private_6 = OpTypePointer Private %6
150 %void = OpTypeVoid
151 %10 = OpTypeFunction %void
152 %uint_0 = OpConstant %uint 0
153 %uint_1 = OpConstant %uint 1
154 %v3uint = OpTypeVector %uint 3
155 %_ptr_Input_v3uint = OpTypePointer Input %v3uint
156 %_ptr_Image_uint = OpTypePointer Image %uint
157 %4 = OpVariable %_ptr_UniformConstant_6 UniformConstant
158 %16 = OpVariable %_ptr_Private_6 Private
159 %gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input
160 %2 = OpFunction %void None %10
161 %17 = OpLabel
162 ; Make sure the variable was moved.
163 ; CHECK: OpFunction
164 ; CHECK-NEXT: OpLabel
165 ; CHECK-NEXT: OpVariable %_ptr_Function_6 Function
166 %18 = OpLoad %6 %4
167 OpStore %16 %18
168 %19 = OpImageTexelPointer %_ptr_Image_uint %16 %uint_0 %uint_0
169 %20 = OpAtomicIAdd %uint %19 %uint_1 %uint_0 %uint_1
170 OpReturn
171 OpFunctionEnd
172 )";
173 SinglePassRunAndMatch<PrivateToLocalPass>(text, false);
174 }
175
TEST_F(PrivateToLocalTest,UsedInTwoFunctions)176 TEST_F(PrivateToLocalTest, UsedInTwoFunctions) {
177 // Should not change because it is used in multiple functions.
178 const std::string text = R"(
179 OpCapability Shader
180 %1 = OpExtInstImport "GLSL.std.450"
181 OpMemoryModel Logical GLSL450
182 OpEntryPoint Fragment %2 "main"
183 OpExecutionMode %2 OriginUpperLeft
184 OpSource GLSL 430
185 %3 = OpTypeVoid
186 %4 = OpTypeFunction %3
187 %5 = OpTypeFloat 32
188 %6 = OpTypePointer Private %5
189 %8 = OpVariable %6 Private
190 %2 = OpFunction %3 None %4
191 %7 = OpLabel
192 %9 = OpLoad %5 %8
193 OpReturn
194 OpFunctionEnd
195 %10 = OpFunction %3 None %4
196 %11 = OpLabel
197 %12 = OpLoad %5 %8
198 OpReturn
199 OpFunctionEnd
200 )";
201 auto result = SinglePassRunAndDisassemble<StrengthReductionPass>(
202 text, /* skip_nop = */ true, /* do_validation = */ false);
203 EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
204 }
205
TEST_F(PrivateToLocalTest,UsedInFunctionCall)206 TEST_F(PrivateToLocalTest, UsedInFunctionCall) {
207 // Should not change because it is used in a function call. Changing the
208 // signature of the function would require cloning the function, which is not
209 // worth it.
210 const std::string text = R"(
211 OpCapability Shader
212 %1 = OpExtInstImport "GLSL.std.450"
213 OpMemoryModel Logical GLSL450
214 OpEntryPoint Fragment %2 "main"
215 OpExecutionMode %2 OriginUpperLeft
216 OpSource GLSL 430
217 %void = OpTypeVoid
218 %4 = OpTypeFunction %void
219 %float = OpTypeFloat 32
220 %_ptr_Private_float = OpTypePointer Private %float
221 %7 = OpTypeFunction %void %_ptr_Private_float
222 %8 = OpVariable %_ptr_Private_float Private
223 %2 = OpFunction %void None %4
224 %9 = OpLabel
225 %10 = OpFunctionCall %void %11 %8
226 OpReturn
227 OpFunctionEnd
228 %11 = OpFunction %void None %7
229 %12 = OpFunctionParameter %_ptr_Private_float
230 %13 = OpLabel
231 %14 = OpLoad %float %12
232 OpReturn
233 OpFunctionEnd
234 )";
235 auto result = SinglePassRunAndDisassemble<StrengthReductionPass>(
236 text, /* skip_nop = */ true, /* do_validation = */ false);
237 EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
238 }
239
TEST_F(PrivateToLocalTest,CreatePointerToAmbiguousStruct1)240 TEST_F(PrivateToLocalTest, CreatePointerToAmbiguousStruct1) {
241 // Test that the correct pointer type is picked up.
242 const std::string text = R"(
243 ; CHECK: [[struct1:%[a-zA-Z_\d]+]] = OpTypeStruct
244 ; CHECK: [[struct2:%[a-zA-Z_\d]+]] = OpTypeStruct
245 ; CHECK: [[priv_ptr:%[\w]+]] = OpTypePointer Private [[struct1]]
246 ; CHECK: [[fuct_ptr2:%[\w]+]] = OpTypePointer Function [[struct2]]
247 ; CHECK: [[fuct_ptr1:%[\w]+]] = OpTypePointer Function [[struct1]]
248 ; CHECK: OpFunction
249 ; CHECK: OpLabel
250 ; CHECK-NEXT: [[newvar:%[a-zA-Z_\d]+]] = OpVariable [[fuct_ptr1]] Function
251 ; CHECK: OpLoad [[struct1]] [[newvar]]
252 OpCapability Shader
253 %1 = OpExtInstImport "GLSL.std.450"
254 OpMemoryModel Logical GLSL450
255 OpEntryPoint Fragment %2 "main"
256 OpExecutionMode %2 OriginUpperLeft
257 OpSource GLSL 430
258 %3 = OpTypeVoid
259 %4 = OpTypeFunction %3
260 %5 = OpTypeFloat 32
261 %struct1 = OpTypeStruct %5
262 %struct2 = OpTypeStruct %5
263 %6 = OpTypePointer Private %struct1
264 %func_ptr2 = OpTypePointer Function %struct2
265 %8 = OpVariable %6 Private
266 %2 = OpFunction %3 None %4
267 %7 = OpLabel
268 %9 = OpLoad %struct1 %8
269 OpReturn
270 OpFunctionEnd
271 )";
272 SinglePassRunAndMatch<PrivateToLocalPass>(text, false);
273 }
274
TEST_F(PrivateToLocalTest,CreatePointerToAmbiguousStruct2)275 TEST_F(PrivateToLocalTest, CreatePointerToAmbiguousStruct2) {
276 // Test that the correct pointer type is picked up.
277 const std::string text = R"(
278 ; CHECK: [[struct1:%[a-zA-Z_\d]+]] = OpTypeStruct
279 ; CHECK: [[struct2:%[a-zA-Z_\d]+]] = OpTypeStruct
280 ; CHECK: [[priv_ptr:%[\w]+]] = OpTypePointer Private [[struct2]]
281 ; CHECK: [[fuct_ptr1:%[\w]+]] = OpTypePointer Function [[struct1]]
282 ; CHECK: [[fuct_ptr2:%[\w]+]] = OpTypePointer Function [[struct2]]
283 ; CHECK: OpFunction
284 ; CHECK: OpLabel
285 ; CHECK-NEXT: [[newvar:%[a-zA-Z_\d]+]] = OpVariable [[fuct_ptr2]] Function
286 ; CHECK: OpLoad [[struct2]] [[newvar]]
287 OpCapability Shader
288 %1 = OpExtInstImport "GLSL.std.450"
289 OpMemoryModel Logical GLSL450
290 OpEntryPoint Fragment %2 "main"
291 OpExecutionMode %2 OriginUpperLeft
292 OpSource GLSL 430
293 %3 = OpTypeVoid
294 %4 = OpTypeFunction %3
295 %5 = OpTypeFloat 32
296 %struct1 = OpTypeStruct %5
297 %struct2 = OpTypeStruct %5
298 %6 = OpTypePointer Private %struct2
299 %func_ptr2 = OpTypePointer Function %struct1
300 %8 = OpVariable %6 Private
301 %2 = OpFunction %3 None %4
302 %7 = OpLabel
303 %9 = OpLoad %struct2 %8
304 OpReturn
305 OpFunctionEnd
306 )";
307 SinglePassRunAndMatch<PrivateToLocalPass>(text, false);
308 }
309
TEST_F(PrivateToLocalTest,SPV14RemoveFromInterface)310 TEST_F(PrivateToLocalTest, SPV14RemoveFromInterface) {
311 const std::string text = R"(
312 ; CHECK-NOT: OpEntryPoint GLCompute %foo "foo" %in %priv
313 ; CHECK: OpEntryPoint GLCompute %foo "foo" %in
314 ; CHECK: %priv = OpVariable {{%\w+}} Function
315 OpCapability Shader
316 OpMemoryModel Logical GLSL450
317 OpEntryPoint GLCompute %foo "foo" %in %priv
318 OpExecutionMode %foo LocalSize 1 1 1
319 OpName %foo "foo"
320 OpName %in "in"
321 OpName %priv "priv"
322 %void = OpTypeVoid
323 %int = OpTypeInt 32 0
324 %ptr_ssbo_int = OpTypePointer StorageBuffer %int
325 %ptr_private_int = OpTypePointer Private %int
326 %in = OpVariable %ptr_ssbo_int StorageBuffer
327 %priv = OpVariable %ptr_private_int Private
328 %void_fn = OpTypeFunction %void
329 %foo = OpFunction %void None %void_fn
330 %entry = OpLabel
331 %ld = OpLoad %int %in
332 OpStore %priv %ld
333 OpReturn
334 OpFunctionEnd
335 )";
336
337 SetTargetEnv(SPV_ENV_UNIVERSAL_1_4);
338 SinglePassRunAndMatch<PrivateToLocalPass>(text, true);
339 }
340
TEST_F(PrivateToLocalTest,SPV14RemoveFromInterfaceMultipleEntryPoints)341 TEST_F(PrivateToLocalTest, SPV14RemoveFromInterfaceMultipleEntryPoints) {
342 const std::string text = R"(
343 ; CHECK-NOT: OpEntryPoint GLCompute %foo "foo" %in %priv
344 ; CHECK-NOT: OpEntryPoint GLCompute %foo "bar" %in %priv
345 ; CHECK: OpEntryPoint GLCompute %foo "foo" %in
346 ; CHECK: OpEntryPoint GLCompute %foo "bar" %in
347 ; CHECK: %priv = OpVariable {{%\w+}} Function
348 OpCapability Shader
349 OpMemoryModel Logical GLSL450
350 OpEntryPoint GLCompute %foo "foo" %in %priv
351 OpEntryPoint GLCompute %foo "bar" %in %priv
352 OpExecutionMode %foo LocalSize 1 1 1
353 OpName %foo "foo"
354 OpName %in "in"
355 OpName %priv "priv"
356 %void = OpTypeVoid
357 %int = OpTypeInt 32 0
358 %ptr_ssbo_int = OpTypePointer StorageBuffer %int
359 %ptr_private_int = OpTypePointer Private %int
360 %in = OpVariable %ptr_ssbo_int StorageBuffer
361 %priv = OpVariable %ptr_private_int Private
362 %void_fn = OpTypeFunction %void
363 %foo = OpFunction %void None %void_fn
364 %entry = OpLabel
365 %ld = OpLoad %int %in
366 OpStore %priv %ld
367 OpReturn
368 OpFunctionEnd
369 )";
370
371 SetTargetEnv(SPV_ENV_UNIVERSAL_1_4);
372 SinglePassRunAndMatch<PrivateToLocalPass>(text, true);
373 }
374
TEST_F(PrivateToLocalTest,SPV14RemoveFromInterfaceMultipleVariables)375 TEST_F(PrivateToLocalTest, SPV14RemoveFromInterfaceMultipleVariables) {
376 const std::string text = R"(
377 ; CHECK-NOT: OpEntryPoint GLCompute %foo "foo" %in %priv1 %priv2
378 ; CHECK: OpEntryPoint GLCompute %foo "foo" %in
379 ; CHECK: %priv1 = OpVariable {{%\w+}} Function
380 ; CHECK: %priv2 = OpVariable {{%\w+}} Function
381 OpCapability Shader
382 OpMemoryModel Logical GLSL450
383 OpEntryPoint GLCompute %foo "foo" %in %priv1 %priv2
384 OpExecutionMode %foo LocalSize 1 1 1
385 OpName %foo "foo"
386 OpName %in "in"
387 OpName %priv1 "priv1"
388 OpName %priv2 "priv2"
389 %void = OpTypeVoid
390 %int = OpTypeInt 32 0
391 %ptr_ssbo_int = OpTypePointer StorageBuffer %int
392 %ptr_private_int = OpTypePointer Private %int
393 %in = OpVariable %ptr_ssbo_int StorageBuffer
394 %priv1 = OpVariable %ptr_private_int Private
395 %priv2 = OpVariable %ptr_private_int Private
396 %void_fn = OpTypeFunction %void
397 %foo = OpFunction %void None %void_fn
398 %entry = OpLabel
399 %1 = OpFunctionCall %void %bar1
400 %2 = OpFunctionCall %void %bar2
401 OpReturn
402 OpFunctionEnd
403 %bar1 = OpFunction %void None %void_fn
404 %3 = OpLabel
405 %ld1 = OpLoad %int %in
406 OpStore %priv1 %ld1
407 OpReturn
408 OpFunctionEnd
409 %bar2 = OpFunction %void None %void_fn
410 %4 = OpLabel
411 %ld2 = OpLoad %int %in
412 OpStore %priv2 %ld2
413 OpReturn
414 OpFunctionEnd
415 )";
416
417 SetTargetEnv(SPV_ENV_UNIVERSAL_1_4);
418 SinglePassRunAndMatch<PrivateToLocalPass>(text, true);
419 }
420
TEST_F(PrivateToLocalTest,IdBoundOverflow1)421 TEST_F(PrivateToLocalTest, IdBoundOverflow1) {
422 const std::string text = R"(
423 OpCapability Shader
424 OpMemoryModel Logical GLSL450
425 OpEntryPoint Fragment %4 "main"
426 OpExecutionMode %4 OriginLowerLeft
427 OpSource HLSL 84
428 %2 = OpTypeVoid
429 %3 = OpTypeFunction %2
430 %6 = OpTypeFloat 32
431 %7 = OpTypeVector %6 4
432 %8 = OpTypeStruct %7
433 %4194302 = OpTypeStruct %8 %8
434 %9 = OpTypeStruct %8 %8
435 %11 = OpTypePointer Private %7
436 %18 = OpTypeStruct %6 %9
437 %12 = OpVariable %11 Private
438 %4 = OpFunction %2 None %3
439 %5 = OpLabel
440 %13 = OpLoad %7 %12
441 OpReturn
442 OpFunctionEnd
443 )";
444
445 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
446
447 std::vector<Message> messages = {
448 {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."}};
449 SetMessageConsumer(GetTestMessageConsumer(messages));
450 auto result = SinglePassRunToBinary<PrivateToLocalPass>(text, true);
451 EXPECT_EQ(Pass::Status::Failure, std::get<1>(result));
452 }
453
TEST_F(PrivateToLocalTest,DebugPrivateToLocal)454 TEST_F(PrivateToLocalTest, DebugPrivateToLocal) {
455 // Debug instructions must not have any impact on changing the private
456 // variable to a local.
457 const std::string text = R"(
458 OpCapability Shader
459 %1 = OpExtInstImport "GLSL.std.450"
460 %10 = OpExtInstImport "OpenCL.DebugInfo.100"
461 OpMemoryModel Logical GLSL450
462 OpEntryPoint Fragment %2 "main"
463 OpExecutionMode %2 OriginUpperLeft
464 %11 = OpString "test"
465 OpSource GLSL 430
466 %13 = OpTypeInt 32 0
467 %14 = OpConstant %13 32
468 %3 = OpTypeVoid
469 %4 = OpTypeFunction %3
470 ; CHECK: [[float:%[a-zA-Z_\d]+]] = OpTypeFloat 32
471 %5 = OpTypeFloat 32
472 ; CHECK: [[newtype:%[a-zA-Z_\d]+]] = OpTypePointer Function [[float]]
473 %6 = OpTypePointer Private %5
474 ; CHECK-NOT: OpVariable [[.+]] Private
475 %8 = OpVariable %6 Private
476
477 %12 = OpExtInst %3 %10 DebugTypeBasic %11 %14 Float
478 %15 = OpExtInst %3 %10 DebugSource %11
479 %16 = OpExtInst %3 %10 DebugCompilationUnit 1 4 %15 GLSL
480 ; CHECK-NOT: DebugGlobalVariable
481 ; CHECK: [[dbg_newvar:%[a-zA-Z_\d]+]] = OpExtInst {{%\w+}} {{%\w+}} DebugLocalVariable
482 %17 = OpExtInst %3 %10 DebugGlobalVariable %11 %12 %15 0 0 %16 %11 %8 FlagIsDefinition
483
484 ; CHECK: OpFunction
485 %2 = OpFunction %3 None %4
486 ; CHECK: OpLabel
487 %7 = OpLabel
488 ; CHECK-NEXT: [[newvar:%[a-zA-Z_\d]+]] = OpVariable [[newtype]] Function
489 ; CHECK-NEXT: DebugDeclare [[dbg_newvar]] [[newvar]]
490 ; CHECK: OpLoad [[float]] [[newvar]]
491 %9 = OpLoad %5 %8
492 OpReturn
493 OpFunctionEnd
494 )";
495 SinglePassRunAndMatch<PrivateToLocalPass>(text, true);
496 }
497
498 } // namespace
499 } // namespace opt
500 } // namespace spvtools
501