1 // Copyright (c) 2018 Google LLC.
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
7 // http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include <gmock/gmock.h>
19 #include "../pass_fixture.h"
20 #include "opt/licm_pass.h"
24 using namespace spvtools;
25 using ::testing::UnorderedElementsAre;
27 using PassClassTest = PassTest<::testing::Test>;
30 Tests that all loop types are handled appropriately by the LICM pass.
32 Generated from the following GLSL fragment shader
33 --eliminate-local-multi-store has also been run on the spv binary
37 for (i_1 = 0; i_1 < 10; i_1++) {
51 for (i_4 = 0; i_4 < 10; i_4++) {
54 hoist = i_1 + i_2 + i_3;
62 TEST_F(PassClassTest, AllLoopTypes) {
63 const std::string before_hoist = R"(OpCapability Shader
64 %1 = OpExtInstImport "GLSL.std.450"
65 OpMemoryModel Logical GLSL450
66 OpEntryPoint Fragment %main "main"
67 OpExecutionMode %main OriginUpperLeft
71 %4 = OpTypeFunction %void
73 %_ptr_Function_int = OpTypePointer Function %int
74 %int_0 = OpConstant %int 0
75 %int_10 = OpConstant %int 10
77 %int_1 = OpConstant %int 1
78 %main = OpFunction %void None %4
82 %13 = OpPhi %int %int_0 %11 %14 %15
83 OpLoopMerge %16 %15 None
86 %18 = OpSLessThan %bool %13 %int_10
87 OpBranchConditional %18 %19 %16
91 %14 = OpIAdd %int %13 %int_1
96 %21 = OpPhi %int %int_0 %16 %22 %23
97 OpLoopMerge %24 %23 None
100 %26 = OpSLessThan %bool %21 %int_10
101 OpBranchConditional %26 %27 %24
103 %22 = OpIAdd %int %21 %int_1
110 %29 = OpPhi %int %int_0 %24 %30 %31
111 OpLoopMerge %32 %31 None
114 %30 = OpIAdd %int %29 %int_1
117 %34 = OpSLessThan %bool %30 %int_10
118 OpBranchConditional %34 %28 %32
122 %36 = OpPhi %int %int_0 %32 %37 %38
123 %39 = OpPhi %int %int_0 %32 %40 %38
124 %41 = OpPhi %int %int_0 %32 %42 %38
125 %43 = OpPhi %int %int_0 %32 %44 %38
126 OpLoopMerge %45 %38 None
129 %47 = OpSLessThan %bool %39 %int_10
130 OpBranchConditional %47 %48 %45
134 %37 = OpPhi %int %36 %48 %50 %51
135 %42 = OpPhi %int %41 %48 %52 %51
136 %44 = OpPhi %int %43 %48 %53 %51
137 OpLoopMerge %54 %51 None
140 %56 = OpSLessThan %bool %42 %int_10
141 OpBranchConditional %56 %57 %54
145 %59 = OpPhi %int %37 %57 %50 %60
146 %61 = OpPhi %int %44 %57 %53 %60
147 OpLoopMerge %62 %60 None
150 %64 = OpIAdd %int %13 %21
151 %50 = OpIAdd %int %64 %30
152 %53 = OpIAdd %int %61 %int_1
155 %65 = OpSLessThan %bool %53 %int_10
156 OpBranchConditional %65 %58 %62
158 %52 = OpIAdd %int %42 %int_1
165 %40 = OpIAdd %int %39 %int_1
172 const std::string after_hoist = R"(OpCapability Shader
173 %1 = OpExtInstImport "GLSL.std.450"
174 OpMemoryModel Logical GLSL450
175 OpEntryPoint Fragment %main "main"
176 OpExecutionMode %main OriginUpperLeft
180 %4 = OpTypeFunction %void
181 %int = OpTypeInt 32 1
182 %_ptr_Function_int = OpTypePointer Function %int
183 %int_0 = OpConstant %int 0
184 %int_10 = OpConstant %int 10
186 %int_1 = OpConstant %int 1
187 %main = OpFunction %void None %4
191 %13 = OpPhi %int %int_0 %11 %14 %15
192 OpLoopMerge %16 %15 None
195 %18 = OpSLessThan %bool %13 %int_10
196 OpBranchConditional %18 %19 %16
200 %14 = OpIAdd %int %13 %int_1
205 %21 = OpPhi %int %int_0 %16 %22 %23
206 OpLoopMerge %24 %23 None
209 %26 = OpSLessThan %bool %21 %int_10
210 OpBranchConditional %26 %27 %24
212 %22 = OpIAdd %int %21 %int_1
219 %29 = OpPhi %int %int_0 %24 %30 %31
220 OpLoopMerge %32 %31 None
223 %30 = OpIAdd %int %29 %int_1
226 %34 = OpSLessThan %bool %30 %int_10
227 OpBranchConditional %34 %28 %32
229 %64 = OpIAdd %int %13 %21
230 %50 = OpIAdd %int %64 %30
233 %36 = OpPhi %int %int_0 %32 %37 %38
234 %39 = OpPhi %int %int_0 %32 %40 %38
235 %41 = OpPhi %int %int_0 %32 %42 %38
236 %43 = OpPhi %int %int_0 %32 %44 %38
237 OpLoopMerge %45 %38 None
240 %47 = OpSLessThan %bool %39 %int_10
241 OpBranchConditional %47 %48 %45
245 %37 = OpPhi %int %36 %48 %50 %51
246 %42 = OpPhi %int %41 %48 %52 %51
247 %44 = OpPhi %int %43 %48 %53 %51
248 OpLoopMerge %54 %51 None
251 %56 = OpSLessThan %bool %42 %int_10
252 OpBranchConditional %56 %57 %54
256 %59 = OpPhi %int %37 %57 %50 %60
257 %61 = OpPhi %int %44 %57 %53 %60
258 OpLoopMerge %62 %60 None
261 %53 = OpIAdd %int %61 %int_1
264 %65 = OpSLessThan %bool %53 %int_10
265 OpBranchConditional %65 %58 %62
267 %52 = OpIAdd %int %42 %int_1
274 %40 = OpIAdd %int %39 %int_1
281 SinglePassRunAndCheck<opt::LICMPass>(before_hoist, after_hoist, true);