Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

spirv-fuzz: Fix to TransformationDuplicateRegionWithSelection #3941

Merged
merged 2 commits into from
Oct 20, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions source/fuzz/fuzzer_pass_duplicate_regions_with_selections.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,9 +124,8 @@ void FuzzerPassDuplicateRegionsWithSelections::Apply() {
TransformationDuplicateRegionWithSelection(
GetFuzzerContext()->GetFreshId(), condition_id,
GetFuzzerContext()->GetFreshId(), entry_block->id(),
exit_block->id(), std::move(original_label_to_duplicate_label),
std::move(original_id_to_duplicate_id),
std::move(original_id_to_phi_id));
exit_block->id(), original_label_to_duplicate_label,
original_id_to_duplicate_id, original_id_to_phi_id);
MaybeApplyTransformation(transformation);
}
}
Expand Down
15 changes: 15 additions & 0 deletions source/fuzz/transformation_duplicate_region_with_selection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -589,6 +589,21 @@ void TransformationDuplicateRegionWithSelection::Apply(
}
});

opt::Instruction* merge_block_terminator = merge_block->terminator();
switch (merge_block_terminator->opcode()) {
case SpvOpReturnValue:
case SpvOpBranchConditional: {
uint32_t operand = merge_block_terminator->GetSingleWordInOperand(0);
if (original_id_to_phi_id.count(operand)) {
merge_block_terminator->SetInOperand(
0, {original_id_to_phi_id.at(operand)});
}
break;
}
default:
break;
}

// Insert the merge block after the |duplicated_exit_block| (the
// last duplicated block).
enclosing_function->InsertBasicBlockAfter(std::move(merge_block),
Expand Down
2 changes: 1 addition & 1 deletion source/fuzz/transformation_merge_function_returns.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -509,7 +509,7 @@ void TransformationMergeFunctionReturns::Apply(
{SPV_OPERAND_TYPE_LOOP_CONTROL, {SpvLoopControlMaskNone}}}));

// Add conditional branch:
// OpBranchConditional %true %block_after_entry %outer_header_id
// OpBranchConditional %true %block_after_entry %outer_header_id
// This will always branch to %block_after_entry, but it also creates a back
// edge for the loop (which is never traversed).
outer_loop_header->AddInstruction(MakeUnique<opt::Instruction>(
Expand Down
2 changes: 1 addition & 1 deletion test/fuzz/fuzzer_replayer_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1590,7 +1590,7 @@ const std::string kTestShader6 = R"(
%2 = OpFunction %132 None %133
%164 = OpLabel
%184 = OpLoad %15 %40
%213 = OpLoad %38 %41
%213 = OpLoad %38 %41
%216 = OpSampledImage %45 %184 %213
%217 = OpImageSampleImplicitLod %76 %216 %112 Bias %55
OpReturn
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ TEST(TransformationComputeDataSynonymFactClosureTest, DataSynonymFacts) {
// void main() {
// T myT = T(bool[5](true, false, true, false, true),
// mat4x2(vec2(1.0, 2.0), vec2(3.0, 4.0),
// vec2(5.0, 6.0), vec2(7.0, 8.0)),
// vec2(5.0, 6.0), vec2(7.0, 8.0)),
// S(10, uvec2(100u, 200u)));
// }

Expand Down
228 changes: 226 additions & 2 deletions test/fuzz/transformation_duplicate_region_with_selection_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1904,7 +1904,7 @@ TEST(TransformationDuplicateRegionWithSelectionTest,
%9 = OpConstant %6 0
%16 = OpConstant %6 100
%17 = OpTypeBool
%50 = OpConstantTrue %17
%50 = OpConstantTrue %17
%20 = OpConstant %6 1
%4 = OpFunction %2 None %3
%5 = OpLabel
Expand Down Expand Up @@ -1971,7 +1971,7 @@ TEST(TransformationDuplicateRegionWithSelectionTest,
%9 = OpConstant %6 0
%16 = OpConstant %6 100
%17 = OpTypeBool
%50 = OpConstantTrue %17
%50 = OpConstantTrue %17
%20 = OpConstant %6 1
%4 = OpFunction %2 None %3
%5 = OpLabel
Expand Down Expand Up @@ -2015,6 +2015,230 @@ TEST(TransformationDuplicateRegionWithSelectionTest,
ASSERT_TRUE(IsEqual(env, expected_shader, context.get()));
}

TEST(TransformationDuplicateRegionWithSelectionTest,
RegionExitIsOpBranchConditionalUsingBooleanDefinedInBlock) {
std::string shader = R"(
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %4 "main"
OpExecutionMode %4 OriginUpperLeft
OpSource ESSL 320
OpName %4 "main"
OpName %8 "i"
%2 = OpTypeVoid
%3 = OpTypeFunction %2
%6 = OpTypeInt 32 1
%7 = OpTypePointer Function %6
%9 = OpConstant %6 0
%16 = OpConstant %6 100
%17 = OpTypeBool
%50 = OpConstantTrue %17
%20 = OpConstant %6 1
%4 = OpFunction %2 None %3
%5 = OpLabel
%8 = OpVariable %7 Function
OpStore %8 %9
OpBranch %10
%10 = OpLabel
OpLoopMerge %12 %13 None
OpBranch %14
%14 = OpLabel
%15 = OpLoad %6 %8
%18 = OpSLessThan %17 %15 %16
OpBranchConditional %18 %11 %12
%11 = OpLabel
%19 = OpLoad %6 %8
%21 = OpIAdd %6 %19 %20
%70 = OpCopyObject %17 %50
OpStore %8 %21
OpBranchConditional %70 %13 %12
%13 = OpLabel
%22 = OpLoad %6 %8
%23 = OpIAdd %6 %22 %20
OpStore %8 %23
OpBranch %10
%12 = OpLabel
OpReturn
OpFunctionEnd
)";

const auto env = SPV_ENV_UNIVERSAL_1_4;
const auto consumer = nullptr;
const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
spvtools::ValidatorOptions validator_options;
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
kConsoleMessageConsumer));
TransformationContext transformation_context(
MakeUnique<FactManager>(context.get()), validator_options);
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
kConsoleMessageConsumer));

TransformationDuplicateRegionWithSelection transformation_good_1 =
TransformationDuplicateRegionWithSelection(
600, 50, 601, 11, 11, {{11, 602}}, {{19, 603}, {21, 604}, {70, 608}},
{{19, 605}, {21, 606}, {70, 607}});
ASSERT_TRUE(transformation_good_1.IsApplicable(context.get(),
transformation_context));
ApplyAndCheckFreshIds(transformation_good_1, context.get(),
&transformation_context);
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
kConsoleMessageConsumer));

