Loop invariant code motion initial implementation
[platform/upstream/SPIRV-Tools.git] / test / opt / loop_optimizations / hoist_all_loop_types.cpp
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
19 #include "../pass_fixture.h"
20 #include "opt/licm_pass.h"
21
22 namespace {
23
24 using namespace spvtools;
25 using ::testing::UnorderedElementsAre;
26
27 using PassClassTest = PassTest<::testing::Test>;
28
29 /*
30   Tests that all loop types are handled appropriately by the LICM pass.
31
32   Generated from the following GLSL fragment shader
33 --eliminate-local-multi-store has also been run on the spv binary
34 #version 440 core
35 void main(){
36   int i_1 = 0;
37   for (i_1 = 0; i_1 < 10; i_1++) {
38   }
39   int i_2 = 0;
40   while (i_2 < 10) {
41     i_2++;
42   }
43   int i_3 = 0;
44   do {
45     i_3++;
46   } while (i_3 < 10);
47   int hoist = 0;
48   int i_4 = 0;
49   int i_5 = 0;
50   int i_6 = 0;
51   for (i_4 = 0; i_4 < 10; i_4++) {
52     while (i_5 < 10) {
53       do {
54         hoist = i_1 + i_2 + i_3;
55         i_6++;
56       } while (i_6 < 10);
57       i_5++;
58     }
59   }
60 }
61 */
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
68 OpSource GLSL 440
69 OpName %main "main"
70 %void = OpTypeVoid
71 %4 = OpTypeFunction %void
72 %int = OpTypeInt 32 1
73 %_ptr_Function_int = OpTypePointer Function %int
74 %int_0 = OpConstant %int 0
75 %int_10 = OpConstant %int 10
76 %bool = OpTypeBool
77 %int_1 = OpConstant %int 1
78 %main = OpFunction %void None %4
79 %11 = OpLabel
80 OpBranch %12
81 %12 = OpLabel
82 %13 = OpPhi %int %int_0 %11 %14 %15
83 OpLoopMerge %16 %15 None
84 OpBranch %17
85 %17 = OpLabel
86 %18 = OpSLessThan %bool %13 %int_10
87 OpBranchConditional %18 %19 %16
88 %19 = OpLabel
89 OpBranch %15
90 %15 = OpLabel
91 %14 = OpIAdd %int %13 %int_1
92 OpBranch %12
93 %16 = OpLabel
94 OpBranch %20
95 %20 = OpLabel
96 %21 = OpPhi %int %int_0 %16 %22 %23
97 OpLoopMerge %24 %23 None
98 OpBranch %25
99 %25 = OpLabel
100 %26 = OpSLessThan %bool %21 %int_10
101 OpBranchConditional %26 %27 %24
102 %27 = OpLabel
103 %22 = OpIAdd %int %21 %int_1
104 OpBranch %23
105 %23 = OpLabel
106 OpBranch %20
107 %24 = OpLabel
108 OpBranch %28
109 %28 = OpLabel
110 %29 = OpPhi %int %int_0 %24 %30 %31
111 OpLoopMerge %32 %31 None
112 OpBranch %33
113 %33 = OpLabel
114 %30 = OpIAdd %int %29 %int_1
115 OpBranch %31
116 %31 = OpLabel
117 %34 = OpSLessThan %bool %30 %int_10
118 OpBranchConditional %34 %28 %32
119 %32 = OpLabel
120 OpBranch %35
121 %35 = OpLabel
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
127 OpBranch %46
128 %46 = OpLabel
129 %47 = OpSLessThan %bool %39 %int_10
130 OpBranchConditional %47 %48 %45
131 %48 = OpLabel
132 OpBranch %49
133 %49 = OpLabel
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
138 OpBranch %55
139 %55 = OpLabel
140 %56 = OpSLessThan %bool %42 %int_10
141 OpBranchConditional %56 %57 %54
142 %57 = OpLabel
143 OpBranch %58
144 %58 = OpLabel
145 %59 = OpPhi %int %37 %57 %50 %60
146 %61 = OpPhi %int %44 %57 %53 %60
147 OpLoopMerge %62 %60 None
148 OpBranch %63
149 %63 = OpLabel
150 %64 = OpIAdd %int %13 %21
151 %50 = OpIAdd %int %64 %30
152 %53 = OpIAdd %int %61 %int_1
153 OpBranch %60
154 %60 = OpLabel
155 %65 = OpSLessThan %bool %53 %int_10
156 OpBranchConditional %65 %58 %62
157 %62 = OpLabel
158 %52 = OpIAdd %int %42 %int_1
159 OpBranch %51
160 %51 = OpLabel
161 OpBranch %49
162 %54 = OpLabel
163 OpBranch %38
164 %38 = OpLabel
165 %40 = OpIAdd %int %39 %int_1
166 OpBranch %35
167 %45 = OpLabel
168 OpReturn
169 OpFunctionEnd
170 )";
171
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
177 OpSource GLSL 440
178 OpName %main "main"
179 %void = OpTypeVoid
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
185 %bool = OpTypeBool
186 %int_1 = OpConstant %int 1
187 %main = OpFunction %void None %4
188 %11 = OpLabel
189 OpBranch %12
190 %12 = OpLabel
191 %13 = OpPhi %int %int_0 %11 %14 %15
192 OpLoopMerge %16 %15 None
193 OpBranch %17
194 %17 = OpLabel
195 %18 = OpSLessThan %bool %13 %int_10
196 OpBranchConditional %18 %19 %16
197 %19 = OpLabel
198 OpBranch %15
199 %15 = OpLabel
200 %14 = OpIAdd %int %13 %int_1
201 OpBranch %12
202 %16 = OpLabel
203 OpBranch %20
204 %20 = OpLabel
205 %21 = OpPhi %int %int_0 %16 %22 %23
206 OpLoopMerge %24 %23 None
207 OpBranch %25
208 %25 = OpLabel
209 %26 = OpSLessThan %bool %21 %int_10
210 OpBranchConditional %26 %27 %24
211 %27 = OpLabel
212 %22 = OpIAdd %int %21 %int_1
213 OpBranch %23
214 %23 = OpLabel
215 OpBranch %20
216 %24 = OpLabel
217 OpBranch %28
218 %28 = OpLabel
219 %29 = OpPhi %int %int_0 %24 %30 %31
220 OpLoopMerge %32 %31 None
221 OpBranch %33
222 %33 = OpLabel
223 %30 = OpIAdd %int %29 %int_1
224 OpBranch %31
225 %31 = OpLabel
226 %34 = OpSLessThan %bool %30 %int_10
227 OpBranchConditional %34 %28 %32
228 %32 = OpLabel
229 %64 = OpIAdd %int %13 %21
230 %50 = OpIAdd %int %64 %30
231 OpBranch %35
232 %35 = OpLabel
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
238 OpBranch %46
239 %46 = OpLabel
240 %47 = OpSLessThan %bool %39 %int_10
241 OpBranchConditional %47 %48 %45
242 %48 = OpLabel
243 OpBranch %49
244 %49 = OpLabel
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
249 OpBranch %55
250 %55 = OpLabel
251 %56 = OpSLessThan %bool %42 %int_10
252 OpBranchConditional %56 %57 %54
253 %57 = OpLabel
254 OpBranch %58
255 %58 = OpLabel
256 %59 = OpPhi %int %37 %57 %50 %60
257 %61 = OpPhi %int %44 %57 %53 %60
258 OpLoopMerge %62 %60 None
259 OpBranch %63
260 %63 = OpLabel
261 %53 = OpIAdd %int %61 %int_1
262 OpBranch %60
263 %60 = OpLabel
264 %65 = OpSLessThan %bool %53 %int_10
265 OpBranchConditional %65 %58 %62
266 %62 = OpLabel
267 %52 = OpIAdd %int %42 %int_1
268 OpBranch %51
269 %51 = OpLabel
270 OpBranch %49
271 %54 = OpLabel
272 OpBranch %38
273 %38 = OpLabel
274 %40 = OpIAdd %int %39 %int_1
275 OpBranch %35
276 %45 = OpLabel
277 OpReturn
278 OpFunctionEnd
279 )";
280
281   SinglePassRunAndCheck<opt::LICMPass>(before_hoist, after_hoist, true);
282 }
283
284 }  // namespace