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#include "source/opt/licm_pass.h"
19#include "test/opt/pass_fixture.h"
20
21namespace spvtools {
22namespace opt {
23namespace {
24
25using ::testing::UnorderedElementsAre;
26using PassClassTest = PassTest<::testing::Test>;
27
28/*
29  A simple test for the LICM pass
30
31  Generated from the following GLSL fragment shader
32--eliminate-local-multi-store has also been run on the spv binary
33#version 440 core
34void main(){
35  int a = 1;
36  int b = 2;
37  int hoist = 0;
38  for (int i = 0; i < 10; i++) {
39    // invariant
40    hoist = a + b;
41  }
42}
43*/
44TEST_F(PassClassTest, SimpleHoist) {
45  const std::string before_hoist = R"(OpCapability Shader
46%1 = OpExtInstImport "GLSL.std.450"
47OpMemoryModel Logical GLSL450
48OpEntryPoint Fragment %main "main"
49OpExecutionMode %main OriginUpperLeft
50OpSource GLSL 440
51OpName %main "main"
52%void = OpTypeVoid
53%4 = OpTypeFunction %void
54%int = OpTypeInt 32 1
55%_ptr_Function_int = OpTypePointer Function %int
56%int_1 = OpConstant %int 1
57%int_2 = OpConstant %int 2
58%int_0 = OpConstant %int 0
59%int_10 = OpConstant %int 10
60%bool = OpTypeBool
61%main = OpFunction %void None %4
62%12 = OpLabel
63OpBranch %13
64%13 = OpLabel
65%14 = OpPhi %int %int_0 %12 %15 %16
66%17 = OpPhi %int %int_0 %12 %18 %16
67OpLoopMerge %19 %16 None
68OpBranch %20
69%20 = OpLabel
70%21 = OpSLessThan %bool %17 %int_10
71OpBranchConditional %21 %22 %19
72%22 = OpLabel
73%15 = OpIAdd %int %int_1 %int_2
74OpBranch %16
75%16 = OpLabel
76%18 = OpIAdd %int %17 %int_1
77OpBranch %13
78%19 = OpLabel
79OpReturn
80OpFunctionEnd
81)";
82
83  const std::string after_hoist = R"(OpCapability Shader
84%1 = OpExtInstImport "GLSL.std.450"
85OpMemoryModel Logical GLSL450
86OpEntryPoint Fragment %main "main"
87OpExecutionMode %main OriginUpperLeft
88OpSource GLSL 440
89OpName %main "main"
90%void = OpTypeVoid
91%4 = OpTypeFunction %void
92%int = OpTypeInt 32 1
93%_ptr_Function_int = OpTypePointer Function %int
94%int_1 = OpConstant %int 1
95%int_2 = OpConstant %int 2
96%int_0 = OpConstant %int 0
97%int_10 = OpConstant %int 10
98%bool = OpTypeBool
99%main = OpFunction %void None %4
100%12 = OpLabel
101%15 = OpIAdd %int %int_1 %int_2
102OpBranch %13
103%13 = OpLabel
104%14 = OpPhi %int %int_0 %12 %15 %16
105%17 = OpPhi %int %int_0 %12 %18 %16
106OpLoopMerge %19 %16 None
107OpBranch %20
108%20 = OpLabel
109%21 = OpSLessThan %bool %17 %int_10
110OpBranchConditional %21 %22 %19
111%22 = OpLabel
112OpBranch %16
113%16 = OpLabel
114%18 = OpIAdd %int %17 %int_1
115OpBranch %13
116%19 = OpLabel
117OpReturn
118OpFunctionEnd
119)";
120
121  SinglePassRunAndCheck<LICMPass>(before_hoist, after_hoist, true);
122}
123
124}  // namespace
125}  // namespace opt
126}  // namespace spvtools
127