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