Loop invariant code motion initial implementation
[platform/upstream/SPIRV-Tools.git] / test / opt / loop_optimizations / hoist_without_preheader.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 generate a preheader when one is not present
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     if (i == 5) {
41       break;
42     }
43   }
44   for (int i = 0; i < 10; i++) {
45     hoist = a + b;
46   }
47 }
48 */
49 TEST_F(PassClassTest, HoistWithoutPreheader) {
50   const std::string before_hoist = R"(OpCapability Shader
51 %1 = OpExtInstImport "GLSL.std.450"
52 OpMemoryModel Logical GLSL450
53 OpEntryPoint Fragment %main "main"
54 OpExecutionMode %main OriginUpperLeft
55 OpSource GLSL 440
56 OpName %main "main"
57 %void = OpTypeVoid
58 %4 = OpTypeFunction %void
59 %int = OpTypeInt 32 1
60 %_ptr_Function_int = OpTypePointer Function %int
61 %int_1 = OpConstant %int 1
62 %int_2 = OpConstant %int 2
63 %int_0 = OpConstant %int 0
64 %int_10 = OpConstant %int 10
65 %bool = OpTypeBool
66 %int_5 = OpConstant %int 5
67 %main = OpFunction %void None %4
68 %13 = OpLabel
69 OpBranch %14
70 %14 = OpLabel
71 %15 = OpPhi %int %int_0 %13 %16 %17
72 OpLoopMerge %25 %17 None
73 OpBranch %19
74 %19 = OpLabel
75 %20 = OpSLessThan %bool %15 %int_10
76 OpBranchConditional %20 %21 %25
77 %21 = OpLabel
78 %22 = OpIEqual %bool %15 %int_5
79 OpSelectionMerge %23 None
80 OpBranchConditional %22 %24 %23
81 %24 = OpLabel
82 OpBranch %25
83 %23 = OpLabel
84 OpBranch %17
85 %17 = OpLabel
86 %16 = OpIAdd %int %15 %int_1
87 OpBranch %14
88 %25 = OpLabel
89 %26 = OpPhi %int %int_0 %24 %int_0 %19 %27 %28
90 %29 = OpPhi %int %int_0 %24 %int_0 %19 %30 %28
91 OpLoopMerge %31 %28 None
92 OpBranch %32
93 %32 = OpLabel
94 %33 = OpSLessThan %bool %29 %int_10
95 OpBranchConditional %33 %34 %31
96 %34 = OpLabel
97 %27 = OpIAdd %int %int_1 %int_2
98 OpBranch %28
99 %28 = OpLabel
100 %30 = OpIAdd %int %29 %int_1
101 OpBranch %25
102 %31 = OpLabel
103 OpReturn
104 OpFunctionEnd
105 )";
106
107   const std::string after_hoist = R"(OpCapability Shader
108 %1 = OpExtInstImport "GLSL.std.450"
109 OpMemoryModel Logical GLSL450
110 OpEntryPoint Fragment %main "main"
111 OpExecutionMode %main OriginUpperLeft
112 OpSource GLSL 440
113 OpName %main "main"
114 %void = OpTypeVoid
115 %4 = OpTypeFunction %void
116 %int = OpTypeInt 32 1
117 %_ptr_Function_int = OpTypePointer Function %int
118 %int_1 = OpConstant %int 1
119 %int_2 = OpConstant %int 2
120 %int_0 = OpConstant %int 0
121 %int_10 = OpConstant %int 10
122 %bool = OpTypeBool
123 %int_5 = OpConstant %int 5
124 %main = OpFunction %void None %4
125 %13 = OpLabel
126 OpBranch %14
127 %14 = OpLabel
128 %15 = OpPhi %int %int_0 %13 %16 %17
129 OpLoopMerge %18 %17 None
130 OpBranch %19
131 %19 = OpLabel
132 %20 = OpSLessThan %bool %15 %int_10
133 OpBranchConditional %20 %21 %34
134 %21 = OpLabel
135 %22 = OpIEqual %bool %15 %int_5
136 OpSelectionMerge %23 None
137 OpBranchConditional %22 %24 %23
138 %24 = OpLabel
139 OpBranch %34
140 %23 = OpLabel
141 OpBranch %17
142 %17 = OpLabel
143 %16 = OpIAdd %int %15 %int_1
144 OpBranch %14
145 %34 = OpLabel
146 %35 = OpPhi %int %int_0 %24 %int_0 %19
147 %36 = OpPhi %int %int_0 %24 %int_0 %19
148 %26 = OpIAdd %int %int_1 %int_2
149 OpBranch %18
150 %18 = OpLabel
151 %25 = OpPhi %int %26 %27 %35 %34
152 %28 = OpPhi %int %29 %27 %36 %34
153 OpLoopMerge %30 %27 None
154 OpBranch %31
155 %31 = OpLabel
156 %32 = OpSLessThan %bool %28 %int_10
157 OpBranchConditional %32 %33 %30
158 %33 = OpLabel
159 OpBranch %27
160 %27 = OpLabel
161 %29 = OpIAdd %int %28 %int_1
162 OpBranch %18
163 %30 = OpLabel
164 OpReturn
165 OpFunctionEnd
166 )";
167
168   SinglePassRunAndCheck<opt::LICMPass>(before_hoist, after_hoist, true);
169 }
170
171 }  // namespace