Home | History | Annotate | Download | only in opt
      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 
     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 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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