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_move_block_down.h"
16 #include "test/fuzz/fuzz_test_util.h"
17
18 namespace spvtools {
19 namespace fuzz {
20 namespace {
21
TEST(TransformationMoveBlockDownTest,NoMovePossible1)22 TEST(TransformationMoveBlockDownTest, NoMovePossible1) {
23 // Block 11 cannot be moved down as it dominates block 12.
24 std::string shader = R"(
25 OpCapability Shader
26 %1 = OpExtInstImport "GLSL.std.450"
27 OpMemoryModel Logical GLSL450
28 OpEntryPoint Fragment %4 "main"
29 OpExecutionMode %4 OriginUpperLeft
30 OpSource ESSL 310
31 OpDecorate %8 RelaxedPrecision
32 %2 = OpTypeVoid
33 %3 = OpTypeFunction %2
34 %6 = OpTypeInt 32 1
35 %7 = OpTypePointer Function %6
36 %9 = OpConstant %6 1
37 %10 = OpConstant %6 2
38 %4 = OpFunction %2 None %3
39 %5 = OpLabel
40 %8 = OpVariable %7 Function
41 OpBranch %11
42 %11 = OpLabel
43 OpStore %8 %9
44 OpBranch %12
45 %12 = OpLabel
46 OpStore %8 %10
47 OpReturn
48 OpFunctionEnd
49 )";
50
51 const auto env = SPV_ENV_UNIVERSAL_1_3;
52 const auto consumer = nullptr;
53 const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
54
55 FactManager fact_manager;
56 spvtools::ValidatorOptions validator_options;
57 TransformationContext transformation_context(&fact_manager,
58 validator_options);
59
60 auto transformation = TransformationMoveBlockDown(11);
61 ASSERT_FALSE(
62 transformation.IsApplicable(context.get(), transformation_context));
63 }
64
TEST(TransformationMoveBlockDownTest,NoMovePossible2)65 TEST(TransformationMoveBlockDownTest, NoMovePossible2) {
66 // Block 5 cannot be moved down as it is the entry block.
67 std::string shader = R"(
68 OpCapability Shader
69 %1 = OpExtInstImport "GLSL.std.450"
70 OpMemoryModel Logical GLSL450
71 OpEntryPoint Fragment %4 "main"
72 OpExecutionMode %4 OriginUpperLeft
73 OpSource ESSL 310
74 OpDecorate %8 RelaxedPrecision
75 %2 = OpTypeVoid
76 %3 = OpTypeFunction %2
77 %6 = OpTypeInt 32 1
78 %7 = OpTypePointer Function %6
79 %9 = OpConstant %6 1
80 %10 = OpConstant %6 2
81 %4 = OpFunction %2 None %3
82 %5 = OpLabel
83 %8 = OpVariable %7 Function
84 OpStore %8 %9
85 OpStore %8 %10
86 OpReturn
87 %11 = OpLabel
88 OpReturn
89 OpFunctionEnd
90 )";
91
92 const auto env = SPV_ENV_UNIVERSAL_1_3;
93 const auto consumer = nullptr;
94 const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
95
96 FactManager fact_manager;
97 spvtools::ValidatorOptions validator_options;
98 TransformationContext transformation_context(&fact_manager,
99 validator_options);
100
101 auto transformation = TransformationMoveBlockDown(5);
102 ASSERT_FALSE(
103 transformation.IsApplicable(context.get(), transformation_context));
104 }
105
TEST(TransformationMoveBlockDownTest,NoMovePossible3)106 TEST(TransformationMoveBlockDownTest, NoMovePossible3) {
107 // Block 100 does not exist, so cannot be moved down.
108 std::string shader = R"(
109 OpCapability Shader
110 %1 = OpExtInstImport "GLSL.std.450"
111 OpMemoryModel Logical GLSL450
112 OpEntryPoint Fragment %4 "main"
113 OpExecutionMode %4 OriginUpperLeft
114 OpSource ESSL 310
115 OpDecorate %8 RelaxedPrecision
116 %2 = OpTypeVoid
117 %3 = OpTypeFunction %2
118 %6 = OpTypeInt 32 1
119 %7 = OpTypePointer Function %6
120 %9 = OpConstant %6 1
121 %10 = OpConstant %6 2
122 %4 = OpFunction %2 None %3
123 %5 = OpLabel
124 %8 = OpVariable %7 Function
125 OpBranch %11
126 %11 = OpLabel
127 OpStore %8 %9
128 OpBranch %12
129 %12 = OpLabel
130 OpStore %8 %10
131 OpReturn
132 OpFunctionEnd
133 )";
134
135 const auto env = SPV_ENV_UNIVERSAL_1_3;
136 const auto consumer = nullptr;
137 const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
138
139 FactManager fact_manager;
140 spvtools::ValidatorOptions validator_options;
141 TransformationContext transformation_context(&fact_manager,
142 validator_options);
143
144 auto transformation = TransformationMoveBlockDown(100);
145 ASSERT_FALSE(
146 transformation.IsApplicable(context.get(), transformation_context));
147 }
148
TEST(TransformationMoveBlockDownTest,NoMovePossible4)149 TEST(TransformationMoveBlockDownTest, NoMovePossible4) {
150 // Block 12 is the last block in its function, so cannot be moved down.
151 std::string shader = R"(
152 OpCapability Shader
153 %1 = OpExtInstImport "GLSL.std.450"
154 OpMemoryModel Logical GLSL450
155 OpEntryPoint Fragment %4 "main"
156 OpExecutionMode %4 OriginUpperLeft
157 OpSource ESSL 310
158 OpDecorate %8 RelaxedPrecision
159 %2 = OpTypeVoid
160 %3 = OpTypeFunction %2
161 %6 = OpTypeInt 32 1
162 %7 = OpTypePointer Function %6
163 %9 = OpConstant %6 1
164 %10 = OpConstant %6 2
165 %4 = OpFunction %2 None %3
166 %5 = OpLabel
167 %8 = OpVariable %7 Function
168 OpBranch %11
169 %11 = OpLabel
170 OpStore %8 %9
171 OpBranch %12
172 %12 = OpLabel
173 OpStore %8 %10
174 OpReturn
175 OpFunctionEnd
176 %13 = OpFunction %2 None %3
177 %14 = OpLabel
178 OpReturn
179 OpFunctionEnd
180 )";
181
182 const auto env = SPV_ENV_UNIVERSAL_1_3;
183 const auto consumer = nullptr;
184 const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
185
186 FactManager fact_manager;
187 spvtools::ValidatorOptions validator_options;
188 TransformationContext transformation_context(&fact_manager,
189 validator_options);
190
191 auto transformation = TransformationMoveBlockDown(12);
192 ASSERT_FALSE(
193 transformation.IsApplicable(context.get(), transformation_context));
194 }
195
TEST(TransformationMoveBlockDownTest,ManyMovesPossible)196 TEST(TransformationMoveBlockDownTest, ManyMovesPossible) {
197 // The SPIR-V arising from this shader has lots of opportunities for moving
198 // blocks around.
199 //
200 // void main() {
201 // int x;
202 // int y;
203 // if (x < y) {
204 // x = 1;
205 // if (y == x) {
206 // x = 3;
207 // } else {
208 // x = 4;
209 // }
210 // } else {
211 // if (y < x) {
212 // x = 5;
213 // } else {
214 // x = 6;
215 // }
216 // }
217 // }
218
219 std::string before_transformation = R"(
220 OpCapability Shader
221 %1 = OpExtInstImport "GLSL.std.450"
222 OpMemoryModel Logical GLSL450
223 OpEntryPoint Fragment %4 "main"
224 OpExecutionMode %4 OriginUpperLeft
225 OpSource ESSL 310
226 OpName %4 "main"
227 OpName %8 "x"
228 OpName %10 "y"
229 OpDecorate %8 RelaxedPrecision
230 OpDecorate %9 RelaxedPrecision
231 OpDecorate %10 RelaxedPrecision
232 OpDecorate %11 RelaxedPrecision
233 OpDecorate %17 RelaxedPrecision
234 OpDecorate %18 RelaxedPrecision
235 OpDecorate %26 RelaxedPrecision
236 OpDecorate %27 RelaxedPrecision
237 %2 = OpTypeVoid
238 %3 = OpTypeFunction %2
239 %6 = OpTypeInt 32 1
240 %7 = OpTypePointer Function %6
241 %12 = OpTypeBool
242 %16 = OpConstant %6 1
243 %22 = OpConstant %6 3
244 %24 = OpConstant %6 4
245 %31 = OpConstant %6 5
246 %33 = OpConstant %6 6
247 %4 = OpFunction %2 None %3
248 %5 = OpLabel
249 %8 = OpVariable %7 Function
250 %10 = OpVariable %7 Function
251 %9 = OpLoad %6 %8
252 %11 = OpLoad %6 %10
253 %13 = OpSLessThan %12 %9 %11
254 OpSelectionMerge %15 None
255 OpBranchConditional %13 %14 %25
256 %14 = OpLabel
257 OpStore %8 %16
258 %17 = OpLoad %6 %10
259 %18 = OpLoad %6 %8
260 %19 = OpIEqual %12 %17 %18
261 OpSelectionMerge %21 None
262 OpBranchConditional %19 %20 %23
263 %20 = OpLabel
264 OpStore %8 %22
265 OpBranch %21
266 %23 = OpLabel
267 OpStore %8 %24
268 OpBranch %21
269 %21 = OpLabel
270 OpBranch %15
271 %25 = OpLabel
272 %26 = OpLoad %6 %10
273 %27 = OpLoad %6 %8
274 %28 = OpSLessThan %12 %26 %27
275 OpSelectionMerge %30 None
276 OpBranchConditional %28 %29 %32
277 %29 = OpLabel
278 OpStore %8 %31
279 OpBranch %30
280 %32 = OpLabel
281 OpStore %8 %33
282 OpBranch %30
283 %30 = OpLabel
284 OpBranch %15
285 %15 = OpLabel
286 OpReturn
287 OpFunctionEnd
288 )";
289
290 const auto env = SPV_ENV_UNIVERSAL_1_3;
291 const auto consumer = nullptr;
292 const auto context =
293 BuildModule(env, consumer, before_transformation, kFuzzAssembleOption);
294
295 FactManager fact_manager;
296 spvtools::ValidatorOptions validator_options;
297 TransformationContext transformation_context(&fact_manager,
298 validator_options);
299
300 // The block ids are: 5 14 20 23 21 25 29 32 30 15
301 // We make a transformation to move each of them down, plus a transformation
302 // to move a non-block, 27, down.
303 auto move_down_5 = TransformationMoveBlockDown(5);
304 auto move_down_14 = TransformationMoveBlockDown(14);
305 auto move_down_20 = TransformationMoveBlockDown(20);
306 auto move_down_23 = TransformationMoveBlockDown(23);
307 auto move_down_21 = TransformationMoveBlockDown(21);
308 auto move_down_25 = TransformationMoveBlockDown(25);
309 auto move_down_29 = TransformationMoveBlockDown(29);
310 auto move_down_32 = TransformationMoveBlockDown(32);
311 auto move_down_30 = TransformationMoveBlockDown(30);
312 auto move_down_15 = TransformationMoveBlockDown(15);
313 auto move_down_27 = TransformationMoveBlockDown(27);
314
315 // Dominance is as follows:
316 // 5 dominates everything else
317 // 14 dominates 20, 23, 21
318 // 20 dominates nothing
319 // 23 dominates nothing
320 // 21 dominates nothing
321 // 25 dominates 29, 32, 30
322 // 29 dominates nothing
323 // 32 dominates nothing
324 // 30 dominates nothing
325 // 15 dominates nothing
326
327 // Current ordering: 5 14 20 23 21 25 29 32 30 15
328 ASSERT_FALSE(move_down_5.IsApplicable(context.get(), transformation_context));
329 ASSERT_FALSE(
330 move_down_14.IsApplicable(context.get(), transformation_context));
331 ASSERT_TRUE(move_down_20.IsApplicable(context.get(), transformation_context));
332 ASSERT_TRUE(move_down_23.IsApplicable(context.get(), transformation_context));
333 ASSERT_TRUE(move_down_21.IsApplicable(context.get(), transformation_context));
334 ASSERT_FALSE(
335 move_down_25.IsApplicable(context.get(), transformation_context));
336 ASSERT_TRUE(move_down_29.IsApplicable(context.get(), transformation_context));
337 ASSERT_TRUE(move_down_32.IsApplicable(context.get(), transformation_context));
338 ASSERT_TRUE(move_down_30.IsApplicable(context.get(), transformation_context));
339 ASSERT_FALSE(
340 move_down_15.IsApplicable(context.get(), transformation_context));
341
342 // Let's bubble 20 all the way down.
343
344 move_down_20.Apply(context.get(), &transformation_context);
345 ASSERT_TRUE(IsValid(env, context.get()));
346
347 // Current ordering: 5 14 23 20 21 25 29 32 30 15
348 ASSERT_FALSE(move_down_5.IsApplicable(context.get(), transformation_context));
349 ASSERT_FALSE(
350 move_down_14.IsApplicable(context.get(), transformation_context));
351 ASSERT_TRUE(move_down_23.IsApplicable(context.get(), transformation_context));
352 ASSERT_TRUE(move_down_20.IsApplicable(context.get(), transformation_context));
353 ASSERT_TRUE(move_down_21.IsApplicable(context.get(), transformation_context));
354 ASSERT_FALSE(
355 move_down_25.IsApplicable(context.get(), transformation_context));
356 ASSERT_TRUE(move_down_29.IsApplicable(context.get(), transformation_context));
357 ASSERT_TRUE(move_down_32.IsApplicable(context.get(), transformation_context));
358 ASSERT_TRUE(move_down_30.IsApplicable(context.get(), transformation_context));
359 ASSERT_FALSE(
360 move_down_15.IsApplicable(context.get(), transformation_context));
361
362 move_down_20.Apply(context.get(), &transformation_context);
363 ASSERT_TRUE(IsValid(env, context.get()));
364
365 // Current ordering: 5 14 23 21 20 25 29 32 30 15
366 ASSERT_FALSE(move_down_5.IsApplicable(context.get(), transformation_context));
367 ASSERT_FALSE(
368 move_down_14.IsApplicable(context.get(), transformation_context));
369 ASSERT_TRUE(move_down_23.IsApplicable(context.get(), transformation_context));
370 ASSERT_TRUE(move_down_21.IsApplicable(context.get(), transformation_context));
371 ASSERT_TRUE(move_down_20.IsApplicable(context.get(), transformation_context));
372 ASSERT_FALSE(
373 move_down_25.IsApplicable(context.get(), transformation_context));
374 ASSERT_TRUE(move_down_29.IsApplicable(context.get(), transformation_context));
375 ASSERT_TRUE(move_down_32.IsApplicable(context.get(), transformation_context));
376 ASSERT_TRUE(move_down_30.IsApplicable(context.get(), transformation_context));
377 ASSERT_FALSE(
378 move_down_15.IsApplicable(context.get(), transformation_context));
379
380 move_down_20.Apply(context.get(), &transformation_context);
381 ASSERT_TRUE(IsValid(env, context.get()));
382
383 // Current ordering: 5 14 23 21 25 20 29 32 30 15
384 ASSERT_FALSE(move_down_5.IsApplicable(context.get(), transformation_context));
385 ASSERT_FALSE(
386 move_down_14.IsApplicable(context.get(), transformation_context));
387 ASSERT_TRUE(move_down_23.IsApplicable(context.get(), transformation_context));
388 ASSERT_TRUE(move_down_21.IsApplicable(context.get(), transformation_context));
389 ASSERT_TRUE(move_down_25.IsApplicable(context.get(), transformation_context));
390 ASSERT_TRUE(move_down_20.IsApplicable(context.get(), transformation_context));
391 ASSERT_TRUE(move_down_29.IsApplicable(context.get(), transformation_context));
392 ASSERT_TRUE(move_down_32.IsApplicable(context.get(), transformation_context));
393 ASSERT_TRUE(move_down_30.IsApplicable(context.get(), transformation_context));
394 ASSERT_FALSE(
395 move_down_15.IsApplicable(context.get(), transformation_context));
396
397 move_down_20.Apply(context.get(), &transformation_context);
398 ASSERT_TRUE(IsValid(env, context.get()));
399
400 // Current ordering: 5 14 23 21 25 29 20 32 30 15
401 ASSERT_FALSE(move_down_5.IsApplicable(context.get(), transformation_context));
402 ASSERT_FALSE(
403 move_down_14.IsApplicable(context.get(), transformation_context));
404 ASSERT_TRUE(move_down_23.IsApplicable(context.get(), transformation_context));
405 ASSERT_TRUE(move_down_21.IsApplicable(context.get(), transformation_context));
406 ASSERT_FALSE(
407 move_down_25.IsApplicable(context.get(), transformation_context));
408 ASSERT_TRUE(move_down_29.IsApplicable(context.get(), transformation_context));
409 ASSERT_TRUE(move_down_20.IsApplicable(context.get(), transformation_context));
410 ASSERT_TRUE(move_down_32.IsApplicable(context.get(), transformation_context));
411 ASSERT_TRUE(move_down_30.IsApplicable(context.get(), transformation_context));
412 ASSERT_FALSE(
413 move_down_15.IsApplicable(context.get(), transformation_context));
414
415 move_down_20.Apply(context.get(), &transformation_context);
416 ASSERT_TRUE(IsValid(env, context.get()));
417
418 // Current ordering: 5 14 23 21 25 29 32 20 30 15
419 ASSERT_FALSE(move_down_5.IsApplicable(context.get(), transformation_context));
420 ASSERT_FALSE(
421 move_down_14.IsApplicable(context.get(), transformation_context));
422 ASSERT_TRUE(move_down_23.IsApplicable(context.get(), transformation_context));
423 ASSERT_TRUE(move_down_21.IsApplicable(context.get(), transformation_context));
424 ASSERT_FALSE(
425 move_down_25.IsApplicable(context.get(), transformation_context));
426 ASSERT_TRUE(move_down_29.IsApplicable(context.get(), transformation_context));
427 ASSERT_TRUE(move_down_32.IsApplicable(context.get(), transformation_context));
428 ASSERT_TRUE(move_down_20.IsApplicable(context.get(), transformation_context));
429 ASSERT_TRUE(move_down_30.IsApplicable(context.get(), transformation_context));
430 ASSERT_FALSE(
431 move_down_15.IsApplicable(context.get(), transformation_context));
432
433 move_down_20.Apply(context.get(), &transformation_context);
434 ASSERT_TRUE(IsValid(env, context.get()));
435
436 // Current ordering: 5 14 23 21 25 29 32 30 20 15
437 ASSERT_FALSE(move_down_5.IsApplicable(context.get(), transformation_context));
438 ASSERT_FALSE(
439 move_down_14.IsApplicable(context.get(), transformation_context));
440 ASSERT_TRUE(move_down_23.IsApplicable(context.get(), transformation_context));
441 ASSERT_TRUE(move_down_21.IsApplicable(context.get(), transformation_context));
442 ASSERT_FALSE(
443 move_down_25.IsApplicable(context.get(), transformation_context));
444 ASSERT_TRUE(move_down_29.IsApplicable(context.get(), transformation_context));
445 ASSERT_TRUE(move_down_32.IsApplicable(context.get(), transformation_context));
446 ASSERT_TRUE(move_down_30.IsApplicable(context.get(), transformation_context));
447 ASSERT_TRUE(move_down_20.IsApplicable(context.get(), transformation_context));
448 ASSERT_FALSE(
449 move_down_15.IsApplicable(context.get(), transformation_context));
450
451 move_down_20.Apply(context.get(), &transformation_context);
452 ASSERT_TRUE(IsValid(env, context.get()));
453
454 std::string after_bubbling_20_down = R"(
455 OpCapability Shader
456 %1 = OpExtInstImport "GLSL.std.450"
457 OpMemoryModel Logical GLSL450
458 OpEntryPoint Fragment %4 "main"
459 OpExecutionMode %4 OriginUpperLeft
460 OpSource ESSL 310
461 OpName %4 "main"
462 OpName %8 "x"
463 OpName %10 "y"
464 OpDecorate %8 RelaxedPrecision
465 OpDecorate %9 RelaxedPrecision
466 OpDecorate %10 RelaxedPrecision
467 OpDecorate %11 RelaxedPrecision
468 OpDecorate %17 RelaxedPrecision
469 OpDecorate %18 RelaxedPrecision
470 OpDecorate %26 RelaxedPrecision
471 OpDecorate %27 RelaxedPrecision
472 %2 = OpTypeVoid
473 %3 = OpTypeFunction %2
474 %6 = OpTypeInt 32 1
475 %7 = OpTypePointer Function %6
476 %12 = OpTypeBool
477 %16 = OpConstant %6 1
478 %22 = OpConstant %6 3
479 %24 = OpConstant %6 4
480 %31 = OpConstant %6 5
481 %33 = OpConstant %6 6
482 %4 = OpFunction %2 None %3
483 %5 = OpLabel
484 %8 = OpVariable %7 Function
485 %10 = OpVariable %7 Function
486 %9 = OpLoad %6 %8
487 %11 = OpLoad %6 %10
488 %13 = OpSLessThan %12 %9 %11
489 OpSelectionMerge %15 None
490 OpBranchConditional %13 %14 %25
491 %14 = OpLabel
492 OpStore %8 %16
493 %17 = OpLoad %6 %10
494 %18 = OpLoad %6 %8
495 %19 = OpIEqual %12 %17 %18
496 OpSelectionMerge %21 None
497 OpBranchConditional %19 %20 %23
498 %23 = OpLabel
499 OpStore %8 %24
500 OpBranch %21
501 %21 = OpLabel
502 OpBranch %15
503 %25 = OpLabel
504 %26 = OpLoad %6 %10
505 %27 = OpLoad %6 %8
506 %28 = OpSLessThan %12 %26 %27
507 OpSelectionMerge %30 None
508 OpBranchConditional %28 %29 %32
509 %29 = OpLabel
510 OpStore %8 %31
511 OpBranch %30
512 %32 = OpLabel
513 OpStore %8 %33
514 OpBranch %30
515 %30 = OpLabel
516 OpBranch %15
517 %15 = OpLabel
518 OpReturn
519 %20 = OpLabel
520 OpStore %8 %22
521 OpBranch %21
522 OpFunctionEnd
523 )";
524 ASSERT_TRUE(IsEqual(env, after_bubbling_20_down, context.get()));
525
526 // Current ordering: 5 14 23 21 25 29 32 30 15 20
527 ASSERT_FALSE(move_down_5.IsApplicable(context.get(), transformation_context));
528 ASSERT_FALSE(
529 move_down_14.IsApplicable(context.get(), transformation_context));
530 ASSERT_TRUE(move_down_23.IsApplicable(context.get(), transformation_context));
531 ASSERT_TRUE(move_down_21.IsApplicable(context.get(), transformation_context));
532 ASSERT_FALSE(
533 move_down_25.IsApplicable(context.get(), transformation_context));
534 ASSERT_TRUE(move_down_29.IsApplicable(context.get(), transformation_context));
535 ASSERT_TRUE(move_down_32.IsApplicable(context.get(), transformation_context));
536 ASSERT_TRUE(move_down_30.IsApplicable(context.get(), transformation_context));
537 ASSERT_TRUE(move_down_15.IsApplicable(context.get(), transformation_context));
538 ASSERT_FALSE(
539 move_down_20.IsApplicable(context.get(), transformation_context));
540
541 move_down_23.Apply(context.get(), &transformation_context);
542 ASSERT_TRUE(IsValid(env, context.get()));
543
544 // Current ordering: 5 14 21 23 25 29 32 30 15 20
545 ASSERT_FALSE(move_down_5.IsApplicable(context.get(), transformation_context));
546 ASSERT_FALSE(
547 move_down_14.IsApplicable(context.get(), transformation_context));
548 ASSERT_TRUE(move_down_21.IsApplicable(context.get(), transformation_context));
549 ASSERT_TRUE(move_down_23.IsApplicable(context.get(), transformation_context));
550 ASSERT_FALSE(
551 move_down_25.IsApplicable(context.get(), transformation_context));
552 ASSERT_TRUE(move_down_29.IsApplicable(context.get(), transformation_context));
553 ASSERT_TRUE(move_down_32.IsApplicable(context.get(), transformation_context));
554 ASSERT_TRUE(move_down_30.IsApplicable(context.get(), transformation_context));
555 ASSERT_TRUE(move_down_15.IsApplicable(context.get(), transformation_context));
556 ASSERT_FALSE(
557 move_down_20.IsApplicable(context.get(), transformation_context));
558
559 move_down_23.Apply(context.get(), &transformation_context);
560 ASSERT_TRUE(IsValid(env, context.get()));
561
562 // Current ordering: 5 14 21 25 23 29 32 30 15 20
563 ASSERT_FALSE(move_down_5.IsApplicable(context.get(), transformation_context));
564 ASSERT_FALSE(
565 move_down_14.IsApplicable(context.get(), transformation_context));
566 ASSERT_TRUE(move_down_21.IsApplicable(context.get(), transformation_context));
567 ASSERT_TRUE(move_down_25.IsApplicable(context.get(), transformation_context));
568 ASSERT_TRUE(move_down_23.IsApplicable(context.get(), transformation_context));
569 ASSERT_TRUE(move_down_29.IsApplicable(context.get(), transformation_context));
570 ASSERT_TRUE(move_down_32.IsApplicable(context.get(), transformation_context));
571 ASSERT_TRUE(move_down_30.IsApplicable(context.get(), transformation_context));
572 ASSERT_TRUE(move_down_15.IsApplicable(context.get(), transformation_context));
573 ASSERT_FALSE(
574 move_down_20.IsApplicable(context.get(), transformation_context));
575
576 move_down_21.Apply(context.get(), &transformation_context);
577 ASSERT_TRUE(IsValid(env, context.get()));
578
579 // Current ordering: 5 14 25 21 23 29 32 30 15 20
580 ASSERT_FALSE(move_down_5.IsApplicable(context.get(), transformation_context));
581 ASSERT_TRUE(move_down_14.IsApplicable(context.get(), transformation_context));
582 ASSERT_TRUE(move_down_21.IsApplicable(context.get(), transformation_context));
583 ASSERT_TRUE(move_down_25.IsApplicable(context.get(), transformation_context));
584 ASSERT_TRUE(move_down_23.IsApplicable(context.get(), transformation_context));
585 ASSERT_TRUE(move_down_29.IsApplicable(context.get(), transformation_context));
586 ASSERT_TRUE(move_down_32.IsApplicable(context.get(), transformation_context));
587 ASSERT_TRUE(move_down_30.IsApplicable(context.get(), transformation_context));
588 ASSERT_TRUE(move_down_15.IsApplicable(context.get(), transformation_context));
589 ASSERT_FALSE(
590 move_down_20.IsApplicable(context.get(), transformation_context));
591
592 move_down_14.Apply(context.get(), &transformation_context);
593 ASSERT_TRUE(IsValid(env, context.get()));
594
595 std::string after_more_shuffling = R"(
596 OpCapability Shader
597 %1 = OpExtInstImport "GLSL.std.450"
598 OpMemoryModel Logical GLSL450
599 OpEntryPoint Fragment %4 "main"
600 OpExecutionMode %4 OriginUpperLeft
601 OpSource ESSL 310
602 OpName %4 "main"
603 OpName %8 "x"
604 OpName %10 "y"
605 OpDecorate %8 RelaxedPrecision
606 OpDecorate %9 RelaxedPrecision
607 OpDecorate %10 RelaxedPrecision
608 OpDecorate %11 RelaxedPrecision
609 OpDecorate %17 RelaxedPrecision
610 OpDecorate %18 RelaxedPrecision
611 OpDecorate %26 RelaxedPrecision
612 OpDecorate %27 RelaxedPrecision
613 %2 = OpTypeVoid
614 %3 = OpTypeFunction %2
615 %6 = OpTypeInt 32 1
616 %7 = OpTypePointer Function %6
617 %12 = OpTypeBool
618 %16 = OpConstant %6 1
619 %22 = OpConstant %6 3
620 %24 = OpConstant %6 4
621 %31 = OpConstant %6 5
622 %33 = OpConstant %6 6
623 %4 = OpFunction %2 None %3
624 %5 = OpLabel
625 %8 = OpVariable %7 Function
626 %10 = OpVariable %7 Function
627 %9 = OpLoad %6 %8
628 %11 = OpLoad %6 %10
629 %13 = OpSLessThan %12 %9 %11
630 OpSelectionMerge %15 None
631 OpBranchConditional %13 %14 %25
632 %25 = OpLabel
633 %26 = OpLoad %6 %10
634 %27 = OpLoad %6 %8
635 %28 = OpSLessThan %12 %26 %27
636 OpSelectionMerge %30 None
637 OpBranchConditional %28 %29 %32
638 %14 = OpLabel
639 OpStore %8 %16
640 %17 = OpLoad %6 %10
641 %18 = OpLoad %6 %8
642 %19 = OpIEqual %12 %17 %18
643 OpSelectionMerge %21 None
644 OpBranchConditional %19 %20 %23
645 %21 = OpLabel
646 OpBranch %15
647 %23 = OpLabel
648 OpStore %8 %24
649 OpBranch %21
650 %29 = OpLabel
651 OpStore %8 %31
652 OpBranch %30
653 %32 = OpLabel
654 OpStore %8 %33
655 OpBranch %30
656 %30 = OpLabel
657 OpBranch %15
658 %15 = OpLabel
659 OpReturn
660 %20 = OpLabel
661 OpStore %8 %22
662 OpBranch %21
663 OpFunctionEnd
664 )";
665 ASSERT_TRUE(IsEqual(env, after_more_shuffling, context.get()));
666
667 // Final ordering: 5 25 14 21 23 29 32 30 15 20
668 ASSERT_FALSE(move_down_5.IsApplicable(context.get(), transformation_context));
669 ASSERT_TRUE(move_down_25.IsApplicable(context.get(), transformation_context));
670 ASSERT_FALSE(
671 move_down_14.IsApplicable(context.get(), transformation_context));
672 ASSERT_TRUE(move_down_21.IsApplicable(context.get(), transformation_context));
673 ASSERT_TRUE(move_down_23.IsApplicable(context.get(), transformation_context));
674 ASSERT_TRUE(move_down_29.IsApplicable(context.get(), transformation_context));
675 ASSERT_TRUE(move_down_32.IsApplicable(context.get(), transformation_context));
676 ASSERT_TRUE(move_down_30.IsApplicable(context.get(), transformation_context));
677 ASSERT_TRUE(move_down_15.IsApplicable(context.get(), transformation_context));
678 ASSERT_FALSE(
679 move_down_20.IsApplicable(context.get(), transformation_context));
680 }
681
TEST(TransformationMoveBlockDownTest,DoNotMoveUnreachable)682 TEST(TransformationMoveBlockDownTest, DoNotMoveUnreachable) {
683 // Block 6 is unreachable, so cannot be moved down.
684 std::string shader = R"(
685 OpCapability Shader
686 %1 = OpExtInstImport "GLSL.std.450"
687 OpMemoryModel Logical GLSL450
688 OpEntryPoint Fragment %4 "main"
689 OpExecutionMode %4 OriginUpperLeft
690 OpSource ESSL 310
691 OpName %4 "main"
692 %2 = OpTypeVoid
693 %3 = OpTypeFunction %2
694 %10 = OpTypeInt 32 1
695 %4 = OpFunction %2 None %3
696 %5 = OpLabel
697 OpReturn
698 %6 = OpLabel
699 %7 = OpUndef %10
700 OpBranch %8
701 %8 = OpLabel
702 %9 = OpCopyObject %10 %7
703 OpReturn
704 OpFunctionEnd
705 )";
706
707 const auto env = SPV_ENV_UNIVERSAL_1_3;
708 const auto consumer = nullptr;
709 const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
710 ASSERT_TRUE(IsValid(env, context.get()));
711
712 FactManager fact_manager;
713 spvtools::ValidatorOptions validator_options;
714 TransformationContext transformation_context(&fact_manager,
715 validator_options);
716
717 auto transformation = TransformationMoveBlockDown(6);
718 ASSERT_FALSE(
719 transformation.IsApplicable(context.get(), transformation_context));
720 }
721
722 } // namespace
723 } // namespace fuzz
724 } // namespace spvtools
725