Loop invariant code motion initial implementation
[platform/upstream/SPIRV-Tools.git] / test / opt / loop_optimizations / hoist_single_nested_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 detect an move an invariant from a nested loop,
31   but not it's parent loop
32
33   Generated from the following GLSL fragment shader
34 --eliminate-local-multi-store has also been run on the spv binary
35 #version 440 core
36 void main(){
37   int a = 2;
38   int hoist = 0;
39   for (int i = 0; i < 10; i++) {
40     for (int j = 0; j < 10; j++) {
41       // hoist 'hoist = a - i' out of j loop, but not i loop
42       hoist = a - i;
43     }
44   }
45 }
46 */
47 TEST_F(PassClassTest, NestedSingleHoist) {
48   const std::string before_hoist = R"(OpCapability Shader
49 %1 = OpExtInstImport "GLSL.std.450"
50 OpMemoryModel Logical GLSL450
51 OpEntryPoint Fragment %main "main"
52 OpExecutionMode %main OriginUpperLeft
53 OpSource GLSL 440
54 OpName %main "main"
55 %void = OpTypeVoid
56 %4 = OpTypeFunction %void
57 %int = OpTypeInt 32 1
58 %_ptr_Function_int = OpTypePointer Function %int
59 %int_2 = OpConstant %int 2
60 %int_0 = OpConstant %int 0
61 %int_10 = OpConstant %int 10
62 %bool = OpTypeBool
63 %int_1 = OpConstant %int 1
64 %12 = OpUndef %int
65 %main = OpFunction %void None %4
66 %13 = OpLabel
67 OpBranch %14
68 %14 = OpLabel
69 %15 = OpPhi %int %int_0 %13 %16 %17
70 %18 = OpPhi %int %int_0 %13 %19 %17
71 %20 = OpPhi %int %12 %13 %21 %17
72 OpLoopMerge %22 %17 None
73 OpBranch %23
74 %23 = OpLabel
75 %24 = OpSLessThan %bool %18 %int_10
76 OpBranchConditional %24 %25 %22
77 %25 = OpLabel
78 OpBranch %26
79 %26 = OpLabel
80 %16 = OpPhi %int %15 %25 %27 %28
81 %21 = OpPhi %int %int_0 %25 %29 %28
82 OpLoopMerge %30 %28 None
83 OpBranch %31
84 %31 = OpLabel
85 %32 = OpSLessThan %bool %21 %int_10
86 OpBranchConditional %32 %33 %30
87 %33 = OpLabel
88 %27 = OpISub %int %int_2 %18
89 OpBranch %28
90 %28 = OpLabel
91 %29 = OpIAdd %int %21 %int_1
92 OpBranch %26
93 %30 = OpLabel
94 OpBranch %17
95 %17 = OpLabel
96 %19 = OpIAdd %int %18 %int_1
97 OpBranch %14
98 %22 = OpLabel
99 OpReturn
100 OpFunctionEnd
101 )";
102
103   const std::string after_hoist = R"(OpCapability Shader
104 %1 = OpExtInstImport "GLSL.std.450"
105 OpMemoryModel Logical GLSL450
106 OpEntryPoint Fragment %main "main"
107 OpExecutionMode %main OriginUpperLeft
108 OpSource GLSL 440
109 OpName %main "main"
110 %void = OpTypeVoid
111 %4 = OpTypeFunction %void
112 %int = OpTypeInt 32 1
113 %_ptr_Function_int = OpTypePointer Function %int
114 %int_2 = OpConstant %int 2
115 %int_0 = OpConstant %int 0
116 %int_10 = OpConstant %int 10
117 %bool = OpTypeBool
118 %int_1 = OpConstant %int 1
119 %12 = OpUndef %int
120 %main = OpFunction %void None %4
121 %13 = OpLabel
122 OpBranch %14
123 %14 = OpLabel
124 %15 = OpPhi %int %int_0 %13 %16 %17
125 %18 = OpPhi %int %int_0 %13 %19 %17
126 %20 = OpPhi %int %12 %13 %21 %17
127 OpLoopMerge %22 %17 None
128 OpBranch %23
129 %23 = OpLabel
130 %24 = OpSLessThan %bool %18 %int_10
131 OpBranchConditional %24 %25 %22
132 %25 = OpLabel
133 %27 = OpISub %int %int_2 %18
134 OpBranch %26
135 %26 = OpLabel
136 %16 = OpPhi %int %15 %25 %27 %28
137 %21 = OpPhi %int %int_0 %25 %29 %28
138 OpLoopMerge %30 %28 None
139 OpBranch %31
140 %31 = OpLabel
141 %32 = OpSLessThan %bool %21 %int_10
142 OpBranchConditional %32 %33 %30
143 %33 = OpLabel
144 OpBranch %28
145 %28 = OpLabel
146 %29 = OpIAdd %int %21 %int_1
147 OpBranch %26
148 %30 = OpLabel
149 OpBranch %17
150 %17 = OpLabel
151 %19 = OpIAdd %int %18 %int_1
152 OpBranch %14
153 %22 = OpLabel
154 OpReturn
155 OpFunctionEnd
156 )";
157
158   SinglePassRunAndCheck<opt::LICMPass>(before_hoist, after_hoist, true);
159 }
160
161 }  // namespace