1 // Copyright (c) 2018 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include <string>
16 
17 #include "gmock/gmock.h"
18 #include "test/opt/assembly_builder.h"
19 #include "test/opt/pass_fixture.h"
20 #include "test/opt/pass_utils.h"
21 
22 namespace spvtools {
23 namespace opt {
24 namespace {
25 
26 using CombineAccessChainsTest = PassTest<::testing::Test>;
27 
TEST_F(CombineAccessChainsTest,PtrAccessChainFromAccessChainConstant)28 TEST_F(CombineAccessChainsTest, PtrAccessChainFromAccessChainConstant) {
29   const std::string text = R"(
30 ; CHECK: [[int:%\w+]] = OpTypeInt 32 0
31 ; CHECK: [[int3:%\w+]] = OpConstant [[int]] 3
32 ; CHECK: [[ptr_int:%\w+]] = OpTypePointer Workgroup [[int]]
33 ; CHECK: [[var:%\w+]] = OpVariable {{%\w+}} Workgroup
34 ; CHECK: OpAccessChain [[ptr_int]] [[var]] [[int3]]
35 OpCapability Shader
36 OpCapability VariablePointers
37 OpExtension "SPV_KHR_variable_pointers"
38 OpMemoryModel Logical GLSL450
39 OpEntryPoint Fragment %main "main"
40 OpExecutionMode %main OriginUpperLeft
41 %void = OpTypeVoid
42 %uint = OpTypeInt 32 0
43 %uint_0 = OpConstant %uint 0
44 %uint_3 = OpConstant %uint 3
45 %uint_4 = OpConstant %uint 4
46 %uint_array_4 = OpTypeArray %uint %uint_4
47 %ptr_Workgroup_uint = OpTypePointer Workgroup %uint
48 %ptr_Workgroup_uint_array_4 = OpTypePointer Workgroup %uint_array_4
49 %var = OpVariable %ptr_Workgroup_uint_array_4 Workgroup
50 %void_func = OpTypeFunction %void
51 %main = OpFunction %void None %void_func
52 %main_lab = OpLabel
53 %gep = OpAccessChain %ptr_Workgroup_uint %var %uint_0
54 %ptr_gep = OpPtrAccessChain %ptr_Workgroup_uint %gep %uint_3
55 OpReturn
56 OpFunctionEnd
57 )";
58 
59   SinglePassRunAndMatch<CombineAccessChains>(text, true);
60 }
61 
TEST_F(CombineAccessChainsTest,PtrAccessChainFromInBoundsAccessChainConstant)62 TEST_F(CombineAccessChainsTest, PtrAccessChainFromInBoundsAccessChainConstant) {
63   const std::string text = R"(
64 ; CHECK: [[int:%\w+]] = OpTypeInt 32 0
65 ; CHECK: [[int3:%\w+]] = OpConstant [[int]] 3
66 ; CHECK: [[ptr_int:%\w+]] = OpTypePointer Workgroup [[int]]
67 ; CHECK: [[var:%\w+]] = OpVariable {{%\w+}} Workgroup
68 ; CHECK: OpAccessChain [[ptr_int]] [[var]] [[int3]]
69 OpCapability Shader
70 OpCapability VariablePointers
71 OpExtension "SPV_KHR_variable_pointers"
72 OpMemoryModel Logical GLSL450
73 OpEntryPoint Fragment %main "main"
74 OpExecutionMode %main OriginUpperLeft
75 %void = OpTypeVoid
76 %uint = OpTypeInt 32 0
77 %uint_0 = OpConstant %uint 0
78 %uint_3 = OpConstant %uint 3
79 %uint_4 = OpConstant %uint 4
80 %uint_array_4 = OpTypeArray %uint %uint_4
81 %ptr_Workgroup_uint = OpTypePointer Workgroup %uint
82 %ptr_Workgroup_uint_array_4 = OpTypePointer Workgroup %uint_array_4
83 %var = OpVariable %ptr_Workgroup_uint_array_4 Workgroup
84 %void_func = OpTypeFunction %void
85 %main = OpFunction %void None %void_func
86 %main_lab = OpLabel
87 %gep = OpInBoundsAccessChain %ptr_Workgroup_uint %var %uint_0
88 %ptr_gep = OpPtrAccessChain %ptr_Workgroup_uint %gep %uint_3
89 OpReturn
90 OpFunctionEnd
91 )";
92 
93   SinglePassRunAndMatch<CombineAccessChains>(text, true);
94 }
95 
TEST_F(CombineAccessChainsTest,PtrAccessChainFromAccessChainCombineConstant)96 TEST_F(CombineAccessChainsTest, PtrAccessChainFromAccessChainCombineConstant) {
97   const std::string text = R"(
98 ; CHECK: [[int:%\w+]] = OpTypeInt 32 0
99 ; CHECK: [[ptr_int:%\w+]] = OpTypePointer Workgroup [[int]]
100 ; CHECK: [[var:%\w+]] = OpVariable {{%\w+}} Workgroup
101 ; CHECK: [[int2:%\w+]] = OpConstant [[int]] 2
102 ; CHECK: OpAccessChain [[ptr_int]] [[var]] [[int2]]
103 OpCapability Shader
104 OpCapability VariablePointers
105 OpExtension "SPV_KHR_variable_pointers"
106 OpMemoryModel Logical GLSL450
107 OpEntryPoint Fragment %main "main"
108 OpExecutionMode %main OriginUpperLeft
109 %void = OpTypeVoid
110 %uint = OpTypeInt 32 0
111 %uint_0 = OpConstant %uint 0
112 %uint_1 = OpConstant %uint 1
113 %uint_4 = OpConstant %uint 4
114 %uint_array_4 = OpTypeArray %uint %uint_4
115 %ptr_Workgroup_uint = OpTypePointer Workgroup %uint
116 %ptr_Workgroup_uint_array_4 = OpTypePointer Workgroup %uint_array_4
117 %var = OpVariable %ptr_Workgroup_uint_array_4 Workgroup
118 %void_func = OpTypeFunction %void
119 %main = OpFunction %void None %void_func
120 %main_lab = OpLabel
121 %gep = OpAccessChain %ptr_Workgroup_uint %var %uint_1
122 %ptr_gep = OpPtrAccessChain %ptr_Workgroup_uint %gep %uint_1
123 OpReturn
124 OpFunctionEnd
125 )";
126 
127   SinglePassRunAndMatch<CombineAccessChains>(text, true);
128 }
129 
TEST_F(CombineAccessChainsTest,PtrAccessChainFromAccessChainNonConstant)130 TEST_F(CombineAccessChainsTest, PtrAccessChainFromAccessChainNonConstant) {
131   const std::string text = R"(
132 ; CHECK: [[int:%\w+]] = OpTypeInt 32 0
133 ; CHECK: [[ptr_int:%\w+]] = OpTypePointer Workgroup [[int]]
134 ; CHECK: [[var:%\w+]] = OpVariable {{%\w+}} Workgroup
135 ; CHECK: [[ld1:%\w+]] = OpLoad
136 ; CHECK: [[ld2:%\w+]] = OpLoad
137 ; CHECK: [[add:%\w+]] = OpIAdd [[int]] [[ld1]] [[ld2]]
138 ; CHECK: OpAccessChain [[ptr_int]] [[var]] [[add]]
139 OpCapability Shader
140 OpCapability VariablePointers
141 OpExtension "SPV_KHR_variable_pointers"
142 OpMemoryModel Logical GLSL450
143 OpEntryPoint Fragment %main "main"
144 OpExecutionMode %main OriginUpperLeft
145 %void = OpTypeVoid
146 %uint = OpTypeInt 32 0
147 %uint_0 = OpConstant %uint 0
148 %uint_4 = OpConstant %uint 4
149 %uint_array_4 = OpTypeArray %uint %uint_4
150 %ptr_Workgroup_uint = OpTypePointer Workgroup %uint
151 %ptr_Function_uint = OpTypePointer Function %uint
152 %ptr_Workgroup_uint_array_4 = OpTypePointer Workgroup %uint_array_4
153 %var = OpVariable %ptr_Workgroup_uint_array_4 Workgroup
154 %void_func = OpTypeFunction %void
155 %main = OpFunction %void None %void_func
156 %main_lab = OpLabel
157 %local_var = OpVariable %ptr_Function_uint Function
158 %ld1 = OpLoad %uint %local_var
159 %gep = OpAccessChain %ptr_Workgroup_uint %var %ld1
160 %ld2 = OpLoad %uint %local_var
161 %ptr_gep = OpPtrAccessChain %ptr_Workgroup_uint %gep %ld2
162 OpReturn
163 OpFunctionEnd
164 )";
165 
166   SinglePassRunAndMatch<CombineAccessChains>(text, true);
167 }
168 
TEST_F(CombineAccessChainsTest,PtrAccessChainFromAccessChainExtraIndices)169 TEST_F(CombineAccessChainsTest, PtrAccessChainFromAccessChainExtraIndices) {
170   const std::string text = R"(
171 ; CHECK: [[int:%\w+]] = OpTypeInt 32 0
172 ; CHECK: [[int1:%\w+]] = OpConstant [[int]] 1
173 ; CHECK: [[int2:%\w+]] = OpConstant [[int]] 2
174 ; CHECK: [[int3:%\w+]] = OpConstant [[int]] 3
175 ; CHECK: [[ptr_int:%\w+]] = OpTypePointer Workgroup [[int]]
176 ; CHECK: [[var:%\w+]] = OpVariable {{%\w+}} Workgroup
177 ; CHECK: OpAccessChain [[ptr_int]] [[var]] [[int1]] [[int2]] [[int3]]
178 OpCapability Shader
179 OpCapability VariablePointers
180 OpExtension "SPV_KHR_variable_pointers"
181 OpMemoryModel Logical GLSL450
182 OpEntryPoint Fragment %main "main"
183 OpExecutionMode %main OriginUpperLeft
184 %void = OpTypeVoid
185 %uint = OpTypeInt 32 0
186 %uint_0 = OpConstant %uint 0
187 %uint_1 = OpConstant %uint 1
188 %uint_2 = OpConstant %uint 2
189 %uint_3 = OpConstant %uint 3
190 %uint_4 = OpConstant %uint 4
191 %uint_array_4 = OpTypeArray %uint %uint_4
192 %uint_array_4_array_4 = OpTypeArray %uint_array_4 %uint_4
193 %uint_array_4_array_4_array_4 = OpTypeArray %uint_array_4_array_4 %uint_4
194 %ptr_Workgroup_uint = OpTypePointer Workgroup %uint
195 %ptr_Function_uint = OpTypePointer Function %uint
196 %ptr_Workgroup_uint_array_4 = OpTypePointer Workgroup %uint_array_4
197 %ptr_Workgroup_uint_array_4_array_4 = OpTypePointer Workgroup %uint_array_4_array_4
198 %ptr_Workgroup_uint_array_4_array_4_array_4 = OpTypePointer Workgroup %uint_array_4_array_4_array_4
199 %var = OpVariable %ptr_Workgroup_uint_array_4_array_4_array_4 Workgroup
200 %void_func = OpTypeFunction %void
201 %main = OpFunction %void None %void_func
202 %main_lab = OpLabel
203 %gep = OpAccessChain %ptr_Workgroup_uint_array_4 %var %uint_1 %uint_0
204 %ptr_gep = OpPtrAccessChain %ptr_Workgroup_uint %gep %uint_2 %uint_3
205 OpReturn
206 OpFunctionEnd
207 )";
208 
209   SinglePassRunAndMatch<CombineAccessChains>(text, true);
210 }
211 
TEST_F(CombineAccessChainsTest,PtrAccessChainFromPtrAccessChainCombineElementOperand)212 TEST_F(CombineAccessChainsTest,
213        PtrAccessChainFromPtrAccessChainCombineElementOperand) {
214   const std::string text = R"(
215 ; CHECK: [[int:%\w+]] = OpTypeInt 32 0
216 ; CHECK: [[int3:%\w+]] = OpConstant [[int]] 3
217 ; CHECK: [[ptr_int:%\w+]] = OpTypePointer Workgroup [[int]]
218 ; CHECK: [[var:%\w+]] = OpVariable {{%\w+}} Workgroup
219 ; CHECK: [[int6:%\w+]] = OpConstant [[int]] 6
220 ; CHECK: OpPtrAccessChain [[ptr_int]] [[var]] [[int6]] [[int3]]
221 OpCapability Shader
222 OpCapability VariablePointers
223 OpExtension "SPV_KHR_variable_pointers"
224 OpMemoryModel Logical GLSL450
225 OpEntryPoint Fragment %main "main"
226 OpExecutionMode %main OriginUpperLeft
227 %void = OpTypeVoid
228 %uint = OpTypeInt 32 0
229 %uint_0 = OpConstant %uint 0
230 %uint_3 = OpConstant %uint 3
231 %uint_4 = OpConstant %uint 4
232 %uint_array_4 = OpTypeArray %uint %uint_4
233 %ptr_Workgroup_uint = OpTypePointer Workgroup %uint
234 %ptr_Workgroup_uint_array_4 = OpTypePointer Workgroup %uint_array_4
235 %var = OpVariable %ptr_Workgroup_uint_array_4 Workgroup
236 %void_func = OpTypeFunction %void
237 %main = OpFunction %void None %void_func
238 %main_lab = OpLabel
239 %gep = OpPtrAccessChain %ptr_Workgroup_uint_array_4 %var %uint_3
240 %ptr_gep = OpPtrAccessChain %ptr_Workgroup_uint %gep %uint_3 %uint_3
241 OpReturn
242 OpFunctionEnd
243 )";
244 
245   SinglePassRunAndMatch<CombineAccessChains>(text, true);
246 }
247 
TEST_F(CombineAccessChainsTest,PtrAccessChainFromPtrAccessChainOnlyElementOperand)248 TEST_F(CombineAccessChainsTest,
249        PtrAccessChainFromPtrAccessChainOnlyElementOperand) {
250   const std::string text = R"(
251 ; CHECK: [[int:%\w+]] = OpTypeInt 32 0
252 ; CHECK: [[int4:%\w+]] = OpConstant [[int]] 4
253 ; CHECK: [[array:%\w+]] = OpTypeArray [[int]] [[int4]]
254 ; CHECK: [[ptr_array:%\w+]] = OpTypePointer Workgroup [[array]]
255 ; CHECK: [[var:%\w+]] = OpVariable {{%\w+}} Workgroup
256 ; CHECK: [[int6:%\w+]] = OpConstant [[int]] 6
257 ; CHECK: OpPtrAccessChain [[ptr_array]] [[var]] [[int6]]
258 OpCapability Shader
259 OpCapability VariablePointers
260 OpExtension "SPV_KHR_variable_pointers"
261 OpMemoryModel Logical GLSL450
262 OpEntryPoint Fragment %main "main"
263 OpExecutionMode %main OriginUpperLeft
264 %void = OpTypeVoid
265 %uint = OpTypeInt 32 0
266 %uint_0 = OpConstant %uint 0
267 %uint_3 = OpConstant %uint 3
268 %uint_4 = OpConstant %uint 4
269 %uint_array_4 = OpTypeArray %uint %uint_4
270 %ptr_Workgroup_uint = OpTypePointer Workgroup %uint
271 %ptr_Workgroup_uint_array_4 = OpTypePointer Workgroup %uint_array_4
272 %var = OpVariable %ptr_Workgroup_uint_array_4 Workgroup
273 %void_func = OpTypeFunction %void
274 %main = OpFunction %void None %void_func
275 %main_lab = OpLabel
276 %gep = OpPtrAccessChain %ptr_Workgroup_uint_array_4 %var %uint_3
277 %ptr_gep = OpPtrAccessChain %ptr_Workgroup_uint_array_4 %gep %uint_3
278 OpReturn
279 OpFunctionEnd
280 )";
281 
282   SinglePassRunAndMatch<CombineAccessChains>(text, true);
283 }
284 
TEST_F(CombineAccessChainsTest,PtrAccessChainFromPtrAccessCombineNonElementIndex)285 TEST_F(CombineAccessChainsTest,
286        PtrAccessChainFromPtrAccessCombineNonElementIndex) {
287   const std::string text = R"(
288 ; CHECK: [[int:%\w+]] = OpTypeInt 32 0
289 ; CHECK: [[int3:%\w+]] = OpConstant [[int]] 3
290 ; CHECK: [[ptr_int:%\w+]] = OpTypePointer Workgroup [[int]]
291 ; CHECK: [[var:%\w+]] = OpVariable {{%\w+}} Workgroup
292 ; CHECK: OpPtrAccessChain [[ptr_int]] [[var]] [[int3]] [[int3]] [[int3]]
293 OpCapability Shader
294 OpCapability VariablePointers
295 OpExtension "SPV_KHR_variable_pointers"
296 OpMemoryModel Logical GLSL450
297 OpEntryPoint Fragment %main "main"
298 OpExecutionMode %main OriginUpperLeft
299 %void = OpTypeVoid
300 %uint = OpTypeInt 32 0
301 %uint_0 = OpConstant %uint 0
302 %uint_3 = OpConstant %uint 3
303 %uint_4 = OpConstant %uint 4
304 %uint_array_4 = OpTypeArray %uint %uint_4
305 %uint_array_4_array_4 = OpTypeArray %uint_array_4 %uint_4
306 %ptr_Workgroup_uint = OpTypePointer Workgroup %uint
307 %ptr_Function_uint = OpTypePointer Function %uint
308 %ptr_Workgroup_uint_array_4 = OpTypePointer Workgroup %uint_array_4
309 %ptr_Workgroup_uint_array_4_array_4 = OpTypePointer Workgroup %uint_array_4_array_4
310 %var = OpVariable %ptr_Workgroup_uint_array_4_array_4 Workgroup
311 %void_func = OpTypeFunction %void
312 %main = OpFunction %void None %void_func
313 %main_lab = OpLabel
314 %gep = OpPtrAccessChain %ptr_Workgroup_uint_array_4 %var %uint_3 %uint_0
315 %ptr_gep = OpPtrAccessChain %ptr_Workgroup_uint %gep %uint_3 %uint_3
316 OpReturn
317 OpFunctionEnd
318 )";
319 
320   SinglePassRunAndMatch<CombineAccessChains>(text, true);
321 }
322 
TEST_F(CombineAccessChainsTest,AccessChainFromPtrAccessChainOnlyElementOperand)323 TEST_F(CombineAccessChainsTest,
324        AccessChainFromPtrAccessChainOnlyElementOperand) {
325   const std::string text = R"(
326 ; CHECK: [[int:%\w+]] = OpTypeInt 32 0
327 ; CHECK: [[int3:%\w+]] = OpConstant [[int]] 3
328 ; CHECK: [[ptr_int:%\w+]] = OpTypePointer Workgroup [[int]]
329 ; CHECK: [[var:%\w+]] = OpVariable {{%\w+}} Workgroup
330 ; CHECK: OpPtrAccessChain [[ptr_int]] [[var]] [[int3]] [[int3]]
331 OpCapability Shader
332 OpCapability VariablePointers
333 OpExtension "SPV_KHR_variable_pointers"
334 OpMemoryModel Logical GLSL450
335 OpEntryPoint Fragment %main "main"
336 OpExecutionMode %main OriginUpperLeft
337 %void = OpTypeVoid
338 %uint = OpTypeInt 32 0
339 %uint_0 = OpConstant %uint 0
340 %uint_3 = OpConstant %uint 3
341 %uint_4 = OpConstant %uint 4
342 %uint_array_4 = OpTypeArray %uint %uint_4
343 %ptr_Workgroup_uint = OpTypePointer Workgroup %uint
344 %ptr_Workgroup_uint_array_4 = OpTypePointer Workgroup %uint_array_4
345 %var = OpVariable %ptr_Workgroup_uint_array_4 Workgroup
346 %void_func = OpTypeFunction %void
347 %main = OpFunction %void None %void_func
348 %main_lab = OpLabel
349 %ptr_gep = OpPtrAccessChain %ptr_Workgroup_uint_array_4 %var %uint_3
350 %gep = OpAccessChain %ptr_Workgroup_uint %ptr_gep %uint_3
351 OpReturn
352 OpFunctionEnd
353 )";
354 
355   SinglePassRunAndMatch<CombineAccessChains>(text, true);
356 }
357 
TEST_F(CombineAccessChainsTest,AccessChainFromPtrAccessChainAppend)358 TEST_F(CombineAccessChainsTest, AccessChainFromPtrAccessChainAppend) {
359   const std::string text = R"(
360 ; CHECK: [[int:%\w+]] = OpTypeInt 32 0
361 ; CHECK: [[int1:%\w+]] = OpConstant [[int]] 1
362 ; CHECK: [[int2:%\w+]] = OpConstant [[int]] 2
363 ; CHECK: [[int3:%\w+]] = OpConstant [[int]] 3
364 ; CHECK: [[ptr_int:%\w+]] = OpTypePointer Workgroup [[int]]
365 ; CHECK: [[var:%\w+]] = OpVariable {{%\w+}} Workgroup
366 ; CHECK: OpPtrAccessChain [[ptr_int]] [[var]] [[int1]] [[int2]] [[int3]]
367 OpCapability Shader
368 OpCapability VariablePointers
369 OpExtension "SPV_KHR_variable_pointers"
370 OpMemoryModel Logical GLSL450
371 OpEntryPoint Fragment %main "main"
372 OpExecutionMode %main OriginUpperLeft
373 %void = OpTypeVoid
374 %uint = OpTypeInt 32 0
375 %uint_0 = OpConstant %uint 0
376 %uint_1 = OpConstant %uint 1
377 %uint_2 = OpConstant %uint 2
378 %uint_3 = OpConstant %uint 3
379 %uint_4 = OpConstant %uint 4
380 %uint_array_4 = OpTypeArray %uint %uint_4
381 %uint_array_4_array_4 = OpTypeArray %uint_array_4 %uint_4
382 %ptr_Workgroup_uint = OpTypePointer Workgroup %uint
383 %ptr_Workgroup_uint_array_4 = OpTypePointer Workgroup %uint_array_4
384 %ptr_Workgroup_uint_array_4_array_4 = OpTypePointer Workgroup %uint_array_4_array_4
385 %var = OpVariable %ptr_Workgroup_uint_array_4_array_4 Workgroup
386 %void_func = OpTypeFunction %void
387 %main = OpFunction %void None %void_func
388 %main_lab = OpLabel
389 %ptr_gep = OpPtrAccessChain %ptr_Workgroup_uint_array_4 %var %uint_1 %uint_2
390 %gep = OpAccessChain %ptr_Workgroup_uint %ptr_gep %uint_3
391 OpReturn
392 OpFunctionEnd
393 )";
394 
395   SinglePassRunAndMatch<CombineAccessChains>(text, true);
396 }
397 
TEST_F(CombineAccessChainsTest,AccessChainFromAccessChainAppend)398 TEST_F(CombineAccessChainsTest, AccessChainFromAccessChainAppend) {
399   const std::string text = R"(
400 ; CHECK: [[int:%\w+]] = OpTypeInt 32 0
401 ; CHECK: [[int1:%\w+]] = OpConstant [[int]] 1
402 ; CHECK: [[int2:%\w+]] = OpConstant [[int]] 2
403 ; CHECK: [[ptr_int:%\w+]] = OpTypePointer Workgroup [[int]]
404 ; CHECK: [[var:%\w+]] = OpVariable {{%\w+}} Workgroup
405 ; CHECK: OpAccessChain [[ptr_int]] [[var]] [[int1]] [[int2]]
406 OpCapability Shader
407 OpCapability VariablePointers
408 OpExtension "SPV_KHR_variable_pointers"
409 OpMemoryModel Logical GLSL450
410 OpEntryPoint Fragment %main "main"
411 OpExecutionMode %main OriginUpperLeft
412 %void = OpTypeVoid
413 %uint = OpTypeInt 32 0
414 %uint_0 = OpConstant %uint 0
415 %uint_1 = OpConstant %uint 1
416 %uint_2 = OpConstant %uint 2
417 %uint_3 = OpConstant %uint 3
418 %uint_4 = OpConstant %uint 4
419 %uint_array_4 = OpTypeArray %uint %uint_4
420 %uint_array_4_array_4 = OpTypeArray %uint_array_4 %uint_4
421 %ptr_Workgroup_uint = OpTypePointer Workgroup %uint
422 %ptr_Workgroup_uint_array_4 = OpTypePointer Workgroup %uint_array_4
423 %ptr_Workgroup_uint_array_4_array_4 = OpTypePointer Workgroup %uint_array_4_array_4
424 %var = OpVariable %ptr_Workgroup_uint_array_4_array_4 Workgroup
425 %void_func = OpTypeFunction %void
426 %main = OpFunction %void None %void_func
427 %main_lab = OpLabel
428 %ptr_gep = OpAccessChain %ptr_Workgroup_uint_array_4 %var %uint_1
429 %gep = OpAccessChain %ptr_Workgroup_uint %ptr_gep %uint_2
430 OpReturn
431 OpFunctionEnd
432 )";
433 
434   SinglePassRunAndMatch<CombineAccessChains>(text, true);
435 }
436 
TEST_F(CombineAccessChainsTest,NonConstantStructSlide)437 TEST_F(CombineAccessChainsTest, NonConstantStructSlide) {
438   const std::string text = R"(
439 ; CHECK: [[int0:%\w+]] = OpConstant {{%\w+}} 0
440 ; CHECK: [[var:%\w+]] = OpVariable {{%\w+}} Workgroup
441 ; CHECK: [[ld:%\w+]] = OpLoad
442 ; CHECK: OpPtrAccessChain {{%\w+}} [[var]] [[ld]] [[int0]]
443 OpCapability Shader
444 OpCapability VariablePointers
445 OpExtension "SPV_KHR_variable_pointers"
446 OpMemoryModel Logical GLSL450
447 OpEntryPoint Fragment %main "main"
448 OpExecutionMode %main OriginUpperLeft
449 %void = OpTypeVoid
450 %uint = OpTypeInt 32 0
451 %uint_0 = OpConstant %uint 0
452 %struct = OpTypeStruct %uint %uint
453 %ptr_Workgroup_struct = OpTypePointer Workgroup %struct
454 %ptr_Workgroup_uint = OpTypePointer Workgroup %uint
455 %ptr_Function_uint = OpTypePointer Function %uint
456 %wg_var = OpVariable %ptr_Workgroup_struct Workgroup
457 %void_func = OpTypeFunction %void
458 %main = OpFunction %void None %void_func
459 %1 = OpLabel
460 %func_var = OpVariable %ptr_Function_uint Function
461 %ld = OpLoad %uint %func_var
462 %ptr_gep = OpPtrAccessChain %ptr_Workgroup_struct %wg_var %ld
463 %gep = OpAccessChain %ptr_Workgroup_uint %ptr_gep %uint_0
464 OpReturn
465 OpFunctionEnd
466 )";
467 
468   SinglePassRunAndMatch<CombineAccessChains>(text, true);
469 }
470 
TEST_F(CombineAccessChainsTest,DontCombineNonConstantStructSlide)471 TEST_F(CombineAccessChainsTest, DontCombineNonConstantStructSlide) {
472   const std::string text = R"(
473 ; CHECK: [[int0:%\w+]] = OpConstant {{%\w+}} 0
474 ; CHECK: [[ld:%\w+]] = OpLoad
475 ; CHECK: [[gep:%\w+]] = OpAccessChain
476 ; CHECK: OpPtrAccessChain {{%\w+}} [[gep]] [[ld]] [[int0]]
477 OpCapability Shader
478 OpCapability VariablePointers
479 OpExtension "SPV_KHR_variable_pointers"
480 OpMemoryModel Logical GLSL450
481 OpEntryPoint Fragment %main "main"
482 OpExecutionMode %main OriginUpperLeft
483 %void = OpTypeVoid
484 %uint = OpTypeInt 32 0
485 %uint_0 = OpConstant %uint 0
486 %uint_4 = OpConstant %uint 4
487 %struct = OpTypeStruct %uint %uint
488 %struct_array_4 = OpTypeArray %struct %uint_4
489 %ptr_Workgroup_uint = OpTypePointer Workgroup %uint
490 %ptr_Function_uint = OpTypePointer Function %uint
491 %ptr_Workgroup_struct = OpTypePointer Workgroup %struct
492 %ptr_Workgroup_struct_array_4 = OpTypePointer Workgroup %struct_array_4
493 %wg_var = OpVariable %ptr_Workgroup_struct_array_4 Workgroup
494 %void_func = OpTypeFunction %void
495 %main = OpFunction %void None %void_func
496 %1 = OpLabel
497 %func_var = OpVariable %ptr_Function_uint Function
498 %ld = OpLoad %uint %func_var
499 %gep = OpAccessChain %ptr_Workgroup_struct %wg_var %uint_0
500 %ptr_gep = OpPtrAccessChain %ptr_Workgroup_uint %gep %ld %uint_0
501 OpReturn
502 OpFunctionEnd
503 )";
504 
505   SinglePassRunAndMatch<CombineAccessChains>(text, true);
506 }
507 
TEST_F(CombineAccessChainsTest,CombineNonConstantStructSlideElement)508 TEST_F(CombineAccessChainsTest, CombineNonConstantStructSlideElement) {
509   const std::string text = R"(
510 ; CHECK: [[int0:%\w+]] = OpConstant {{%\w+}} 0
511 ; CHECK: [[var:%\w+]] = OpVariable {{%\w+}} Workgroup
512 ; CHECK: [[ld:%\w+]] = OpLoad
513 ; CHECK: [[add:%\w+]] = OpIAdd {{%\w+}} [[ld]] [[ld]]
514 ; CHECK: OpPtrAccessChain {{%\w+}} [[var]] [[add]] [[int0]]
515 OpCapability Shader
516 OpCapability VariablePointers
517 OpExtension "SPV_KHR_variable_pointers"
518 OpMemoryModel Logical GLSL450
519 OpEntryPoint Fragment %main "main"
520 OpExecutionMode %main OriginUpperLeft
521 %void = OpTypeVoid
522 %uint = OpTypeInt 32 0
523 %uint_0 = OpConstant %uint 0
524 %uint_4 = OpConstant %uint 4
525 %struct = OpTypeStruct %uint %uint
526 %ptr_Workgroup_uint = OpTypePointer Workgroup %uint
527 %ptr_Function_uint = OpTypePointer Function %uint
528 %ptr_Workgroup_struct = OpTypePointer Workgroup %struct
529 %wg_var = OpVariable %ptr_Workgroup_struct Workgroup
530 %void_func = OpTypeFunction %void
531 %main = OpFunction %void None %void_func
532 %1 = OpLabel
533 %func_var = OpVariable %ptr_Function_uint Function
534 %ld = OpLoad %uint %func_var
535 %gep = OpPtrAccessChain %ptr_Workgroup_struct %wg_var %ld
536 %ptr_gep = OpPtrAccessChain %ptr_Workgroup_uint %gep %ld %uint_0
537 OpReturn
538 OpFunctionEnd
539 )";
540 
541   SinglePassRunAndMatch<CombineAccessChains>(text, true);
542 }
543 
TEST_F(CombineAccessChainsTest,PtrAccessChainFromInBoundsPtrAccessChain)544 TEST_F(CombineAccessChainsTest, PtrAccessChainFromInBoundsPtrAccessChain) {
545   const std::string text = R"(
546 ; CHECK: [[int:%\w+]] = OpTypeInt 32 0
547 ; CHECK: [[int4:%\w+]] = OpConstant [[int]] 4
548 ; CHECK: [[array:%\w+]] = OpTypeArray [[int]] [[int4]]
549 ; CHECK: [[ptr_array:%\w+]] = OpTypePointer Workgroup [[array]]
550 ; CHECK: [[var:%\w+]] = OpVariable {{%\w+}} Workgroup
551 ; CHECK: [[int6:%\w+]] = OpConstant [[int]] 6
552 ; CHECK: OpPtrAccessChain [[ptr_array]] [[var]] [[int6]]
553 OpCapability Shader
554 OpCapability VariablePointers
555 OpCapability Addresses
556 OpExtension "SPV_KHR_variable_pointers"
557 OpMemoryModel Logical GLSL450
558 OpEntryPoint Fragment %main "main"
559 OpExecutionMode %main OriginUpperLeft
560 %void = OpTypeVoid
561 %uint = OpTypeInt 32 0
562 %uint_0 = OpConstant %uint 0
563 %uint_3 = OpConstant %uint 3
564 %uint_4 = OpConstant %uint 4
565 %uint_array_4 = OpTypeArray %uint %uint_4
566 %ptr_Workgroup_uint = OpTypePointer Workgroup %uint
567 %ptr_Workgroup_uint_array_4 = OpTypePointer Workgroup %uint_array_4
568 %var = OpVariable %ptr_Workgroup_uint_array_4 Workgroup
569 %void_func = OpTypeFunction %void
570 %main = OpFunction %void None %void_func
571 %main_lab = OpLabel
572 %gep = OpInBoundsPtrAccessChain %ptr_Workgroup_uint_array_4 %var %uint_3
573 %ptr_gep = OpPtrAccessChain %ptr_Workgroup_uint_array_4 %gep %uint_3
574 OpReturn
575 OpFunctionEnd
576 )";
577 
578   SinglePassRunAndMatch<CombineAccessChains>(text, true);
579 }
580 
TEST_F(CombineAccessChainsTest,InBoundsPtrAccessChainFromPtrAccessChain)581 TEST_F(CombineAccessChainsTest, InBoundsPtrAccessChainFromPtrAccessChain) {
582   const std::string text = R"(
583 ; CHECK: [[int:%\w+]] = OpTypeInt 32 0
584 ; CHECK: [[int4:%\w+]] = OpConstant [[int]] 4
585 ; CHECK: [[array:%\w+]] = OpTypeArray [[int]] [[int4]]
586 ; CHECK: [[ptr_array:%\w+]] = OpTypePointer Workgroup [[array]]
587 ; CHECK: [[var:%\w+]] = OpVariable {{%\w+}} Workgroup
588 ; CHECK: [[int6:%\w+]] = OpConstant [[int]] 6
589 ; CHECK: OpPtrAccessChain [[ptr_array]] [[var]] [[int6]]
590 OpCapability Shader
591 OpCapability VariablePointers
592 OpCapability Addresses
593 OpExtension "SPV_KHR_variable_pointers"
594 OpMemoryModel Logical GLSL450
595 OpEntryPoint Fragment %main "main"
596 OpExecutionMode %main OriginUpperLeft
597 %void = OpTypeVoid
598 %uint = OpTypeInt 32 0
599 %uint_0 = OpConstant %uint 0
600 %uint_3 = OpConstant %uint 3
601 %uint_4 = OpConstant %uint 4
602 %uint_array_4 = OpTypeArray %uint %uint_4
603 %ptr_Workgroup_uint = OpTypePointer Workgroup %uint
604 %ptr_Workgroup_uint_array_4 = OpTypePointer Workgroup %uint_array_4
605 %var = OpVariable %ptr_Workgroup_uint_array_4 Workgroup
606 %void_func = OpTypeFunction %void
607 %main = OpFunction %void None %void_func
608 %main_lab = OpLabel
609 %gep = OpPtrAccessChain %ptr_Workgroup_uint_array_4 %var %uint_3
610 %ptr_gep = OpInBoundsPtrAccessChain %ptr_Workgroup_uint_array_4 %gep %uint_3
611 OpReturn
612 OpFunctionEnd
613 )";
614 
615   SinglePassRunAndMatch<CombineAccessChains>(text, true);
616 }
617 
TEST_F(CombineAccessChainsTest,InBoundsPtrAccessChainFromInBoundsPtrAccessChain)618 TEST_F(CombineAccessChainsTest,
619        InBoundsPtrAccessChainFromInBoundsPtrAccessChain) {
620   const std::string text = R"(
621 ; CHECK: [[int:%\w+]] = OpTypeInt 32 0
622 ; CHECK: [[int4:%\w+]] = OpConstant [[int]] 4
623 ; CHECK: [[array:%\w+]] = OpTypeArray [[int]] [[int4]]
624 ; CHECK: [[ptr_array:%\w+]] = OpTypePointer Workgroup [[array]]
625 ; CHECK: [[var:%\w+]] = OpVariable {{%\w+}} Workgroup
626 ; CHECK: [[int6:%\w+]] = OpConstant [[int]] 6
627 ; CHECK: OpInBoundsPtrAccessChain [[ptr_array]] [[var]] [[int6]]
628 OpCapability Shader
629 OpCapability VariablePointers
630 OpCapability Addresses
631 OpExtension "SPV_KHR_variable_pointers"
632 OpMemoryModel Logical GLSL450
633 OpEntryPoint Fragment %main "main"
634 OpExecutionMode %main OriginUpperLeft
635 %void = OpTypeVoid
636 %uint = OpTypeInt 32 0
637 %uint_0 = OpConstant %uint 0
638 %uint_3 = OpConstant %uint 3
639 %uint_4 = OpConstant %uint 4
640 %uint_array_4 = OpTypeArray %uint %uint_4
641 %ptr_Workgroup_uint = OpTypePointer Workgroup %uint
642 %ptr_Workgroup_uint_array_4 = OpTypePointer Workgroup %uint_array_4
643 %var = OpVariable %ptr_Workgroup_uint_array_4 Workgroup
644 %void_func = OpTypeFunction %void
645 %main = OpFunction %void None %void_func
646 %main_lab = OpLabel
647 %gep = OpInBoundsPtrAccessChain %ptr_Workgroup_uint_array_4 %var %uint_3
648 %ptr_gep = OpInBoundsPtrAccessChain %ptr_Workgroup_uint_array_4 %gep %uint_3
649 OpReturn
650 OpFunctionEnd
651 )";
652 
653   SinglePassRunAndMatch<CombineAccessChains>(text, true);
654 }
655 
TEST_F(CombineAccessChainsTest,NoIndexAccessChains)656 TEST_F(CombineAccessChainsTest, NoIndexAccessChains) {
657   const std::string text = R"(
658 ; CHECK: [[var:%\w+]] = OpVariable
659 ; CHECK-NOT: OpConstant
660 ; CHECK: [[gep:%\w+]] = OpAccessChain {{%\w+}} [[var]]
661 ; CHECK: OpAccessChain {{%\w+}} [[var]]
662 OpCapability Shader
663 OpMemoryModel Logical GLSL450
664 OpEntryPoint Fragment %func "func"
665 OpExecutionMode %func OriginUpperLeft
666 %void = OpTypeVoid
667 %uint = OpTypeInt 32 0
668 %ptr_Workgroup_uint = OpTypePointer Workgroup %uint
669 %var = OpVariable %ptr_Workgroup_uint Workgroup
670 %void_func = OpTypeFunction %void
671 %func = OpFunction %void None %void_func
672 %1 = OpLabel
673 %gep1 = OpAccessChain %ptr_Workgroup_uint %var
674 %gep2 = OpAccessChain %ptr_Workgroup_uint %gep1
675 OpReturn
676 OpFunctionEnd
677 )";
678 
679   SinglePassRunAndMatch<CombineAccessChains>(text, true);
680 }
681 
TEST_F(CombineAccessChainsTest,NoIndexPtrAccessChains)682 TEST_F(CombineAccessChainsTest, NoIndexPtrAccessChains) {
683   const std::string text = R"(
684 ; CHECK: [[int0:%\w+]] = OpConstant {{%\w+}} 0
685 ; CHECK: [[var:%\w+]] = OpVariable
686 ; CHECK: [[gep:%\w+]] = OpPtrAccessChain {{%\w+}} [[var]] [[int0]]
687 ; CHECK: OpCopyObject {{%\w+}} [[gep]]
688 OpCapability Shader
689 OpCapability VariablePointers
690 OpExtension "SPV_KHR_variable_pointers"
691 OpMemoryModel Logical GLSL450
692 OpEntryPoint Fragment %func "func"
693 OpExecutionMode %func OriginUpperLeft
694 %void = OpTypeVoid
695 %uint = OpTypeInt 32 0
696 %uint_0 = OpConstant %uint 0
697 %ptr_Workgroup_uint = OpTypePointer Workgroup %uint
698 %var = OpVariable %ptr_Workgroup_uint Workgroup
699 %void_func = OpTypeFunction %void
700 %func = OpFunction %void None %void_func
701 %1 = OpLabel
702 %gep1 = OpPtrAccessChain %ptr_Workgroup_uint %var %uint_0
703 %gep2 = OpAccessChain %ptr_Workgroup_uint %gep1
704 OpReturn
705 OpFunctionEnd
706 )";
707 
708   SinglePassRunAndMatch<CombineAccessChains>(text, true);
709 }
710 
TEST_F(CombineAccessChainsTest,NoIndexPtrAccessChains2)711 TEST_F(CombineAccessChainsTest, NoIndexPtrAccessChains2) {
712   const std::string text = R"(
713 ; CHECK: [[int0:%\w+]] = OpConstant {{%\w+}} 0
714 ; CHECK: [[var:%\w+]] = OpVariable
715 ; CHECK: OpPtrAccessChain {{%\w+}} [[var]] [[int0]]
716 OpCapability Shader
717 OpCapability VariablePointers
718 OpExtension "SPV_KHR_variable_pointers"
719 OpMemoryModel Logical GLSL450
720 OpEntryPoint Fragment %func "func"
721 OpExecutionMode %func OriginUpperLeft
722 %void = OpTypeVoid
723 %uint = OpTypeInt 32 0
724 %uint_0 = OpConstant %uint 0
725 %ptr_Workgroup_uint = OpTypePointer Workgroup %uint
726 %var = OpVariable %ptr_Workgroup_uint Workgroup
727 %void_func = OpTypeFunction %void
728 %func = OpFunction %void None %void_func
729 %1 = OpLabel
730 %gep1 = OpAccessChain %ptr_Workgroup_uint %var
731 %gep2 = OpPtrAccessChain %ptr_Workgroup_uint %gep1 %uint_0
732 OpReturn
733 OpFunctionEnd
734 )";
735 
736   SinglePassRunAndMatch<CombineAccessChains>(text, true);
737 }
738 
TEST_F(CombineAccessChainsTest,CombineMixedSign)739 TEST_F(CombineAccessChainsTest, CombineMixedSign) {
740   const std::string text = R"(
741 ; CHECK: [[uint:%\w+]] = OpTypeInt 32 0
742 ; CHECK: [[var:%\w+]] = OpVariable
743 ; CHECK: [[uint2:%\w+]] = OpConstant [[uint]] 2
744 ; CHECK: OpInBoundsPtrAccessChain {{%\w+}} [[var]] [[uint2]]
745 OpCapability Shader
746 OpCapability VariablePointers
747 OpCapability Addresses
748 OpExtension "SPV_KHR_variable_pointers"
749 OpMemoryModel Logical GLSL450
750 OpEntryPoint Fragment %func "func"
751 OpExecutionMode %func OriginUpperLeft
752 %void = OpTypeVoid
753 %uint = OpTypeInt 32 0
754 %int = OpTypeInt 32 1
755 %uint_1 = OpConstant %uint 1
756 %int_1 = OpConstant %int 1
757 %ptr_Workgroup_uint = OpTypePointer Workgroup %uint
758 %var = OpVariable %ptr_Workgroup_uint Workgroup
759 %void_func = OpTypeFunction %void
760 %func = OpFunction %void None %void_func
761 %1 = OpLabel
762 %gep1 = OpInBoundsPtrAccessChain %ptr_Workgroup_uint %var %uint_1
763 %gep2 = OpInBoundsPtrAccessChain %ptr_Workgroup_uint %gep1 %int_1
764 OpReturn
765 OpFunctionEnd
766 )";
767 
768   SinglePassRunAndMatch<CombineAccessChains>(text, true);
769 }
770 
771 }  // namespace
772 }  // namespace opt
773 }  // namespace spvtools
774