spirv-fuzz: Handle dead blocks in TransformationEquationInstruction (#3933)

Fixes #3926.
This commit is contained in:
Alastair Donaldson 2020-10-19 17:32:56 +01:00 committed by GitHub
parent 6cdae9da72
commit cd1d3b6e0c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 66 additions and 4 deletions

View File

@ -50,8 +50,8 @@ bool TransformationEquationInstruction::IsApplicable(
if (!insert_before) {
return false;
}
// The input ids must all exist, not be OpUndef, and be available before this
// instruction.
// The input ids must all exist, not be OpUndef, not be irrelevant, and be
// available before this instruction.
for (auto id : message_.in_operand_id()) {
auto inst = ir_context->get_def_use_mgr()->GetDef(id);
if (!inst) {
@ -92,8 +92,13 @@ void TransformationEquationInstruction::Apply(
ir_context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
transformation_context->GetFactManager()->AddFactIdEquation(
message_.fresh_id(), static_cast<SpvOp>(message_.opcode()), rhs_id);
// Add an equation fact as long as the result id is not irrelevant (it could
// be if we are inserting into a dead block).
if (!transformation_context->GetFactManager()->IdIsIrrelevant(
message_.fresh_id())) {
transformation_context->GetFactManager()->AddFactIdEquation(
message_.fresh_id(), static_cast<SpvOp>(message_.opcode()), rhs_id);
}
}
protobufs::Transformation TransformationEquationInstruction::ToMessage() const {

View File

@ -1618,6 +1618,63 @@ TEST(TransformationEquationInstructionTest, HandlesIrrelevantIds) {
transformation.IsApplicable(context.get(), transformation_context));
}
TEST(TransformationEquationInstructionTest, HandlesDeadBlock) {
std::string shader = R"(
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %12 "main"
OpExecutionMode %12 OriginUpperLeft
OpSource ESSL 310
%2 = OpTypeVoid
%3 = OpTypeFunction %2
%6 = OpTypeInt 32 1
%30 = OpTypeVector %6 3
%15 = OpConstant %6 24
%16 = OpConstant %6 37
%31 = OpConstantComposite %30 %15 %16 %15
%33 = OpTypeBool
%32 = OpConstantTrue %33
%12 = OpFunction %2 None %3
%13 = OpLabel
OpSelectionMerge %40 None
OpBranchConditional %32 %40 %41
%41 = OpLabel
OpBranch %40
%40 = OpLabel
OpReturn
OpFunctionEnd
)";
const auto env = SPV_ENV_UNIVERSAL_1_3;
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);
transformation_context.GetFactManager()->AddFactBlockIsDead(41);
TransformationEquationInstruction transformation1(
14, SpvOpIAdd, {15, 16},
MakeInstructionDescriptor(13, SpvOpSelectionMerge, 0));
// No synonym is created since block is dead.
TransformationEquationInstruction transformation2(
100, SpvOpISub, {14, 16}, MakeInstructionDescriptor(41, SpvOpBranch, 0));
ASSERT_TRUE(
transformation1.IsApplicable(context.get(), transformation_context));
ApplyAndCheckFreshIds(transformation1, context.get(),
&transformation_context);
ASSERT_TRUE(
transformation2.IsApplicable(context.get(), transformation_context));
ApplyAndCheckFreshIds(transformation2, context.get(),
&transformation_context);
ASSERT_FALSE(transformation_context.GetFactManager()->IsSynonymous(
MakeDataDescriptor(100, {}), MakeDataDescriptor(15, {})));
}
} // namespace
} // namespace fuzz
} // namespace spvtools