Loop invariant code motion initial implementation
[platform/upstream/SPIRV-Tools.git] / test / opt / loop_optimizations / hoist_from_independent_loops.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 the LICM pass will analyse multiple independent loops in a function
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 a = 1;
37   int b = 2;
38   int hoist = 0;
39   for (int i = 0; i < 10; i++) {
40     // invariant
41     hoist = a + b;
42   }
43   for (int i = 0; i < 10; i++) {
44     // invariant
45     hoist = a + b;
46   }
47   int c = 1;
48   int d = 2;
49   int hoist2 = 0;
50   for (int i = 0; i < 10; i++) {
51     // invariant
52     hoist2 = c + d;
53   }
54 }
55 */
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
62 OpSource GLSL 440
63 OpName %main "main"
64 %void = OpTypeVoid
65 %4 = OpTypeFunction %void
66 %int = OpTypeInt 32 1
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
72 %bool = OpTypeBool
73 %main = OpFunction %void None %4
74 %12 = OpLabel
75 OpBranch %13
76 %13 = OpLabel
77 %14 = OpPhi %int %int_0 %12 %15 %16
78 %17 = OpPhi %int %int_0 %12 %18 %16
79 OpLoopMerge %19 %16 None
80 OpBranch %20
81 %20 = OpLabel
82 %21 = OpSLessThan %bool %17 %int_10
83 OpBranchConditional %21 %22 %19
84 %22 = OpLabel
85 %15 = OpIAdd %int %int_1 %int_2
86 OpBranch %16
87 %16 = OpLabel
88 %18 = OpIAdd %int %17 %int_1
89 OpBranch %13
90 %19 = OpLabel
91 OpBranch %23
92 %23 = OpLabel
93 %24 = OpPhi %int %14 %19 %25 %26
94 %27 = OpPhi %int %int_0 %19 %28 %26
95 OpLoopMerge %29 %26 None
96 OpBranch %30
97 %30 = OpLabel
98 %31 = OpSLessThan %bool %27 %int_10
99 OpBranchConditional %31 %32 %29
100 %32 = OpLabel
101 %25 = OpIAdd %int %int_1 %int_2
102 OpBranch %26
103 %26 = OpLabel
104 %28 = OpIAdd %int %27 %int_1
105 OpBranch %23
106 %29 = OpLabel
107 OpBranch %33
108 %33 = OpLabel
109 %34 = OpPhi %int %int_0 %29 %35 %36
110 %37 = OpPhi %int %int_0 %29 %38 %36
111 OpLoopMerge %39 %36 None
112 OpBranch %40
113 %40 = OpLabel
114 %41 = OpSLessThan %bool %37 %int_10
115 OpBranchConditional %41 %42 %39
116 %42 = OpLabel
117 %35 = OpIAdd %int %int_1 %int_2
118 OpBranch %36
119 %36 = OpLabel
120 %38 = OpIAdd %int %37 %int_1
121 OpBranch %33
122 %39 = OpLabel
123 OpReturn
124 OpFunctionEnd
125 )";
126
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
132 OpSource GLSL 440
133 OpName %main "main"
134 %void = OpTypeVoid
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
142 %bool = OpTypeBool
143 %main = OpFunction %void None %4
144 %12 = OpLabel
145 %15 = OpIAdd %int %int_1 %int_2
146 OpBranch %13
147 %13 = OpLabel
148 %14 = OpPhi %int %int_0 %12 %15 %16
149 %17 = OpPhi %int %int_0 %12 %18 %16
150 OpLoopMerge %19 %16 None
151 OpBranch %20
152 %20 = OpLabel
153 %21 = OpSLessThan %bool %17 %int_10
154 OpBranchConditional %21 %22 %19
155 %22 = OpLabel
156 OpBranch %16
157 %16 = OpLabel
158 %18 = OpIAdd %int %17 %int_1
159 OpBranch %13
160 %19 = OpLabel
161 %25 = OpIAdd %int %int_1 %int_2
162 OpBranch %23
163 %23 = OpLabel
164 %24 = OpPhi %int %14 %19 %25 %26
165 %27 = OpPhi %int %int_0 %19 %28 %26
166 OpLoopMerge %29 %26 None
167 OpBranch %30
168 %30 = OpLabel
169 %31 = OpSLessThan %bool %27 %int_10
170 OpBranchConditional %31 %32 %29
171 %32 = OpLabel
172 OpBranch %26
173 %26 = OpLabel
174 %28 = OpIAdd %int %27 %int_1
175 OpBranch %23
176 %29 = OpLabel
177 %35 = OpIAdd %int %int_1 %int_2
178 OpBranch %33
179 %33 = OpLabel
180 %34 = OpPhi %int %int_0 %29 %35 %36
181 %37 = OpPhi %int %int_0 %29 %38 %36
182 OpLoopMerge %39 %36 None
183 OpBranch %40
184 %40 = OpLabel
185 %41 = OpSLessThan %bool %37 %int_10
186 OpBranchConditional %41 %42 %39
187 %42 = OpLabel
188 OpBranch %36
189 %36 = OpLabel
190 %38 = OpIAdd %int %37 %int_1
191 OpBranch %33
192 %39 = OpLabel
193 OpReturn
194 OpFunctionEnd
195 )";
196
197   SinglePassRunAndCheck<opt::LICMPass>(before_hoist, after_hoist, true);
198 }
199
200 }  // namespace