1// Copyright (c) 2018 Google Inc.
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 "source/reduce/operand_to_dominating_id_reduction_opportunity_finder.h"
16
17#include "source/opt/build_module.h"
18#include "source/reduce/reduction_opportunity.h"
19#include "test/reduce/reduce_test_util.h"
20
21namespace spvtools {
22namespace reduce {
23namespace {
24
25TEST(OperandToDominatingIdReductionPassTest, BasicCheck) {
26  std::string original = R"(
27               OpCapability Shader
28          %1 = OpExtInstImport "GLSL.std.450"
29               OpMemoryModel Logical GLSL450
30               OpEntryPoint Fragment %4 "main"
31               OpExecutionMode %4 OriginUpperLeft
32               OpSource ESSL 310
33          %2 = OpTypeVoid
34          %3 = OpTypeFunction %2
35          %6 = OpTypeInt 32 1
36          %7 = OpTypePointer Function %6
37          %9 = OpConstant %6 2
38          %4 = OpFunction %2 None %3
39          %5 = OpLabel
40          %8 = OpVariable %7 Function
41         %10 = OpVariable %7 Function
42         %14 = OpVariable %7 Function
43               OpStore %8 %9
44         %11 = OpLoad %6 %8
45         %12 = OpLoad %6 %8
46         %13 = OpIAdd %6 %11 %12
47               OpStore %10 %13
48         %15 = OpLoad %6 %10
49               OpStore %14 %15
50               OpReturn
51               OpFunctionEnd
52  )";
53
54  const auto env = SPV_ENV_UNIVERSAL_1_3;
55  const auto consumer = nullptr;
56  const auto context =
57      BuildModule(env, consumer, original, kReduceAssembleOption);
58  const auto ops = OperandToDominatingIdReductionOpportunityFinder()
59                       .GetAvailableOpportunities(context.get(), 0);
60  ASSERT_EQ(10, ops.size());
61  ASSERT_TRUE(ops[0]->PreconditionHolds());
62  ops[0]->TryToApply();
63
64  std::string after_op_0 = R"(
65               OpCapability Shader
66          %1 = OpExtInstImport "GLSL.std.450"
67               OpMemoryModel Logical GLSL450
68               OpEntryPoint Fragment %4 "main"
69               OpExecutionMode %4 OriginUpperLeft
70               OpSource ESSL 310
71          %2 = OpTypeVoid
72          %3 = OpTypeFunction %2
73          %6 = OpTypeInt 32 1
74          %7 = OpTypePointer Function %6
75          %9 = OpConstant %6 2
76          %4 = OpFunction %2 None %3
77          %5 = OpLabel
78          %8 = OpVariable %7 Function
79         %10 = OpVariable %7 Function
80         %14 = OpVariable %7 Function
81               OpStore %8 %9
82         %11 = OpLoad %6 %8
83         %12 = OpLoad %6 %8
84         %13 = OpIAdd %6 %11 %12
85               OpStore %8 %13 ; %10 -> %8
86         %15 = OpLoad %6 %10
87               OpStore %14 %15
88               OpReturn
89               OpFunctionEnd
90  )";
91
92  CheckEqual(env, after_op_0, context.get());
93
94  ASSERT_TRUE(ops[1]->PreconditionHolds());
95  ops[1]->TryToApply();
96
97  std::string after_op_1 = R"(
98               OpCapability Shader
99          %1 = OpExtInstImport "GLSL.std.450"
100               OpMemoryModel Logical GLSL450
101               OpEntryPoint Fragment %4 "main"
102               OpExecutionMode %4 OriginUpperLeft
103               OpSource ESSL 310
104          %2 = OpTypeVoid
105          %3 = OpTypeFunction %2
106          %6 = OpTypeInt 32 1
107          %7 = OpTypePointer Function %6
108          %9 = OpConstant %6 2
109          %4 = OpFunction %2 None %3
110          %5 = OpLabel
111          %8 = OpVariable %7 Function
112         %10 = OpVariable %7 Function
113         %14 = OpVariable %7 Function
114               OpStore %8 %9
115         %11 = OpLoad %6 %8
116         %12 = OpLoad %6 %8
117         %13 = OpIAdd %6 %11 %12
118               OpStore %8 %13 ; %10 -> %8
119         %15 = OpLoad %6 %8 ; %10 -> %8
120               OpStore %14 %15
121               OpReturn
122               OpFunctionEnd
123  )";
124
125  CheckEqual(env, after_op_1, context.get());
126
127  ASSERT_TRUE(ops[2]->PreconditionHolds());
128  ops[2]->TryToApply();
129
130  std::string after_op_2 = R"(
131               OpCapability Shader
132          %1 = OpExtInstImport "GLSL.std.450"
133               OpMemoryModel Logical GLSL450
134               OpEntryPoint Fragment %4 "main"
135               OpExecutionMode %4 OriginUpperLeft
136               OpSource ESSL 310
137          %2 = OpTypeVoid
138          %3 = OpTypeFunction %2
139          %6 = OpTypeInt 32 1
140          %7 = OpTypePointer Function %6
141          %9 = OpConstant %6 2
142          %4 = OpFunction %2 None %3
143          %5 = OpLabel
144          %8 = OpVariable %7 Function
145         %10 = OpVariable %7 Function
146         %14 = OpVariable %7 Function
147               OpStore %8 %9
148         %11 = OpLoad %6 %8
149         %12 = OpLoad %6 %8
150         %13 = OpIAdd %6 %11 %12
151               OpStore %8 %13 ; %10 -> %8
152         %15 = OpLoad %6 %8 ; %10 -> %8
153               OpStore %8 %15 ; %14 -> %8
154               OpReturn
155               OpFunctionEnd
156  )";
157
158  CheckEqual(env, after_op_2, context.get());
159
160  // The precondition has been disabled by an earlier opportunity's application.
161  ASSERT_FALSE(ops[3]->PreconditionHolds());
162
163  ASSERT_TRUE(ops[4]->PreconditionHolds());
164  ops[4]->TryToApply();
165
166  std::string after_op_4 = R"(
167               OpCapability Shader
168          %1 = OpExtInstImport "GLSL.std.450"
169               OpMemoryModel Logical GLSL450
170               OpEntryPoint Fragment %4 "main"
171               OpExecutionMode %4 OriginUpperLeft
172               OpSource ESSL 310
173          %2 = OpTypeVoid
174          %3 = OpTypeFunction %2
175          %6 = OpTypeInt 32 1
176          %7 = OpTypePointer Function %6
177          %9 = OpConstant %6 2
178          %4 = OpFunction %2 None %3
179          %5 = OpLabel
180          %8 = OpVariable %7 Function
181         %10 = OpVariable %7 Function
182         %14 = OpVariable %7 Function
183               OpStore %8 %9
184         %11 = OpLoad %6 %8
185         %12 = OpLoad %6 %8
186         %13 = OpIAdd %6 %11 %11 ; %12 -> %11
187               OpStore %8 %13 ; %10 -> %8
188         %15 = OpLoad %6 %8 ; %10 -> %8
189               OpStore %8 %15 ; %14 -> %8
190               OpReturn
191               OpFunctionEnd
192  )";
193  CheckEqual(env, after_op_4, context.get());
194}
195
196}  // namespace
197}  // namespace reduce
198}  // namespace spvtools
199