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