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 LocalRedundancyEliminationTest = PassTest<::testing::Test>;
     31 
     32 // Remove an instruction when it was already computed.
     33 TEST_F(LocalRedundancyEliminationTest, RemoveRedundantAdd) {
     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           %5 = OpTypeFloat 32
     44           %6 = OpTypePointer Function %5
     45           %2 = OpFunction %3 None %4
     46           %7 = OpLabel
     47           %8 = OpVariable %6 Function
     48           %9 = OpLoad %5 %8
     49          %10 = OpFAdd %5 %9 %9
     50 ; CHECK: OpFAdd
     51 ; CHECK-NOT: OpFAdd
     52          %11 = OpFAdd %5 %9 %9
     53                OpReturn
     54                OpFunctionEnd
     55   )";
     56   SinglePassRunAndMatch<LocalRedundancyEliminationPass>(text, false);
     57 }
     58 
     59 // Make sure we keep instruction that are different, but look similar.
     60 TEST_F(LocalRedundancyEliminationTest, KeepDifferentAdd) {
     61   const std::string text = R"(
     62                OpCapability Shader
     63           %1 = OpExtInstImport "GLSL.std.450"
     64                OpMemoryModel Logical GLSL450
     65                OpEntryPoint Fragment %2 "main"
     66                OpExecutionMode %2 OriginUpperLeft
     67                OpSource GLSL 430
     68           %3 = OpTypeVoid
     69           %4 = OpTypeFunction %3
     70           %5 = OpTypeFloat 32
     71           %6 = OpTypePointer Function %5
     72           %2 = OpFunction %3 None %4
     73           %7 = OpLabel
     74           %8 = OpVariable %6 Function
     75           %9 = OpLoad %5 %8
     76          %10 = OpFAdd %5 %9 %9
     77 ; CHECK: OpFAdd
     78                OpStore %8 %10
     79          %11 = OpLoad %5 %8
     80 ; CHECK: %11 = OpLoad
     81          %12 = OpFAdd %5 %11 %11
     82 ; CHECK: OpFAdd [[:%\w+]] %11 %11
     83                OpReturn
     84                OpFunctionEnd
     85   )";
     86   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
     87   SinglePassRunAndMatch<LocalRedundancyEliminationPass>(text, false);
     88 }
     89 
     90 // This test is check that the values are being propagated properly, and that
     91 // we are able to identify sequences of instruction that are not needed.
     92 TEST_F(LocalRedundancyEliminationTest, RemoveMultipleInstructions) {
     93   const std::string text = R"(
     94                OpCapability Shader
     95           %1 = OpExtInstImport "GLSL.std.450"
     96                OpMemoryModel Logical GLSL450
     97                OpEntryPoint Fragment %2 "main"
     98                OpExecutionMode %2 OriginUpperLeft
     99                OpSource GLSL 430
    100           %3 = OpTypeVoid
    101           %4 = OpTypeFunction %3
    102           %5 = OpTypeFloat 32
    103           %6 = OpTypePointer Uniform %5
    104           %8 = OpVariable %6 Uniform
    105           %2 = OpFunction %3 None %4
    106           %7 = OpLabel
    107 ; CHECK: [[r1:%\w+]] = OpLoad
    108           %9 = OpLoad %5 %8
    109 ; CHECK-NEXT: [[r2:%\w+]] = OpFAdd [[:%\w+]] [[r1]] [[r1]]
    110          %10 = OpFAdd %5 %9 %9
    111 ; CHECK-NEXT: [[r3:%\w+]] = OpFMul [[:%\w+]] [[r2]] [[r1]]
    112          %11 = OpFMul %5 %10 %9
    113 ; CHECK-NOT: OpLoad
    114          %12 = OpLoad %5 %8
    115 ; CHECK-NOT: OpFAdd [[:\w+]] %12 %12
    116          %13 = OpFAdd %5 %12 %12
    117 ; CHECK-NOT: OpFMul
    118          %14 = OpFMul %5 %13 %12
    119 ; CHECK-NEXT: [[:%\w+]] = OpFAdd [[:%\w+]] [[r3]] [[r3]]
    120          %15 = OpFAdd %5 %14 %11
    121                OpReturn
    122                OpFunctionEnd
    123   )";
    124   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
    125   SinglePassRunAndMatch<LocalRedundancyEliminationPass>(text, false);
    126 }
    127 
    128 // Redundant instructions in different blocks should be kept.
    129 TEST_F(LocalRedundancyEliminationTest, KeepInstructionsInDifferentBlocks) {
    130   const std::string text = R"(
    131                OpCapability Shader
    132           %1 = OpExtInstImport "GLSL.std.450"
    133                OpMemoryModel Logical GLSL450
    134                OpEntryPoint Fragment %2 "main"
    135                OpExecutionMode %2 OriginUpperLeft
    136                OpSource GLSL 430
    137           %3 = OpTypeVoid
    138           %4 = OpTypeFunction %3
    139           %5 = OpTypeFloat 32
    140           %6 = OpTypePointer Function %5
    141           %2 = OpFunction %3 None %4
    142         %bb1 = OpLabel
    143           %8 = OpVariable %6 Function
    144           %9 = OpLoad %5 %8
    145          %10 = OpFAdd %5 %9 %9
    146 ; CHECK: OpFAdd
    147                OpBranch %bb2
    148         %bb2 = OpLabel
    149 ; CHECK: OpFAdd
    150          %11 = OpFAdd %5 %9 %9
    151                OpReturn
    152                OpFunctionEnd
    153   )";
    154   SinglePassRunAndMatch<LocalRedundancyEliminationPass>(text, false);
    155 }
    156 
    157 }  // namespace
    158 }  // namespace opt
    159 }  // namespace spvtools
    160