aboutsummaryrefslogtreecommitdiff
path: root/test/val/val_cfg_test.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'test/val/val_cfg_test.cpp')
-rw-r--r--test/val/val_cfg_test.cpp191
1 files changed, 76 insertions, 115 deletions
diff --git a/test/val/val_cfg_test.cpp b/test/val/val_cfg_test.cpp
index 76477468..ede51a9e 100644
--- a/test/val/val_cfg_test.cpp
+++ b/test/val/val_cfg_test.cpp
@@ -637,41 +637,6 @@ TEST_P(ValidateCFG, BranchToBlockInOtherFunctionBad) {
" %Main = OpFunction %void None %9\n"));
}
-TEST_P(ValidateCFG, HeaderDoesntDominatesMergeBad) {
- bool is_shader = GetParam() == SpvCapabilityShader;
- Block entry("entry");
- Block head("head", SpvOpBranchConditional);
- Block f("f");
- Block merge("merge", SpvOpReturn);
-
- head.SetBody("%cond = OpSLessThan %boolt %one %two\n");
-
- if (is_shader) head.AppendBody("OpSelectionMerge %merge None\n");
-
- std::string str = GetDefaultHeader(GetParam()) +
- nameOps("head", "merge", std::make_pair("func", "Main")) +
- types_consts() +
- "%func = OpFunction %voidt None %funct\n";
-
- str += entry >> merge;
- str += head >> std::vector<Block>({merge, f});
- str += f >> merge;
- str += merge;
- str += "OpFunctionEnd\n";
-
- CompileSuccessfully(str);
- if (is_shader) {
- ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
- EXPECT_THAT(
- getDiagnosticString(),
- MatchesRegex("The selection construct with the selection header "
- ".\\[%head\\] does not dominate the merge block "
- ".\\[%merge\\]\n %merge = OpLabel\n"));
- } else {
- ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
- }
-}
-
TEST_P(ValidateCFG, HeaderDoesntStrictlyDominateMergeBad) {
// If a merge block is reachable, then it must be strictly dominated by
// its header block.
@@ -698,7 +663,8 @@ TEST_P(ValidateCFG, HeaderDoesntStrictlyDominateMergeBad) {
EXPECT_THAT(
getDiagnosticString(),
MatchesRegex("The selection construct with the selection header "
- ".\\[%head\\] does not strictly dominate the merge block "
+ ".\\[%head\\] does not strictly structurally dominate the "
+ "merge block "
".\\[%head\\]\n %head = OpLabel\n"));
} else {
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()) << str;
@@ -907,16 +873,7 @@ std::string GetUnreachableContinueUnreachableLoopInst(SpvCapability cap) {
TEST_P(ValidateCFG, UnreachableContinueUnreachableLoopInst) {
CompileSuccessfully(GetUnreachableContinueUnreachableLoopInst(GetParam()));
- if (GetParam() == SpvCapabilityShader) {
- // Shader causes additional structured CFG checks that cause a failure.
- ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
- EXPECT_THAT(getDiagnosticString(),
- HasSubstr("Back-edges (1[%branch] -> 3[%target]) can only be "
- "formed between a block and a loop header."));
-
- } else {
- ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
- }
+ ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
}
std::string GetUnreachableMergeWithComplexBody(SpvCapability cap) {
@@ -1070,12 +1027,10 @@ std::string GetUnreachableContinueWithBranchUse(SpvCapability cap) {
std::string header = GetDefaultHeader(cap);
Block entry("entry");
- Block foo("foo", SpvOpBranch);
Block branch("branch", SpvOpBranch);
Block merge("merge", SpvOpReturn);
Block target("target", SpvOpBranch);
- foo >> target;
target >> branch;
entry.AppendBody("%placeholder = OpVariable %intptrt Function\n");
@@ -1092,7 +1047,6 @@ std::string GetUnreachableContinueWithBranchUse(SpvCapability cap) {
str += branch >> std::vector<Block>({merge});
str += merge;
str += target;
- str += foo;
str += "OpFunctionEnd\n";
return str;
@@ -1156,6 +1110,7 @@ std::string GetUnreachableMergeAndContinue(SpvCapability cap) {
Block body("body", SpvOpBranchConditional);
Block t("t", SpvOpReturn);
Block f("f", SpvOpReturn);
+ Block pre_target("pre_target", SpvOpBranch);
target >> branch;
body.SetBody("%cond = OpSLessThan %boolt %one %two\n");
@@ -1163,10 +1118,10 @@ std::string GetUnreachableMergeAndContinue(SpvCapability cap) {
std::string str = header;
if (cap == SpvCapabilityShader) {
branch.AppendBody("OpLoopMerge %merge %target None\n");
- body.AppendBody("OpSelectionMerge %target None\n");
+ body.AppendBody("OpSelectionMerge %pre_target None\n");
}
- str += nameOps("branch", "merge", "target", "body", "t", "f",
+ str += nameOps("branch", "merge", "pre_target", "target", "body", "t", "f",
std::make_pair("func", "Main"));
str += types_consts();
str += "%func = OpFunction %voidt None %funct\n";
@@ -1176,6 +1131,7 @@ std::string GetUnreachableMergeAndContinue(SpvCapability cap) {
str += t;
str += f;
str += merge;
+ str += pre_target >> target;
str += target;
str += "OpFunctionEnd\n";
@@ -1296,9 +1252,10 @@ TEST_P(ValidateCFG, NestedLoops) {
loop2.SetBody("OpLoopMerge %loop2_merge %loop2 None\n");
}
- std::string str = GetDefaultHeader(GetParam()) +
- nameOps("loop2", "loop2_merge") + types_consts() +
- "%func = OpFunction %voidt None %funct\n";
+ std::string str =
+ GetDefaultHeader(GetParam()) +
+ nameOps("loop1", "loop1_cont_break_block", "loop2", "loop2_merge") +
+ types_consts() + "%func = OpFunction %voidt None %funct\n";
str += entry >> loop1;
str += loop1 >> loop1_cont_break_block;
@@ -1389,11 +1346,13 @@ TEST_P(ValidateCFG, BackEdgeBlockDoesntPostDominateContinueTargetBad) {
CompileSuccessfully(str);
if (GetParam() == SpvCapabilityShader) {
ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
- EXPECT_THAT(getDiagnosticString(),
- MatchesRegex("The continue construct with the continue target "
- ".\\[%loop1_cont\\] is not post dominated by the "
- "back-edge block .\\[%be_block\\]\n"
- " %be_block = OpLabel\n"));
+ EXPECT_THAT(
+ getDiagnosticString(),
+ MatchesRegex(
+ "The continue construct with the continue target "
+ ".\\[%loop1_cont\\] is not structurally post dominated by the "
+ "back-edge block .\\[%be_block\\]\n"
+ " %be_block = OpLabel\n"));
} else {
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
}
@@ -1529,10 +1488,11 @@ TEST_P(ValidateCFG, ContinueTargetMustBePostDominatedByBackEdge) {
if (is_shader) {
ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
EXPECT_THAT(getDiagnosticString(),
- MatchesRegex("The continue construct with the continue target "
- ".\\[%cheader\\] is not post dominated by the "
- "back-edge block .\\[%be_block\\]\n"
- " %be_block = OpLabel\n"));
+ MatchesRegex(
+ "The continue construct with the continue target "
+ ".\\[%cheader\\] is not structurally post dominated by the "
+ "back-edge block .\\[%be_block\\]\n"
+ " %be_block = OpLabel\n"));
} else {
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
}
@@ -1561,11 +1521,12 @@ TEST_P(ValidateCFG, BranchOutOfConstructToMergeBad) {
CompileSuccessfully(str);
if (is_shader) {
ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
- EXPECT_THAT(getDiagnosticString(),
- MatchesRegex("The continue construct with the continue target "
- ".\\[%loop\\] is not post dominated by the "
- "back-edge block .\\[%cont\\]\n"
- " %cont = OpLabel\n"))
+ EXPECT_THAT(
+ getDiagnosticString(),
+ MatchesRegex("The continue construct with the continue target "
+ ".\\[%loop\\] is not structurally post dominated by the "
+ "back-edge block .\\[%cont\\]\n"
+ " %cont = OpLabel\n"))
<< str;
} else {
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
@@ -1597,11 +1558,12 @@ TEST_P(ValidateCFG, BranchOutOfConstructBad) {
CompileSuccessfully(str);
if (is_shader) {
ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
- EXPECT_THAT(getDiagnosticString(),
- MatchesRegex("The continue construct with the continue target "
- ".\\[%loop\\] is not post dominated by the "
- "back-edge block .\\[%cont\\]\n"
- " %cont = OpLabel\n"));
+ EXPECT_THAT(
+ getDiagnosticString(),
+ MatchesRegex("The continue construct with the continue target "
+ ".\\[%loop\\] is not structurally post dominated by the "
+ "back-edge block .\\[%cont\\]\n"
+ " %cont = OpLabel\n"));
} else {
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
}
@@ -1824,40 +1786,6 @@ TEST_P(ValidateCFG, SingleLatchBlockMultipleBranchesToLoopHeader) {
<< str << getDiagnosticString();
}
-TEST_P(ValidateCFG, SingleLatchBlockHeaderContinueTargetIsItselfGood) {
- // This test case ensures we don't count a Continue Target from a loop
- // header to itself as a self-loop when computing back edges.
- // Also, it detects that there is an edge from %latch to the pseudo-exit
- // node, rather than from %loop. In particular, it detects that we
- // have used the *reverse* textual order of blocks when computing
- // predecessor traversal roots.
- bool is_shader = GetParam() == SpvCapabilityShader;
- Block entry("entry");
- Block loop("loop");
- Block latch("latch");
- Block merge("merge", SpvOpReturn);
-
- entry.SetBody("%cond = OpSLessThan %boolt %one %two\n");
- if (is_shader) {
- loop.SetBody("OpLoopMerge %merge %loop None\n");
- }
-
- std::string str = GetDefaultHeader(GetParam()) +
- nameOps("entry", "loop", "latch", "merge") +
- types_consts() +
- "%func = OpFunction %voidt None %funct\n";
-
- str += entry >> loop;
- str += loop >> latch;
- str += latch >> loop;
- str += merge;
- str += "OpFunctionEnd";
-
- CompileSuccessfully(str);
- EXPECT_EQ(SPV_SUCCESS, ValidateInstructions())
- << str << getDiagnosticString();
-}
-
// Unit test to check the case where a basic block is the entry block of 2
// different constructs. In this case, the basic block is the entry block of a
// continue construct as well as a selection construct. See issue# 517 for more
@@ -2872,8 +2800,8 @@ OpFunctionEnd
CompileSuccessfully(text);
EXPECT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
EXPECT_THAT(getDiagnosticString(),
- HasSubstr("block <ID> 9 branches to the loop construct, but not "
- "to the loop header <ID> 7"));
+ HasSubstr("Back-edges (10[%10] -> 9[%9]) can only be formed "
+ "between a block and a loop header"));
}
TEST_F(ValidateCFG, LoopMergeMergeBlockNotLabel) {
@@ -3275,9 +3203,10 @@ OpFunctionEnd
CompileSuccessfully(text);
EXPECT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
- EXPECT_THAT(getDiagnosticString(),
- HasSubstr("block <ID> 13[%13] exits the selection headed by <ID> "
- "9[%9], but not via a structured exit"));
+ EXPECT_THAT(
+ getDiagnosticString(),
+ HasSubstr("The continue construct with the continue target 9[%9] is not "
+ "structurally post dominated by the back-edge block 13[%13]"));
}
TEST_F(ValidateCFG, BreakFromSwitch) {
@@ -4285,9 +4214,11 @@ TEST_F(ValidateCFG, StructuredSelections_RegisterBothTrueAndFalse) {
CompileSuccessfully(text);
EXPECT_NE(SPV_SUCCESS, ValidateInstructions());
- EXPECT_THAT(getDiagnosticString(),
- HasSubstr("The selection construct with the selection header "
- "8[%8] does not dominate the merge block 10[%10]\n"));
+ EXPECT_THAT(
+ getDiagnosticString(),
+ HasSubstr(
+ "The selection construct with the selection header "
+ "8[%8] does not structurally dominate the merge block 10[%10]\n"));
}
TEST_F(ValidateCFG, UnreachableIsStaticallyReachable) {
@@ -4624,6 +4555,36 @@ OpFunctionEnd
"must be different labels"));
}
+TEST_F(ValidateCFG, BadBackEdgeUnreachableContinue) {
+ const std::string text = R"(
+OpCapability Shader
+OpCapability Linkage
+OpMemoryModel Logical GLSL450
+%1 = OpTypeVoid
+%2 = OpTypeFunction %1
+%3 = OpFunction %1 None %2
+%4 = OpLabel
+OpBranch %5
+%5 = OpLabel
+OpLoopMerge %6 %7 None
+OpBranch %8
+%8 = OpLabel
+OpBranch %5
+%7 = OpLabel
+OpUnreachable
+%6 = OpLabel
+OpUnreachable
+OpFunctionEnd
+)";
+
+ CompileSuccessfully(text);
+ EXPECT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
+ EXPECT_THAT(
+ getDiagnosticString(),
+ HasSubstr("The continue construct with the continue target 7[%7] "
+ "does not structurally dominate the back-edge block 8[%8]"));
+}
+
} // namespace
} // namespace val
} // namespace spvtools