Skip to content

Commit

Permalink
spirv-fuzz: Improve code coverage of tests (KhronosGroup#3686)
Browse files Browse the repository at this point in the history
Improves the code coverage of tests for the following transformations:

1. TransformationAddRelaxedDecoration
2. TransformationReplaceCopyMemoryWithLoadStore
3. TransformationReplaceCopyObjectWithStoreLoad
4. TransformationReplaceLoadStoreWithCopyMemory
5. TransformationReplaceAddSubMulWithCarryingExtended
  • Loading branch information
Antoni Karpiński authored Aug 14, 2020
1 parent eade36d commit c20995e
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,6 @@ bool TransformationReplaceCopyObjectWithStoreLoad::IsApplicable(
return false;
}

// It must be valid to insert the OpStore and OpLoad instruction before it.
if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpStore,
copy_object_instruction) ||
!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpLoad,
copy_object_instruction)) {
return false;
}

// A pointer type instruction pointing to the value type must be defined.
auto pointer_type_id = fuzzerutil::MaybeGetPointerType(
ir_context, copy_object_instruction->type_id(),
Expand Down
12 changes: 2 additions & 10 deletions source/fuzz/transformation_replace_load_store_with_copy_memory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,26 +45,18 @@ bool TransformationReplaceLoadStoreWithCopyMemory::IsApplicable(
opt::IRContext* ir_context, const TransformationContext& /*unused*/) const {
// This transformation is only applicable to the pair of OpLoad and OpStore
// instructions.
if (message_.load_instruction_descriptor().target_instruction_opcode() !=
SpvOpLoad) {
return false;
}
if (message_.store_instruction_descriptor().target_instruction_opcode() !=
SpvOpStore) {
return false;
}

// The OpLoad instruction must be defined.
auto load_instruction =
FindInstruction(message_.load_instruction_descriptor(), ir_context);
if (!load_instruction) {
if (!load_instruction || load_instruction->opcode() != SpvOpLoad) {
return false;
}

// The OpStore instruction must be defined.
auto store_instruction =
FindInstruction(message_.store_instruction_descriptor(), ir_context);
if (!store_instruction) {
if (!store_instruction || store_instruction->opcode() != SpvOpStore) {
return false;
}

Expand Down
3 changes: 3 additions & 0 deletions test/fuzz/transformation_add_relaxed_decoration_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ TEST(TransformationAddRelaxedDecorationTest, BasicScenarios) {
// Invalid: 200 is not an id.
ASSERT_FALSE(TransformationAddRelaxedDecoration(200).IsApplicable(
context.get(), transformation_context));
// Invalid: 1 is not in a block.
ASSERT_FALSE(TransformationAddRelaxedDecoration(1).IsApplicable(
context.get(), transformation_context));
// Invalid: 27 is not in a dead block.
ASSERT_FALSE(TransformationAddRelaxedDecoration(27).IsApplicable(
context.get(), transformation_context));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,10 @@ TEST(TransformationReplaceCopyObjectWithStoreLoad, BasicScenarios) {
ASSERT_FALSE(transformation_invalid_4.IsApplicable(context.get(),
transformation_context));

// Invalid: initializer_id=15 is invalid.
// Invalid: initializer_id=15 has the wrong type relative to the OpCopyObject
// instruction.
auto transformation_invalid_5 = TransformationReplaceCopyObjectWithStoreLoad(
27, 30, SpvStorageClassPrivate, 15);
27, 30, SpvStorageClassFunction, 15);
ASSERT_FALSE(transformation_invalid_5.IsApplicable(context.get(),
transformation_context));

Expand Down
101 changes: 92 additions & 9 deletions test/fuzz/transformation_replace_load_store_with_copy_memory_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ TEST(TransformationReplaceLoadStoreWithCopyMemoryTest, BasicScenarios) {
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %4 "main"
OpEntryPoint Fragment %4 "main" %26 %28 %31 %33
OpExecutionMode %4 OriginUpperLeft
OpSource ESSL 310
OpName %4 "main"
Expand All @@ -37,6 +37,12 @@ TEST(TransformationReplaceLoadStoreWithCopyMemoryTest, BasicScenarios) {
OpName %14 "d"
OpName %18 "e"
OpName %20 "f"
OpName %26 "i1"
OpName %28 "i2"
OpName %31 "g1"
OpName %33 "g2"
OpDecorate %26 Location 0
OpDecorate %28 Location 1
%2 = OpTypeVoid
%3 = OpTypeFunction %2
%6 = OpTypeInt 32 1
Expand All @@ -49,6 +55,16 @@ TEST(TransformationReplaceLoadStoreWithCopyMemoryTest, BasicScenarios) {
%17 = OpTypePointer Function %16
%19 = OpConstant %16 2
%21 = OpConstant %16 3
%25 = OpTypePointer Output %6
%26 = OpVariable %25 Output
%27 = OpConstant %6 1
%28 = OpVariable %25 Output
%30 = OpTypePointer Private %6
%31 = OpVariable %30 Private
%32 = OpConstant %6 0
%33 = OpVariable %30 Private
%35 = OpTypeBool
%36 = OpConstantTrue %35
%4 = OpFunction %2 None %3
%5 = OpLabel
%8 = OpVariable %7 Function
Expand All @@ -70,6 +86,20 @@ TEST(TransformationReplaceLoadStoreWithCopyMemoryTest, BasicScenarios) {
OpStore %14 %23
%24 = OpLoad %16 %18
OpStore %20 %24
OpStore %26 %27
OpStore %28 %27
%29 = OpLoad %6 %26
OpMemoryBarrier %32 %32
OpStore %28 %29
OpStore %31 %32
OpStore %33 %32
%34 = OpLoad %6 %33
OpSelectionMerge %38 None
OpBranchConditional %36 %37 %38
%37 = OpLabel
OpStore %31 %34
OpBranch %38
%38 = OpLabel
OpReturn
OpFunctionEnd
)";
Expand All @@ -85,20 +115,29 @@ TEST(TransformationReplaceLoadStoreWithCopyMemoryTest, BasicScenarios) {
ASSERT_TRUE(IsValid(env, context.get()));

auto bad_instruction_descriptor_1 =
MakeInstructionDescriptor(5, SpvOpVariable, 0);
MakeInstructionDescriptor(11, SpvOpConstant, 0);

auto load_instruction_descriptor_1 =
MakeInstructionDescriptor(5, SpvOpLoad, 0);
MakeInstructionDescriptor(22, SpvOpLoad, 0);
auto load_instruction_descriptor_2 =
MakeInstructionDescriptor(5, SpvOpLoad, 1);
MakeInstructionDescriptor(23, SpvOpLoad, 0);
auto load_instruction_descriptor_3 =
MakeInstructionDescriptor(5, SpvOpLoad, 2);
MakeInstructionDescriptor(24, SpvOpLoad, 0);
auto load_instruction_descriptor_other_block =
MakeInstructionDescriptor(34, SpvOpLoad, 0);
auto load_instruction_descriptor_unsafe =
MakeInstructionDescriptor(29, SpvOpLoad, 0);

auto store_instruction_descriptor_1 =
MakeInstructionDescriptor(22, SpvOpStore, 0);
auto store_instruction_descriptor_2 =
MakeInstructionDescriptor(23, SpvOpStore, 0);
auto store_instruction_descriptor_3 =
MakeInstructionDescriptor(24, SpvOpStore, 0);
auto store_instruction_descriptor_other_block =
MakeInstructionDescriptor(37, SpvOpStore, 0);
auto store_instruction_descriptor_unsafe =
MakeInstructionDescriptor(29, SpvOpStore, 0);

// Bad: |load_instruction_descriptor| is incorrect.
auto transformation_bad_1 = TransformationReplaceLoadStoreWithCopyMemory(
Expand All @@ -118,13 +157,27 @@ TEST(TransformationReplaceLoadStoreWithCopyMemoryTest, BasicScenarios) {
ASSERT_FALSE(
transformation_bad_3.IsApplicable(context.get(), transformation_context));

// Bad: There is a interfering OpCopyMemory instruction between the OpLoad and
// the OpStore.
// Bad: There is an interfering OpCopyMemory instruction between the OpLoad
// and the OpStore.
auto transformation_bad_4 = TransformationReplaceLoadStoreWithCopyMemory(
load_instruction_descriptor_1, store_instruction_descriptor_1);
ASSERT_FALSE(
transformation_bad_4.IsApplicable(context.get(), transformation_context));

// Bad: There is an interfering OpMemoryBarrier instruction between the OpLoad
// and the OpStore.
auto transformation_bad_5 = TransformationReplaceLoadStoreWithCopyMemory(
load_instruction_descriptor_unsafe, store_instruction_descriptor_unsafe);
ASSERT_FALSE(
transformation_bad_5.IsApplicable(context.get(), transformation_context));

// Bad: OpLoad and OpStore instructions are in different blocks.
auto transformation_bad_6 = TransformationReplaceLoadStoreWithCopyMemory(
load_instruction_descriptor_other_block,
store_instruction_descriptor_other_block);
ASSERT_FALSE(
transformation_bad_6.IsApplicable(context.get(), transformation_context));

auto transformation_good_1 = TransformationReplaceLoadStoreWithCopyMemory(
load_instruction_descriptor_2, store_instruction_descriptor_2);
ASSERT_TRUE(transformation_good_1.IsApplicable(context.get(),
Expand All @@ -143,7 +196,7 @@ TEST(TransformationReplaceLoadStoreWithCopyMemoryTest, BasicScenarios) {
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %4 "main"
OpEntryPoint Fragment %4 "main" %26 %28 %31 %33
OpExecutionMode %4 OriginUpperLeft
OpSource ESSL 310
OpName %4 "main"
Expand All @@ -153,6 +206,12 @@ TEST(TransformationReplaceLoadStoreWithCopyMemoryTest, BasicScenarios) {
OpName %14 "d"
OpName %18 "e"
OpName %20 "f"
OpName %26 "i1"
OpName %28 "i2"
OpName %31 "g1"
OpName %33 "g2"
OpDecorate %26 Location 0
OpDecorate %28 Location 1
%2 = OpTypeVoid
%3 = OpTypeFunction %2
%6 = OpTypeInt 32 1
Expand All @@ -165,6 +224,16 @@ TEST(TransformationReplaceLoadStoreWithCopyMemoryTest, BasicScenarios) {
%17 = OpTypePointer Function %16
%19 = OpConstant %16 2
%21 = OpConstant %16 3
%25 = OpTypePointer Output %6
%26 = OpVariable %25 Output
%27 = OpConstant %6 1
%28 = OpVariable %25 Output
%30 = OpTypePointer Private %6
%31 = OpVariable %30 Private
%32 = OpConstant %6 0
%33 = OpVariable %30 Private
%35 = OpTypeBool
%36 = OpConstantTrue %35
%4 = OpFunction %2 None %3
%5 = OpLabel
%8 = OpVariable %7 Function
Expand All @@ -186,9 +255,23 @@ TEST(TransformationReplaceLoadStoreWithCopyMemoryTest, BasicScenarios) {
OpCopyMemory %14 %12
%24 = OpLoad %16 %18
OpCopyMemory %20 %18
OpStore %26 %27
OpStore %28 %27
%29 = OpLoad %6 %26
OpMemoryBarrier %32 %32
OpStore %28 %29
OpStore %31 %32
OpStore %33 %32
%34 = OpLoad %6 %33
OpSelectionMerge %38 None
OpBranchConditional %36 %37 %38
%37 = OpLabel
OpStore %31 %34
OpBranch %38
%38 = OpLabel
OpReturn
OpFunctionEnd
)";
)";
ASSERT_TRUE(IsEqual(env, after_transformations, context.get()));
}

Expand Down

0 comments on commit c20995e

Please sign in to comment.