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 generate a preheader when one is not present
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++) {
44 for (int i = 0; i < 10; i++) {
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
58 %4 = OpTypeFunction %void
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
66 %int_5 = OpConstant %int 5
67 %main = OpFunction %void None %4
71 %15 = OpPhi %int %int_0 %13 %16 %17
72 OpLoopMerge %25 %17 None
75 %20 = OpSLessThan %bool %15 %int_10
76 OpBranchConditional %20 %21 %25
78 %22 = OpIEqual %bool %15 %int_5
79 OpSelectionMerge %23 None
80 OpBranchConditional %22 %24 %23
86 %16 = OpIAdd %int %15 %int_1
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
94 %33 = OpSLessThan %bool %29 %int_10
95 OpBranchConditional %33 %34 %31
97 %27 = OpIAdd %int %int_1 %int_2
100 %30 = OpIAdd %int %29 %int_1
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
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
123 %int_5 = OpConstant %int 5
124 %main = OpFunction %void None %4
128 %15 = OpPhi %int %int_0 %13 %16 %17
129 OpLoopMerge %18 %17 None
132 %20 = OpSLessThan %bool %15 %int_10
133 OpBranchConditional %20 %21 %34
135 %22 = OpIEqual %bool %15 %int_5
136 OpSelectionMerge %23 None
137 OpBranchConditional %22 %24 %23
143 %16 = OpIAdd %int %15 %int_1
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
151 %25 = OpPhi %int %26 %27 %35 %34
152 %28 = OpPhi %int %29 %27 %36 %34
153 OpLoopMerge %30 %27 None
156 %32 = OpSLessThan %bool %28 %int_10
157 OpBranchConditional %32 %33 %30
161 %29 = OpIAdd %int %28 %int_1
168 SinglePassRunAndCheck<opt::LICMPass>(before_hoist, after_hoist, true);