Home | History | Annotate | Download | only in opt
      1 // Copyright (c) 2017 Google Inc.
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //     http://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 
     15 #include <string>
     16 
     17 #include "gmock/gmock.h"
     18 #include "source/opt/build_module.h"
     19 #include "source/opt/value_number_table.h"
     20 #include "test/opt/assembly_builder.h"
     21 #include "test/opt/pass_fixture.h"
     22 #include "test/opt/pass_utils.h"
     23 
     24 namespace spvtools {
     25 namespace opt {
     26 namespace {
     27 
     28 using ::testing::HasSubstr;
     29 using ::testing::MatchesRegex;
     30 using PrivateToLocalTest = PassTest<::testing::Test>;
     31 
     32 TEST_F(PrivateToLocalTest, ChangeToLocal) {
     33   // Change the private variable to a local, and change the types accordingly.
     34   const std::string text = R"(
     35                OpCapability Shader
     36           %1 = OpExtInstImport "GLSL.std.450"
     37                OpMemoryModel Logical GLSL450
     38                OpEntryPoint Fragment %2 "main"
     39                OpExecutionMode %2 OriginUpperLeft
     40                OpSource GLSL 430
     41           %3 = OpTypeVoid
     42           %4 = OpTypeFunction %3
     43 ; CHECK: [[float:%[a-zA-Z_\d]+]] = OpTypeFloat 32
     44           %5 = OpTypeFloat 32
     45 ; CHECK: [[newtype:%[a-zA-Z_\d]+]] = OpTypePointer Function [[float]]
     46           %6 = OpTypePointer Private %5
     47 ; CHECK-NOT: OpVariable [[.+]] Private
     48           %8 = OpVariable %6 Private
     49 ; CHECK: OpFunction
     50           %2 = OpFunction %3 None %4
     51 ; CHECK: OpLabel
     52           %7 = OpLabel
     53 ; CHECK-NEXT: [[newvar:%[a-zA-Z_\d]+]] = OpVariable [[newtype]] Function
     54 ; CHECK: OpLoad [[float]] [[newvar]]
     55           %9 = OpLoad %5 %8
     56                OpReturn
     57                OpFunctionEnd
     58   )";
     59   SinglePassRunAndMatch<PrivateToLocalPass>(text, false);
     60 }
     61 
     62 TEST_F(PrivateToLocalTest, ReuseExistingType) {
     63   // Change the private variable to a local, and change the types accordingly.
     64   const std::string text = R"(
     65                OpCapability Shader
     66           %1 = OpExtInstImport "GLSL.std.450"
     67                OpMemoryModel Logical GLSL450
     68                OpEntryPoint Fragment %2 "main"
     69                OpExecutionMode %2 OriginUpperLeft
     70                OpSource GLSL 430
     71           %3 = OpTypeVoid
     72           %4 = OpTypeFunction %3
     73 ; CHECK: [[float:%[a-zA-Z_\d]+]] = OpTypeFloat 32
     74           %5 = OpTypeFloat 32
     75         %func_ptr = OpTypePointer Function %5
     76 ; CHECK: [[newtype:%[a-zA-Z_\d]+]] = OpTypePointer Function [[float]]
     77 ; CHECK-NOT: [[%[a-zA-Z_\d]+]] = OpTypePointer Function [[float]]
     78           %6 = OpTypePointer Private %5
     79 ; CHECK-NOT: OpVariable [[.+]] Private
     80           %8 = OpVariable %6 Private
     81 ; CHECK: OpFunction
     82           %2 = OpFunction %3 None %4
     83 ; CHECK: OpLabel
     84           %7 = OpLabel
     85 ; CHECK-NEXT: [[newvar:%[a-zA-Z_\d]+]] = OpVariable [[newtype]] Function
     86 ; CHECK: OpLoad [[float]] [[newvar]]
     87           %9 = OpLoad %5 %8
     88                OpReturn
     89                OpFunctionEnd
     90   )";
     91   SinglePassRunAndMatch<PrivateToLocalPass>(text, false);
     92 }
     93 
     94 TEST_F(PrivateToLocalTest, UpdateAccessChain) {
     95   // Change the private variable to a local, and change the AccessChain.
     96   const std::string text = R"(
     97                OpCapability Shader
     98           %1 = OpExtInstImport "GLSL.std.450"
     99                OpMemoryModel Logical GLSL450
    100                OpEntryPoint Fragment %2 "main"
    101                OpExecutionMode %2 OriginUpperLeft
    102                OpSource GLSL 430
    103        %uint = OpTypeInt 32 0
    104      %uint_0 = OpConstant %uint 0
    105        %void = OpTypeVoid
    106           %6 = OpTypeFunction %void
    107 ; CHECK: [[float:%[a-zA-Z_\d]+]] = OpTypeFloat
    108       %float = OpTypeFloat 32
    109 ; CHECK: [[struct:%[a-zA-Z_\d]+]] = OpTypeStruct
    110   %_struct_8 = OpTypeStruct %float
    111 %_ptr_Private_float = OpTypePointer Private %float
    112 ; CHECK: [[new_struct_type:%[a-zA-Z_\d]+]] = OpTypePointer Function [[struct]]
    113 ; CHECK: [[new_float_type:%[a-zA-Z_\d]+]] = OpTypePointer Function [[float]]
    114 %_ptr_Private__struct_8 = OpTypePointer Private %_struct_8
    115 ; CHECK-NOT: OpVariable [[.+]] Private
    116          %11 = OpVariable %_ptr_Private__struct_8 Private
    117 ; CHECK: OpFunction
    118           %2 = OpFunction %void None %6
    119 ; CHECK: OpLabel
    120          %12 = OpLabel
    121 ; CHECK-NEXT: [[newvar:%[a-zA-Z_\d]+]] = OpVariable [[new_struct_type]] Function
    122 ; CHECK: [[member:%[a-zA-Z_\d]+]] = OpAccessChain [[new_float_type]] [[newvar]]
    123          %13 = OpAccessChain %_ptr_Private_float %11 %uint_0
    124 ; CHECK: OpLoad [[float]] [[member]]
    125          %14 = OpLoad %float %13
    126                OpReturn
    127                OpFunctionEnd
    128   )";
    129   SinglePassRunAndMatch<PrivateToLocalPass>(text, false);
    130 }
    131 
    132 TEST_F(PrivateToLocalTest, UseTexelPointer) {
    133   // Change the private variable to a local, and change the OpImageTexelPointer.
    134   const std::string text = R"(
    135 OpCapability SampledBuffer
    136                OpCapability StorageImageExtendedFormats
    137                OpCapability ImageBuffer
    138                OpCapability Shader
    139           %1 = OpExtInstImport "GLSL.std.450"
    140                OpMemoryModel Logical GLSL450
    141                OpEntryPoint GLCompute %2 "min" %gl_GlobalInvocationID
    142                OpExecutionMode %2 LocalSize 64 1 1
    143                OpSource HLSL 600
    144                OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId
    145                OpDecorate %4 DescriptorSet 4
    146                OpDecorate %4 Binding 70
    147        %uint = OpTypeInt 32 0
    148           %6 = OpTypeImage %uint Buffer 0 0 0 2 R32ui
    149 %_ptr_UniformConstant_6 = OpTypePointer UniformConstant %6
    150 %_ptr_Private_6 = OpTypePointer Private %6
    151        %void = OpTypeVoid
    152          %10 = OpTypeFunction %void
    153      %uint_0 = OpConstant %uint 0
    154      %uint_1 = OpConstant %uint 1
    155      %v3uint = OpTypeVector %uint 3
    156 %_ptr_Input_v3uint = OpTypePointer Input %v3uint
    157 %_ptr_Image_uint = OpTypePointer Image %uint
    158           %4 = OpVariable %_ptr_UniformConstant_6 UniformConstant
    159          %16 = OpVariable %_ptr_Private_6 Private
    160 %gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input
    161           %2 = OpFunction %void None %10
    162          %17 = OpLabel
    163 ; Make sure the variable was moved.
    164 ; CHECK: OpFunction
    165 ; CHECK-NEXT: OpLabel
    166 ; CHECK-NEXT: OpVariable %_ptr_Function_6 Function
    167          %18 = OpLoad %6 %4
    168                OpStore %16 %18
    169          %19 = OpImageTexelPointer %_ptr_Image_uint %16 %uint_0 %uint_0
    170          %20 = OpAtomicIAdd %uint %19 %uint_1 %uint_0 %uint_1
    171                OpReturn
    172                OpFunctionEnd
    173   )";
    174   SinglePassRunAndMatch<PrivateToLocalPass>(text, false);
    175 }
    176 
    177 TEST_F(PrivateToLocalTest, UsedInTwoFunctions) {
    178   // Should not change because it is used in multiple functions.
    179   const std::string text = R"(
    180                OpCapability Shader
    181           %1 = OpExtInstImport "GLSL.std.450"
    182                OpMemoryModel Logical GLSL450
    183                OpEntryPoint Fragment %2 "main"
    184                OpExecutionMode %2 OriginUpperLeft
    185                OpSource GLSL 430
    186           %3 = OpTypeVoid
    187           %4 = OpTypeFunction %3
    188           %5 = OpTypeFloat 32
    189           %6 = OpTypePointer Private %5
    190           %8 = OpVariable %6 Private
    191           %2 = OpFunction %3 None %4
    192           %7 = OpLabel
    193           %9 = OpLoad %5 %8
    194                OpReturn
    195                OpFunctionEnd
    196          %10 = OpFunction %3 None %4
    197          %11 = OpLabel
    198          %12 = OpLoad %5 %8
    199                OpReturn
    200                OpFunctionEnd
    201   )";
    202   auto result = SinglePassRunAndDisassemble<StrengthReductionPass>(
    203       text, /* skip_nop = */ true, /* do_validation = */ false);
    204   EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
    205 }
    206 
    207 TEST_F(PrivateToLocalTest, UsedInFunctionCall) {
    208   // Should not change because it is used in a function call.  Changing the
    209   // signature of the function would require cloning the function, which is not
    210   // worth it.
    211   const std::string text = R"(
    212                OpCapability Shader
    213           %1 = OpExtInstImport "GLSL.std.450"
    214                OpMemoryModel Logical GLSL450
    215                OpEntryPoint Fragment %2 "main"
    216                OpExecutionMode %2 OriginUpperLeft
    217                OpSource GLSL 430
    218        %void = OpTypeVoid
    219           %4 = OpTypeFunction %void
    220       %float = OpTypeFloat 32
    221 %_ptr_Private_float = OpTypePointer Private %float
    222           %7 = OpTypeFunction %void %_ptr_Private_float
    223           %8 = OpVariable %_ptr_Private_float Private
    224           %2 = OpFunction %void None %4
    225           %9 = OpLabel
    226          %10 = OpFunctionCall %void %11 %8
    227                OpReturn
    228                OpFunctionEnd
    229          %11 = OpFunction %void None %7
    230          %12 = OpFunctionParameter %_ptr_Private_float
    231          %13 = OpLabel
    232          %14 = OpLoad %float %12
    233                OpReturn
    234                OpFunctionEnd
    235   )";
    236   auto result = SinglePassRunAndDisassemble<StrengthReductionPass>(
    237       text, /* skip_nop = */ true, /* do_validation = */ false);
    238   EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
    239 }
    240 
    241 TEST_F(PrivateToLocalTest, CreatePointerToAmbiguousStruct1) {
    242   // Test that the correct pointer type is picked up.
    243   const std::string text = R"(
    244 ; CHECK: [[struct1:%[a-zA-Z_\d]+]] = OpTypeStruct
    245 ; CHECK: [[struct2:%[a-zA-Z_\d]+]] = OpTypeStruct
    246 ; CHECK: [[priv_ptr:%[\w]+]] = OpTypePointer Private [[struct1]]
    247 ; CHECK: [[fuct_ptr2:%[\w]+]] = OpTypePointer Function [[struct2]]
    248 ; CHECK: [[fuct_ptr1:%[\w]+]] = OpTypePointer Function [[struct1]]
    249 ; CHECK: OpFunction
    250 ; CHECK: OpLabel
    251 ; CHECK-NEXT: [[newvar:%[a-zA-Z_\d]+]] = OpVariable [[fuct_ptr1]] Function
    252 ; CHECK: OpLoad [[struct1]] [[newvar]]
    253                OpCapability Shader
    254           %1 = OpExtInstImport "GLSL.std.450"
    255                OpMemoryModel Logical GLSL450
    256                OpEntryPoint Fragment %2 "main"
    257                OpExecutionMode %2 OriginUpperLeft
    258                OpSource GLSL 430
    259           %3 = OpTypeVoid
    260           %4 = OpTypeFunction %3
    261           %5 = OpTypeFloat 32
    262     %struct1 = OpTypeStruct %5
    263     %struct2 = OpTypeStruct %5
    264           %6 = OpTypePointer Private %struct1
    265   %func_ptr2 = OpTypePointer Function %struct2
    266           %8 = OpVariable %6 Private
    267           %2 = OpFunction %3 None %4
    268           %7 = OpLabel
    269           %9 = OpLoad %struct1 %8
    270                OpReturn
    271                OpFunctionEnd
    272   )";
    273   SinglePassRunAndMatch<PrivateToLocalPass>(text, false);
    274 }
    275 
    276 TEST_F(PrivateToLocalTest, CreatePointerToAmbiguousStruct2) {
    277   // Test that the correct pointer type is picked up.
    278   const std::string text = R"(
    279 ; CHECK: [[struct1:%[a-zA-Z_\d]+]] = OpTypeStruct
    280 ; CHECK: [[struct2:%[a-zA-Z_\d]+]] = OpTypeStruct
    281 ; CHECK: [[priv_ptr:%[\w]+]] = OpTypePointer Private [[struct2]]
    282 ; CHECK: [[fuct_ptr1:%[\w]+]] = OpTypePointer Function [[struct1]]
    283 ; CHECK: [[fuct_ptr2:%[\w]+]] = OpTypePointer Function [[struct2]]
    284 ; CHECK: OpFunction
    285 ; CHECK: OpLabel
    286 ; CHECK-NEXT: [[newvar:%[a-zA-Z_\d]+]] = OpVariable [[fuct_ptr2]] Function
    287 ; CHECK: OpLoad [[struct2]] [[newvar]]
    288                OpCapability Shader
    289           %1 = OpExtInstImport "GLSL.std.450"
    290                OpMemoryModel Logical GLSL450
    291                OpEntryPoint Fragment %2 "main"
    292                OpExecutionMode %2 OriginUpperLeft
    293                OpSource GLSL 430
    294           %3 = OpTypeVoid
    295           %4 = OpTypeFunction %3
    296           %5 = OpTypeFloat 32
    297     %struct1 = OpTypeStruct %5
    298     %struct2 = OpTypeStruct %5
    299           %6 = OpTypePointer Private %struct2
    300   %func_ptr2 = OpTypePointer Function %struct1
    301           %8 = OpVariable %6 Private
    302           %2 = OpFunction %3 None %4
    303           %7 = OpLabel
    304           %9 = OpLoad %struct2 %8
    305                OpReturn
    306                OpFunctionEnd
    307   )";
    308   SinglePassRunAndMatch<PrivateToLocalPass>(text, false);
    309 }
    310 
    311 }  // namespace
    312 }  // namespace opt
    313 }  // namespace spvtools
    314