mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2025-01-12 01:20:05 +00:00
spirv-fuzz: Fix OutlineFunction in presence of unreachable blocks (#4308)
This change prevents TransformationOutlineFunction from outlining a region of blocks if some block in the region has an unreachable predecessor. This avoids a bug whereby the region would be outlined, and the unreachable predecessors would be left behind, referring to blocks that are no longer in the function.
This commit is contained in:
parent
9646c733e9
commit
0861a8fa21
@ -175,6 +175,19 @@ bool TransformationOutlineFunction::IsApplicable(
|
||||
// This is achieved by going through every block in the function that contains
|
||||
// the region.
|
||||
for (auto& block : *entry_block->GetParent()) {
|
||||
if (region_set.count(&block) != 0) {
|
||||
// The block is in the region. Check that it does not have any unreachable
|
||||
// predecessors. If it does, then we do not regard the region as single-
|
||||
// entry-single-exit and hence do not outline it.
|
||||
for (auto pred : ir_context->cfg()->preds(block.id())) {
|
||||
if (!fuzzerutil::BlockIsReachableInItsFunction(
|
||||
ir_context, ir_context->cfg()->block(pred))) {
|
||||
// The predecessor is unreachable.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (&block == exit_block) {
|
||||
// It is OK (and typically expected) for the exit block of the region to
|
||||
// have successors outside the region.
|
||||
|
@ -3207,6 +3207,45 @@ TEST(TransformationOutlineFunctionTest, Miscellaneous4) {
|
||||
ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
|
||||
}
|
||||
|
||||
TEST(TransformationOutlineFunctionTest, NoOutlineWithUnreachableBlocks) {
|
||||
// This checks that outlining will not be performed if a node in the region
|
||||
// has an unreachable predecessor.
|
||||
|
||||
std::string shader = R"(
|
||||
OpCapability Shader
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %4 "main"
|
||||
OpExecutionMode %4 OriginUpperLeft
|
||||
OpSource ESSL 310
|
||||
OpName %4 "main"
|
||||
%2 = OpTypeVoid
|
||||
%3 = OpTypeFunction %2
|
||||
%4 = OpFunction %2 None %3
|
||||
%7 = OpLabel
|
||||
OpBranch %5
|
||||
%5 = OpLabel
|
||||
OpReturn
|
||||
%6 = OpLabel
|
||||
OpBranch %5
|
||||
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);
|
||||
TransformationOutlineFunction transformation(5, 5, /* not relevant */ 200,
|
||||
100, 101, 102, 103,
|
||||
/* not relevant */ 201, {}, {});
|
||||
ASSERT_FALSE(
|
||||
transformation.IsApplicable(context.get(), transformation_context));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace fuzz
|
||||
} // namespace spvtools
|
||||
|
Loading…
Reference in New Issue
Block a user