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 move invariants through multiple loops
     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 = 2;
     36   int b = 1;
     37   int hoist = 0;
     38   for (int i = 0; i < 10; i++) {
     39     for (int j = 0; j < 10; j++) {
     40       // hoist 'hoist = a - b' out of both loops
     41       hoist = a - b;
     42     }
     43   }
     44 }
     45 */
     46 TEST_F(PassClassTest, NestedDoubleHoist) {
     47   const std::string before_hoist = R"(OpCapability Shader
     48 %1 = OpExtInstImport "GLSL.std.450"
     49 OpMemoryModel Logical GLSL450
     50 OpEntryPoint Fragment %main "main"
     51 OpExecutionMode %main OriginUpperLeft
     52 OpSource GLSL 440
     53 OpName %main "main"
     54 %void = OpTypeVoid
     55 %4 = OpTypeFunction %void
     56 %int = OpTypeInt 32 1
     57 %_ptr_Function_int = OpTypePointer Function %int
     58 %int_2 = OpConstant %int 2
     59 %int_1 = OpConstant %int 1
     60 %int_0 = OpConstant %int 0
     61 %int_10 = OpConstant %int 10
     62 %bool = OpTypeBool
     63 %12 = OpUndef %int
     64 %main = OpFunction %void None %4
     65 %13 = OpLabel
     66 OpBranch %14
     67 %14 = OpLabel
     68 %15 = OpPhi %int %int_0 %13 %16 %17
     69 %18 = OpPhi %int %int_0 %13 %19 %17
     70 %20 = OpPhi %int %12 %13 %21 %17
     71 OpLoopMerge %22 %17 None
     72 OpBranch %23
     73 %23 = OpLabel
     74 %24 = OpSLessThan %bool %18 %int_10
     75 OpBranchConditional %24 %25 %22
     76 %25 = OpLabel
     77 OpBranch %26
     78 %26 = OpLabel
     79 %16 = OpPhi %int %15 %25 %27 %28
     80 %21 = OpPhi %int %int_0 %25 %29 %28
     81 OpLoopMerge %30 %28 None
     82 OpBranch %31
     83 %31 = OpLabel
     84 %32 = OpSLessThan %bool %21 %int_10
     85 OpBranchConditional %32 %33 %30
     86 %33 = OpLabel
     87 %27 = OpISub %int %int_2 %int_1
     88 OpBranch %28
     89 %28 = OpLabel
     90 %29 = OpIAdd %int %21 %int_1
     91 OpBranch %26
     92 %30 = OpLabel
     93 OpBranch %17
     94 %17 = OpLabel
     95 %19 = OpIAdd %int %18 %int_1
     96 OpBranch %14
     97 %22 = OpLabel
     98 OpReturn
     99 OpFunctionEnd
    100 )";
    101 
    102   const std::string after_hoist = R"(OpCapability Shader
    103 %1 = OpExtInstImport "GLSL.std.450"
    104 OpMemoryModel Logical GLSL450
    105 OpEntryPoint Fragment %main "main"
    106 OpExecutionMode %main OriginUpperLeft
    107 OpSource GLSL 440
    108 OpName %main "main"
    109 %void = OpTypeVoid
    110 %4 = OpTypeFunction %void
    111 %int = OpTypeInt 32 1
    112 %_ptr_Function_int = OpTypePointer Function %int
    113 %int_2 = OpConstant %int 2
    114 %int_1 = OpConstant %int 1
    115 %int_0 = OpConstant %int 0
    116 %int_10 = OpConstant %int 10
    117 %bool = OpTypeBool
    118 %12 = OpUndef %int
    119 %main = OpFunction %void None %4
    120 %13 = OpLabel
    121 %27 = OpISub %int %int_2 %int_1
    122 OpBranch %14
    123 %14 = OpLabel
    124 %15 = OpPhi %int %int_0 %13 %16 %17
    125 %18 = OpPhi %int %int_0 %13 %19 %17
    126 %20 = OpPhi %int %12 %13 %21 %17
    127 OpLoopMerge %22 %17 None
    128 OpBranch %23
    129 %23 = OpLabel
    130 %24 = OpSLessThan %bool %18 %int_10
    131 OpBranchConditional %24 %25 %22
    132 %25 = OpLabel
    133 OpBranch %26
    134 %26 = OpLabel
    135 %16 = OpPhi %int %15 %25 %27 %28
    136 %21 = OpPhi %int %int_0 %25 %29 %28
    137 OpLoopMerge %30 %28 None
    138 OpBranch %31
    139 %31 = OpLabel
    140 %32 = OpSLessThan %bool %21 %int_10
    141 OpBranchConditional %32 %33 %30
    142 %33 = OpLabel
    143 OpBranch %28
    144 %28 = OpLabel
    145 %29 = OpIAdd %int %21 %int_1
    146 OpBranch %26
    147 %30 = OpLabel
    148 OpBranch %17
    149 %17 = OpLabel
    150 %19 = OpIAdd %int %18 %int_1
    151 OpBranch %14
    152 %22 = OpLabel
    153 OpReturn
    154 OpFunctionEnd
    155 )";
    156 
    157   SinglePassRunAndCheck<LICMPass>(before_hoist, after_hoist, true);
    158 }
    159 
    160 }  // namespace
    161 }  // namespace opt
    162 }  // namespace spvtools
    163