• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2019 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 "source/reduce/remove_function_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 
21 namespace spvtools {
22 namespace reduce {
23 namespace {
24 
25 // Helper to count the number of functions in the module.
26 // Remove if there turns out to be a more direct way to do this.
count_functions(opt::IRContext * context)27 uint32_t count_functions(opt::IRContext* context) {
28   uint32_t result = 0;
29   for (auto& function : *context->module()) {
30     (void)(function);
31     ++result;
32   }
33   return result;
34 }
35 
TEST(RemoveFunctionTest,BasicCheck)36 TEST(RemoveFunctionTest, BasicCheck) {
37   std::string shader = R"(
38                OpCapability Shader
39           %1 = OpExtInstImport "GLSL.std.450"
40                OpMemoryModel Logical GLSL450
41                OpEntryPoint Fragment %4 "main"
42                OpExecutionMode %4 OriginUpperLeft
43                OpSource ESSL 310
44           %2 = OpTypeVoid
45           %3 = OpTypeFunction %2
46           %4 = OpFunction %2 None %3
47           %5 = OpLabel
48                OpReturn
49                OpFunctionEnd
50           %6 = OpFunction %2 None %3
51           %7 = OpLabel
52                OpReturn
53                OpFunctionEnd
54           %8 = OpFunction %2 None %3
55           %9 = OpLabel
56          %10 = OpFunctionCall %2 %6
57                OpReturn
58                OpFunctionEnd
59   )";
60 
61   const auto env = SPV_ENV_UNIVERSAL_1_3;
62   const auto consumer = nullptr;
63   const auto context =
64       BuildModule(env, consumer, shader, kReduceAssembleOption);
65 
66   ASSERT_EQ(3, count_functions(context.get()));
67 
68   auto ops =
69       RemoveFunctionReductionOpportunityFinder().GetAvailableOpportunities(
70           context.get(), 0);
71   ASSERT_EQ(1, ops.size());
72 
73   ASSERT_TRUE(ops[0]->PreconditionHolds());
74   ops[0]->TryToApply();
75 
76   ASSERT_EQ(2, count_functions(context.get()));
77 
78   std::string after_first = R"(
79                OpCapability Shader
80           %1 = OpExtInstImport "GLSL.std.450"
81                OpMemoryModel Logical GLSL450
82                OpEntryPoint Fragment %4 "main"
83                OpExecutionMode %4 OriginUpperLeft
84                OpSource ESSL 310
85           %2 = OpTypeVoid
86           %3 = OpTypeFunction %2
87           %4 = OpFunction %2 None %3
88           %5 = OpLabel
89                OpReturn
90                OpFunctionEnd
91           %6 = OpFunction %2 None %3
92           %7 = OpLabel
93                OpReturn
94                OpFunctionEnd
95   )";
96 
97   CheckEqual(env, after_first, context.get());
98 
99   ops = RemoveFunctionReductionOpportunityFinder().GetAvailableOpportunities(
100       context.get(), 0);
101 
102   ASSERT_EQ(1, ops.size());
103 
104   ASSERT_TRUE(ops[0]->PreconditionHolds());
105   ops[0]->TryToApply();
106 
107   ASSERT_EQ(1, count_functions(context.get()));
108 
109   std::string after_second = R"(
110                OpCapability Shader
111           %1 = OpExtInstImport "GLSL.std.450"
112                OpMemoryModel Logical GLSL450
113                OpEntryPoint Fragment %4 "main"
114                OpExecutionMode %4 OriginUpperLeft
115                OpSource ESSL 310
116           %2 = OpTypeVoid
117           %3 = OpTypeFunction %2
118           %4 = OpFunction %2 None %3
119           %5 = OpLabel
120                OpReturn
121                OpFunctionEnd
122   )";
123 
124   CheckEqual(env, after_second, context.get());
125 }
126 
TEST(RemoveFunctionTest,NothingToRemove)127 TEST(RemoveFunctionTest, NothingToRemove) {
128   std::string shader = R"(
129                OpCapability Shader
130           %1 = OpExtInstImport "GLSL.std.450"
131                OpMemoryModel Logical GLSL450
132                OpEntryPoint Fragment %4 "main"
133                OpExecutionMode %4 OriginUpperLeft
134                OpSource ESSL 310
135           %2 = OpTypeVoid
136           %3 = OpTypeFunction %2
137           %4 = OpFunction %2 None %3
138           %5 = OpLabel
139          %11 = OpFunctionCall %2 %8
140                OpReturn
141                OpFunctionEnd
142           %6 = OpFunction %2 None %3
143           %7 = OpLabel
144                OpReturn
145                OpFunctionEnd
146           %8 = OpFunction %2 None %3
147           %9 = OpLabel
148          %10 = OpFunctionCall %2 %6
149                OpReturn
150                OpFunctionEnd
151   )";
152 
153   const auto env = SPV_ENV_UNIVERSAL_1_3;
154   const auto consumer = nullptr;
155   const auto context =
156       BuildModule(env, consumer, shader, kReduceAssembleOption);
157   auto ops =
158       RemoveFunctionReductionOpportunityFinder().GetAvailableOpportunities(
159           context.get(), 0);
160   ASSERT_EQ(0, ops.size());
161 }
162 
TEST(RemoveFunctionTest,TwoRemovableFunctions)163 TEST(RemoveFunctionTest, TwoRemovableFunctions) {
164   std::string shader = R"(
165                OpCapability Shader
166           %1 = OpExtInstImport "GLSL.std.450"
167                OpMemoryModel Logical GLSL450
168                OpEntryPoint Fragment %4 "main"
169                OpExecutionMode %4 OriginUpperLeft
170                OpSource ESSL 310
171           %2 = OpTypeVoid
172           %3 = OpTypeFunction %2
173           %4 = OpFunction %2 None %3
174           %5 = OpLabel
175                OpReturn
176                OpFunctionEnd
177           %6 = OpFunction %2 None %3
178           %7 = OpLabel
179                OpReturn
180                OpFunctionEnd
181           %8 = OpFunction %2 None %3
182           %9 = OpLabel
183                OpReturn
184                OpFunctionEnd
185   )";
186 
187   const auto env = SPV_ENV_UNIVERSAL_1_3;
188   const auto consumer = nullptr;
189   const auto context =
190       BuildModule(env, consumer, shader, kReduceAssembleOption);
191 
192   ASSERT_EQ(3, count_functions(context.get()));
193 
194   auto ops =
195       RemoveFunctionReductionOpportunityFinder().GetAvailableOpportunities(
196           context.get(), 0);
197   ASSERT_EQ(2, ops.size());
198 
199   ASSERT_TRUE(ops[0]->PreconditionHolds());
200   ops[0]->TryToApply();
201   ASSERT_EQ(2, count_functions(context.get()));
202   ASSERT_TRUE(ops[1]->PreconditionHolds());
203   ops[1]->TryToApply();
204   ASSERT_EQ(1, count_functions(context.get()));
205 
206   std::string after = R"(
207                OpCapability Shader
208           %1 = OpExtInstImport "GLSL.std.450"
209                OpMemoryModel Logical GLSL450
210                OpEntryPoint Fragment %4 "main"
211                OpExecutionMode %4 OriginUpperLeft
212                OpSource ESSL 310
213           %2 = OpTypeVoid
214           %3 = OpTypeFunction %2
215           %4 = OpFunction %2 None %3
216           %5 = OpLabel
217                OpReturn
218                OpFunctionEnd
219   )";
220 
221   CheckEqual(env, after, context.get());
222 }
223 
TEST(RemoveFunctionTest,NoRemovalsDueToOpName)224 TEST(RemoveFunctionTest, NoRemovalsDueToOpName) {
225   std::string shader = R"(
226                OpCapability Shader
227           %1 = OpExtInstImport "GLSL.std.450"
228                OpMemoryModel Logical GLSL450
229                OpEntryPoint Fragment %4 "main"
230                OpExecutionMode %4 OriginUpperLeft
231                OpSource ESSL 310
232                OpName %4 "main"
233                OpName %6 "foo("
234                OpName %8 "bar("
235           %2 = OpTypeVoid
236           %3 = OpTypeFunction %2
237           %4 = OpFunction %2 None %3
238           %5 = OpLabel
239                OpReturn
240                OpFunctionEnd
241           %6 = OpFunction %2 None %3
242           %7 = OpLabel
243                OpReturn
244                OpFunctionEnd
245           %8 = OpFunction %2 None %3
246           %9 = OpLabel
247                OpReturn
248                OpFunctionEnd
249   )";
250 
251   const auto env = SPV_ENV_UNIVERSAL_1_3;
252   const auto consumer = nullptr;
253   const auto context =
254       BuildModule(env, consumer, shader, kReduceAssembleOption);
255   auto ops =
256       RemoveFunctionReductionOpportunityFinder().GetAvailableOpportunities(
257           context.get(), 0);
258   ASSERT_EQ(0, ops.size());
259 }
260 
TEST(RemoveFunctionTest,NoRemovalDueToLinkageDecoration)261 TEST(RemoveFunctionTest, NoRemovalDueToLinkageDecoration) {
262   // The non-entry point function is not removable because it is referenced by a
263   // linkage decoration. Thus no function can be removed.
264   std::string shader = R"(
265                OpCapability Shader
266                OpCapability Linkage
267                OpMemoryModel Logical GLSL450
268                OpEntryPoint Fragment %1 "main"
269                OpName %1 "main"
270                OpDecorate %2 LinkageAttributes "ExportedFunc" Export
271           %4 = OpTypeVoid
272           %5 = OpTypeFunction %4
273           %1 = OpFunction %4 None %5
274           %6 = OpLabel
275                OpReturn
276                OpFunctionEnd
277           %2 = OpFunction %4 None %5
278           %7 = OpLabel
279                OpReturn
280                OpFunctionEnd
281   )";
282 
283   const auto env = SPV_ENV_UNIVERSAL_1_3;
284   const auto consumer = nullptr;
285   const auto context =
286       BuildModule(env, consumer, shader, kReduceAssembleOption);
287   auto ops =
288       RemoveFunctionReductionOpportunityFinder().GetAvailableOpportunities(
289           context.get(), 0);
290   ASSERT_EQ(0, ops.size());
291 }
292 
293 }  // namespace
294 }  // namespace reduce
295 }  // namespace spvtools
296