Squashed 'third_party/SPIRV-Tools/' changes from 7b8f00f00a..43c99b5ee0
43c99b5ee0 Roll external/spirv-headers/ 47f2465ee..1d31a1004 (13 commits) (#5012)
235182cfee Fix use of invalid analysis (#5013)
9c6a925c87 Fix infinite loop in validator (#5006)
git-subtree-dir: third_party/SPIRV-Tools
git-subtree-split: 43c99b5ee087704a5ae0909d0ce7be3eff416905
Change-Id: Iccccf7fd25f76cfa20c2ea99f3f6bce8a4847ffc
diff --git a/DEPS b/DEPS
index a134582..80b67dc 100644
--- a/DEPS
+++ b/DEPS
@@ -6,7 +6,7 @@
'effcee_revision': '35912e1b7778ec2ddcff7e7188177761539e59e0',
'googletest_revision': 'd9bb8412d60b993365abb53f00b6dad9b2c01b62',
're2_revision': 'd2836d1b1c34c4e330a85a1006201db474bf2c8a',
- 'spirv_headers_revision': '47f2465ee3e78ec5ec38f00b2c405d9475797228',
+ 'spirv_headers_revision': '1d31a100405cf8783ca7a31e31cdd727c9fc54c3',
}
deps = {
diff --git a/source/opt/block_merge_util.cpp b/source/opt/block_merge_util.cpp
index a893ab5..fe23e36 100644
--- a/source/opt/block_merge_util.cpp
+++ b/source/opt/block_merge_util.cpp
@@ -171,6 +171,11 @@
// sbi must follow bi in func's ordering.
assert(sbi != func->end());
+ if (sbi->tail()->opcode() == spv::Op::OpSwitch &&
+ sbi->MergeBlockIdIfAny() != 0) {
+ context->InvalidateAnalyses(IRContext::Analysis::kAnalysisStructuredCFG);
+ }
+
// Update the inst-to-block mapping for the instructions in sbi.
for (auto& inst : *sbi) {
context->set_instr_block(&inst, &*bi);
diff --git a/source/val/construct.cpp b/source/val/construct.cpp
index 1b6a54f..1ca81d4 100644
--- a/source/val/construct.cpp
+++ b/source/val/construct.cpp
@@ -167,7 +167,9 @@
if ((use.first->opcode() == spv::Op::OpLoopMerge ||
use.first->opcode() == spv::Op::OpSelectionMerge) &&
use.second == 1 &&
- use.first->block()->structurally_dominates(*block)) {
+ use.first->block()->structurally_dominates(*block) &&
+ // A header likely declared itself as its merge.
+ use.first->block() != block) {
return use.first->block();
}
}
diff --git a/source/val/validate_cfg.cpp b/source/val/validate_cfg.cpp
index 06e4d67..24d2416 100644
--- a/source/val/validate_cfg.cpp
+++ b/source/val/validate_cfg.cpp
@@ -752,6 +752,7 @@
_.getIdName(merge->id()),
"does not structurally dominate");
}
+
// If it's really a merge block for a selection or loop, then it must be
// *strictly* structrually dominated by the header.
if (construct.ExitBlockIsMergeBlock() && (header == merge)) {
diff --git a/test/opt/block_merge_test.cpp b/test/opt/block_merge_test.cpp
index 6129bb2..57c5061 100644
--- a/test/opt/block_merge_test.cpp
+++ b/test/opt/block_merge_test.cpp
@@ -1287,6 +1287,39 @@
EXPECT_EQ(opt::Pass::Status::SuccessWithoutChange, std::get<1>(result));
}
+TEST_F(BlockMergeTest, RebuildStructuredCFG) {
+ const std::string text = R"(
+; CHECK: = OpFunction
+; CHECK-NEXT: [[entry:%\w+]] = OpLabel
+; CHECK-NEXT: OpSelectionMerge [[merge:%\w+]] None
+; CHECK-NEXT: OpSwitch {{%\w+}} [[merge]] 0 [[other:%\w+]]
+; CHECK [[other]] = OpLabel
+; CHECK: OpBranch [[merge]]
+; CHECK [[merge]] = OpLabel
+OpCapability Shader
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %main "main"
+OpExecutionMode %main LocalSize 1 1 1
+%void = OpTypeVoid
+%int = OpTypeInt 32 0
+%int_1 = OpConstant %int 1
+%void_fn = OpTypeFunction %void
+%main = OpFunction %void None %void_fn
+%entry = OpLabel
+OpBranch %switch
+%switch = OpLabel
+OpSelectionMerge %merge None
+OpSwitch %int_1 %merge 0 %other
+%other = OpLabel
+OpBranch %merge
+%merge = OpLabel
+OpReturn
+OpFunctionEnd
+)";
+
+ SinglePassRunAndMatch<BlockMergePass>(text, true);
+}
+
// TODO(greg-lunarg): Add tests to verify handling of these cases:
//
// More complex control flow
diff --git a/test/val/val_cfg_test.cpp b/test/val/val_cfg_test.cpp
index d2edec1..561e817 100644
--- a/test/val/val_cfg_test.cpp
+++ b/test/val/val_cfg_test.cpp
@@ -4630,6 +4630,50 @@
"blocks but the standard requires exactly one"));
}
+TEST_F(ValidateCFG, BadSwitch) {
+ const std::string text = R"(
+ OpCapability StorageImageExtendedFormats
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %2 "blah" %58
+ OpExecutionMode %2 OriginUpperLeft
+ OpName %BAD "BAD"
+ %11 = OpTypeVoid
+ %12 = OpTypeFunction %11
+ %19 = OpTypeInt 32 1
+ %21 = OpConstant %19 555758549
+ %2 = OpFunction %11 None %12
+ %4 = OpLabel
+ OpBranch %33
+ %33 = OpLabel
+ OpLoopMerge %34 %35 None
+ OpBranch %55
+ %BAD = OpLabel
+ OpSelectionMerge %53 None
+ OpSwitch %21 %34 196153896 %53 20856160 %34 33570306 %34 593494531 %52
+ %55 = OpLabel
+ OpLoopMerge %52 %58 DontUnroll
+ OpBranch %35
+ %58 = OpLabel
+ OpSelectionMerge %58 None
+ OpSwitch %21 %52 178168 %55 608223677 %34 604111047 %34 -553516825 %34 -106432813 %BAD 6946864 %55 1257373689 %55 973090296 %35 -113180668 %55 537002232 %BAD 13762553 %BAD 1030172152 %35 -553516825 %55 -262137 %35 -1091822332 %BAD 131320 %52 131321 %35 131320 %52 131321 %35 -1091822332 %BAD
+ %53 = OpLabel
+ OpBranch %35
+ %52 = OpLabel
+ OpBranch %34
+ %35 = OpLabel
+ OpBranch %33
+ %34 = OpLabel
+ OpKill
+ OpFunctionEnd
+)";
+
+ CompileSuccessfully(text);
+ EXPECT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("exits the selection headed by <ID> '3[%BAD]', but not "
+ "via a structured exit"));
+}
+
} // namespace
} // namespace val
} // namespace spvtools