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