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 the LICM pass will analyse multiple independent loops in a function
32 Generated from the following GLSL fragment shader
33 --eliminate-local-multi-store has also been run on the spv binary
39 for (int i = 0; i < 10; i++) {
43 for (int i = 0; i < 10; i++) {
50 for (int i = 0; i < 10; i++) {
56 TEST_F(PassClassTest, HoistFromIndependentLoops) {
57 const std::string before_hoist = R"(OpCapability Shader
58 %1 = OpExtInstImport "GLSL.std.450"
59 OpMemoryModel Logical GLSL450
60 OpEntryPoint Fragment %main "main"
61 OpExecutionMode %main OriginUpperLeft
65 %4 = OpTypeFunction %void
67 %_ptr_Function_int = OpTypePointer Function %int
68 %int_1 = OpConstant %int 1
69 %int_2 = OpConstant %int 2
70 %int_0 = OpConstant %int 0
71 %int_10 = OpConstant %int 10
73 %main = OpFunction %void None %4
77 %14 = OpPhi %int %int_0 %12 %15 %16
78 %17 = OpPhi %int %int_0 %12 %18 %16
79 OpLoopMerge %19 %16 None
82 %21 = OpSLessThan %bool %17 %int_10
83 OpBranchConditional %21 %22 %19
85 %15 = OpIAdd %int %int_1 %int_2
88 %18 = OpIAdd %int %17 %int_1
93 %24 = OpPhi %int %14 %19 %25 %26
94 %27 = OpPhi %int %int_0 %19 %28 %26
95 OpLoopMerge %29 %26 None
98 %31 = OpSLessThan %bool %27 %int_10
99 OpBranchConditional %31 %32 %29
101 %25 = OpIAdd %int %int_1 %int_2
104 %28 = OpIAdd %int %27 %int_1
109 %34 = OpPhi %int %int_0 %29 %35 %36
110 %37 = OpPhi %int %int_0 %29 %38 %36
111 OpLoopMerge %39 %36 None
114 %41 = OpSLessThan %bool %37 %int_10
115 OpBranchConditional %41 %42 %39
117 %35 = OpIAdd %int %int_1 %int_2
120 %38 = OpIAdd %int %37 %int_1
127 const std::string after_hoist = R"(OpCapability Shader
128 %1 = OpExtInstImport "GLSL.std.450"
129 OpMemoryModel Logical GLSL450
130 OpEntryPoint Fragment %main "main"
131 OpExecutionMode %main OriginUpperLeft
135 %4 = OpTypeFunction %void
136 %int = OpTypeInt 32 1
137 %_ptr_Function_int = OpTypePointer Function %int
138 %int_1 = OpConstant %int 1
139 %int_2 = OpConstant %int 2
140 %int_0 = OpConstant %int 0
141 %int_10 = OpConstant %int 10
143 %main = OpFunction %void None %4
145 %15 = OpIAdd %int %int_1 %int_2
148 %14 = OpPhi %int %int_0 %12 %15 %16
149 %17 = OpPhi %int %int_0 %12 %18 %16
150 OpLoopMerge %19 %16 None
153 %21 = OpSLessThan %bool %17 %int_10
154 OpBranchConditional %21 %22 %19
158 %18 = OpIAdd %int %17 %int_1
161 %25 = OpIAdd %int %int_1 %int_2
164 %24 = OpPhi %int %14 %19 %25 %26
165 %27 = OpPhi %int %int_0 %19 %28 %26
166 OpLoopMerge %29 %26 None
169 %31 = OpSLessThan %bool %27 %int_10
170 OpBranchConditional %31 %32 %29
174 %28 = OpIAdd %int %27 %int_1
177 %35 = OpIAdd %int %int_1 %int_2
180 %34 = OpPhi %int %int_0 %29 %35 %36
181 %37 = OpPhi %int %int_0 %29 %38 %36
182 OpLoopMerge %39 %36 None
185 %41 = OpSLessThan %bool %37 %int_10
186 OpBranchConditional %41 %42 %39
190 %38 = OpIAdd %int %37 %int_1
197 SinglePassRunAndCheck<opt::LICMPass>(before_hoist, after_hoist, true);