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