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