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 "source/opt/scalar_replacement_pass.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 ScalarReplacementPassName = ::testing::Test;
27
TEST_F(ScalarReplacementPassName,Default)28 TEST_F(ScalarReplacementPassName, Default) {
29 auto srp = ScalarReplacementPass();
30 EXPECT_STREQ(srp.name(), "scalar-replacement=100");
31 }
32
TEST_F(ScalarReplacementPassName,Large)33 TEST_F(ScalarReplacementPassName, Large) {
34 auto srp = ScalarReplacementPass(0xffffffffu);
35 EXPECT_STREQ(srp.name(), "scalar-replacement=4294967295");
36 }
37
38 using ScalarReplacementTest = PassTest<::testing::Test>;
39
TEST_F(ScalarReplacementTest,SimpleStruct)40 TEST_F(ScalarReplacementTest, SimpleStruct) {
41 const std::string text = R"(
42 ;
43 ; CHECK: [[struct:%\w+]] = OpTypeStruct [[elem:%\w+]]
44 ; CHECK: [[struct_ptr:%\w+]] = OpTypePointer Function [[struct]]
45 ; CHECK: [[elem_ptr:%\w+]] = OpTypePointer Function [[elem]]
46 ; CHECK: OpConstantNull [[struct]]
47 ; CHECK: [[null:%\w+]] = OpConstantNull [[elem]]
48 ; CHECK-NOT: OpVariable [[struct_ptr]]
49 ; CHECK: [[one:%\w+]] = OpVariable [[elem_ptr]] Function [[null]]
50 ; CHECK-NEXT: [[two:%\w+]] = OpVariable [[elem_ptr]] Function [[null]]
51 ; CHECK-NOT: OpVariable [[elem_ptr]] Function [[null]]
52 ; CHECK-NOT: OpVariable [[struct_ptr]]
53 ; CHECK-NOT: OpInBoundsAccessChain
54 ; CHECK: [[l1:%\w+]] = OpLoad [[elem]] [[two]]
55 ; CHECK-NOT: OpAccessChain
56 ; CHECK: [[l2:%\w+]] = OpLoad [[elem]] [[one]]
57 ; CHECK: OpIAdd [[elem]] [[l1]] [[l2]]
58 ;
59 OpCapability Shader
60 OpCapability Linkage
61 OpMemoryModel Logical GLSL450
62 OpName %6 "simple_struct"
63 %1 = OpTypeVoid
64 %2 = OpTypeInt 32 0
65 %3 = OpTypeStruct %2 %2 %2 %2
66 %4 = OpTypePointer Function %3
67 %5 = OpTypePointer Function %2
68 %6 = OpTypeFunction %2
69 %7 = OpConstantNull %3
70 %8 = OpConstant %2 0
71 %9 = OpConstant %2 1
72 %10 = OpConstant %2 2
73 %11 = OpConstant %2 3
74 %12 = OpFunction %2 None %6
75 %13 = OpLabel
76 %14 = OpVariable %4 Function %7
77 %15 = OpInBoundsAccessChain %5 %14 %8
78 %16 = OpLoad %2 %15
79 %17 = OpAccessChain %5 %14 %10
80 %18 = OpLoad %2 %17
81 %19 = OpIAdd %2 %16 %18
82 OpReturnValue %19
83 OpFunctionEnd
84 )";
85
86 SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
87 }
88
TEST_F(ScalarReplacementTest,StructInitialization)89 TEST_F(ScalarReplacementTest, StructInitialization) {
90 const std::string text = R"(
91 ;
92 ; CHECK: [[elem:%\w+]] = OpTypeInt 32 0
93 ; CHECK: [[struct:%\w+]] = OpTypeStruct [[elem]] [[elem]] [[elem]] [[elem]]
94 ; CHECK: [[struct_ptr:%\w+]] = OpTypePointer Function [[struct]]
95 ; CHECK: [[elem_ptr:%\w+]] = OpTypePointer Function [[elem]]
96 ; CHECK: [[zero:%\w+]] = OpConstant [[elem]] 0
97 ; CHECK: [[undef:%\w+]] = OpUndef [[elem]]
98 ; CHECK: [[two:%\w+]] = OpConstant [[elem]] 2
99 ; CHECK: [[null:%\w+]] = OpConstantNull [[elem]]
100 ; CHECK-NOT: OpVariable [[struct_ptr]]
101 ; CHECK: OpVariable [[elem_ptr]] Function [[null]]
102 ; CHECK-NEXT: OpVariable [[elem_ptr]] Function [[two]]
103 ; CHECK-NOT: OpVariable [[elem_ptr]] Function [[undef]]
104 ; CHECK-NEXT: OpVariable [[elem_ptr]] Function
105 ; CHECK-NEXT: OpVariable [[elem_ptr]] Function [[zero]]
106 ; CHECK-NOT: OpVariable [[elem_ptr]] Function [[undef]]
107 ;
108 OpCapability Shader
109 OpCapability Linkage
110 OpMemoryModel Logical GLSL450
111 OpName %6 "struct_init"
112 %1 = OpTypeVoid
113 %2 = OpTypeInt 32 0
114 %3 = OpTypeStruct %2 %2 %2 %2
115 %4 = OpTypePointer Function %3
116 %20 = OpTypePointer Function %2
117 %6 = OpTypeFunction %1
118 %7 = OpConstant %2 0
119 %8 = OpUndef %2
120 %9 = OpConstant %2 2
121 %30 = OpConstant %2 1
122 %31 = OpConstant %2 3
123 %10 = OpConstantNull %2
124 %11 = OpConstantComposite %3 %7 %8 %9 %10
125 %12 = OpFunction %1 None %6
126 %13 = OpLabel
127 %14 = OpVariable %4 Function %11
128 %15 = OpAccessChain %20 %14 %7
129 OpStore %15 %10
130 %16 = OpAccessChain %20 %14 %9
131 OpStore %16 %10
132 %17 = OpAccessChain %20 %14 %30
133 OpStore %17 %10
134 %18 = OpAccessChain %20 %14 %31
135 OpStore %18 %10
136 OpReturn
137 OpFunctionEnd
138 )";
139
140 SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
141 }
142
TEST_F(ScalarReplacementTest,SpecConstantInitialization)143 TEST_F(ScalarReplacementTest, SpecConstantInitialization) {
144 const std::string text = R"(
145 ;
146 ; CHECK: [[int:%\w+]] = OpTypeInt 32 0
147 ; CHECK: [[struct:%\w+]] = OpTypeStruct [[int]] [[int]]
148 ; CHECK: [[struct_ptr:%\w+]] = OpTypePointer Function [[struct]]
149 ; CHECK: [[int_ptr:%\w+]] = OpTypePointer Function [[int]]
150 ; CHECK: [[spec_comp:%\w+]] = OpSpecConstantComposite [[struct]]
151 ; CHECK: [[ex0:%\w+]] = OpSpecConstantOp [[int]] CompositeExtract [[spec_comp]] 0
152 ; CHECK: [[ex1:%\w+]] = OpSpecConstantOp [[int]] CompositeExtract [[spec_comp]] 1
153 ; CHECK-NOT: OpVariable [[struct]]
154 ; CHECK: OpVariable [[int_ptr]] Function [[ex1]]
155 ; CHECK-NEXT: OpVariable [[int_ptr]] Function [[ex0]]
156 ; CHECK-NOT: OpVariable [[struct]]
157 ;
158 OpCapability Shader
159 OpCapability Linkage
160 OpMemoryModel Logical GLSL450
161 OpName %6 "spec_const"
162 %1 = OpTypeVoid
163 %2 = OpTypeInt 32 0
164 %3 = OpTypeStruct %2 %2
165 %4 = OpTypePointer Function %3
166 %20 = OpTypePointer Function %2
167 %5 = OpTypeFunction %1
168 %6 = OpConstant %2 0
169 %30 = OpConstant %2 1
170 %7 = OpSpecConstant %2 0
171 %8 = OpSpecConstantOp %2 IAdd %7 %7
172 %9 = OpSpecConstantComposite %3 %7 %8
173 %10 = OpFunction %1 None %5
174 %11 = OpLabel
175 %12 = OpVariable %4 Function %9
176 %13 = OpAccessChain %20 %12 %6
177 %14 = OpLoad %2 %13
178 %15 = OpAccessChain %20 %12 %30
179 %16 = OpLoad %2 %15
180 OpReturn
181 OpFunctionEnd
182 )";
183
184 SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
185 }
186
187 // TODO(alanbaker): Re-enable when vector and matrix scalarization is supported.
188 // TEST_F(ScalarReplacementTest, VectorInitialization) {
189 // const std::string text = R"(
190 // ;
191 // ; CHECK: [[elem:%\w+]] = OpTypeInt 32 0
192 // ; CHECK: [[vector:%\w+]] = OpTypeVector [[elem]] 4
193 // ; CHECK: [[vector_ptr:%\w+]] = OpTypePointer Function [[vector]]
194 // ; CHECK: [[elem_ptr:%\w+]] = OpTypePointer Function [[elem]]
195 // ; CHECK: [[zero:%\w+]] = OpConstant [[elem]] 0
196 // ; CHECK: [[undef:%\w+]] = OpUndef [[elem]]
197 // ; CHECK: [[two:%\w+]] = OpConstant [[elem]] 2
198 // ; CHECK: [[null:%\w+]] = OpConstantNull [[elem]]
199 // ; CHECK-NOT: OpVariable [[vector_ptr]]
200 // ; CHECK: OpVariable [[elem_ptr]] Function [[zero]]
201 // ; CHECK-NOT: OpVariable [[elem_ptr]] Function [[undef]]
202 // ; CHECK-NEXT: OpVariable [[elem_ptr]] Function
203 // ; CHECK-NEXT: OpVariable [[elem_ptr]] Function [[two]]
204 // ; CHECK-NEXT: OpVariable [[elem_ptr]] Function [[null]]
205 // ; CHECK-NOT: OpVariable [[elem_ptr]] Function [[undef]]
206 // ;
207 // OpCapability Shader
208 // OpCapability Linkage
209 // OpMemoryModel Logical GLSL450
210 // OpName %6 "vector_init"
211 // %1 = OpTypeVoid
212 // %2 = OpTypeInt 32 0
213 // %3 = OpTypeVector %2 4
214 // %4 = OpTypePointer Function %3
215 // %20 = OpTypePointer Function %2
216 // %6 = OpTypeFunction %1
217 // %7 = OpConstant %2 0
218 // %8 = OpUndef %2
219 // %9 = OpConstant %2 2
220 // %30 = OpConstant %2 1
221 // %31 = OpConstant %2 3
222 // %10 = OpConstantNull %2
223 // %11 = OpConstantComposite %3 %10 %9 %8 %7
224 // %12 = OpFunction %1 None %6
225 // %13 = OpLabel
226 // %14 = OpVariable %4 Function %11
227 // %15 = OpAccessChain %20 %14 %7
228 // OpStore %15 %10
229 // %16 = OpAccessChain %20 %14 %9
230 // OpStore %16 %10
231 // %17 = OpAccessChain %20 %14 %30
232 // OpStore %17 %10
233 // %18 = OpAccessChain %20 %14 %31
234 // OpStore %18 %10
235 // OpReturn
236 // OpFunctionEnd
237 // )";
238 //
239 // SinglePassRunAndMatch<opt::ScalarReplacementPass>(text, true);
240 // }
241 //
242 // TEST_F(ScalarReplacementTest, MatrixInitialization) {
243 // const std::string text = R"(
244 // ;
245 // ; CHECK: [[float:%\w+]] = OpTypeFloat 32
246 // ; CHECK: [[vector:%\w+]] = OpTypeVector [[float]] 2
247 // ; CHECK: [[matrix:%\w+]] = OpTypeMatrix [[vector]] 2
248 // ; CHECK: [[matrix_ptr:%\w+]] = OpTypePointer Function [[matrix]]
249 // ; CHECK: [[float_ptr:%\w+]] = OpTypePointer Function [[float]]
250 // ; CHECK: [[vec_ptr:%\w+]] = OpTypePointer Function [[vector]]
251 // ; CHECK: [[zerof:%\w+]] = OpConstant [[float]] 0
252 // ; CHECK: [[onef:%\w+]] = OpConstant [[float]] 1
253 // ; CHECK: [[one_zero:%\w+]] = OpConstantComposite [[vector]] [[onef]]
254 // [[zerof]] ; CHECK: [[zero_one:%\w+]] = OpConstantComposite [[vector]]
255 // [[zerof]] [[onef]] ; CHECK: [[const_mat:%\w+]] = OpConstantComposite
256 // [[matrix]] [[one_zero]]
257 // [[zero_one]] ; CHECK-NOT: OpVariable [[matrix]] ; CHECK-NOT: OpVariable
258 // [[vector]] Function [[one_zero]] ; CHECK: [[f1:%\w+]] = OpVariable
259 // [[float_ptr]] Function [[zerof]] ; CHECK-NEXT: [[f2:%\w+]] = OpVariable
260 // [[float_ptr]] Function [[onef]] ; CHECK-NEXT: [[vec_var:%\w+]] = OpVariable
261 // [[vec_ptr]] Function [[zero_one]] ; CHECK-NOT: OpVariable [[matrix]] ;
262 // CHECK-NOT: OpVariable [[vector]] Function [[one_zero]]
263 // ;
264 // OpCapability Shader
265 // OpCapability Linkage
266 // OpMemoryModel Logical GLSL450
267 // OpName %7 "matrix_init"
268 // %1 = OpTypeVoid
269 // %2 = OpTypeFloat 32
270 // %3 = OpTypeVector %2 2
271 // %4 = OpTypeMatrix %3 2
272 // %5 = OpTypePointer Function %4
273 // %6 = OpTypePointer Function %2
274 // %30 = OpTypePointer Function %3
275 // %10 = OpTypeInt 32 0
276 // %7 = OpTypeFunction %1 %10
277 // %8 = OpConstant %2 0.0
278 // %9 = OpConstant %2 1.0
279 // %11 = OpConstant %10 0
280 // %12 = OpConstant %10 1
281 // %13 = OpConstantComposite %3 %9 %8
282 // %14 = OpConstantComposite %3 %8 %9
283 // %15 = OpConstantComposite %4 %13 %14
284 // %16 = OpFunction %1 None %7
285 // %31 = OpFunctionParameter %10
286 // %17 = OpLabel
287 // %18 = OpVariable %5 Function %15
288 // %19 = OpAccessChain %6 %18 %11 %12
289 // OpStore %19 %8
290 // %20 = OpAccessChain %6 %18 %11 %11
291 // OpStore %20 %8
292 // %21 = OpAccessChain %30 %18 %12
293 // OpStore %21 %14
294 // OpReturn
295 // OpFunctionEnd
296 // )";
297 //
298 // SinglePassRunAndMatch<opt::ScalarReplacementPass>(text, true);
299 // }
300
TEST_F(ScalarReplacementTest,ElideAccessChain)301 TEST_F(ScalarReplacementTest, ElideAccessChain) {
302 const std::string text = R"(
303 ;
304 ; CHECK: [[var:%\w+]] = OpVariable
305 ; CHECK-NOT: OpAccessChain
306 ; CHECK: OpStore [[var]]
307 ;
308 OpCapability Shader
309 OpCapability Linkage
310 OpMemoryModel Logical GLSL450
311 OpName %6 "elide_access_chain"
312 %1 = OpTypeVoid
313 %2 = OpTypeInt 32 0
314 %3 = OpTypeStruct %2 %2 %2 %2
315 %4 = OpTypePointer Function %3
316 %20 = OpTypePointer Function %2
317 %6 = OpTypeFunction %1
318 %7 = OpConstant %2 0
319 %8 = OpUndef %2
320 %9 = OpConstant %2 2
321 %10 = OpConstantNull %2
322 %11 = OpConstantComposite %3 %7 %8 %9 %10
323 %12 = OpFunction %1 None %6
324 %13 = OpLabel
325 %14 = OpVariable %4 Function %11
326 %15 = OpAccessChain %20 %14 %7
327 OpStore %15 %10
328 OpReturn
329 OpFunctionEnd
330 )";
331
332 SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
333 }
334
TEST_F(ScalarReplacementTest,ElideMultipleAccessChains)335 TEST_F(ScalarReplacementTest, ElideMultipleAccessChains) {
336 const std::string text = R"(
337 ;
338 ; CHECK: [[var:%\w+]] = OpVariable
339 ; CHECK-NOT: OpInBoundsAccessChain
340 ; CHECK OpStore [[var]]
341 ;
342 OpCapability Shader
343 OpCapability Linkage
344 OpMemoryModel Logical GLSL450
345 OpName %6 "elide_two_access_chains"
346 %1 = OpTypeVoid
347 %2 = OpTypeFloat 32
348 %3 = OpTypeStruct %2 %2
349 %4 = OpTypeStruct %3 %3
350 %5 = OpTypePointer Function %4
351 %6 = OpTypePointer Function %2
352 %7 = OpTypeFunction %1
353 %8 = OpConstant %2 0.0
354 %9 = OpConstant %2 1.0
355 %10 = OpTypeInt 32 0
356 %11 = OpConstant %10 0
357 %12 = OpConstant %10 1
358 %13 = OpConstantComposite %3 %9 %8
359 %14 = OpConstantComposite %3 %8 %9
360 %15 = OpConstantComposite %4 %13 %14
361 %16 = OpFunction %1 None %7
362 %17 = OpLabel
363 %18 = OpVariable %5 Function %15
364 %19 = OpInBoundsAccessChain %6 %18 %11 %12
365 OpStore %19 %8
366 OpReturn
367 OpFunctionEnd
368 )";
369
370 SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
371 }
372
TEST_F(ScalarReplacementTest,ReplaceAccessChain)373 TEST_F(ScalarReplacementTest, ReplaceAccessChain) {
374 const std::string text = R"(
375 ;
376 ; CHECK: [[param:%\w+]] = OpFunctionParameter
377 ; CHECK: [[var:%\w+]] = OpVariable
378 ; CHECK: [[access:%\w+]] = OpAccessChain {{%\w+}} [[var]] [[param]]
379 ; CHECK: OpStore [[access]]
380 ;
381 OpCapability Shader
382 OpCapability Linkage
383 OpMemoryModel Logical GLSL450
384 OpName %7 "replace_access_chain"
385 %1 = OpTypeVoid
386 %2 = OpTypeFloat 32
387 %10 = OpTypeInt 32 0
388 %uint_2 = OpConstant %10 2
389 %3 = OpTypeArray %2 %uint_2
390 %4 = OpTypeStruct %3 %3
391 %5 = OpTypePointer Function %4
392 %20 = OpTypePointer Function %3
393 %6 = OpTypePointer Function %2
394 %7 = OpTypeFunction %1 %10
395 %8 = OpConstant %2 0.0
396 %9 = OpConstant %2 1.0
397 %11 = OpConstant %10 0
398 %12 = OpConstant %10 1
399 %13 = OpConstantComposite %3 %9 %8
400 %14 = OpConstantComposite %3 %8 %9
401 %15 = OpConstantComposite %4 %13 %14
402 %16 = OpFunction %1 None %7
403 %32 = OpFunctionParameter %10
404 %17 = OpLabel
405 %18 = OpVariable %5 Function %15
406 %19 = OpAccessChain %6 %18 %11 %32
407 OpStore %19 %8
408 OpReturn
409 OpFunctionEnd
410 )";
411
412 SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
413 }
414
TEST_F(ScalarReplacementTest,ArrayInitialization)415 TEST_F(ScalarReplacementTest, ArrayInitialization) {
416 const std::string text = R"(
417 ;
418 ; CHECK: [[float:%\w+]] = OpTypeFloat 32
419 ; CHECK: [[array:%\w+]] = OpTypeArray
420 ; CHECK: [[array_ptr:%\w+]] = OpTypePointer Function [[array]]
421 ; CHECK: [[float_ptr:%\w+]] = OpTypePointer Function [[float]]
422 ; CHECK: [[float0:%\w+]] = OpConstant [[float]] 0
423 ; CHECK: [[float1:%\w+]] = OpConstant [[float]] 1
424 ; CHECK: [[float2:%\w+]] = OpConstant [[float]] 2
425 ; CHECK-NOT: OpVariable [[array_ptr]]
426 ; CHECK: [[var0:%\w+]] = OpVariable [[float_ptr]] Function [[float0]]
427 ; CHECK-NEXT: [[var1:%\w+]] = OpVariable [[float_ptr]] Function [[float1]]
428 ; CHECK-NEXT: [[var2:%\w+]] = OpVariable [[float_ptr]] Function [[float2]]
429 ; CHECK-NOT: OpVariable [[array_ptr]]
430 ;
431 OpCapability Shader
432 OpCapability Linkage
433 OpMemoryModel Logical GLSL450
434 OpName %func "array_init"
435 %void = OpTypeVoid
436 %uint = OpTypeInt 32 0
437 %float = OpTypeFloat 32
438 %uint_0 = OpConstant %uint 0
439 %uint_1 = OpConstant %uint 1
440 %uint_2 = OpConstant %uint 2
441 %uint_3 = OpConstant %uint 3
442 %float_array = OpTypeArray %float %uint_3
443 %array_ptr = OpTypePointer Function %float_array
444 %float_ptr = OpTypePointer Function %float
445 %float_0 = OpConstant %float 0
446 %float_1 = OpConstant %float 1
447 %float_2 = OpConstant %float 2
448 %const_array = OpConstantComposite %float_array %float_2 %float_1 %float_0
449 %func = OpTypeFunction %void
450 %1 = OpFunction %void None %func
451 %2 = OpLabel
452 %3 = OpVariable %array_ptr Function %const_array
453 %4 = OpInBoundsAccessChain %float_ptr %3 %uint_0
454 OpStore %4 %float_0
455 %5 = OpInBoundsAccessChain %float_ptr %3 %uint_1
456 OpStore %5 %float_0
457 %6 = OpInBoundsAccessChain %float_ptr %3 %uint_2
458 OpStore %6 %float_0
459 OpReturn
460 OpFunctionEnd
461 )";
462
463 SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
464 }
465
TEST_F(ScalarReplacementTest,NonUniformCompositeInitialization)466 TEST_F(ScalarReplacementTest, NonUniformCompositeInitialization) {
467 const std::string text = R"(
468 ;
469 ; CHECK: [[uint:%\w+]] = OpTypeInt 32 0
470 ; CHECK: [[long:%\w+]] = OpTypeInt 64 1
471 ; CHECK: [[dvector:%\w+]] = OpTypeVector
472 ; CHECK: [[vector:%\w+]] = OpTypeVector
473 ; CHECK: [[array:%\w+]] = OpTypeArray
474 ; CHECK: [[matrix:%\w+]] = OpTypeMatrix
475 ; CHECK: [[struct1:%\w+]] = OpTypeStruct [[uint]] [[vector]]
476 ; CHECK: [[struct2:%\w+]] = OpTypeStruct [[struct1]] [[matrix]] [[array]] [[uint]]
477 ; CHECK: [[struct1_ptr:%\w+]] = OpTypePointer Function [[struct1]]
478 ; CHECK: [[matrix_ptr:%\w+]] = OpTypePointer Function [[matrix]]
479 ; CHECK: [[array_ptr:%\w+]] = OpTypePointer Function [[array]]
480 ; CHECK: [[uint_ptr:%\w+]] = OpTypePointer Function [[uint]]
481 ; CHECK: [[struct2_ptr:%\w+]] = OpTypePointer Function [[struct2]]
482 ; CHECK: [[const_array:%\w+]] = OpConstantComposite [[array]]
483 ; CHECK: [[const_matrix:%\w+]] = OpConstantNull [[matrix]]
484 ; CHECK: [[const_struct1:%\w+]] = OpConstantComposite [[struct1]]
485 ; CHECK: OpUndef [[uint]]
486 ; CHECK: OpUndef [[vector]]
487 ; CHECK: OpUndef [[long]]
488 ; CHECK: OpFunction
489 ; CHECK-NOT: OpVariable [[struct2_ptr]] Function
490 ; CHECK: OpVariable [[uint_ptr]] Function
491 ; CHECK-NEXT: OpVariable [[matrix_ptr]] Function [[const_matrix]]
492 ; CHECK-NOT: OpVariable [[struct1_ptr]] Function [[const_struct1]]
493 ; CHECK-NOT: OpVariable [[struct2_ptr]] Function
494 ;
495 OpCapability Shader
496 OpCapability Linkage
497 OpCapability Int64
498 OpCapability Float64
499 OpMemoryModel Logical GLSL450
500 OpName %func "non_uniform_composite_init"
501 %void = OpTypeVoid
502 %uint = OpTypeInt 32 0
503 %int64 = OpTypeInt 64 1
504 %float = OpTypeFloat 32
505 %double = OpTypeFloat 64
506 %double2 = OpTypeVector %double 2
507 %float4 = OpTypeVector %float 4
508 %int64_0 = OpConstant %int64 0
509 %int64_1 = OpConstant %int64 1
510 %int64_2 = OpConstant %int64 2
511 %int64_3 = OpConstant %int64 3
512 %int64_array3 = OpTypeArray %int64 %int64_3
513 %matrix_double2 = OpTypeMatrix %double2 2
514 %struct1 = OpTypeStruct %uint %float4
515 %struct2 = OpTypeStruct %struct1 %matrix_double2 %int64_array3 %uint
516 %struct1_ptr = OpTypePointer Function %struct1
517 %matrix_double2_ptr = OpTypePointer Function %matrix_double2
518 %int64_array_ptr = OpTypePointer Function %int64_array3
519 %uint_ptr = OpTypePointer Function %uint
520 %struct2_ptr = OpTypePointer Function %struct2
521 %const_uint = OpConstant %uint 0
522 %const_int64_array = OpConstantComposite %int64_array3 %int64_0 %int64_1 %int64_2
523 %const_double2 = OpConstantNull %double2
524 %const_matrix_double2 = OpConstantNull %matrix_double2
525 %undef_float4 = OpUndef %float4
526 %const_struct1 = OpConstantComposite %struct1 %const_uint %undef_float4
527 %const_struct2 = OpConstantComposite %struct2 %const_struct1 %const_matrix_double2 %const_int64_array %const_uint
528 %func = OpTypeFunction %void
529 %1 = OpFunction %void None %func
530 %2 = OpLabel
531 %var = OpVariable %struct2_ptr Function %const_struct2
532 %3 = OpAccessChain %struct1_ptr %var %int64_0
533 OpStore %3 %const_struct1
534 %4 = OpAccessChain %matrix_double2_ptr %var %int64_1
535 OpStore %4 %const_matrix_double2
536 %5 = OpAccessChain %int64_array_ptr %var %int64_2
537 OpStore %5 %const_int64_array
538 %6 = OpAccessChain %uint_ptr %var %int64_3
539 OpStore %6 %const_uint
540 OpReturn
541 OpFunctionEnd
542 )";
543
544 SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
545 }
546
TEST_F(ScalarReplacementTest,ElideUncombinedAccessChains)547 TEST_F(ScalarReplacementTest, ElideUncombinedAccessChains) {
548 const std::string text = R"(
549 ;
550 ; CHECK: [[uint:%\w+]] = OpTypeInt 32 0
551 ; CHECK: [[uint_ptr:%\w+]] = OpTypePointer Function [[uint]]
552 ; CHECK: [[const:%\w+]] = OpConstant [[uint]] 0
553 ; CHECK: [[var:%\w+]] = OpVariable [[uint_ptr]] Function
554 ; CHECK-NOT: OpAccessChain
555 ; CHECK: OpStore [[var]] [[const]]
556 ;
557 OpCapability Shader
558 OpCapability Linkage
559 OpMemoryModel Logical GLSL450
560 OpName %func "elide_uncombined_access_chains"
561 %void = OpTypeVoid
562 %uint = OpTypeInt 32 0
563 %struct1 = OpTypeStruct %uint
564 %struct2 = OpTypeStruct %struct1
565 %uint_ptr = OpTypePointer Function %uint
566 %struct1_ptr = OpTypePointer Function %struct1
567 %struct2_ptr = OpTypePointer Function %struct2
568 %uint_0 = OpConstant %uint 0
569 %func = OpTypeFunction %void
570 %1 = OpFunction %void None %func
571 %2 = OpLabel
572 %var = OpVariable %struct2_ptr Function
573 %3 = OpAccessChain %struct1_ptr %var %uint_0
574 %4 = OpAccessChain %uint_ptr %3 %uint_0
575 OpStore %4 %uint_0
576 OpReturn
577 OpFunctionEnd
578 )";
579
580 SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
581 }
582
TEST_F(ScalarReplacementTest,ElideSingleUncombinedAccessChains)583 TEST_F(ScalarReplacementTest, ElideSingleUncombinedAccessChains) {
584 const std::string text = R"(
585 ;
586 ; CHECK: [[uint:%\w+]] = OpTypeInt 32 0
587 ; CHECK: [[array:%\w+]] = OpTypeArray [[uint]]
588 ; CHECK: [[array_ptr:%\w+]] = OpTypePointer Function [[array]]
589 ; CHECK: [[const:%\w+]] = OpConstant [[uint]] 0
590 ; CHECK: [[param:%\w+]] = OpFunctionParameter [[uint]]
591 ; CHECK: [[var:%\w+]] = OpVariable [[array_ptr]] Function
592 ; CHECK: [[access:%\w+]] = OpAccessChain {{.*}} [[var]] [[param]]
593 ; CHECK: OpStore [[access]] [[const]]
594 ;
595 OpCapability Shader
596 OpCapability Linkage
597 OpMemoryModel Logical GLSL450
598 OpName %func "elide_single_uncombined_access_chains"
599 %void = OpTypeVoid
600 %uint = OpTypeInt 32 0
601 %uint_1 = OpConstant %uint 1
602 %array = OpTypeArray %uint %uint_1
603 %struct2 = OpTypeStruct %array
604 %uint_ptr = OpTypePointer Function %uint
605 %array_ptr = OpTypePointer Function %array
606 %struct2_ptr = OpTypePointer Function %struct2
607 %uint_0 = OpConstant %uint 0
608 %func = OpTypeFunction %void %uint
609 %1 = OpFunction %void None %func
610 %param = OpFunctionParameter %uint
611 %2 = OpLabel
612 %var = OpVariable %struct2_ptr Function
613 %3 = OpAccessChain %array_ptr %var %uint_0
614 %4 = OpAccessChain %uint_ptr %3 %param
615 OpStore %4 %uint_0
616 OpReturn
617 OpFunctionEnd
618 )";
619
620 SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
621 }
622
TEST_F(ScalarReplacementTest,ReplaceWholeLoad)623 TEST_F(ScalarReplacementTest, ReplaceWholeLoad) {
624 const std::string text = R"(
625 ;
626 ; CHECK: [[uint:%\w+]] = OpTypeInt 32 0
627 ; CHECK: [[struct1:%\w+]] = OpTypeStruct [[uint]] [[uint]]
628 ; CHECK: [[uint_ptr:%\w+]] = OpTypePointer Function [[uint]]
629 ; CHECK: [[const:%\w+]] = OpConstant [[uint]] 0
630 ; CHECK: [[var1:%\w+]] = OpVariable [[uint_ptr]] Function
631 ; CHECK: [[var0:%\w+]] = OpVariable [[uint_ptr]] Function
632 ; CHECK: [[l1:%\w+]] = OpLoad [[uint]] [[var1]]
633 ; CHECK: [[l0:%\w+]] = OpLoad [[uint]] [[var0]]
634 ; CHECK: OpCompositeConstruct [[struct1]] [[l0]] [[l1]]
635 ;
636 OpCapability Shader
637 OpCapability Linkage
638 OpMemoryModel Logical GLSL450
639 OpName %func "replace_whole_load"
640 %void = OpTypeVoid
641 %uint = OpTypeInt 32 0
642 %struct1 = OpTypeStruct %uint %uint
643 %uint_ptr = OpTypePointer Function %uint
644 %struct1_ptr = OpTypePointer Function %struct1
645 %uint_0 = OpConstant %uint 0
646 %uint_1 = OpConstant %uint 1
647 %func = OpTypeFunction %void
648 %1 = OpFunction %void None %func
649 %2 = OpLabel
650 %var = OpVariable %struct1_ptr Function
651 %load = OpLoad %struct1 %var
652 %3 = OpAccessChain %uint_ptr %var %uint_0
653 OpStore %3 %uint_0
654 %4 = OpAccessChain %uint_ptr %var %uint_1
655 OpStore %4 %uint_0
656 OpReturn
657 OpFunctionEnd
658 )";
659
660 SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
661 }
662
TEST_F(ScalarReplacementTest,ReplaceWholeLoadCopyMemoryAccess)663 TEST_F(ScalarReplacementTest, ReplaceWholeLoadCopyMemoryAccess) {
664 const std::string text = R"(
665 ;
666 ; CHECK: [[uint:%\w+]] = OpTypeInt 32 0
667 ; CHECK: [[struct1:%\w+]] = OpTypeStruct [[uint]] [[uint]]
668 ; CHECK: [[uint_ptr:%\w+]] = OpTypePointer Function [[uint]]
669 ; CHECK: [[undef:%\w+]] = OpUndef [[uint]]
670 ; CHECK: [[var0:%\w+]] = OpVariable [[uint_ptr]] Function
671 ; CHECK: [[l0:%\w+]] = OpLoad [[uint]] [[var0]] Nontemporal
672 ; CHECK: OpCompositeConstruct [[struct1]] [[l0]] [[undef]]
673 ;
674 OpCapability Shader
675 OpCapability Linkage
676 OpMemoryModel Logical GLSL450
677 OpName %func "replace_whole_load_copy_memory_access"
678 %void = OpTypeVoid
679 %uint = OpTypeInt 32 0
680 %struct1 = OpTypeStruct %uint %uint
681 %uint_ptr = OpTypePointer Function %uint
682 %struct1_ptr = OpTypePointer Function %struct1
683 %uint_0 = OpConstant %uint 0
684 %func = OpTypeFunction %void
685 %1 = OpFunction %void None %func
686 %2 = OpLabel
687 %var = OpVariable %struct1_ptr Function
688 %load = OpLoad %struct1 %var Nontemporal
689 %3 = OpAccessChain %uint_ptr %var %uint_0
690 OpStore %3 %uint_0
691 OpReturn
692 OpFunctionEnd
693 )";
694
695 SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
696 }
697
TEST_F(ScalarReplacementTest,ReplaceWholeStore)698 TEST_F(ScalarReplacementTest, ReplaceWholeStore) {
699 const std::string text = R"(
700 ;
701 ; CHECK: [[uint:%\w+]] = OpTypeInt 32 0
702 ; CHECK: [[struct1:%\w+]] = OpTypeStruct [[uint]] [[uint]]
703 ; CHECK: [[uint_ptr:%\w+]] = OpTypePointer Function [[uint]]
704 ; CHECK: [[const:%\w+]] = OpConstant [[uint]] 0
705 ; CHECK: [[const_struct:%\w+]] = OpConstantComposite [[struct1]] [[const]] [[const]]
706 ; CHECK: [[var0:%\w+]] = OpVariable [[uint_ptr]] Function
707 ; CHECK: [[ex0:%\w+]] = OpCompositeExtract [[uint]] [[const_struct]] 0
708 ; CHECK: OpStore [[var0]] [[ex0]]
709 ;
710 OpCapability Shader
711 OpCapability Linkage
712 OpMemoryModel Logical GLSL450
713 OpName %func "replace_whole_store"
714 %void = OpTypeVoid
715 %uint = OpTypeInt 32 0
716 %struct1 = OpTypeStruct %uint %uint
717 %uint_ptr = OpTypePointer Function %uint
718 %struct1_ptr = OpTypePointer Function %struct1
719 %uint_0 = OpConstant %uint 0
720 %const_struct = OpConstantComposite %struct1 %uint_0 %uint_0
721 %func = OpTypeFunction %void
722 %1 = OpFunction %void None %func
723 %2 = OpLabel
724 %var = OpVariable %struct1_ptr Function
725 OpStore %var %const_struct
726 %3 = OpAccessChain %uint_ptr %var %uint_0
727 %4 = OpLoad %uint %3
728 OpReturn
729 OpFunctionEnd
730 )";
731
732 SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
733 }
734
TEST_F(ScalarReplacementTest,ReplaceWholeStoreCopyMemoryAccess)735 TEST_F(ScalarReplacementTest, ReplaceWholeStoreCopyMemoryAccess) {
736 const std::string text = R"(
737 ;
738 ; CHECK: [[uint:%\w+]] = OpTypeInt 32 0
739 ; CHECK: [[struct1:%\w+]] = OpTypeStruct [[uint]] [[uint]]
740 ; CHECK: [[uint_ptr:%\w+]] = OpTypePointer Function [[uint]]
741 ; CHECK: [[const:%\w+]] = OpConstant [[uint]] 0
742 ; CHECK: [[const_struct:%\w+]] = OpConstantComposite [[struct1]] [[const]] [[const]]
743 ; CHECK: [[var0:%\w+]] = OpVariable [[uint_ptr]] Function
744 ; CHECK-NOT: OpVariable
745 ; CHECK: [[ex0:%\w+]] = OpCompositeExtract [[uint]] [[const_struct]] 0
746 ; CHECK: OpStore [[var0]] [[ex0]] Aligned 4
747 ;
748 OpCapability Shader
749 OpCapability Linkage
750 OpMemoryModel Logical GLSL450
751 OpName %func "replace_whole_store_copy_memory_access"
752 %void = OpTypeVoid
753 %uint = OpTypeInt 32 0
754 %struct1 = OpTypeStruct %uint %uint
755 %uint_ptr = OpTypePointer Function %uint
756 %struct1_ptr = OpTypePointer Function %struct1
757 %uint_0 = OpConstant %uint 0
758 %const_struct = OpConstantComposite %struct1 %uint_0 %uint_0
759 %func = OpTypeFunction %void
760 %1 = OpFunction %void None %func
761 %2 = OpLabel
762 %var = OpVariable %struct1_ptr Function
763 OpStore %var %const_struct Aligned 4
764 %3 = OpAccessChain %uint_ptr %var %uint_0
765 %4 = OpLoad %uint %3
766 OpReturn
767 OpFunctionEnd
768 )";
769
770 SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
771 }
772
TEST_F(ScalarReplacementTest,DontTouchVolatileLoad)773 TEST_F(ScalarReplacementTest, DontTouchVolatileLoad) {
774 const std::string text = R"(
775 ;
776 ; CHECK: [[struct:%\w+]] = OpTypeStruct
777 ; CHECK: [[struct_ptr:%\w+]] = OpTypePointer Function [[struct]]
778 ; CHECK: OpLabel
779 ; CHECK-NEXT: OpVariable [[struct_ptr]]
780 ; CHECK-NOT: OpVariable
781 ;
782 OpCapability Shader
783 OpCapability Linkage
784 OpMemoryModel Logical GLSL450
785 OpName %func "dont_touch_volatile_load"
786 %void = OpTypeVoid
787 %uint = OpTypeInt 32 0
788 %struct1 = OpTypeStruct %uint
789 %uint_ptr = OpTypePointer Function %uint
790 %struct1_ptr = OpTypePointer Function %struct1
791 %uint_0 = OpConstant %uint 0
792 %func = OpTypeFunction %void
793 %1 = OpFunction %void None %func
794 %2 = OpLabel
795 %var = OpVariable %struct1_ptr Function
796 %3 = OpAccessChain %uint_ptr %var %uint_0
797 %4 = OpLoad %uint %3 Volatile
798 OpReturn
799 OpFunctionEnd
800 )";
801
802 SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
803 }
804
TEST_F(ScalarReplacementTest,DontTouchVolatileStore)805 TEST_F(ScalarReplacementTest, DontTouchVolatileStore) {
806 const std::string text = R"(
807 ;
808 ; CHECK: [[struct:%\w+]] = OpTypeStruct
809 ; CHECK: [[struct_ptr:%\w+]] = OpTypePointer Function [[struct]]
810 ; CHECK: OpLabel
811 ; CHECK-NEXT: OpVariable [[struct_ptr]]
812 ; CHECK-NOT: OpVariable
813 ;
814 OpCapability Shader
815 OpCapability Linkage
816 OpMemoryModel Logical GLSL450
817 OpName %func "dont_touch_volatile_store"
818 %void = OpTypeVoid
819 %uint = OpTypeInt 32 0
820 %struct1 = OpTypeStruct %uint
821 %uint_ptr = OpTypePointer Function %uint
822 %struct1_ptr = OpTypePointer Function %struct1
823 %uint_0 = OpConstant %uint 0
824 %func = OpTypeFunction %void
825 %1 = OpFunction %void None %func
826 %2 = OpLabel
827 %var = OpVariable %struct1_ptr Function
828 %3 = OpAccessChain %uint_ptr %var %uint_0
829 OpStore %3 %uint_0 Volatile
830 OpReturn
831 OpFunctionEnd
832 )";
833
834 SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
835 }
836
TEST_F(ScalarReplacementTest,DontTouchSpecNonFunctionVariable)837 TEST_F(ScalarReplacementTest, DontTouchSpecNonFunctionVariable) {
838 const std::string text = R"(
839 ;
840 ; CHECK: [[struct:%\w+]] = OpTypeStruct
841 ; CHECK: [[struct_ptr:%\w+]] = OpTypePointer Uniform [[struct]]
842 ; CHECK: OpConstant
843 ; CHECK-NEXT: OpVariable [[struct_ptr]]
844 ; CHECK-NOT: OpVariable
845 ;
846 OpCapability Shader
847 OpCapability Linkage
848 OpMemoryModel Logical GLSL450
849 OpName %func "dont_touch_spec_constant_access_chain"
850 %void = OpTypeVoid
851 %uint = OpTypeInt 32 0
852 %struct1 = OpTypeStruct %uint
853 %uint_ptr = OpTypePointer Uniform %uint
854 %struct1_ptr = OpTypePointer Uniform %struct1
855 %uint_0 = OpConstant %uint 0
856 %var = OpVariable %struct1_ptr Uniform
857 %func = OpTypeFunction %void
858 %1 = OpFunction %void None %func
859 %2 = OpLabel
860 %3 = OpAccessChain %uint_ptr %var %uint_0
861 OpStore %3 %uint_0 Volatile
862 OpReturn
863 OpFunctionEnd
864 )";
865
866 SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
867 }
868
TEST_F(ScalarReplacementTest,DontTouchSpecConstantAccessChain)869 TEST_F(ScalarReplacementTest, DontTouchSpecConstantAccessChain) {
870 const std::string text = R"(
871 ;
872 ; CHECK: [[array:%\w+]] = OpTypeArray
873 ; CHECK: [[array_ptr:%\w+]] = OpTypePointer Function [[array]]
874 ; CHECK: OpLabel
875 ; CHECK-NEXT: OpVariable [[array_ptr]]
876 ; CHECK-NOT: OpVariable
877 ;
878 OpCapability Shader
879 OpCapability Linkage
880 OpMemoryModel Logical GLSL450
881 OpName %func "dont_touch_spec_constant_access_chain"
882 %void = OpTypeVoid
883 %uint = OpTypeInt 32 0
884 %uint_1 = OpConstant %uint 1
885 %array = OpTypeArray %uint %uint_1
886 %uint_ptr = OpTypePointer Function %uint
887 %array_ptr = OpTypePointer Function %array
888 %uint_0 = OpConstant %uint 0
889 %spec_const = OpSpecConstant %uint 0
890 %func = OpTypeFunction %void
891 %1 = OpFunction %void None %func
892 %2 = OpLabel
893 %var = OpVariable %array_ptr Function
894 %3 = OpAccessChain %uint_ptr %var %spec_const
895 OpStore %3 %uint_0 Volatile
896 OpReturn
897 OpFunctionEnd
898 )";
899
900 SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
901 }
902
TEST_F(ScalarReplacementTest,NoPartialAccesses)903 TEST_F(ScalarReplacementTest, NoPartialAccesses) {
904 const std::string text = R"(
905 ;
906 ; CHECK: [[uint:%\w+]] = OpTypeInt 32 0
907 ; CHECK: [[uint_ptr:%\w+]] = OpTypePointer Function [[uint]]
908 ; CHECK: OpLabel
909 ; CHECK-NOT: OpVariable
910 ;
911 OpCapability Shader
912 OpCapability Linkage
913 OpMemoryModel Logical GLSL450
914 OpName %func "no_partial_accesses"
915 %void = OpTypeVoid
916 %uint = OpTypeInt 32 0
917 %struct1 = OpTypeStruct %uint
918 %uint_ptr = OpTypePointer Function %uint
919 %struct1_ptr = OpTypePointer Function %struct1
920 %const = OpConstantNull %struct1
921 %func = OpTypeFunction %void
922 %1 = OpFunction %void None %func
923 %2 = OpLabel
924 %var = OpVariable %struct1_ptr Function
925 OpStore %var %const
926 OpReturn
927 OpFunctionEnd
928 )";
929
930 SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
931 }
932
TEST_F(ScalarReplacementTest,DontTouchPtrAccessChain)933 TEST_F(ScalarReplacementTest, DontTouchPtrAccessChain) {
934 const std::string text = R"(
935 ;
936 ; CHECK: [[struct:%\w+]] = OpTypeStruct
937 ; CHECK: [[struct_ptr:%\w+]] = OpTypePointer Function [[struct]]
938 ; CHECK: OpLabel
939 ; CHECK-NEXT: OpVariable [[struct_ptr]]
940 ; CHECK-NOT: OpVariable
941 ;
942 OpCapability Shader
943 OpCapability Linkage
944 OpMemoryModel Logical GLSL450
945 OpName %func "dont_touch_ptr_access_chain"
946 %void = OpTypeVoid
947 %uint = OpTypeInt 32 0
948 %struct1 = OpTypeStruct %uint
949 %uint_ptr = OpTypePointer Function %uint
950 %struct1_ptr = OpTypePointer Function %struct1
951 %uint_0 = OpConstant %uint 0
952 %func = OpTypeFunction %void
953 %1 = OpFunction %void None %func
954 %2 = OpLabel
955 %var = OpVariable %struct1_ptr Function
956 %3 = OpPtrAccessChain %uint_ptr %var %uint_0 %uint_0
957 OpStore %3 %uint_0
958 %4 = OpAccessChain %uint_ptr %var %uint_0
959 OpStore %4 %uint_0
960 OpReturn
961 OpFunctionEnd
962 )";
963
964 SinglePassRunAndMatch<ScalarReplacementPass>(text, false);
965 }
966
TEST_F(ScalarReplacementTest,DontTouchInBoundsPtrAccessChain)967 TEST_F(ScalarReplacementTest, DontTouchInBoundsPtrAccessChain) {
968 const std::string text = R"(
969 ;
970 ; CHECK: [[struct:%\w+]] = OpTypeStruct
971 ; CHECK: [[struct_ptr:%\w+]] = OpTypePointer Function [[struct]]
972 ; CHECK: OpLabel
973 ; CHECK-NEXT: OpVariable [[struct_ptr]]
974 ; CHECK-NOT: OpVariable
975 ;
976 OpCapability Shader
977 OpCapability Linkage
978 OpMemoryModel Logical GLSL450
979 OpName %func "dont_touch_in_bounds_ptr_access_chain"
980 %void = OpTypeVoid
981 %uint = OpTypeInt 32 0
982 %struct1 = OpTypeStruct %uint
983 %uint_ptr = OpTypePointer Function %uint
984 %struct1_ptr = OpTypePointer Function %struct1
985 %uint_0 = OpConstant %uint 0
986 %func = OpTypeFunction %void
987 %1 = OpFunction %void None %func
988 %2 = OpLabel
989 %var = OpVariable %struct1_ptr Function
990 %3 = OpInBoundsPtrAccessChain %uint_ptr %var %uint_0 %uint_0
991 OpStore %3 %uint_0
992 %4 = OpInBoundsAccessChain %uint_ptr %var %uint_0
993 OpStore %4 %uint_0
994 OpReturn
995 OpFunctionEnd
996 )";
997
998 SinglePassRunAndMatch<ScalarReplacementPass>(text, false);
999 }
1000
TEST_F(ScalarReplacementTest,DonTouchAliasedDecoration)1001 TEST_F(ScalarReplacementTest, DonTouchAliasedDecoration) {
1002 const std::string text = R"(
1003 ;
1004 ; CHECK: [[struct:%\w+]] = OpTypeStruct
1005 ; CHECK: [[struct_ptr:%\w+]] = OpTypePointer Function [[struct]]
1006 ; CHECK: OpLabel
1007 ; CHECK-NEXT: OpVariable [[struct_ptr]]
1008 ; CHECK-NOT: OpVariable
1009 ;
1010 OpCapability Shader
1011 OpCapability Linkage
1012 OpMemoryModel Logical GLSL450
1013 OpName %func "aliased"
1014 OpDecorate %var Aliased
1015 %void = OpTypeVoid
1016 %uint = OpTypeInt 32 0
1017 %struct1 = OpTypeStruct %uint
1018 %uint_ptr = OpTypePointer Function %uint
1019 %struct1_ptr = OpTypePointer Function %struct1
1020 %uint_0 = OpConstant %uint 0
1021 %func = OpTypeFunction %void
1022 %1 = OpFunction %void None %func
1023 %2 = OpLabel
1024 %var = OpVariable %struct1_ptr Function
1025 %3 = OpAccessChain %uint_ptr %var %uint_0
1026 %4 = OpLoad %uint %3
1027 OpReturn
1028 OpFunctionEnd
1029 )";
1030
1031 SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
1032 }
1033
TEST_F(ScalarReplacementTest,CopyRestrictDecoration)1034 TEST_F(ScalarReplacementTest, CopyRestrictDecoration) {
1035 const std::string text = R"(
1036 ;
1037 ; CHECK: OpName
1038 ; CHECK-NEXT: OpDecorate [[var0:%\w+]] Restrict
1039 ; CHECK-NEXT: OpDecorate [[var1:%\w+]] Restrict
1040 ; CHECK: [[int:%\w+]] = OpTypeInt
1041 ; CHECK: [[struct:%\w+]] = OpTypeStruct
1042 ; CHECK: [[int_ptr:%\w+]] = OpTypePointer Function [[int]]
1043 ; CHECK: [[struct_ptr:%\w+]] = OpTypePointer Function [[struct]]
1044 ; CHECK: OpLabel
1045 ; CHECK-NEXT: [[var1]] = OpVariable [[int_ptr]]
1046 ; CHECK-NEXT: [[var0]] = OpVariable [[int_ptr]]
1047 ; CHECK-NOT: OpVariable [[struct_ptr]]
1048 ;
1049 OpCapability Shader
1050 OpCapability Linkage
1051 OpMemoryModel Logical GLSL450
1052 OpName %func "restrict"
1053 OpDecorate %var Restrict
1054 %void = OpTypeVoid
1055 %uint = OpTypeInt 32 0
1056 %struct1 = OpTypeStruct %uint %uint
1057 %uint_ptr = OpTypePointer Function %uint
1058 %struct1_ptr = OpTypePointer Function %struct1
1059 %uint_0 = OpConstant %uint 0
1060 %uint_1 = OpConstant %uint 1
1061 %func = OpTypeFunction %void
1062 %1 = OpFunction %void None %func
1063 %2 = OpLabel
1064 %var = OpVariable %struct1_ptr Function
1065 %3 = OpAccessChain %uint_ptr %var %uint_0
1066 %4 = OpLoad %uint %3
1067 %5 = OpAccessChain %uint_ptr %var %uint_1
1068 %6 = OpLoad %uint %5
1069 OpReturn
1070 OpFunctionEnd
1071 )";
1072
1073 SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
1074 }
1075
TEST_F(ScalarReplacementTest,DontClobberDecoratesOnSubtypes)1076 TEST_F(ScalarReplacementTest, DontClobberDecoratesOnSubtypes) {
1077 const std::string text = R"(
1078 ;
1079 ; CHECK: OpDecorate [[array:%\w+]] ArrayStride 1
1080 ; CHECK: [[uint:%\w+]] = OpTypeInt 32 0
1081 ; CHECK: [[array]] = OpTypeArray [[uint]]
1082 ; CHECK: [[array_ptr:%\w+]] = OpTypePointer Function [[array]]
1083 ; CHECK: OpLabel
1084 ; CHECK-NEXT: OpVariable [[array_ptr]] Function
1085 ; CHECK-NOT: OpVariable
1086 ;
1087 OpCapability Shader
1088 OpCapability Linkage
1089 OpMemoryModel Logical GLSL450
1090 OpName %func "array_stride"
1091 OpDecorate %array ArrayStride 1
1092 %void = OpTypeVoid
1093 %uint = OpTypeInt 32 0
1094 %uint_1 = OpConstant %uint 1
1095 %array = OpTypeArray %uint %uint_1
1096 %struct1 = OpTypeStruct %array
1097 %uint_ptr = OpTypePointer Function %uint
1098 %struct1_ptr = OpTypePointer Function %struct1
1099 %uint_0 = OpConstant %uint 0
1100 %func = OpTypeFunction %void %uint
1101 %1 = OpFunction %void None %func
1102 %param = OpFunctionParameter %uint
1103 %2 = OpLabel
1104 %var = OpVariable %struct1_ptr Function
1105 %3 = OpAccessChain %uint_ptr %var %uint_0 %param
1106 %4 = OpLoad %uint %3
1107 OpReturn
1108 OpFunctionEnd
1109 )";
1110
1111 SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
1112 }
1113
TEST_F(ScalarReplacementTest,DontCopyMemberDecorate)1114 TEST_F(ScalarReplacementTest, DontCopyMemberDecorate) {
1115 const std::string text = R"(
1116 ;
1117 ; CHECK-NOT: OpDecorate
1118 ; CHECK: [[uint:%\w+]] = OpTypeInt 32 0
1119 ; CHECK: [[struct:%\w+]] = OpTypeStruct [[uint]]
1120 ; CHECK: [[uint_ptr:%\w+]] = OpTypePointer Function [[uint]]
1121 ; CHECK: [[struct_ptr:%\w+]] = OpTypePointer Function [[struct]]
1122 ; CHECK: OpLabel
1123 ; CHECK-NEXT: OpVariable [[uint_ptr]] Function
1124 ; CHECK-NOT: OpVariable
1125 ;
1126 OpCapability Shader
1127 OpCapability Linkage
1128 OpMemoryModel Logical GLSL450
1129 OpName %func "member_decorate"
1130 OpMemberDecorate %struct1 0 Offset 1
1131 %void = OpTypeVoid
1132 %uint = OpTypeInt 32 0
1133 %uint_1 = OpConstant %uint 1
1134 %struct1 = OpTypeStruct %uint
1135 %uint_ptr = OpTypePointer Function %uint
1136 %struct1_ptr = OpTypePointer Function %struct1
1137 %uint_0 = OpConstant %uint 0
1138 %func = OpTypeFunction %void %uint
1139 %1 = OpFunction %void None %func
1140 %2 = OpLabel
1141 %var = OpVariable %struct1_ptr Function
1142 %3 = OpAccessChain %uint_ptr %var %uint_0
1143 %4 = OpLoad %uint %3
1144 OpReturn
1145 OpFunctionEnd
1146 )";
1147
1148 SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
1149 }
1150
TEST_F(ScalarReplacementTest,NoPartialAccesses2)1151 TEST_F(ScalarReplacementTest, NoPartialAccesses2) {
1152 const std::string text = R"(
1153 ;
1154 ; CHECK: [[float:%\w+]] = OpTypeFloat 32
1155 ; CHECK: [[float_ptr:%\w+]] = OpTypePointer Function [[float]]
1156 ; CHECK: OpVariable [[float_ptr]] Function
1157 ; CHECK: OpVariable [[float_ptr]] Function
1158 ; CHECK: OpVariable [[float_ptr]] Function
1159 ; CHECK: OpVariable [[float_ptr]] Function
1160 ; CHECK: OpVariable [[float_ptr]] Function
1161 ; CHECK: OpVariable [[float_ptr]] Function
1162 ; CHECK: OpVariable [[float_ptr]] Function
1163 ; CHECK-NOT: OpVariable
1164 ;
1165 OpCapability Shader
1166 %1 = OpExtInstImport "GLSL.std.450"
1167 OpMemoryModel Logical GLSL450
1168 OpEntryPoint Fragment %main "main" %fo
1169 OpExecutionMode %main OriginUpperLeft
1170 OpSource GLSL 430
1171 OpName %main "main"
1172 OpName %S "S"
1173 OpMemberName %S 0 "x"
1174 OpMemberName %S 1 "y"
1175 OpName %ts1 "ts1"
1176 OpName %S_0 "S"
1177 OpMemberName %S_0 0 "x"
1178 OpMemberName %S_0 1 "y"
1179 OpName %U_t "U_t"
1180 OpMemberName %U_t 0 "g_s1"
1181 OpMemberName %U_t 1 "g_s2"
1182 OpMemberName %U_t 2 "g_s3"
1183 OpName %_ ""
1184 OpName %ts2 "ts2"
1185 OpName %_Globals_ "_Globals_"
1186 OpMemberName %_Globals_ 0 "g_b"
1187 OpName %__0 ""
1188 OpName %ts3 "ts3"
1189 OpName %ts4 "ts4"
1190 OpName %fo "fo"
1191 OpMemberDecorate %S_0 0 Offset 0
1192 OpMemberDecorate %S_0 1 Offset 4
1193 OpMemberDecorate %U_t 0 Offset 0
1194 OpMemberDecorate %U_t 1 Offset 8
1195 OpMemberDecorate %U_t 2 Offset 16
1196 OpDecorate %U_t BufferBlock
1197 OpDecorate %_ DescriptorSet 0
1198 OpMemberDecorate %_Globals_ 0 Offset 0
1199 OpDecorate %_Globals_ Block
1200 OpDecorate %__0 DescriptorSet 0
1201 OpDecorate %__0 Binding 0
1202 OpDecorate %fo Location 0
1203 %void = OpTypeVoid
1204 %15 = OpTypeFunction %void
1205 %float = OpTypeFloat 32
1206 %S = OpTypeStruct %float %float
1207 %_ptr_Function_S = OpTypePointer Function %S
1208 %S_0 = OpTypeStruct %float %float
1209 %U_t = OpTypeStruct %S_0 %S_0 %S_0
1210 %_ptr_Uniform_U_t = OpTypePointer Uniform %U_t
1211 %_ = OpVariable %_ptr_Uniform_U_t Uniform
1212 %int = OpTypeInt 32 1
1213 %int_0 = OpConstant %int 0
1214 %_ptr_Uniform_S_0 = OpTypePointer Uniform %S_0
1215 %_ptr_Function_float = OpTypePointer Function %float
1216 %int_1 = OpConstant %int 1
1217 %uint = OpTypeInt 32 0
1218 %_Globals_ = OpTypeStruct %uint
1219 %_ptr_Uniform__Globals_ = OpTypePointer Uniform %_Globals_
1220 %__0 = OpVariable %_ptr_Uniform__Globals_ Uniform
1221 %_ptr_Uniform_uint = OpTypePointer Uniform %uint
1222 %bool = OpTypeBool
1223 %uint_0 = OpConstant %uint 0
1224 %_ptr_Output_float = OpTypePointer Output %float
1225 %fo = OpVariable %_ptr_Output_float Output
1226 %main = OpFunction %void None %15
1227 %30 = OpLabel
1228 %ts1 = OpVariable %_ptr_Function_S Function
1229 %ts2 = OpVariable %_ptr_Function_S Function
1230 %ts3 = OpVariable %_ptr_Function_S Function
1231 %ts4 = OpVariable %_ptr_Function_S Function
1232 %31 = OpAccessChain %_ptr_Uniform_S_0 %_ %int_0
1233 %32 = OpLoad %S_0 %31
1234 %33 = OpCompositeExtract %float %32 0
1235 %34 = OpAccessChain %_ptr_Function_float %ts1 %int_0
1236 OpStore %34 %33
1237 %35 = OpCompositeExtract %float %32 1
1238 %36 = OpAccessChain %_ptr_Function_float %ts1 %int_1
1239 OpStore %36 %35
1240 %37 = OpAccessChain %_ptr_Uniform_S_0 %_ %int_1
1241 %38 = OpLoad %S_0 %37
1242 %39 = OpCompositeExtract %float %38 0
1243 %40 = OpAccessChain %_ptr_Function_float %ts2 %int_0
1244 OpStore %40 %39
1245 %41 = OpCompositeExtract %float %38 1
1246 %42 = OpAccessChain %_ptr_Function_float %ts2 %int_1
1247 OpStore %42 %41
1248 %43 = OpAccessChain %_ptr_Uniform_uint %__0 %int_0
1249 %44 = OpLoad %uint %43
1250 %45 = OpINotEqual %bool %44 %uint_0
1251 OpSelectionMerge %46 None
1252 OpBranchConditional %45 %47 %48
1253 %47 = OpLabel
1254 %49 = OpLoad %S %ts1
1255 OpStore %ts3 %49
1256 OpBranch %46
1257 %48 = OpLabel
1258 %50 = OpLoad %S %ts2
1259 OpStore %ts3 %50
1260 OpBranch %46
1261 %46 = OpLabel
1262 %51 = OpLoad %S %ts3
1263 OpStore %ts4 %51
1264 %52 = OpAccessChain %_ptr_Function_float %ts4 %int_1
1265 %53 = OpLoad %float %52
1266 OpStore %fo %53
1267 OpReturn
1268 OpFunctionEnd
1269 )";
1270
1271 SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
1272 }
1273
TEST_F(ScalarReplacementTest,ReplaceWholeLoadAndStore)1274 TEST_F(ScalarReplacementTest, ReplaceWholeLoadAndStore) {
1275 const std::string text = R"(
1276 ;
1277 ; CHECK: [[uint:%\w+]] = OpTypeInt 32 0
1278 ; CHECK: [[struct1:%\w+]] = OpTypeStruct [[uint]] [[uint]]
1279 ; CHECK: [[uint_ptr:%\w+]] = OpTypePointer Function [[uint]]
1280 ; CHECK: [[const:%\w+]] = OpConstant [[uint]] 0
1281 ; CHECK: [[undef:%\w+]] = OpUndef [[uint]]
1282 ; CHECK: [[var0:%\w+]] = OpVariable [[uint_ptr]] Function
1283 ; CHECK: [[var1:%\w+]] = OpVariable [[uint_ptr]] Function
1284 ; CHECK-NOT: OpVariable
1285 ; CHECK: [[l0:%\w+]] = OpLoad [[uint]] [[var0]]
1286 ; CHECK: [[c0:%\w+]] = OpCompositeConstruct [[struct1]] [[l0]] [[undef]]
1287 ; CHECK: [[e0:%\w+]] = OpCompositeExtract [[uint]] [[c0]] 0
1288 ; CHECK: OpStore [[var1]] [[e0]]
1289 ; CHECK: [[l1:%\w+]] = OpLoad [[uint]] [[var1]]
1290 ; CHECK: [[c1:%\w+]] = OpCompositeConstruct [[struct1]] [[l1]] [[undef]]
1291 ; CHECK: [[e1:%\w+]] = OpCompositeExtract [[uint]] [[c1]] 0
1292 ;
1293 OpCapability Shader
1294 OpCapability Linkage
1295 OpMemoryModel Logical GLSL450
1296 OpName %func "replace_whole_load"
1297 %void = OpTypeVoid
1298 %uint = OpTypeInt 32 0
1299 %struct1 = OpTypeStruct %uint %uint
1300 %uint_ptr = OpTypePointer Function %uint
1301 %struct1_ptr = OpTypePointer Function %struct1
1302 %uint_0 = OpConstant %uint 0
1303 %uint_1 = OpConstant %uint 1
1304 %func = OpTypeFunction %void
1305 %1 = OpFunction %void None %func
1306 %2 = OpLabel
1307 %var2 = OpVariable %struct1_ptr Function
1308 %var1 = OpVariable %struct1_ptr Function
1309 %load1 = OpLoad %struct1 %var1
1310 OpStore %var2 %load1
1311 %load2 = OpLoad %struct1 %var2
1312 %3 = OpCompositeExtract %uint %load2 0
1313 OpReturn
1314 OpFunctionEnd
1315 )";
1316
1317 SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
1318 }
1319
TEST_F(ScalarReplacementTest,ReplaceWholeLoadAndStore2)1320 TEST_F(ScalarReplacementTest, ReplaceWholeLoadAndStore2) {
1321 // TODO: We can improve this case by ensuring that |var2| is processed first.
1322 const std::string text = R"(
1323 ;
1324 ; CHECK: [[uint:%\w+]] = OpTypeInt 32 0
1325 ; CHECK: [[struct1:%\w+]] = OpTypeStruct [[uint]] [[uint]]
1326 ; CHECK: [[uint_ptr:%\w+]] = OpTypePointer Function [[uint]]
1327 ; CHECK: [[const:%\w+]] = OpConstant [[uint]] 0
1328 ; CHECK: [[undef:%\w+]] = OpUndef [[uint]]
1329 ; CHECK: [[var1:%\w+]] = OpVariable [[uint_ptr]] Function
1330 ; CHECK: [[var0a:%\w+]] = OpVariable [[uint_ptr]] Function
1331 ; CHECK: [[var0b:%\w+]] = OpVariable [[uint_ptr]] Function
1332 ; CHECK-NOT: OpVariable
1333 ; CHECK: [[l0a:%\w+]] = OpLoad [[uint]] [[var0a]]
1334 ; CHECK: [[l0b:%\w+]] = OpLoad [[uint]] [[var0b]]
1335 ; CHECK: [[c0:%\w+]] = OpCompositeConstruct [[struct1]] [[l0b]] [[l0a]]
1336 ; CHECK: [[e0:%\w+]] = OpCompositeExtract [[uint]] [[c0]] 0
1337 ; CHECK: OpStore [[var1]] [[e0]]
1338 ; CHECK: [[l1:%\w+]] = OpLoad [[uint]] [[var1]]
1339 ; CHECK: [[c1:%\w+]] = OpCompositeConstruct [[struct1]] [[l1]] [[undef]]
1340 ; CHECK: [[e1:%\w+]] = OpCompositeExtract [[uint]] [[c1]] 0
1341 ;
1342 OpCapability Shader
1343 OpCapability Linkage
1344 OpMemoryModel Logical GLSL450
1345 OpName %func "replace_whole_load"
1346 %void = OpTypeVoid
1347 %uint = OpTypeInt 32 0
1348 %struct1 = OpTypeStruct %uint %uint
1349 %uint_ptr = OpTypePointer Function %uint
1350 %struct1_ptr = OpTypePointer Function %struct1
1351 %uint_0 = OpConstant %uint 0
1352 %uint_1 = OpConstant %uint 1
1353 %func = OpTypeFunction %void
1354 %1 = OpFunction %void None %func
1355 %2 = OpLabel
1356 %var1 = OpVariable %struct1_ptr Function
1357 %var2 = OpVariable %struct1_ptr Function
1358 %load1 = OpLoad %struct1 %var1
1359 OpStore %var2 %load1
1360 %load2 = OpLoad %struct1 %var2
1361 %3 = OpCompositeExtract %uint %load2 0
1362 OpReturn
1363 OpFunctionEnd
1364 )";
1365
1366 SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
1367 }
1368
TEST_F(ScalarReplacementTest,CreateAmbiguousNullConstant1)1369 TEST_F(ScalarReplacementTest, CreateAmbiguousNullConstant1) {
1370 const std::string text = R"(
1371 ;
1372 ; CHECK: [[uint:%\w+]] = OpTypeInt 32 0
1373 ; CHECK: [[struct1:%\w+]] = OpTypeStruct [[uint]] [[struct_member:%\w+]]
1374 ; CHECK: [[uint_ptr:%\w+]] = OpTypePointer Function [[uint]]
1375 ; CHECK: [[const:%\w+]] = OpConstant [[uint]] 0
1376 ; CHECK: [[undef:%\w+]] = OpUndef [[struct_member]]
1377 ; CHECK: [[var0a:%\w+]] = OpVariable [[uint_ptr]] Function
1378 ; CHECK: [[var1:%\w+]] = OpVariable [[uint_ptr]] Function
1379 ; CHECK: [[var0b:%\w+]] = OpVariable [[uint_ptr]] Function
1380 ; CHECK-NOT: OpVariable
1381 ; CHECK: OpStore [[var1]]
1382 ; CHECK: [[l1:%\w+]] = OpLoad [[uint]] [[var1]]
1383 ; CHECK: [[c1:%\w+]] = OpCompositeConstruct [[struct1]] [[l1]] [[undef]]
1384 ; CHECK: [[e1:%\w+]] = OpCompositeExtract [[uint]] [[c1]] 0
1385 ;
1386 OpCapability Shader
1387 OpCapability Linkage
1388 OpMemoryModel Logical GLSL450
1389 OpName %func "replace_whole_load"
1390 %void = OpTypeVoid
1391 %uint = OpTypeInt 32 0
1392 %struct2 = OpTypeStruct %uint
1393 %struct3 = OpTypeStruct %uint
1394 %struct1 = OpTypeStruct %uint %struct2
1395 %uint_ptr = OpTypePointer Function %uint
1396 %struct1_ptr = OpTypePointer Function %struct1
1397 %uint_0 = OpConstant %uint 0
1398 %uint_1 = OpConstant %uint 1
1399 %func = OpTypeFunction %void
1400 %1 = OpFunction %void None %func
1401 %2 = OpLabel
1402 %var1 = OpVariable %struct1_ptr Function
1403 %var2 = OpVariable %struct1_ptr Function
1404 %load1 = OpLoad %struct1 %var1
1405 OpStore %var2 %load1
1406 %load2 = OpLoad %struct1 %var2
1407 %3 = OpCompositeExtract %uint %load2 0
1408 OpReturn
1409 OpFunctionEnd
1410 )";
1411
1412 SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
1413 }
1414
TEST_F(ScalarReplacementTest,SpecConstantArray)1415 TEST_F(ScalarReplacementTest, SpecConstantArray) {
1416 const std::string text = R"(
1417 ; CHECK: [[int:%\w+]] = OpTypeInt
1418 ; CHECK: [[spec_const:%\w+]] = OpSpecConstant [[int]] 4
1419 ; CHECK: [[spec_op:%\w+]] = OpSpecConstantOp [[int]] IAdd [[spec_const]] [[spec_const]]
1420 ; CHECK: [[array1:%\w+]] = OpTypeArray [[int]] [[spec_const]]
1421 ; CHECK: [[array2:%\w+]] = OpTypeArray [[int]] [[spec_op]]
1422 ; CHECK: [[ptr_array1:%\w+]] = OpTypePointer Function [[array1]]
1423 ; CHECK: [[ptr_array2:%\w+]] = OpTypePointer Function [[array2]]
1424 ; CHECK: OpLabel
1425 ; CHECK-NEXT: OpVariable [[ptr_array1]] Function
1426 ; CHECK-NEXT: OpVariable [[ptr_array2]] Function
1427 ; CHECK-NOT: OpVariable
1428 OpCapability Shader
1429 OpCapability Linkage
1430 OpMemoryModel Logical GLSL450
1431 %void = OpTypeVoid
1432 %void_fn = OpTypeFunction %void
1433 %int = OpTypeInt 32 0
1434 %spec_const = OpSpecConstant %int 4
1435 %spec_op = OpSpecConstantOp %int IAdd %spec_const %spec_const
1436 %array_1 = OpTypeArray %int %spec_const
1437 %array_2 = OpTypeArray %int %spec_op
1438 %ptr_array_1_Function = OpTypePointer Function %array_1
1439 %ptr_array_2_Function = OpTypePointer Function %array_2
1440 %func = OpFunction %void None %void_fn
1441 %1 = OpLabel
1442 %var_1 = OpVariable %ptr_array_1_Function Function
1443 %var_2 = OpVariable %ptr_array_2_Function Function
1444 OpReturn
1445 OpFunctionEnd
1446 )";
1447
1448 SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
1449 }
1450
TEST_F(ScalarReplacementTest,CreateAmbiguousNullConstant2)1451 TEST_F(ScalarReplacementTest, CreateAmbiguousNullConstant2) {
1452 const std::string text = R"(
1453 ;
1454 ; CHECK: [[uint:%\w+]] = OpTypeInt 32 0
1455 ; CHECK: [[struct1:%\w+]] = OpTypeStruct [[uint]] [[struct_member:%\w+]]
1456 ; CHECK: [[uint_ptr:%\w+]] = OpTypePointer Function [[uint]]
1457 ; CHECK: [[const:%\w+]] = OpConstant [[uint]] 0
1458 ; CHECK: [[undef:%\w+]] = OpUndef [[struct_member]]
1459 ; CHECK: [[var0a:%\w+]] = OpVariable [[uint_ptr]] Function
1460 ; CHECK: [[var1:%\w+]] = OpVariable [[uint_ptr]] Function
1461 ; CHECK: [[var0b:%\w+]] = OpVariable [[uint_ptr]] Function
1462 ; CHECK: OpStore [[var1]]
1463 ; CHECK: [[l1:%\w+]] = OpLoad [[uint]] [[var1]]
1464 ; CHECK: [[c1:%\w+]] = OpCompositeConstruct [[struct1]] [[l1]] [[undef]]
1465 ; CHECK: [[e1:%\w+]] = OpCompositeExtract [[uint]] [[c1]] 0
1466 ;
1467 OpCapability Shader
1468 OpCapability Linkage
1469 OpMemoryModel Logical GLSL450
1470 OpName %func "replace_whole_load"
1471 %void = OpTypeVoid
1472 %uint = OpTypeInt 32 0
1473 %struct3 = OpTypeStruct %uint
1474 %struct2 = OpTypeStruct %uint
1475 %struct1 = OpTypeStruct %uint %struct2
1476 %uint_ptr = OpTypePointer Function %uint
1477 %struct1_ptr = OpTypePointer Function %struct1
1478 %uint_0 = OpConstant %uint 0
1479 %uint_1 = OpConstant %uint 1
1480 %func = OpTypeFunction %void
1481 %1 = OpFunction %void None %func
1482 %2 = OpLabel
1483 %var1 = OpVariable %struct1_ptr Function
1484 %var2 = OpVariable %struct1_ptr Function
1485 %load1 = OpLoad %struct1 %var1
1486 OpStore %var2 %load1
1487 %load2 = OpLoad %struct1 %var2
1488 %3 = OpCompositeExtract %uint %load2 0
1489 OpReturn
1490 OpFunctionEnd
1491 )";
1492
1493 SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
1494 }
1495
1496 // Test that a struct of size 4 is not replaced when there is a limit of 2.
TEST_F(ScalarReplacementTest,TestLimit)1497 TEST_F(ScalarReplacementTest, TestLimit) {
1498 const std::string text = R"(
1499 OpCapability Shader
1500 OpCapability Linkage
1501 OpMemoryModel Logical GLSL450
1502 OpName %6 "simple_struct"
1503 %1 = OpTypeVoid
1504 %2 = OpTypeInt 32 0
1505 %3 = OpTypeStruct %2 %2 %2 %2
1506 %4 = OpTypePointer Function %3
1507 %5 = OpTypePointer Function %2
1508 %6 = OpTypeFunction %2
1509 %7 = OpConstantNull %3
1510 %8 = OpConstant %2 0
1511 %9 = OpConstant %2 1
1512 %10 = OpConstant %2 2
1513 %11 = OpConstant %2 3
1514 %12 = OpFunction %2 None %6
1515 %13 = OpLabel
1516 %14 = OpVariable %4 Function %7
1517 %15 = OpInBoundsAccessChain %5 %14 %8
1518 %16 = OpLoad %2 %15
1519 %17 = OpAccessChain %5 %14 %10
1520 %18 = OpLoad %2 %17
1521 %19 = OpIAdd %2 %16 %18
1522 OpReturnValue %19
1523 OpFunctionEnd
1524 )";
1525
1526 auto result =
1527 SinglePassRunAndDisassemble<ScalarReplacementPass>(text, true, false, 2);
1528 EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
1529 }
1530
1531 // Test that a struct of size 4 is replaced when there is a limit of 0 (no
1532 // limit). This is the same spir-v as a test above, so we do not check that it
1533 // is correctly transformed. We leave that to the test above.
TEST_F(ScalarReplacementTest,TestUnimited)1534 TEST_F(ScalarReplacementTest, TestUnimited) {
1535 const std::string text = R"(
1536 OpCapability Shader
1537 OpCapability Linkage
1538 OpMemoryModel Logical GLSL450
1539 OpName %6 "simple_struct"
1540 %1 = OpTypeVoid
1541 %2 = OpTypeInt 32 0
1542 %3 = OpTypeStruct %2 %2 %2 %2
1543 %4 = OpTypePointer Function %3
1544 %5 = OpTypePointer Function %2
1545 %6 = OpTypeFunction %2
1546 %7 = OpConstantNull %3
1547 %8 = OpConstant %2 0
1548 %9 = OpConstant %2 1
1549 %10 = OpConstant %2 2
1550 %11 = OpConstant %2 3
1551 %12 = OpFunction %2 None %6
1552 %13 = OpLabel
1553 %14 = OpVariable %4 Function %7
1554 %15 = OpInBoundsAccessChain %5 %14 %8
1555 %16 = OpLoad %2 %15
1556 %17 = OpAccessChain %5 %14 %10
1557 %18 = OpLoad %2 %17
1558 %19 = OpIAdd %2 %16 %18
1559 OpReturnValue %19
1560 OpFunctionEnd
1561 )";
1562
1563 auto result =
1564 SinglePassRunAndDisassemble<ScalarReplacementPass>(text, true, false, 0);
1565 EXPECT_EQ(Pass::Status::SuccessWithChange, std::get<1>(result));
1566 }
1567
TEST_F(ScalarReplacementTest,AmbigousPointer)1568 TEST_F(ScalarReplacementTest, AmbigousPointer) {
1569 const std::string text = R"(
1570 ; CHECK: [[s1:%\w+]] = OpTypeStruct %uint
1571 ; CHECK: [[s2:%\w+]] = OpTypeStruct %uint
1572 ; CHECK: [[s3:%\w+]] = OpTypeStruct [[s2]]
1573 ; CHECK: [[s3_const:%\w+]] = OpConstantComposite [[s3]]
1574 ; CHECK: [[s2_ptr:%\w+]] = OpTypePointer Function [[s2]]
1575 ; CHECK: OpCompositeExtract [[s2]] [[s3_const]]
1576
1577 OpCapability Shader
1578 %1 = OpExtInstImport "GLSL.std.450"
1579 OpMemoryModel Logical GLSL450
1580 OpEntryPoint Fragment %2 "main"
1581 OpExecutionMode %2 OriginUpperLeft
1582 OpSource ESSL 310
1583 %void = OpTypeVoid
1584 %5 = OpTypeFunction %void
1585 %uint = OpTypeInt 32 0
1586 %_struct_7 = OpTypeStruct %uint
1587 %_struct_8 = OpTypeStruct %uint
1588 %_struct_9 = OpTypeStruct %_struct_8
1589 %uint_1 = OpConstant %uint 1
1590 %11 = OpConstantComposite %_struct_8 %uint_1
1591 %12 = OpConstantComposite %_struct_9 %11
1592 %_ptr_Function__struct_9 = OpTypePointer Function %_struct_9
1593 %_ptr_Function__struct_7 = OpTypePointer Function %_struct_7
1594 %2 = OpFunction %void None %5
1595 %15 = OpLabel
1596 %var = OpVariable %_ptr_Function__struct_9 Function
1597 OpStore %var %12
1598 %ld = OpLoad %_struct_9 %var
1599 %ex = OpCompositeExtract %_struct_8 %ld 0
1600 OpReturn
1601 OpFunctionEnd
1602 )";
1603
1604 SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
1605 }
1606
1607 // Test that scalar replacement does not crash when there is an OpAccessChain
1608 // with no index. If we choose to handle this case in the future, then the
1609 // result can change.
TEST_F(ScalarReplacementTest,TestAccessChainWithNoIndexes)1610 TEST_F(ScalarReplacementTest, TestAccessChainWithNoIndexes) {
1611 const std::string text = R"(
1612 OpCapability Shader
1613 OpMemoryModel Logical GLSL450
1614 OpEntryPoint Fragment %1 "main"
1615 OpExecutionMode %1 OriginLowerLeft
1616 %void = OpTypeVoid
1617 %3 = OpTypeFunction %void
1618 %float = OpTypeFloat 32
1619 %_struct_5 = OpTypeStruct %float
1620 %_ptr_Function__struct_5 = OpTypePointer Function %_struct_5
1621 %1 = OpFunction %void None %3
1622 %7 = OpLabel
1623 %8 = OpVariable %_ptr_Function__struct_5 Function
1624 %9 = OpAccessChain %_ptr_Function__struct_5 %8
1625 OpReturn
1626 OpFunctionEnd
1627 )";
1628
1629 auto result =
1630 SinglePassRunAndDisassemble<ScalarReplacementPass>(text, true, false);
1631 EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
1632 }
1633
1634 // Test that id overflow is handled gracefully.
TEST_F(ScalarReplacementTest,IdBoundOverflow1)1635 TEST_F(ScalarReplacementTest, IdBoundOverflow1) {
1636 const std::string text = R"(
1637 OpCapability ImageQuery
1638 OpMemoryModel Logical GLSL450
1639 OpEntryPoint Fragment %4 "main"
1640 OpExecutionMode %4 OriginUpperLeft
1641 OpDecorate %4194302 DescriptorSet 1073495039
1642 %2 = OpTypeVoid
1643 %3 = OpTypeFunction %2
1644 %6 = OpTypeFloat 32
1645 %7 = OpTypeStruct %6 %6
1646 %557056 = OpTypeStruct %7
1647 %9 = OpTypePointer Function %7
1648 %18 = OpTypeFunction %7 %9
1649 %4 = OpFunction %2 Pure|Const %3
1650 %1836763 = OpLabel
1651 %4194302 = OpVariable %9 Function
1652 %10 = OpVariable %9 Function
1653 OpKill
1654 %4194301 = OpLabel
1655 %524296 = OpLoad %7 %4194302
1656 OpKill
1657 OpFunctionEnd
1658 )";
1659
1660 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
1661
1662 std::vector<Message> messages = {
1663 {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."},
1664 {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."}};
1665 SetMessageConsumer(GetTestMessageConsumer(messages));
1666 auto result = SinglePassRunToBinary<ScalarReplacementPass>(text, true, false);
1667 EXPECT_EQ(Pass::Status::Failure, std::get<1>(result));
1668 }
1669
1670 // Test that id overflow is handled gracefully.
TEST_F(ScalarReplacementTest,IdBoundOverflow2)1671 TEST_F(ScalarReplacementTest, IdBoundOverflow2) {
1672 const std::string text = R"(
1673 OpCapability Shader
1674 OpMemoryModel Logical GLSL450
1675 OpEntryPoint Fragment %4 "main" %17
1676 OpExecutionMode %4 OriginUpperLeft
1677 %2 = OpTypeVoid
1678 %3 = OpTypeFunction %2
1679 %6 = OpTypeFloat 32
1680 %7 = OpTypeVector %6 4
1681 %8 = OpTypeStruct %7
1682 %9 = OpTypePointer Function %8
1683 %16 = OpTypePointer Output %7
1684 %21 = OpTypeInt 32 1
1685 %22 = OpConstant %21 0
1686 %23 = OpTypePointer Function %7
1687 %17 = OpVariable %16 Output
1688 %4 = OpFunction %2 None %3
1689 %5 = OpLabel
1690 %4194300 = OpVariable %23 Function
1691 %10 = OpVariable %9 Function
1692 %4194301 = OpAccessChain %23 %10 %22
1693 %4194302 = OpLoad %7 %4194301
1694 OpStore %4194300 %4194302
1695 %15 = OpLoad %7 %4194300
1696 OpStore %17 %15
1697 OpReturn
1698 OpFunctionEnd
1699 )";
1700
1701 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
1702
1703 std::vector<Message> messages = {
1704 {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."}};
1705 SetMessageConsumer(GetTestMessageConsumer(messages));
1706 auto result = SinglePassRunToBinary<ScalarReplacementPass>(text, true, false);
1707 EXPECT_EQ(Pass::Status::Failure, std::get<1>(result));
1708 }
1709
1710 // Test that id overflow is handled gracefully.
TEST_F(ScalarReplacementTest,IdBoundOverflow3)1711 TEST_F(ScalarReplacementTest, IdBoundOverflow3) {
1712 const std::string text = R"(
1713 OpCapability InterpolationFunction
1714 OpExtension "z"
1715 OpMemoryModel Logical GLSL450
1716 OpEntryPoint Fragment %4 "main"
1717 OpExecutionMode %4 OriginUpperLeft
1718 %2 = OpTypeVoid
1719 %3 = OpTypeFunction %2
1720 %6 = OpTypeFloat 32
1721 %7 = OpTypeStruct %6 %6
1722 %9 = OpTypePointer Function %7
1723 %18 = OpTypeFunction %7 %9
1724 %21 = OpTypeInt 32 0
1725 %22 = OpConstant %21 4293000676
1726 %4194302 = OpConstantNull %6
1727 %4 = OpFunction %2 Inline|Pure %3
1728 %786464 = OpLabel
1729 %4194298 = OpVariable %9 Function
1730 %10 = OpVariable %9 Function
1731 %4194299 = OpUDiv %21 %22 %22
1732 %4194300 = OpLoad %7 %10
1733 %50959 = OpLoad %7 %4194298
1734 OpKill
1735 OpFunctionEnd
1736 %1 = OpFunction %7 None %18
1737 %19 = OpFunctionParameter %9
1738 %147667 = OpLabel
1739 %2044391 = OpUDiv %21 %22 %22
1740 %25 = OpLoad %7 %19
1741 OpReturnValue %25
1742 OpFunctionEnd
1743 %4194295 = OpFunction %2 None %3
1744 %4194296 = OpLabel
1745 OpKill
1746 OpFunctionEnd
1747 )";
1748
1749 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
1750
1751 std::vector<Message> messages = {
1752 {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."},
1753 {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."},
1754 {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."},
1755 {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."},
1756 {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."},
1757 {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."},
1758 {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."},
1759 {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."},
1760 {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."}};
1761 SetMessageConsumer(GetTestMessageConsumer(messages));
1762 auto result = SinglePassRunToBinary<ScalarReplacementPass>(text, true, false);
1763 EXPECT_EQ(Pass::Status::Failure, std::get<1>(result));
1764 }
1765
1766 // Test that replacements for OpAccessChain do not go out of bounds.
1767 // https://github.com/KhronosGroup/SPIRV-Tools/issues/2609.
TEST_F(ScalarReplacementTest,OutOfBoundOpAccessChain)1768 TEST_F(ScalarReplacementTest, OutOfBoundOpAccessChain) {
1769 const std::string text = R"(
1770 OpCapability Shader
1771 %1 = OpExtInstImport "GLSL.std.450"
1772 OpMemoryModel Logical GLSL450
1773 OpEntryPoint Fragment %main "main" %_GLF_color
1774 OpExecutionMode %main OriginUpperLeft
1775 OpSource ESSL 310
1776 OpName %main "main"
1777 OpName %a "a"
1778 OpName %_GLF_color "_GLF_color"
1779 OpDecorate %_GLF_color Location 0
1780 %void = OpTypeVoid
1781 %3 = OpTypeFunction %void
1782 %int = OpTypeInt 32 1
1783 %_ptr_Function_int = OpTypePointer Function %int
1784 %int_1 = OpConstant %int 1
1785 %float = OpTypeFloat 32
1786 %uint = OpTypeInt 32 0
1787 %uint_1 = OpConstant %uint 1
1788 %_arr_float_uint_1 = OpTypeArray %float %uint_1
1789 %_ptr_Function__arr_float_uint_1 = OpTypePointer Function %_arr_float_uint_1
1790 %_ptr_Function_float = OpTypePointer Function %float
1791 %_ptr_Output_float = OpTypePointer Output %float
1792 %_GLF_color = OpVariable %_ptr_Output_float Output
1793 %main = OpFunction %void None %3
1794 %5 = OpLabel
1795 %a = OpVariable %_ptr_Function__arr_float_uint_1 Function
1796 %21 = OpAccessChain %_ptr_Function_float %a %int_1
1797 %22 = OpLoad %float %21
1798 OpStore %_GLF_color %22
1799 OpReturn
1800 OpFunctionEnd
1801 )";
1802
1803 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
1804
1805 auto result =
1806 SinglePassRunAndDisassemble<ScalarReplacementPass>(text, true, false);
1807 EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
1808 }
1809
TEST_F(ScalarReplacementTest,CharIndex)1810 TEST_F(ScalarReplacementTest, CharIndex) {
1811 const std::string text = R"(
1812 ; CHECK: [[int:%\w+]] = OpTypeInt 32 0
1813 ; CHECK: [[ptr:%\w+]] = OpTypePointer Function [[int]]
1814 ; CHECK: OpVariable [[ptr]] Function
1815 OpCapability Shader
1816 OpCapability Int8
1817 OpMemoryModel Logical GLSL450
1818 OpEntryPoint GLCompute %main "main"
1819 OpExecutionMode %main LocalSize 1 1 1
1820 %void = OpTypeVoid
1821 %int = OpTypeInt 32 0
1822 %int_1024 = OpConstant %int 1024
1823 %char = OpTypeInt 8 0
1824 %char_1 = OpConstant %char 1
1825 %array = OpTypeArray %int %int_1024
1826 %ptr_func_array = OpTypePointer Function %array
1827 %ptr_func_int = OpTypePointer Function %int
1828 %void_fn = OpTypeFunction %void
1829 %main = OpFunction %void None %void_fn
1830 %entry = OpLabel
1831 %var = OpVariable %ptr_func_array Function
1832 %gep = OpAccessChain %ptr_func_int %var %char_1
1833 OpStore %gep %int_1024
1834 OpReturn
1835 OpFunctionEnd
1836 )";
1837
1838 SinglePassRunAndMatch<ScalarReplacementPass>(text, true, 0);
1839 }
1840
TEST_F(ScalarReplacementTest,OutOfBoundsOpAccessChainNegative)1841 TEST_F(ScalarReplacementTest, OutOfBoundsOpAccessChainNegative) {
1842 const std::string text = R"(
1843 OpCapability Shader
1844 OpCapability Int8
1845 OpMemoryModel Logical GLSL450
1846 OpEntryPoint GLCompute %main "main"
1847 OpExecutionMode %main LocalSize 1 1 1
1848 %void = OpTypeVoid
1849 %int = OpTypeInt 32 0
1850 %int_1024 = OpConstant %int 1024
1851 %char = OpTypeInt 8 1
1852 %char_n1 = OpConstant %char -1
1853 %array = OpTypeArray %int %int_1024
1854 %ptr_func_array = OpTypePointer Function %array
1855 %ptr_func_int = OpTypePointer Function %int
1856 %void_fn = OpTypeFunction %void
1857 %main = OpFunction %void None %void_fn
1858 %entry = OpLabel
1859 %var = OpVariable %ptr_func_array Function
1860 %gep = OpAccessChain %ptr_func_int %var %char_n1
1861 OpStore %gep %int_1024
1862 OpReturn
1863 OpFunctionEnd
1864 )";
1865
1866 auto result =
1867 SinglePassRunAndDisassemble<ScalarReplacementPass>(text, true, true, 0);
1868 EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
1869 }
1870
TEST_F(ScalarReplacementTest,RelaxedPrecisionMemberDecoration)1871 TEST_F(ScalarReplacementTest, RelaxedPrecisionMemberDecoration) {
1872 const std::string text = R"(
1873 ; CHECK: OpDecorate {{%\w+}} RelaxedPrecision
1874 ; CHECK: OpDecorate [[new_var:%\w+]] RelaxedPrecision
1875 ; CHECK: [[new_var]] = OpVariable %_ptr_Function_v3float Function
1876 ; CHECK: OpLoad %v3float [[new_var]]
1877 OpCapability Shader
1878 OpMemoryModel Logical GLSL450
1879 OpEntryPoint Vertex %1 "Draw2DTexCol_VS" %2 %3
1880 OpSource HLSL 600
1881 OpDecorate %2 Location 0
1882 OpDecorate %3 Location 1
1883 OpDecorate %3 RelaxedPrecision
1884 OpMemberDecorate %_struct_4 1 RelaxedPrecision
1885 %float = OpTypeFloat 32
1886 %int = OpTypeInt 32 1
1887 %int_1 = OpConstant %int 1
1888 %v3float = OpTypeVector %float 3
1889 %_ptr_Input_v3float = OpTypePointer Input %v3float
1890 %void = OpTypeVoid
1891 %11 = OpTypeFunction %void
1892 %_struct_4 = OpTypeStruct %v3float %v3float
1893 %_ptr_Function__struct_4 = OpTypePointer Function %_struct_4
1894 %_ptr_Function_v3float = OpTypePointer Function %v3float
1895 %2 = OpVariable %_ptr_Input_v3float Input
1896 %3 = OpVariable %_ptr_Input_v3float Input
1897 %1 = OpFunction %void None %11
1898 %14 = OpLabel
1899 %15 = OpVariable %_ptr_Function__struct_4 Function
1900 %16 = OpLoad %v3float %2
1901 %17 = OpLoad %v3float %3
1902 %18 = OpCompositeConstruct %_struct_4 %16 %17
1903 OpStore %15 %18
1904 %19 = OpAccessChain %_ptr_Function_v3float %15 %int_1
1905 %20 = OpLoad %v3float %19
1906 OpReturn
1907 OpFunctionEnd
1908 )";
1909
1910 SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
1911 }
1912
TEST_F(ScalarReplacementTest,DebugDeclare)1913 TEST_F(ScalarReplacementTest, DebugDeclare) {
1914 const std::string text = R"(
1915 OpCapability Shader
1916 OpCapability Linkage
1917 %ext = OpExtInstImport "OpenCL.DebugInfo.100"
1918 OpMemoryModel Logical GLSL450
1919 %test = OpString "test"
1920 OpName %6 "simple_struct"
1921 %1 = OpTypeVoid
1922 %2 = OpTypeInt 32 0
1923 %uint_32 = OpConstant %2 32
1924 %3 = OpTypeStruct %2 %2 %2 %2
1925 %4 = OpTypePointer Function %3
1926 %5 = OpTypePointer Function %2
1927 %6 = OpTypeFunction %2
1928 %7 = OpConstantNull %3
1929 %8 = OpConstant %2 0
1930 %9 = OpConstant %2 1
1931 %10 = OpConstant %2 2
1932 %11 = OpConstant %2 3
1933 %null_expr = OpExtInst %1 %ext DebugExpression
1934 %src = OpExtInst %1 %ext DebugSource %test
1935 %cu = OpExtInst %1 %ext DebugCompilationUnit 1 4 %src HLSL
1936 %dbg_tf = OpExtInst %1 %ext DebugTypeBasic %test %uint_32 Float
1937 %main_ty = OpExtInst %1 %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %1
1938 %dbg_main = OpExtInst %1 %ext DebugFunction %test %main_ty %src 0 0 %cu %test FlagIsProtected|FlagIsPrivate 0 %12
1939 %dbg_foo = OpExtInst %1 %ext DebugLocalVariable %test %dbg_tf %src 0 0 %dbg_main FlagIsLocal
1940 %12 = OpFunction %2 None %6
1941 %13 = OpLabel
1942 %scope = OpExtInst %1 %ext DebugScope %dbg_main
1943 %14 = OpVariable %4 Function %7
1944
1945 ; CHECK: [[deref:%\w+]] = OpExtInst %void [[ext:%\w+]] DebugOperation Deref
1946 ; CHECK: [[dbg_local_var:%\w+]] = OpExtInst %void [[ext]] DebugLocalVariable
1947 ; CHECK: [[deref_expr:%\w+]] = OpExtInst %void [[ext]] DebugExpression [[deref]]
1948 ; CHECK: [[repl3:%\w+]] = OpVariable %_ptr_Function_uint Function
1949 ; CHECK: [[repl2:%\w+]] = OpVariable %_ptr_Function_uint Function
1950 ; CHECK: [[repl1:%\w+]] = OpVariable %_ptr_Function_uint Function
1951 ; CHECK: [[repl0:%\w+]] = OpVariable %_ptr_Function_uint Function
1952 ; CHECK: OpExtInst %void [[ext]] DebugValue [[dbg_local_var]] [[repl3]] [[deref_expr]] %int_3
1953 ; CHECK: OpExtInst %void [[ext]] DebugValue [[dbg_local_var]] [[repl2]] [[deref_expr]] %int_2
1954 ; CHECK: OpExtInst %void [[ext]] DebugValue [[dbg_local_var]] [[repl1]] [[deref_expr]] %int_1
1955 ; CHECK: OpExtInst %void [[ext]] DebugValue [[dbg_local_var]] [[repl0]] [[deref_expr]] %int_0
1956 ; CHECK-NOT: DebugDeclare
1957 %decl = OpExtInst %1 %ext DebugDeclare %dbg_foo %14 %null_expr
1958
1959 %15 = OpInBoundsAccessChain %5 %14 %8
1960 %16 = OpLoad %2 %15
1961 %17 = OpAccessChain %5 %14 %10
1962 %18 = OpLoad %2 %17
1963 %19 = OpIAdd %2 %16 %18
1964 OpReturnValue %19
1965 OpFunctionEnd
1966 )";
1967
1968 SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
1969 }
1970
TEST_F(ScalarReplacementTest,DebugValue)1971 TEST_F(ScalarReplacementTest, DebugValue) {
1972 const std::string text = R"(
1973 OpCapability Shader
1974 OpCapability Linkage
1975 %ext = OpExtInstImport "OpenCL.DebugInfo.100"
1976 OpMemoryModel Logical GLSL450
1977 %test = OpString "test"
1978 OpName %6 "simple_struct"
1979 %1 = OpTypeVoid
1980 %2 = OpTypeInt 32 0
1981 %uint_32 = OpConstant %2 32
1982 %3 = OpTypeStruct %2 %2 %2 %2
1983 %4 = OpTypePointer Function %3
1984 %5 = OpTypePointer Function %2
1985 %6 = OpTypeFunction %2
1986 %7 = OpConstantNull %3
1987 %8 = OpConstant %2 0
1988 %9 = OpConstant %2 1
1989 %10 = OpConstant %2 2
1990 %11 = OpConstant %2 3
1991 %deref = OpExtInst %1 %ext DebugOperation Deref
1992 %deref_expr = OpExtInst %1 %ext DebugExpression %deref
1993 %null_expr = OpExtInst %1 %ext DebugExpression
1994 %src = OpExtInst %1 %ext DebugSource %test
1995 %cu = OpExtInst %1 %ext DebugCompilationUnit 1 4 %src HLSL
1996 %dbg_tf = OpExtInst %1 %ext DebugTypeBasic %test %uint_32 Float
1997 %main_ty = OpExtInst %1 %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %1
1998 %dbg_main = OpExtInst %1 %ext DebugFunction %test %main_ty %src 0 0 %cu %test FlagIsProtected|FlagIsPrivate 0 %12
1999 %dbg_foo = OpExtInst %1 %ext DebugLocalVariable %test %dbg_tf %src 0 0 %dbg_main FlagIsLocal
2000 %12 = OpFunction %2 None %6
2001 %13 = OpLabel
2002 %scope = OpExtInst %1 %ext DebugScope %dbg_main
2003 %14 = OpVariable %4 Function %7
2004
2005 ; CHECK: [[deref:%\w+]] = OpExtInst %void [[ext:%\w+]] DebugOperation Deref
2006 ; CHECK: [[deref_expr:%\w+]] = OpExtInst %void [[ext]] DebugExpression [[deref]]
2007 ; CHECK: [[dbg_local_var:%\w+]] = OpExtInst %void [[ext]] DebugLocalVariable
2008 ; CHECK: [[repl3:%\w+]] = OpVariable %_ptr_Function_uint Function
2009 ; CHECK: [[repl2:%\w+]] = OpVariable %_ptr_Function_uint Function
2010 ; CHECK: [[repl1:%\w+]] = OpVariable %_ptr_Function_uint Function
2011 ; CHECK: [[repl0:%\w+]] = OpVariable %_ptr_Function_uint Function
2012 ; CHECK: OpExtInst %void [[ext]] DebugValue [[dbg_local_var]] [[repl0]] [[deref_expr]] %int_0
2013 ; CHECK: OpExtInst %void [[ext]] DebugValue [[dbg_local_var]] [[repl1]] [[deref_expr]] %int_1
2014 ; CHECK: OpExtInst %void [[ext]] DebugValue [[dbg_local_var]] [[repl2]] [[deref_expr]] %int_2
2015 ; CHECK: OpExtInst %void [[ext]] DebugValue [[dbg_local_var]] [[repl3]] [[deref_expr]] %int_3
2016 %value = OpExtInst %1 %ext DebugValue %dbg_foo %14 %deref_expr
2017
2018 %15 = OpInBoundsAccessChain %5 %14 %8
2019 %16 = OpLoad %2 %15
2020 %17 = OpAccessChain %5 %14 %10
2021 %18 = OpLoad %2 %17
2022 %19 = OpIAdd %2 %16 %18
2023 OpReturnValue %19
2024 OpFunctionEnd
2025 )";
2026
2027 SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
2028 }
2029
TEST_F(ScalarReplacementTest,DebugDeclareRecursive)2030 TEST_F(ScalarReplacementTest, DebugDeclareRecursive) {
2031 const std::string text = R"(
2032 OpCapability Shader
2033 OpCapability Linkage
2034 %ext = OpExtInstImport "OpenCL.DebugInfo.100"
2035 OpMemoryModel Logical GLSL450
2036 %test = OpString "test"
2037 OpName %6 "simple_struct"
2038 %1 = OpTypeVoid
2039 %2 = OpTypeInt 32 0
2040 %uint_32 = OpConstant %2 32
2041 %float = OpTypeFloat 32
2042 %float_1 = OpConstant %float 1
2043 %member = OpTypeStruct %2 %float
2044 %3 = OpTypeStruct %2 %member %float
2045 %4 = OpTypePointer Function %3
2046 %5 = OpTypePointer Function %2
2047 %ptr_float_Function = OpTypePointer Function %float
2048 %6 = OpTypeFunction %2
2049 %cmember = OpConstantComposite %member %uint_32 %float_1
2050 %7 = OpConstantComposite %3 %uint_32 %cmember %float_1
2051 %8 = OpConstant %2 0
2052 %9 = OpConstant %2 1
2053 %10 = OpConstant %2 2
2054 %null_expr = OpExtInst %1 %ext DebugExpression
2055 %src = OpExtInst %1 %ext DebugSource %test
2056 %cu = OpExtInst %1 %ext DebugCompilationUnit 1 4 %src HLSL
2057 %dbg_tf = OpExtInst %1 %ext DebugTypeBasic %test %uint_32 Float
2058 %main_ty = OpExtInst %1 %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %1
2059 %dbg_main = OpExtInst %1 %ext DebugFunction %test %main_ty %src 0 0 %cu %test FlagIsProtected|FlagIsPrivate 0 %12
2060 %dbg_foo = OpExtInst %1 %ext DebugLocalVariable %test %dbg_tf %src 0 0 %dbg_main FlagIsLocal
2061 %12 = OpFunction %2 None %6
2062 %13 = OpLabel
2063 %scope = OpExtInst %1 %ext DebugScope %dbg_main
2064 %14 = OpVariable %4 Function %7
2065
2066 ; CHECK: [[deref:%\w+]] = OpExtInst %void [[ext:%\w+]] DebugOperation Deref
2067 ; CHECK: [[dbg_local_var:%\w+]] = OpExtInst %void [[ext]] DebugLocalVariable
2068 ; CHECK: [[deref_expr:%\w+]] = OpExtInst %void [[ext]] DebugExpression [[deref]]
2069 ; CHECK: [[repl2:%\w+]] = OpVariable %_ptr_Function_float Function %float_1
2070 ; CHECK: [[repl1:%\w+]] = OpVariable %_ptr_Function_uint Function %uint_32
2071 ; CHECK: [[repl3:%\w+]] = OpVariable %_ptr_Function_float Function %float_1
2072 ; CHECK: [[repl0:%\w+]] = OpVariable %_ptr_Function_uint Function %uint_32
2073 ; CHECK: OpExtInst %void [[ext]] DebugValue [[dbg_local_var]] [[repl3]] [[deref_expr]] %int_2
2074 ; CHECK: OpExtInst %void [[ext]] DebugValue [[dbg_local_var]] [[repl1]] [[deref_expr]] %int_1 %int_0
2075 ; CHECK: OpExtInst %void [[ext]] DebugValue [[dbg_local_var]] [[repl2]] [[deref_expr]] %int_1 %int_1
2076 ; CHECK: OpExtInst %void [[ext]] DebugValue [[dbg_local_var]] [[repl0]] [[deref_expr]] %int_0
2077 ; CHECK-NOT: DebugDeclare
2078 %decl = OpExtInst %1 %ext DebugDeclare %dbg_foo %14 %null_expr
2079
2080 %15 = OpInBoundsAccessChain %5 %14 %8
2081 %16 = OpLoad %2 %15
2082 %17 = OpAccessChain %ptr_float_Function %14 %10
2083 %18 = OpLoad %float %17
2084 %value = OpConvertFToU %2 %18
2085 %19 = OpIAdd %2 %16 %value
2086 OpReturnValue %19
2087 OpFunctionEnd
2088 )";
2089
2090 SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
2091 }
2092
TEST_F(ScalarReplacementTest,DebugValueWithIndex)2093 TEST_F(ScalarReplacementTest, DebugValueWithIndex) {
2094 const std::string text = R"(
2095 OpCapability Shader
2096 OpCapability Linkage
2097 %ext = OpExtInstImport "OpenCL.DebugInfo.100"
2098 OpMemoryModel Logical GLSL450
2099 %test = OpString "test"
2100 OpName %6 "simple_struct"
2101 %1 = OpTypeVoid
2102 %2 = OpTypeInt 32 0
2103 %uint_32 = OpConstant %2 32
2104 %3 = OpTypeStruct %2 %2 %2 %2
2105 %4 = OpTypePointer Function %3
2106 %5 = OpTypePointer Function %2
2107 %6 = OpTypeFunction %2
2108 %7 = OpConstantNull %3
2109 %8 = OpConstant %2 0
2110 %9 = OpConstant %2 1
2111 %10 = OpConstant %2 2
2112 %11 = OpConstant %2 3
2113 %deref = OpExtInst %1 %ext DebugOperation Deref
2114 %deref_expr = OpExtInst %1 %ext DebugExpression %deref
2115 %null_expr = OpExtInst %1 %ext DebugExpression
2116 %src = OpExtInst %1 %ext DebugSource %test
2117 %cu = OpExtInst %1 %ext DebugCompilationUnit 1 4 %src HLSL
2118 %dbg_tf = OpExtInst %1 %ext DebugTypeBasic %test %uint_32 Float
2119 %main_ty = OpExtInst %1 %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %1
2120 %dbg_main = OpExtInst %1 %ext DebugFunction %test %main_ty %src 0 0 %cu %test FlagIsProtected|FlagIsPrivate 0 %12
2121 %dbg_foo = OpExtInst %1 %ext DebugLocalVariable %test %dbg_tf %src 0 0 %dbg_main FlagIsLocal
2122 %12 = OpFunction %2 None %6
2123 %13 = OpLabel
2124 %scope = OpExtInst %1 %ext DebugScope %dbg_main
2125 %14 = OpVariable %4 Function %7
2126
2127 ; CHECK: [[deref:%\w+]] = OpExtInst %void [[ext:%\w+]] DebugOperation Deref
2128 ; CHECK: [[deref_expr:%\w+]] = OpExtInst %void [[ext]] DebugExpression [[deref]]
2129 ; CHECK: [[dbg_local_var:%\w+]] = OpExtInst %void [[ext]] DebugLocalVariable
2130 ; CHECK: [[repl3:%\w+]] = OpVariable %_ptr_Function_uint Function
2131 ; CHECK: [[repl2:%\w+]] = OpVariable %_ptr_Function_uint Function
2132 ; CHECK: [[repl1:%\w+]] = OpVariable %_ptr_Function_uint Function
2133 ; CHECK: [[repl0:%\w+]] = OpVariable %_ptr_Function_uint Function
2134 ; CHECK: OpExtInst %void [[ext]] DebugValue [[dbg_local_var]] [[repl0]] [[deref_expr]] %uint_0 %uint_1 %uint_2 %int_0
2135 ; CHECK: OpExtInst %void [[ext]] DebugValue [[dbg_local_var]] [[repl1]] [[deref_expr]] %uint_0 %uint_1 %uint_2 %int_1
2136 ; CHECK: OpExtInst %void [[ext]] DebugValue [[dbg_local_var]] [[repl2]] [[deref_expr]] %uint_0 %uint_1 %uint_2 %int_2
2137 ; CHECK: OpExtInst %void [[ext]] DebugValue [[dbg_local_var]] [[repl3]] [[deref_expr]] %uint_0 %uint_1 %uint_2 %int_3
2138 %value = OpExtInst %1 %ext DebugValue %dbg_foo %14 %deref_expr %8 %9 %10
2139
2140 %15 = OpInBoundsAccessChain %5 %14 %8
2141 %16 = OpLoad %2 %15
2142 %17 = OpAccessChain %5 %14 %10
2143 %18 = OpLoad %2 %17
2144 %19 = OpIAdd %2 %16 %18
2145 OpReturnValue %19
2146 OpFunctionEnd
2147 )";
2148
2149 SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
2150 }
2151
TEST_F(ScalarReplacementTest,DebugDeclareForVariableInOtherBB)2152 TEST_F(ScalarReplacementTest, DebugDeclareForVariableInOtherBB) {
2153 const std::string text = R"(
2154 OpCapability Shader
2155 OpCapability Linkage
2156 %ext = OpExtInstImport "OpenCL.DebugInfo.100"
2157 OpMemoryModel Logical GLSL450
2158 %test = OpString "test"
2159 OpName %6 "simple_struct"
2160 %1 = OpTypeVoid
2161 %2 = OpTypeInt 32 0
2162 %uint_32 = OpConstant %2 32
2163 %3 = OpTypeStruct %2 %2 %2 %2
2164 %4 = OpTypePointer Function %3
2165 %5 = OpTypePointer Function %2
2166 %6 = OpTypeFunction %2
2167 %7 = OpConstantNull %3
2168 %8 = OpConstant %2 0
2169 %9 = OpConstant %2 1
2170 %10 = OpConstant %2 2
2171 %11 = OpConstant %2 3
2172 %deref = OpExtInst %1 %ext DebugOperation Deref
2173 %deref_expr = OpExtInst %1 %ext DebugExpression %deref
2174 %null_expr = OpExtInst %1 %ext DebugExpression
2175 %src = OpExtInst %1 %ext DebugSource %test
2176 %cu = OpExtInst %1 %ext DebugCompilationUnit 1 4 %src HLSL
2177 %dbg_tf = OpExtInst %1 %ext DebugTypeBasic %test %uint_32 Float
2178 %main_ty = OpExtInst %1 %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %1
2179 %dbg_main = OpExtInst %1 %ext DebugFunction %test %main_ty %src 0 0 %cu %test FlagIsProtected|FlagIsPrivate 0 %12
2180 %dbg_foo = OpExtInst %1 %ext DebugLocalVariable %test %dbg_tf %src 0 0 %dbg_main FlagIsLocal
2181 %12 = OpFunction %2 None %6
2182 %13 = OpLabel
2183 %scope = OpExtInst %1 %ext DebugScope %dbg_main
2184 %14 = OpVariable %4 Function %7
2185
2186 ; CHECK: [[dbg_local_var:%\w+]] = OpExtInst %void [[ext:%\w+]] DebugLocalVariable
2187 ; CHECK: [[repl3:%\w+]] = OpVariable %_ptr_Function_uint Function
2188 ; CHECK: [[repl2:%\w+]] = OpVariable %_ptr_Function_uint Function
2189 ; CHECK: [[repl1:%\w+]] = OpVariable %_ptr_Function_uint Function
2190 ; CHECK: [[repl0:%\w+]] = OpVariable %_ptr_Function_uint Function
2191 ; CHECK: OpExtInst %void [[ext]] DebugValue [[dbg_local_var]] [[repl3]] [[deref_expr:%\w+]] %int_3
2192 ; CHECK: OpExtInst %void [[ext]] DebugValue [[dbg_local_var]] [[repl2]] [[deref_expr]] %int_2
2193 ; CHECK: OpExtInst %void [[ext]] DebugValue [[dbg_local_var]] [[repl1]] [[deref_expr]] %int_1
2194 ; CHECK: OpExtInst %void [[ext]] DebugValue [[dbg_local_var]] [[repl0]] [[deref_expr]] %int_0
2195
2196 OpBranch %20
2197 %20 = OpLabel
2198 %value = OpExtInst %1 %ext DebugDeclare %dbg_foo %14 %null_expr
2199 %15 = OpInBoundsAccessChain %5 %14 %8
2200 %16 = OpLoad %2 %15
2201 %17 = OpAccessChain %5 %14 %10
2202 %18 = OpLoad %2 %17
2203 %19 = OpIAdd %2 %16 %18
2204 OpReturnValue %19
2205 OpFunctionEnd
2206 )";
2207
2208 SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
2209 }
2210
TEST_F(ScalarReplacementTest,ImageTexelPointer)2211 TEST_F(ScalarReplacementTest, ImageTexelPointer) {
2212 // Test whether the scalar replacement correctly checks the
2213 // OpImageTexelPointer user of an aggregate with an image type.
2214 const std::string text = R"(
2215 ;
2216 ; CHECK: [[imgTy:%\w+]] = OpTypeImage %uint Buffer 2 0 0 2 R32ui
2217 ; CHECK: [[ptrImgTy:%\w+]] = OpTypePointer Function [[imgTy]]
2218 ; CHECK: [[img:%\w+]] = OpVariable [[ptrImgTy]] Function
2219 ; CHECK: [[imgTexelPtr:%\w+]] = OpImageTexelPointer {{%\w+}} [[img]] %uint_0 %uint_0
2220 ; CHECK: OpAtomicIAdd %uint [[imgTexelPtr]] %uint_1 %uint_0 %uint_1
2221 ;
2222 OpCapability Shader
2223 OpCapability SampledBuffer
2224 OpCapability ImageBuffer
2225 OpMemoryModel Logical GLSL450
2226 OpEntryPoint GLCompute %1 "main"
2227 OpExecutionMode %1 LocalSize 64 1 1
2228 %void = OpTypeVoid
2229 %uint = OpTypeInt 32 0
2230 %uint_0 = OpConstant %uint 0
2231 %uint_1 = OpConstant %uint 1
2232 %_ptr_Image_uint = OpTypePointer Image %uint
2233 %type_buffer_image = OpTypeImage %uint Buffer 2 0 0 2 R32ui
2234 %_ptr_Function_type_buffer_image = OpTypePointer Function %type_buffer_image
2235 %image_struct = OpTypeStruct %type_buffer_image %type_buffer_image
2236 %_ptr_Function_image_struct = OpTypePointer Function %image_struct
2237 %func = OpTypeFunction %void
2238 %1 = OpFunction %void None %func
2239 %2 = OpLabel
2240 %3 = OpVariable %_ptr_Function_image_struct Function
2241 %4 = OpAccessChain %_ptr_Function_type_buffer_image %3 %uint_1
2242 %5 = OpImageTexelPointer %_ptr_Image_uint %4 %uint_0 %uint_0
2243 %6 = OpAtomicIAdd %uint %5 %uint_1 %uint_0 %uint_1
2244 OpReturn
2245 OpFunctionEnd
2246 )";
2247
2248 SinglePassRunAndMatch<ScalarReplacementPass>(text, false);
2249 }
2250
TEST_F(ScalarReplacementTest,FunctionDeclaration)2251 TEST_F(ScalarReplacementTest, FunctionDeclaration) {
2252 // Make sure the pass works with a function declaration that is called.
2253 const std::string text = R"(OpCapability Addresses
2254 OpCapability Linkage
2255 OpCapability Kernel
2256 OpCapability Int8
2257 %1 = OpExtInstImport "OpenCL.std"
2258 OpMemoryModel Physical64 OpenCL
2259 OpEntryPoint Kernel %2 "_Z23julia__1166_kernel_77094Bool"
2260 OpExecutionMode %2 ContractionOff
2261 OpSource Unknown 0
2262 OpDecorate %3 LinkageAttributes "julia_error_7712" Import
2263 %void = OpTypeVoid
2264 %5 = OpTypeFunction %void
2265 %3 = OpFunction %void None %5
2266 OpFunctionEnd
2267 %2 = OpFunction %void None %5
2268 %6 = OpLabel
2269 %7 = OpFunctionCall %void %3
2270 OpReturn
2271 OpFunctionEnd
2272 )";
2273
2274 SinglePassRunAndCheck<ScalarReplacementPass>(text, text, false);
2275 }
2276
TEST_F(ScalarReplacementTest,UndefImageMember)2277 TEST_F(ScalarReplacementTest, UndefImageMember) {
2278 // Test that scalar replacement creates an undef for a type that cannot have
2279 // and OpConstantNull.
2280 const std::string text = R"(
2281 ; CHECK: [[image_type:%\w+]] = OpTypeSampledImage {{%\w+}}
2282 ; CHECK: [[struct_type:%\w+]] = OpTypeStruct [[image_type]]
2283 ; CHECK: [[undef:%\w+]] = OpUndef [[image_type]]
2284 ; CHECK: {{%\w+}} = OpCompositeConstruct [[struct_type]] [[undef]]
2285 OpCapability Shader
2286 %1 = OpExtInstImport "GLSL.std.450"
2287 OpMemoryModel Logical GLSL450
2288 OpEntryPoint Fragment %2 "main"
2289 OpExecutionMode %2 OriginUpperLeft
2290 %void = OpTypeVoid
2291 %4 = OpTypeFunction %void
2292 %float = OpTypeFloat 32
2293 %6 = OpTypeImage %float 2D 0 0 0 1 Unknown
2294 %7 = OpTypeSampledImage %6
2295 %_struct_8 = OpTypeStruct %7
2296 %9 = OpTypeFunction %_struct_8
2297 %10 = OpUndef %_struct_8
2298 %_ptr_Function__struct_8 = OpTypePointer Function %_struct_8
2299 %2 = OpFunction %void None %4
2300 %11 = OpLabel
2301 %16 = OpVariable %_ptr_Function__struct_8 Function
2302 OpStore %16 %10
2303 %12 = OpLoad %_struct_8 %16
2304 OpReturn
2305 OpFunctionEnd
2306 )";
2307
2308 SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
2309 }
2310
TEST_F(ScalarReplacementTest,RestrictPointer)2311 TEST_F(ScalarReplacementTest, RestrictPointer) {
2312 // This test makes sure that a variable with the restrict pointer decoration
2313 // is replaced, and that the pointer is applied to the new variable.
2314 const std::string text = R"(
2315 ; CHECK: OpDecorate [[new_var:%\w+]] RestrictPointer
2316 ; CHECK: [[struct_type:%\w+]] = OpTypeStruct %int
2317 ; CHECK: [[ptr_type:%\w+]] = OpTypePointer PhysicalStorageBuffer [[struct_type]]
2318 ; CHECK: [[dup_struct_type:%\w+]] = OpTypeStruct %int
2319 ; CHECK: {{%\w+}} = OpTypePointer PhysicalStorageBuffer [[dup_struct_type]]
2320 ; CHECK: [[var_type:%\w+]] = OpTypePointer Function [[ptr_type]]
2321 ; CHECK: [[new_var]] = OpVariable [[var_type]] Function
2322 OpCapability Shader
2323 OpCapability PhysicalStorageBufferAddresses
2324 %1 = OpExtInstImport "GLSL.std.450"
2325 OpMemoryModel PhysicalStorageBuffer64 GLSL450
2326 OpEntryPoint Fragment %2 "main"
2327 OpExecutionMode %2 OriginUpperLeft
2328 OpMemberDecorate %3 0 Offset 0
2329 OpDecorate %3 Block
2330 OpMemberDecorate %4 0 Offset 0
2331 OpDecorate %4 Block
2332 OpDecorate %5 RestrictPointer
2333 %6 = OpTypeVoid
2334 %7 = OpTypeFunction %6
2335 %8 = OpTypeInt 32 1
2336 %9 = OpConstant %8 0
2337 %3 = OpTypeStruct %8
2338 %10 = OpTypePointer PhysicalStorageBuffer %3
2339 %11 = OpTypeStruct %10
2340 %4 = OpTypeStruct %8
2341 %12 = OpTypePointer PhysicalStorageBuffer %4
2342 %13 = OpTypePointer Function %11
2343 %14 = OpTypePointer Function %10
2344 %15 = OpTypePointer Function %12
2345 %16 = OpUndef %11
2346 %2 = OpFunction %6 None %7
2347 %17 = OpLabel
2348 %5 = OpVariable %13 Function
2349 OpStore %5 %16
2350 %18 = OpAccessChain %14 %5 %9
2351 OpReturn
2352 OpFunctionEnd
2353 )";
2354
2355 SetTargetEnv(SPV_ENV_UNIVERSAL_1_6);
2356 SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
2357 }
2358
2359 } // namespace
2360 } // namespace opt
2361 } // namespace spvtools
2362