aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/fuzz/transformation_add_function.cpp20
-rw-r--r--test/fuzz/transformation_add_function_test.cpp55
2 files changed, 21 insertions, 54 deletions
diff --git a/source/fuzz/transformation_add_function.cpp b/source/fuzz/transformation_add_function.cpp
index 380d59c4..66b379ef 100644
--- a/source/fuzz/transformation_add_function.cpp
+++ b/source/fuzz/transformation_add_function.cpp
@@ -488,7 +488,20 @@ bool TransformationAddFunction::TryToAddLoopLimiters(
// move on from this loop.
continue;
}
- auto back_edge_block = ir_context->cfg()->block(back_edge_block_id);
+
+ // If the loop's merge block is unreachable, then there are no constraints
+ // on where the merge block appears in relation to the blocks of the loop.
+ // This means we need to be careful when adding a branch from the back-edge
+ // block to the merge block: the branch might make the loop merge reachable,
+ // and it might then be dominated by the loop header and possibly by other
+ // blocks in the loop. Since a block needs to appear before those blocks it
+ // strictly dominates, this could make the module invalid. To avoid this
+ // problem we bail out in the case where the loop header does not dominate
+ // the loop merge.
+ if (!ir_context->GetDominatorAnalysis(added_function)
+ ->Dominates(loop_header->id(), loop_header->MergeBlockId())) {
+ return false;
+ }
// Go through the sequence of loop limiter infos and find the one
// corresponding to this loop.
@@ -560,6 +573,7 @@ bool TransformationAddFunction::TryToAddLoopLimiters(
// %t4 = OpLogicalOr %bool %c %t3
// OpBranchConditional %t4 %loop_merge %loop_header
+ auto back_edge_block = ir_context->cfg()->block(back_edge_block_id);
auto back_edge_block_terminator = back_edge_block->terminator();
bool compare_using_greater_than_equal;
if (back_edge_block_terminator->opcode() == SpvOpBranch) {
@@ -675,10 +689,6 @@ bool TransformationAddFunction::TryToAddLoopLimiters(
}
// Add the new edge, by changing OpBranch to OpBranchConditional.
- // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3162): This
- // could be a problem if the merge block was originally unreachable: it
- // might now be dominated by other blocks that it appears earlier than in
- // the module.
back_edge_block_terminator->SetOpcode(SpvOpBranchConditional);
back_edge_block_terminator->SetInOperands(opt::Instruction::OperandList(
{{SPV_OPERAND_TYPE_ID, {loop_limiter_info.compare_id()}},
diff --git a/test/fuzz/transformation_add_function_test.cpp b/test/fuzz/transformation_add_function_test.cpp
index bbd915b0..e0963484 100644
--- a/test/fuzz/transformation_add_function_test.cpp
+++ b/test/fuzz/transformation_add_function_test.cpp
@@ -2246,7 +2246,7 @@ TEST(TransformationAddFunctionTest, LoopLimitersHeaderIsBackEdgeBlock) {
ASSERT_TRUE(IsEqual(env, expected, context.get()));
}
-TEST(TransformationAddFunctionTest, InfiniteLoop1) {
+TEST(TransformationAddFunctionTest, InfiniteLoop) {
std::string shader = R"(
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
@@ -2337,54 +2337,11 @@ TEST(TransformationAddFunctionTest, InfiniteLoop1) {
loop_limiter_info.set_logical_op_id(105);
TransformationAddFunction add_livesafe_function(instructions, 100, 32,
{loop_limiter_info}, 0, {});
- ASSERT_TRUE(add_livesafe_function.IsApplicable(context.get(),
- transformation_context));
- add_livesafe_function.Apply(context.get(), &transformation_context);
- ASSERT_TRUE(IsValid(env, context.get()));
- std::string expected = R"(
- OpCapability Shader
- %1 = OpExtInstImport "GLSL.std.450"
- OpMemoryModel Logical GLSL450
- OpEntryPoint Fragment %4 "main"
- OpExecutionMode %4 OriginUpperLeft
- OpSource ESSL 310
- %2 = OpTypeVoid
- %3 = OpTypeFunction %2
- %8 = OpTypeInt 32 1
- %9 = OpTypePointer Function %8
- %11 = OpConstant %8 0
- %18 = OpConstant %8 10
- %19 = OpTypeBool
- %26 = OpConstantTrue %19
- %27 = OpConstantFalse %19
- %28 = OpTypeInt 32 0
- %29 = OpTypePointer Function %28
- %30 = OpConstant %28 0
- %31 = OpConstant %28 1
- %32 = OpConstant %28 5
- %22 = OpConstant %8 1
- %4 = OpFunction %2 None %3
- %5 = OpLabel
- OpReturn
- OpFunctionEnd
- %6 = OpFunction %2 None %3
- %7 = OpLabel
- %100 = OpVariable %29 Function %30
- %10 = OpVariable %9 Function
- OpStore %10 %11
- OpBranch %12
- %12 = OpLabel
- %102 = OpLoad %28 %100
- %103 = OpIAdd %28 %102 %31
- OpStore %100 %103
- %104 = OpUGreaterThanEqual %19 %102 %32
- OpLoopMerge %14 %12 None
- OpBranchConditional %104 %14 %12
- %14 = OpLabel
- OpReturn
- OpFunctionEnd
- )";
- ASSERT_TRUE(IsEqual(env, expected, context.get()));
+
+ // To make sure the loop's merge block is reachable, it must be dominated by
+ // the loop header.
+ ASSERT_FALSE(add_livesafe_function.IsApplicable(context.get(),
+ transformation_context));
}
TEST(TransformationAddFunctionTest, UnreachableContinueConstruct) {