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