Fix use of invalid analysis (#5013)
Fixes https://crbug.com/1395415
* Block merging needed to invalid structured cfg analysis
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/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