diff --git a/source/val/validate_cfg.cpp b/source/val/validate_cfg.cpp index d401a2e7b..77e4f4f2f 100644 --- a/source/val/validate_cfg.cpp +++ b/source/val/validate_cfg.cpp @@ -839,6 +839,9 @@ spv_result_t StructuredControlFlowChecks( const auto* continue_target = next_inst.block(); if (header->id() != continue_id) { for (auto pred : *continue_target->predecessors()) { + if (!pred->structurally_reachable()) { + continue; + } // Ignore back-edges from within the continue construct. bool is_back_edge = false; for (auto back_edge : back_edges) { diff --git a/test/val/val_cfg_test.cpp b/test/val/val_cfg_test.cpp index 233aee645..d3b5e9020 100644 --- a/test/val/val_cfg_test.cpp +++ b/test/val/val_cfg_test.cpp @@ -5118,6 +5118,43 @@ OpFunctionEnd EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); } +TEST_F(ValidateCFG, StructurallyUnreachableContinuePredecessor) { + const std::string text = R"( + OpCapability Shader + OpMemoryModel Logical GLSL450 + OpEntryPoint Fragment %main "main" + OpExecutionMode %main OriginUpperLeft + OpSource ESSL 310 + OpName %main "main" + %void = OpTypeVoid + %3 = OpTypeFunction %void + %int = OpTypeInt 32 1 + %int_1 = OpConstant %int 1 + %int_n7 = OpConstant %int -7 + %bool = OpTypeBool + %main = OpFunction %void None %3 + %8 = OpLabel + OpBranch %9 + %9 = OpLabel + %10 = OpPhi %int %int_1 %8 %int_n7 %15 + %12 = OpSGreaterThan %bool %10 %int_n7 + OpLoopMerge %13 %15 None + OpBranchConditional %12 %14 %13 + %14 = OpLabel + OpBranch %15 + %15 = OpLabel + OpBranch %9 + %17 = OpLabel + OpBranch %15 + %13 = OpLabel + OpReturn + OpFunctionEnd +)"; + + CompileSuccessfully(text); + EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); +} + } // namespace } // namespace val } // namespace spvtools