• 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_selection_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 
TEST(RemoveSelectionTest,OpportunityBecauseSameTargetBlock)25 TEST(RemoveSelectionTest, OpportunityBecauseSameTargetBlock) {
26   // A test with the following structure. The OpSelectionMerge instruction
27   // should be removed.
28   //
29   // header
30   // ||
31   // block
32   // |
33   // merge
34 
35   std::string shader = R"(
36                OpCapability Shader
37           %1 = OpExtInstImport "GLSL.std.450"
38                OpMemoryModel Logical GLSL450
39                OpEntryPoint Fragment %2 "main"
40                OpExecutionMode %2 OriginUpperLeft
41                OpSource ESSL 310
42                OpName %2 "main"
43           %3 = OpTypeVoid
44           %4 = OpTypeFunction %3
45           %5 = OpTypeInt 32 1
46           %6 = OpTypePointer Function %5
47           %7 = OpTypeBool
48           %8 = OpConstantTrue %7
49           %2 = OpFunction %3 None %4
50           %9 = OpLabel
51                OpSelectionMerge %10 None
52                OpBranchConditional %8 %11 %11
53          %11 = OpLabel
54                OpBranch %10
55          %10 = OpLabel
56                OpReturn
57                OpFunctionEnd
58     )";
59 
60   const auto env = SPV_ENV_UNIVERSAL_1_3;
61   const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
62 
63   auto ops =
64       RemoveSelectionReductionOpportunityFinder().GetAvailableOpportunities(
65           context.get(), 0);
66 
67   ASSERT_EQ(1, ops.size());
68 
69   ASSERT_TRUE(ops[0]->PreconditionHolds());
70   ops[0]->TryToApply();
71   CheckValid(env, context.get());
72 
73   std::string after = R"(
74                OpCapability Shader
75           %1 = OpExtInstImport "GLSL.std.450"
76                OpMemoryModel Logical GLSL450
77                OpEntryPoint Fragment %2 "main"
78                OpExecutionMode %2 OriginUpperLeft
79                OpSource ESSL 310
80                OpName %2 "main"
81           %3 = OpTypeVoid
82           %4 = OpTypeFunction %3
83           %5 = OpTypeInt 32 1
84           %6 = OpTypePointer Function %5
85           %7 = OpTypeBool
86           %8 = OpConstantTrue %7
87           %2 = OpFunction %3 None %4
88           %9 = OpLabel
89                OpBranchConditional %8 %11 %11
90          %11 = OpLabel
91                OpBranch %10
92          %10 = OpLabel
93                OpReturn
94                OpFunctionEnd
95     )";
96   CheckEqual(env, after, context.get());
97 
98   ops = RemoveSelectionReductionOpportunityFinder().GetAvailableOpportunities(
99       context.get(), 0);
100   ASSERT_EQ(0, ops.size());
101 }
102 
TEST(RemoveSelectionTest,OpportunityBecauseSameTargetBlockMerge)103 TEST(RemoveSelectionTest, OpportunityBecauseSameTargetBlockMerge) {
104   // A test with the following structure. The OpSelectionMerge instruction
105   // should be removed.
106   //
107   // header
108   // ||
109   // merge
110 
111   std::string shader = R"(
112                OpCapability Shader
113           %1 = OpExtInstImport "GLSL.std.450"
114                OpMemoryModel Logical GLSL450
115                OpEntryPoint Fragment %2 "main"
116                OpExecutionMode %2 OriginUpperLeft
117                OpSource ESSL 310
118                OpName %2 "main"
119           %3 = OpTypeVoid
120           %4 = OpTypeFunction %3
121           %5 = OpTypeInt 32 1
122           %6 = OpTypePointer Function %5
123           %7 = OpTypeBool
124           %8 = OpConstantTrue %7
125           %2 = OpFunction %3 None %4
126           %9 = OpLabel
127                OpSelectionMerge %10 None
128                OpBranchConditional %8 %10 %10
129          %10 = OpLabel
130                OpReturn
131                OpFunctionEnd
132     )";
133 
134   const auto env = SPV_ENV_UNIVERSAL_1_3;
135   const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
136 
137   auto ops =
138       RemoveSelectionReductionOpportunityFinder().GetAvailableOpportunities(
139           context.get(), 0);
140 
141   ASSERT_EQ(1, ops.size());
142 
143   ASSERT_TRUE(ops[0]->PreconditionHolds());
144   ops[0]->TryToApply();
145   CheckValid(env, context.get());
146 
147   std::string after = R"(
148                OpCapability Shader
149           %1 = OpExtInstImport "GLSL.std.450"
150                OpMemoryModel Logical GLSL450
151                OpEntryPoint Fragment %2 "main"
152                OpExecutionMode %2 OriginUpperLeft
153                OpSource ESSL 310
154                OpName %2 "main"
155           %3 = OpTypeVoid
156           %4 = OpTypeFunction %3
157           %5 = OpTypeInt 32 1
158           %6 = OpTypePointer Function %5
159           %7 = OpTypeBool
160           %8 = OpConstantTrue %7
161           %2 = OpFunction %3 None %4
162           %9 = OpLabel
163                OpBranchConditional %8 %10 %10
164          %10 = OpLabel
165                OpReturn
166                OpFunctionEnd
167     )";
168   CheckEqual(env, after, context.get());
169 
170   ops = RemoveSelectionReductionOpportunityFinder().GetAvailableOpportunities(
171       context.get(), 0);
172   ASSERT_EQ(0, ops.size());
173 }
174 
TEST(RemoveSelectionTest,NoOpportunityBecauseDifferentTargetBlocksOneMerge)175 TEST(RemoveSelectionTest, NoOpportunityBecauseDifferentTargetBlocksOneMerge) {
176   // A test with the following structure. The OpSelectionMerge instruction
177   // should NOT be removed.
178   //
179   // header
180   // |  |
181   // | block
182   // |  |
183   // merge
184 
185   std::string shader = R"(
186                OpCapability Shader
187           %1 = OpExtInstImport "GLSL.std.450"
188                OpMemoryModel Logical GLSL450
189                OpEntryPoint Fragment %2 "main"
190                OpExecutionMode %2 OriginUpperLeft
191                OpSource ESSL 310
192                OpName %2 "main"
193           %3 = OpTypeVoid
194           %4 = OpTypeFunction %3
195           %5 = OpTypeInt 32 1
196           %6 = OpTypePointer Function %5
197           %7 = OpTypeBool
198           %8 = OpConstantTrue %7
199           %2 = OpFunction %3 None %4
200           %9 = OpLabel
201                OpSelectionMerge %10 None
202                OpBranchConditional %8 %10 %11
203          %11 = OpLabel
204                OpBranch %10
205          %10 = OpLabel
206                OpReturn
207                OpFunctionEnd
208     )";
209 
210   const auto env = SPV_ENV_UNIVERSAL_1_3;
211   const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
212 
213   auto ops =
214       RemoveSelectionReductionOpportunityFinder().GetAvailableOpportunities(
215           context.get(), 0);
216   ASSERT_EQ(0, ops.size());
217 }
218 
TEST(RemoveSelectionTest,NoOpportunityBecauseDifferentTargetBlocks)219 TEST(RemoveSelectionTest, NoOpportunityBecauseDifferentTargetBlocks) {
220   // A test with the following structure. The OpSelectionMerge instruction
221   // should NOT be removed.
222   //
223   // header
224   // | |
225   // b b
226   // | |
227   // merge
228 
229   std::string shader = R"(
230                OpCapability Shader
231           %1 = OpExtInstImport "GLSL.std.450"
232                OpMemoryModel Logical GLSL450
233                OpEntryPoint Fragment %2 "main"
234                OpExecutionMode %2 OriginUpperLeft
235                OpSource ESSL 310
236                OpName %2 "main"
237           %3 = OpTypeVoid
238           %4 = OpTypeFunction %3
239           %5 = OpTypeInt 32 1
240           %6 = OpTypePointer Function %5
241           %7 = OpTypeBool
242           %8 = OpConstantTrue %7
243           %2 = OpFunction %3 None %4
244           %9 = OpLabel
245                OpSelectionMerge %10 None
246                OpBranchConditional %8 %11 %12
247          %11 = OpLabel
248                OpBranch %10
249          %12 = OpLabel
250                OpBranch %10
251          %10 = OpLabel
252                OpReturn
253                OpFunctionEnd
254     )";
255 
256   const auto env = SPV_ENV_UNIVERSAL_1_3;
257   const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
258 
259   auto ops =
260       RemoveSelectionReductionOpportunityFinder().GetAvailableOpportunities(
261           context.get(), 0);
262   ASSERT_EQ(0, ops.size());
263 }
264 
TEST(RemoveSelectionTest,NoOpportunityBecauseMergeUsed)265 TEST(RemoveSelectionTest, NoOpportunityBecauseMergeUsed) {
266   // A test with the following structure. The OpSelectionMerge instruction
267   // should NOT be removed.
268   //
269   // header
270   // ||
271   // block
272   // |  |
273   // | block
274   // |  |
275   // merge
276 
277   std::string shader = R"(
278                OpCapability Shader
279           %1 = OpExtInstImport "GLSL.std.450"
280                OpMemoryModel Logical GLSL450
281                OpEntryPoint Fragment %2 "main"
282                OpExecutionMode %2 OriginUpperLeft
283                OpSource ESSL 310
284                OpName %2 "main"
285           %3 = OpTypeVoid
286           %4 = OpTypeFunction %3
287           %5 = OpTypeInt 32 1
288           %6 = OpTypePointer Function %5
289           %7 = OpTypeBool
290           %8 = OpConstantTrue %7
291           %2 = OpFunction %3 None %4
292           %9 = OpLabel
293                OpSelectionMerge %10 None
294                OpBranchConditional %8 %11 %12
295          %11 = OpLabel
296                OpBranchConditional %8 %10 %12
297          %12 = OpLabel
298                OpBranch %10
299          %10 = OpLabel
300                OpReturn
301                OpFunctionEnd
302     )";
303 
304   const auto env = SPV_ENV_UNIVERSAL_1_3;
305   const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
306 
307   auto ops =
308       RemoveSelectionReductionOpportunityFinder().GetAvailableOpportunities(
309           context.get(), 0);
310   ASSERT_EQ(0, ops.size());
311 }
312 
TEST(RemoveSelectionTest,OpportunityBecauseLoopMergeUsed)313 TEST(RemoveSelectionTest, OpportunityBecauseLoopMergeUsed) {
314   // A test with the following structure. The OpSelectionMerge instruction
315   // should be removed.
316   //
317   // loop header
318   //    |
319   //    |
320   //   s.header
321   //    ||
322   //   block
323   //    |    |
324   //    |     |
325   //    |      |    ^ (to loop header)
326   //   s.merge |    |
327   //    |     /   loop continue target (unreachable)
328   // loop merge
329   //
330   //
331   // which becomes:
332   //
333   // loop header
334   //    |
335   //    |
336   //   block
337   //    ||
338   //   block
339   //    |    |
340   //    |     |
341   //    |      |    ^ (to loop header)
342   //   block   |    |
343   //    |     /   loop continue target (unreachable)
344   // loop merge
345 
346   std::string shader = R"(
347                OpCapability Shader
348           %1 = OpExtInstImport "GLSL.std.450"
349                OpMemoryModel Logical GLSL450
350                OpEntryPoint Fragment %2 "main"
351                OpExecutionMode %2 OriginUpperLeft
352                OpSource ESSL 310
353                OpName %2 "main"
354           %3 = OpTypeVoid
355           %4 = OpTypeFunction %3
356           %5 = OpTypeInt 32 1
357           %6 = OpTypePointer Function %5
358           %7 = OpTypeBool
359           %8 = OpConstantTrue %7
360           %2 = OpFunction %3 None %4
361           %9 = OpLabel
362                OpBranch %10
363          %10 = OpLabel
364                OpLoopMerge %11 %12 None
365                OpBranch %13
366          %13 = OpLabel
367                OpSelectionMerge %14 None
368                OpBranchConditional %8 %15 %15
369          %15 = OpLabel
370                OpBranchConditional %8 %14 %11
371          %14 = OpLabel
372                OpBranch %11
373          %12 = OpLabel
374                OpBranch %10
375          %11 = OpLabel
376                OpReturn
377                OpFunctionEnd
378     )";
379 
380   const auto env = SPV_ENV_UNIVERSAL_1_3;
381   const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
382 
383   CheckValid(env, context.get());
384 
385   auto ops =
386       RemoveSelectionReductionOpportunityFinder().GetAvailableOpportunities(
387           context.get(), 0);
388 
389   ASSERT_EQ(1, ops.size());
390 
391   ASSERT_TRUE(ops[0]->PreconditionHolds());
392   ops[0]->TryToApply();
393   CheckValid(env, context.get());
394 
395   std::string after = R"(
396                OpCapability Shader
397           %1 = OpExtInstImport "GLSL.std.450"
398                OpMemoryModel Logical GLSL450
399                OpEntryPoint Fragment %2 "main"
400                OpExecutionMode %2 OriginUpperLeft
401                OpSource ESSL 310
402                OpName %2 "main"
403           %3 = OpTypeVoid
404           %4 = OpTypeFunction %3
405           %5 = OpTypeInt 32 1
406           %6 = OpTypePointer Function %5
407           %7 = OpTypeBool
408           %8 = OpConstantTrue %7
409           %2 = OpFunction %3 None %4
410           %9 = OpLabel
411                OpBranch %10
412          %10 = OpLabel
413                OpLoopMerge %11 %12 None
414                OpBranch %13
415          %13 = OpLabel
416                OpBranchConditional %8 %15 %15
417          %15 = OpLabel
418                OpBranchConditional %8 %14 %11
419          %14 = OpLabel
420                OpBranch %11
421          %12 = OpLabel
422                OpBranch %10
423          %11 = OpLabel
424                OpReturn
425                OpFunctionEnd
426     )";
427   CheckEqual(env, after, context.get());
428 
429   ops = RemoveSelectionReductionOpportunityFinder().GetAvailableOpportunities(
430       context.get(), 0);
431   ASSERT_EQ(0, ops.size());
432 }
433 
TEST(RemoveSelectionTest,OpportunityBecauseLoopContinueUsed)434 TEST(RemoveSelectionTest, OpportunityBecauseLoopContinueUsed) {
435   // A test with the following structure. The OpSelectionMerge instruction
436   // should be removed.
437   //
438   // loop header
439   //    |
440   //    |
441   //   s.header
442   //    ||
443   //   block
444   //    |    |
445   //    |     |
446   //    |      |    ^ (to loop header)
447   //   s.merge |    |
448   //    |     loop continue target
449   // loop merge
450   //
451   //
452   // which becomes:
453   //
454   // loop header
455   //    |
456   //    |
457   //   block
458   //    ||
459   //   block
460   //    |    |
461   //    |     |
462   //    |      |    ^ (to loop header)
463   //   block   |    |
464   //    |     loop continue target
465   // loop merge
466 
467   std::string shader = R"(
468                OpCapability Shader
469           %1 = OpExtInstImport "GLSL.std.450"
470                OpMemoryModel Logical GLSL450
471                OpEntryPoint Fragment %2 "main"
472                OpExecutionMode %2 OriginUpperLeft
473                OpSource ESSL 310
474                OpName %2 "main"
475           %3 = OpTypeVoid
476           %4 = OpTypeFunction %3
477           %5 = OpTypeInt 32 1
478           %6 = OpTypePointer Function %5
479           %7 = OpTypeBool
480           %8 = OpConstantTrue %7
481           %2 = OpFunction %3 None %4
482           %9 = OpLabel
483                OpBranch %10
484          %10 = OpLabel
485                OpLoopMerge %11 %12 None
486                OpBranch %13
487          %13 = OpLabel
488                OpSelectionMerge %14 None
489                OpBranchConditional %8 %15 %15
490          %15 = OpLabel
491                OpBranchConditional %8 %14 %12
492          %14 = OpLabel
493                OpBranch %11
494          %12 = OpLabel
495                OpBranch %10
496          %11 = OpLabel
497                OpReturn
498                OpFunctionEnd
499     )";
500 
501   const auto env = SPV_ENV_UNIVERSAL_1_3;
502   const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
503 
504   CheckValid(env, context.get());
505 
506   auto ops =
507       RemoveSelectionReductionOpportunityFinder().GetAvailableOpportunities(
508           context.get(), 0);
509 
510   ASSERT_EQ(1, ops.size());
511 
512   ASSERT_TRUE(ops[0]->PreconditionHolds());
513   ops[0]->TryToApply();
514   CheckValid(env, context.get());
515 
516   std::string after = R"(
517                OpCapability Shader
518           %1 = OpExtInstImport "GLSL.std.450"
519                OpMemoryModel Logical GLSL450
520                OpEntryPoint Fragment %2 "main"
521                OpExecutionMode %2 OriginUpperLeft
522                OpSource ESSL 310
523                OpName %2 "main"
524           %3 = OpTypeVoid
525           %4 = OpTypeFunction %3
526           %5 = OpTypeInt 32 1
527           %6 = OpTypePointer Function %5
528           %7 = OpTypeBool
529           %8 = OpConstantTrue %7
530           %2 = OpFunction %3 None %4
531           %9 = OpLabel
532                OpBranch %10
533          %10 = OpLabel
534                OpLoopMerge %11 %12 None
535                OpBranch %13
536          %13 = OpLabel
537                OpBranchConditional %8 %15 %15
538          %15 = OpLabel
539                OpBranchConditional %8 %14 %12
540          %14 = OpLabel
541                OpBranch %11
542          %12 = OpLabel
543                OpBranch %10
544          %11 = OpLabel
545                OpReturn
546                OpFunctionEnd
547     )";
548   CheckEqual(env, after, context.get());
549 
550   ops = RemoveSelectionReductionOpportunityFinder().GetAvailableOpportunities(
551       context.get(), 0);
552   ASSERT_EQ(0, ops.size());
553 }
554 
555 }  // namespace
556 }  // namespace reduce
557 }  // namespace spvtools
558