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