Home | History | Annotate | Download | only in loop_optimizations
      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 "source/opt/licm_pass.h"
     19 #include "test/opt/pass_fixture.h"
     20 
     21 namespace spvtools {
     22 namespace opt {
     23 namespace {
     24 
     25 using ::testing::UnorderedElementsAre;
     26 using PassClassTest = PassTest<::testing::Test>;
     27 
     28 /*
     29   Tests that the LICM pass will analyse multiple independent loops in a function
     30 
     31   Generated from the following GLSL fragment shader
     32 --eliminate-local-multi-store has also been run on the spv binary
     33 #version 440 core
     34 void main(){
     35   int a = 1;
     36   int b = 2;
     37   int hoist = 0;
     38   for (int i = 0; i < 10; i++) {
     39     // invariant
     40     hoist = a + b;
     41   }
     42   for (int i = 0; i < 10; i++) {
     43     // invariant
     44     hoist = a + b;
     45   }
     46   int c = 1;
     47   int d = 2;
     48   int hoist2 = 0;
     49   for (int i = 0; i < 10; i++) {
     50     // invariant
     51     hoist2 = c + d;
     52   }
     53 }
     54 */
     55 TEST_F(PassClassTest, HoistFromIndependentLoops) {
     56   const std::string before_hoist = R"(OpCapability Shader
     57 %1 = OpExtInstImport "GLSL.std.450"
     58 OpMemoryModel Logical GLSL450
     59 OpEntryPoint Fragment %main "main"
     60 OpExecutionMode %main OriginUpperLeft
     61 OpSource GLSL 440
     62 OpName %main "main"
     63 %void = OpTypeVoid
     64 %4 = OpTypeFunction %void
     65 %int = OpTypeInt 32 1
     66 %_ptr_Function_int = OpTypePointer Function %int
     67 %int_1 = OpConstant %int 1
     68 %int_2 = OpConstant %int 2
     69 %int_0 = OpConstant %int 0
     70 %int_10 = OpConstant %int 10
     71 %bool = OpTypeBool
     72 %main = OpFunction %void None %4
     73 %12 = OpLabel
     74 OpBranch %13
     75 %13 = OpLabel
     76 %14 = OpPhi %int %int_0 %12 %15 %16
     77 %17 = OpPhi %int %int_0 %12 %18 %16
     78 OpLoopMerge %19 %16 None
     79 OpBranch %20
     80 %20 = OpLabel
     81 %21 = OpSLessThan %bool %17 %int_10
     82 OpBranchConditional %21 %22 %19
     83 %22 = OpLabel
     84 %15 = OpIAdd %int %int_1 %int_2
     85 OpBranch %16
     86 %16 = OpLabel
     87 %18 = OpIAdd %int %17 %int_1
     88 OpBranch %13
     89 %19 = OpLabel
     90 OpBranch %23
     91 %23 = OpLabel
     92 %24 = OpPhi %int %14 %19 %25 %26
     93 %27 = OpPhi %int %int_0 %19 %28 %26
     94 OpLoopMerge %29 %26 None
     95 OpBranch %30
     96 %30 = OpLabel
     97 %31 = OpSLessThan %bool %27 %int_10
     98 OpBranchConditional %31 %32 %29
     99 %32 = OpLabel
    100 %25 = OpIAdd %int %int_1 %int_2
    101 OpBranch %26
    102 %26 = OpLabel
    103 %28 = OpIAdd %int %27 %int_1
    104 OpBranch %23
    105 %29 = OpLabel
    106 OpBranch %33
    107 %33 = OpLabel
    108 %34 = OpPhi %int %int_0 %29 %35 %36
    109 %37 = OpPhi %int %int_0 %29 %38 %36
    110 OpLoopMerge %39 %36 None
    111 OpBranch %40
    112 %40 = OpLabel
    113 %41 = OpSLessThan %bool %37 %int_10
    114 OpBranchConditional %41 %42 %39
    115 %42 = OpLabel
    116 %35 = OpIAdd %int %int_1 %int_2
    117 OpBranch %36
    118 %36 = OpLabel
    119 %38 = OpIAdd %int %37 %int_1
    120 OpBranch %33
    121 %39 = OpLabel
    122 OpReturn
    123 OpFunctionEnd
    124 )";
    125 
    126   const std::string after_hoist = R"(OpCapability Shader
    127 %1 = OpExtInstImport "GLSL.std.450"
    128 OpMemoryModel Logical GLSL450
    129 OpEntryPoint Fragment %main "main"
    130 OpExecutionMode %main OriginUpperLeft
    131 OpSource GLSL 440
    132 OpName %main "main"
    133 %void = OpTypeVoid
    134 %4 = OpTypeFunction %void
    135 %int = OpTypeInt 32 1
    136 %_ptr_Function_int = OpTypePointer Function %int
    137 %int_1 = OpConstant %int 1
    138 %int_2 = OpConstant %int 2
    139 %int_0 = OpConstant %int 0
    140 %int_10 = OpConstant %int 10
    141 %bool = OpTypeBool
    142 %main = OpFunction %void None %4
    143 %12 = OpLabel
    144 %15 = OpIAdd %int %int_1 %int_2
    145 OpBranch %13
    146 %13 = OpLabel
    147 %14 = OpPhi %int %int_0 %12 %15 %16
    148 %17 = OpPhi %int %int_0 %12 %18 %16
    149 OpLoopMerge %19 %16 None
    150 OpBranch %20
    151 %20 = OpLabel
    152 %21 = OpSLessThan %bool %17 %int_10
    153 OpBranchConditional %21 %22 %19
    154 %22 = OpLabel
    155 OpBranch %16
    156 %16 = OpLabel
    157 %18 = OpIAdd %int %17 %int_1
    158 OpBranch %13
    159 %19 = OpLabel
    160 %25 = OpIAdd %int %int_1 %int_2
    161 OpBranch %23
    162 %23 = OpLabel
    163 %24 = OpPhi %int %14 %19 %25 %26
    164 %27 = OpPhi %int %int_0 %19 %28 %26
    165 OpLoopMerge %29 %26 None
    166 OpBranch %30
    167 %30 = OpLabel
    168 %31 = OpSLessThan %bool %27 %int_10
    169 OpBranchConditional %31 %32 %29
    170 %32 = OpLabel
    171 OpBranch %26
    172 %26 = OpLabel
    173 %28 = OpIAdd %int %27 %int_1
    174 OpBranch %23
    175 %29 = OpLabel
    176 %35 = OpIAdd %int %int_1 %int_2
    177 OpBranch %33
    178 %33 = OpLabel
    179 %34 = OpPhi %int %int_0 %29 %35 %36
    180 %37 = OpPhi %int %int_0 %29 %38 %36
    181 OpLoopMerge %39 %36 None
    182 OpBranch %40
    183 %40 = OpLabel
    184 %41 = OpSLessThan %bool %37 %int_10
    185 OpBranchConditional %41 %42 %39
    186 %42 = OpLabel
    187 OpBranch %36
    188 %36 = OpLabel
    189 %38 = OpIAdd %int %37 %int_1
    190 OpBranch %33
    191 %39 = OpLabel
    192 OpReturn
    193 OpFunctionEnd
    194 )";
    195 
    196   SinglePassRunAndCheck<LICMPass>(before_hoist, after_hoist, true);
    197 }
    198 
    199 }  // namespace
    200 }  // namespace opt
    201 }  // namespace spvtools
    202