• 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/fuzz/transformation_add_dead_block.h"
16 #include "test/fuzz/fuzz_test_util.h"
17 
18 namespace spvtools {
19 namespace fuzz {
20 namespace {
21 
TEST(TransformationAddDeadBlockTest,BasicTest)22 TEST(TransformationAddDeadBlockTest, BasicTest) {
23   std::string shader = R"(
24                OpCapability Shader
25           %1 = OpExtInstImport "GLSL.std.450"
26                OpMemoryModel Logical GLSL450
27                OpEntryPoint Fragment %4 "main"
28                OpExecutionMode %4 OriginUpperLeft
29                OpSource ESSL 310
30                OpName %4 "main"
31           %2 = OpTypeVoid
32           %3 = OpTypeFunction %2
33           %6 = OpTypeBool
34           %7 = OpConstantTrue %6
35           %4 = OpFunction %2 None %3
36           %5 = OpLabel
37                OpBranch %8
38           %8 = OpLabel
39                OpReturn
40                OpFunctionEnd
41   )";
42 
43   const auto env = SPV_ENV_UNIVERSAL_1_4;
44   const auto consumer = nullptr;
45   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
46   ASSERT_TRUE(IsValid(env, context.get()));
47 
48   FactManager fact_manager;
49   spvtools::ValidatorOptions validator_options;
50   TransformationContext transformation_context(&fact_manager,
51                                                validator_options);
52 
53   // Id 4 is already in use
54   ASSERT_FALSE(TransformationAddDeadBlock(4, 5, true)
55                    .IsApplicable(context.get(), transformation_context));
56 
57   // Id 7 is not a block
58   ASSERT_FALSE(TransformationAddDeadBlock(100, 7, true)
59                    .IsApplicable(context.get(), transformation_context));
60 
61   TransformationAddDeadBlock transformation(100, 5, true);
62   ASSERT_TRUE(
63       transformation.IsApplicable(context.get(), transformation_context));
64   transformation.Apply(context.get(), &transformation_context);
65   ASSERT_TRUE(IsValid(env, context.get()));
66 
67   ASSERT_TRUE(transformation_context.GetFactManager()->BlockIsDead(100));
68 
69   std::string after_transformation = R"(
70                OpCapability Shader
71           %1 = OpExtInstImport "GLSL.std.450"
72                OpMemoryModel Logical GLSL450
73                OpEntryPoint Fragment %4 "main"
74                OpExecutionMode %4 OriginUpperLeft
75                OpSource ESSL 310
76                OpName %4 "main"
77           %2 = OpTypeVoid
78           %3 = OpTypeFunction %2
79           %6 = OpTypeBool
80           %7 = OpConstantTrue %6
81           %4 = OpFunction %2 None %3
82           %5 = OpLabel
83                OpSelectionMerge %8 None
84                OpBranchConditional %7 %8 %100
85         %100 = OpLabel
86                OpBranch %8
87           %8 = OpLabel
88                OpReturn
89                OpFunctionEnd
90   )";
91   ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
92 }
93 
TEST(TransformationAddDeadBlockTest,TargetBlockMustNotBeSelectionMerge)94 TEST(TransformationAddDeadBlockTest, TargetBlockMustNotBeSelectionMerge) {
95   std::string shader = R"(
96                OpCapability Shader
97           %1 = OpExtInstImport "GLSL.std.450"
98                OpMemoryModel Logical GLSL450
99                OpEntryPoint Fragment %4 "main"
100                OpExecutionMode %4 OriginUpperLeft
101                OpSource ESSL 310
102                OpName %4 "main"
103           %2 = OpTypeVoid
104           %3 = OpTypeFunction %2
105           %6 = OpTypeBool
106           %7 = OpConstantTrue %6
107           %4 = OpFunction %2 None %3
108           %5 = OpLabel
109                OpSelectionMerge %10 None
110                OpBranchConditional %7 %8 %9
111           %8 = OpLabel
112                OpBranch %10
113           %9 = OpLabel
114                OpBranch %10
115          %10 = OpLabel
116                OpReturn
117                OpFunctionEnd
118   )";
119 
120   const auto env = SPV_ENV_UNIVERSAL_1_4;
121   const auto consumer = nullptr;
122   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
123   ASSERT_TRUE(IsValid(env, context.get()));
124 
125   FactManager fact_manager;
126   spvtools::ValidatorOptions validator_options;
127   TransformationContext transformation_context(&fact_manager,
128                                                validator_options);
129 
130   ASSERT_FALSE(TransformationAddDeadBlock(100, 9, true)
131                    .IsApplicable(context.get(), transformation_context));
132 }
133 
TEST(TransformationAddDeadBlockTest,TargetBlockMustNotBeLoopMergeOrContinue)134 TEST(TransformationAddDeadBlockTest, TargetBlockMustNotBeLoopMergeOrContinue) {
135   std::string shader = R"(
136                OpCapability Shader
137           %1 = OpExtInstImport "GLSL.std.450"
138                OpMemoryModel Logical GLSL450
139                OpEntryPoint Fragment %4 "main"
140                OpExecutionMode %4 OriginUpperLeft
141                OpSource ESSL 310
142                OpName %4 "main"
143           %2 = OpTypeVoid
144           %3 = OpTypeFunction %2
145           %6 = OpTypeBool
146           %7 = OpConstantTrue %6
147           %4 = OpFunction %2 None %3
148           %5 = OpLabel
149                OpBranch %8
150           %8 = OpLabel
151                OpLoopMerge %11 %12 None
152                OpBranchConditional %7 %9 %10
153           %9 = OpLabel
154                OpBranch %12
155          %10 = OpLabel
156                OpBranch %11
157          %12 = OpLabel
158                OpBranch %8
159          %11 = OpLabel
160                OpReturn
161                OpFunctionEnd
162   )";
163 
164   const auto env = SPV_ENV_UNIVERSAL_1_4;
165   const auto consumer = nullptr;
166   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
167   ASSERT_TRUE(IsValid(env, context.get()));
168 
169   FactManager fact_manager;
170   spvtools::ValidatorOptions validator_options;
171   TransformationContext transformation_context(&fact_manager,
172                                                validator_options);
173 
174   // Bad because 9's successor is the loop continue target.
175   ASSERT_FALSE(TransformationAddDeadBlock(100, 9, true)
176                    .IsApplicable(context.get(), transformation_context));
177   // Bad because 10's successor is the loop merge.
178   ASSERT_FALSE(TransformationAddDeadBlock(100, 10, true)
179                    .IsApplicable(context.get(), transformation_context));
180 }
181 
TEST(TransformationAddDeadBlockTest,SourceBlockMustNotBeLoopHead)182 TEST(TransformationAddDeadBlockTest, SourceBlockMustNotBeLoopHead) {
183   std::string shader = R"(
184                OpCapability Shader
185           %1 = OpExtInstImport "GLSL.std.450"
186                OpMemoryModel Logical GLSL450
187                OpEntryPoint Fragment %4 "main"
188                OpExecutionMode %4 OriginUpperLeft
189                OpSource ESSL 310
190                OpName %4 "main"
191           %2 = OpTypeVoid
192           %3 = OpTypeFunction %2
193           %6 = OpTypeBool
194           %7 = OpConstantTrue %6
195           %4 = OpFunction %2 None %3
196           %5 = OpLabel
197                OpBranch %8
198           %8 = OpLabel
199                OpLoopMerge %11 %12 None
200                OpBranch %9
201           %9 = OpLabel
202                OpBranchConditional %7 %11 %12
203          %12 = OpLabel
204                OpBranch %8
205          %11 = OpLabel
206                OpReturn
207                OpFunctionEnd
208   )";
209 
210   const auto env = SPV_ENV_UNIVERSAL_1_4;
211   const auto consumer = nullptr;
212   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
213   ASSERT_TRUE(IsValid(env, context.get()));
214 
215   FactManager fact_manager;
216   spvtools::ValidatorOptions validator_options;
217   TransformationContext transformation_context(&fact_manager,
218                                                validator_options);
219 
220   // Bad because 8 is a loop head.
221   ASSERT_FALSE(TransformationAddDeadBlock(100, 8, true)
222                    .IsApplicable(context.get(), transformation_context));
223 }
224 
TEST(TransformationAddDeadBlockTest,OpPhiInTarget)225 TEST(TransformationAddDeadBlockTest, OpPhiInTarget) {
226   std::string shader = R"(
227                OpCapability Shader
228           %1 = OpExtInstImport "GLSL.std.450"
229                OpMemoryModel Logical GLSL450
230                OpEntryPoint Fragment %4 "main"
231                OpExecutionMode %4 OriginUpperLeft
232                OpSource ESSL 310
233                OpName %4 "main"
234           %2 = OpTypeVoid
235           %3 = OpTypeFunction %2
236           %6 = OpTypeBool
237           %7 = OpConstantTrue %6
238           %9 = OpTypeInt 32 0
239          %10 = OpConstant %9 1
240           %4 = OpFunction %2 None %3
241           %5 = OpLabel
242                OpBranch %8
243           %8 = OpLabel
244          %12 = OpPhi %6 %7 %5
245          %13 = OpPhi %9 %10 %5
246                OpReturn
247                OpFunctionEnd
248   )";
249 
250   const auto env = SPV_ENV_UNIVERSAL_1_4;
251   const auto consumer = nullptr;
252   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
253   ASSERT_TRUE(IsValid(env, context.get()));
254 
255   FactManager fact_manager;
256   spvtools::ValidatorOptions validator_options;
257   TransformationContext transformation_context(&fact_manager,
258                                                validator_options);
259 
260   TransformationAddDeadBlock transformation(100, 5, true);
261   ASSERT_TRUE(
262       transformation.IsApplicable(context.get(), transformation_context));
263   transformation.Apply(context.get(), &transformation_context);
264   ASSERT_TRUE(IsValid(env, context.get()));
265 
266   ASSERT_TRUE(transformation_context.GetFactManager()->BlockIsDead(100));
267 
268   std::string after_transformation = R"(
269                OpCapability Shader
270           %1 = OpExtInstImport "GLSL.std.450"
271                OpMemoryModel Logical GLSL450
272                OpEntryPoint Fragment %4 "main"
273                OpExecutionMode %4 OriginUpperLeft
274                OpSource ESSL 310
275                OpName %4 "main"
276           %2 = OpTypeVoid
277           %3 = OpTypeFunction %2
278           %6 = OpTypeBool
279           %7 = OpConstantTrue %6
280           %9 = OpTypeInt 32 0
281          %10 = OpConstant %9 1
282           %4 = OpFunction %2 None %3
283           %5 = OpLabel
284                OpSelectionMerge %8 None
285                OpBranchConditional %7 %8 %100
286         %100 = OpLabel
287                OpBranch %8
288           %8 = OpLabel
289          %12 = OpPhi %6 %7 %5 %7 %100
290          %13 = OpPhi %9 %10 %5 %10 %100
291                OpReturn
292                OpFunctionEnd
293   )";
294   ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
295 }
296 
TEST(TransformationAddDeadBlockTest,BackEdge)297 TEST(TransformationAddDeadBlockTest, BackEdge) {
298   std::string shader = R"(
299                OpCapability Shader
300           %1 = OpExtInstImport "GLSL.std.450"
301                OpMemoryModel Logical GLSL450
302                OpEntryPoint Fragment %4 "main"
303                OpExecutionMode %4 OriginUpperLeft
304                OpSource ESSL 310
305                OpName %4 "main"
306           %2 = OpTypeVoid
307           %3 = OpTypeFunction %2
308           %6 = OpTypeBool
309           %7 = OpConstantTrue %6
310           %4 = OpFunction %2 None %3
311           %5 = OpLabel
312                OpBranch %8
313           %8 = OpLabel
314                OpLoopMerge %10 %9 None
315                OpBranchConditional %7 %9 %10
316           %9 = OpLabel
317                OpBranch %8
318          %10 = OpLabel
319                OpReturn
320                OpFunctionEnd
321   )";
322 
323   const auto env = SPV_ENV_UNIVERSAL_1_4;
324   const auto consumer = nullptr;
325   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
326   ASSERT_TRUE(IsValid(env, context.get()));
327 
328   FactManager fact_manager;
329   spvtools::ValidatorOptions validator_options;
330   TransformationContext transformation_context(&fact_manager,
331                                                validator_options);
332 
333   // 9 is a back edge block, so it would not be OK to add a dead block here,
334   // as then both 9 and the dead block would branch to the loop header, 8.
335   ASSERT_FALSE(TransformationAddDeadBlock(100, 9, true)
336                    .IsApplicable(context.get(), transformation_context));
337 }
338 
339 }  // namespace
340 }  // namespace fuzz
341 }  // namespace spvtools
342