std::string expected_shader = R"(
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %4 "main"
OpExecutionMode %4 OriginUpperLeft
OpSource ESSL 320
OpName %4 "main"
OpName %8 "i"
%2 = OpTypeVoid
%3 = OpTypeFunction %2
%6 = OpTypeInt 32 1
%7 = OpTypePointer Function %6
%9 = OpConstant %6 0
%16 = OpConstant %6 100
%17 = OpTypeBool
%50 = OpConstantTrue %17
%20 = OpConstant %6 1
%4 = OpFunction %2 None %3
%5 = OpLabel
%8 = OpVariable %7 Function
OpStore %8 %9
OpBranch %10
%10 = OpLabel
OpLoopMerge %12 %13 None
OpBranch %14
%14 = OpLabel
%15 = OpLoad %6 %8
%18 = OpSLessThan %17 %15 %16
OpBranchConditional %18 %600 %12
%600 = OpLabel
OpSelectionMerge %601 None
OpBranchConditional %50 %11 %602
%11 = OpLabel
%19 = OpLoad %6 %8
%21 = OpIAdd %6 %19 %20
%70 = OpCopyObject %17 %50
OpStore %8 %21
OpBranch %601
%602 = OpLabel
%603 = OpLoad %6 %8
%604 = OpIAdd %6 %603 %20
%608 = OpCopyObject %17 %50
OpStore %8 %604
OpBranch %601
%601 = OpLabel
%605 = OpPhi %6 %19 %11 %603 %602
%606 = OpPhi %6 %21 %11 %604 %602
%607 = OpPhi %17 %70 %11 %608 %602
OpBranchConditional %607 %13 %12
%13 = OpLabel
%22 = OpLoad %6 %8
%23 = OpIAdd %6 %22 %20
OpStore %8 %23
OpBranch %10
%12 = OpLabel
OpReturn
OpFunctionEnd
)";

ASSERT_TRUE(IsEqual(env, expected_shader, context.get()));
}

TEST(TransformationDuplicateRegionWithSelectionTest,
RegionExitUsesOpReturnValueWithIdDefinedInRegion) {
std::string shader = R"(
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %4 "main"
OpExecutionMode %4 OriginUpperLeft
OpSource ESSL 320
%2 = OpTypeVoid
%3 = OpTypeFunction %2
%6 = OpTypeInt 32 1
%7 = OpTypeFunction %6
%10 = OpConstant %6 2
%30 = OpTypeBool
%31 = OpConstantTrue %30
%4 = OpFunction %2 None %3
%5 = OpLabel
%13 = OpFunctionCall %6 %8
OpReturn
OpFunctionEnd
%8 = OpFunction %6 None %7
%9 = OpLabel
OpBranch %20
%20 = OpLabel
%21 = OpCopyObject %6 %10
OpReturnValue %21
OpFunctionEnd
)";

const auto env = SPV_ENV_UNIVERSAL_1_4;
const auto consumer = nullptr;
const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
spvtools::ValidatorOptions validator_options;
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
kConsoleMessageConsumer));
TransformationContext transformation_context(
MakeUnique<FactManager>(context.get()), validator_options);
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
kConsoleMessageConsumer));

TransformationDuplicateRegionWithSelection transformation_good_1 =
TransformationDuplicateRegionWithSelection(
600, 31, 601, 20, 20, {{20, 602}}, {{21, 603}}, {{21, 605}});
ASSERT_TRUE(transformation_good_1.IsApplicable(context.get(),
transformation_context));
ApplyAndCheckFreshIds(transformation_good_1, context.get(),
&transformation_context);
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
kConsoleMessageConsumer));

std::string expected_shader = R"(
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %4 "main"
OpExecutionMode %4 OriginUpperLeft
OpSource ESSL 320
%2 = OpTypeVoid
%3 = OpTypeFunction %2
%6 = OpTypeInt 32 1
%7 = OpTypeFunction %6
%10 = OpConstant %6 2
%30 = OpTypeBool
%31 = OpConstantTrue %30
%4 = OpFunction %2 None %3
%5 = OpLabel
%13 = OpFunctionCall %6 %8
OpReturn
OpFunctionEnd
%8 = OpFunction %6 None %7
%9 = OpLabel
OpBranch %600
%600 = OpLabel
OpSelectionMerge %601 None
OpBranchConditional %31 %20 %602
%20 = OpLabel
%21 = OpCopyObject %6 %10
OpBranch %601
%602 = OpLabel
%603 = OpCopyObject %6 %10
OpBranch %601
%601 = OpLabel
%605 = OpPhi %6 %21 %20 %603 %602
OpReturnValue %605
OpFunctionEnd
)";

ASSERT_TRUE(IsEqual(env, expected_shader, context.get()));
}

} // namespace
} // namespace fuzz
} // namespace spvtools