Allow merge blocks to merge two header blocks in some cases. (#1890)

In merge blocks, we do not allow the merging of two blocks with merge
instructions.  This is because if the two block are merged only 1 of
those instructions can exists.  However, if the successor block is the
merge block of the predecessor, then we can delete the merge instruction
in the predecessor.  In this case, we are able to merge the blocks.
diff --git a/source/opt/block_merge_pass.cpp b/source/opt/block_merge_pass.cpp
index aa4c1bd..45107cc 100644
--- a/source/opt/block_merge_pass.cpp
+++ b/source/opt/block_merge_pass.cpp
@@ -55,14 +55,6 @@
       continue;
     }
 
-    bool pred_is_header = IsHeader(&*bi);
-    bool succ_is_header = IsHeader(lab_id);
-    if (pred_is_header && succ_is_header) {
-      // Cannot merge two headers together.
-      ++bi;
-      continue;
-    }
-
     bool pred_is_merge = IsMerge(&*bi);
     bool succ_is_merge = IsMerge(lab_id);
     if (pred_is_merge && succ_is_merge) {
@@ -72,7 +64,16 @@
     }
 
     Instruction* merge_inst = bi->GetMergeInst();
+    bool pred_is_header = IsHeader(&*bi);
     if (pred_is_header && lab_id != merge_inst->GetSingleWordInOperand(0u)) {
+      bool succ_is_header = IsHeader(lab_id);
+      if (pred_is_header && succ_is_header) {
+        // Cannot merge two headers together when the successor is not the merge
+        // block of the predecessor.
+        ++bi;
+        continue;
+      }
+
       // If this is a header block and the successor is not its merge, we must
       // be careful about which blocks we are willing to merge together.
       // OpLoopMerge must be followed by a conditional or unconditional branch.
diff --git a/test/opt/block_merge_test.cpp b/test/opt/block_merge_test.cpp
index aaa70cd..0266b8e 100644
--- a/test/opt/block_merge_test.cpp
+++ b/test/opt/block_merge_test.cpp
@@ -691,6 +691,45 @@
 
   SinglePassRunAndMatch<BlockMergePass>(text, true);
 }
+
+TEST_F(BlockMergeTest, MergeHeaders) {
+  // Merge two headers when the second is the merge block of the first.
+  const std::string text = R"(
+; CHECK: OpFunction
+; CHECK-NEXT: OpLabel
+; CHECK-NEXT: OpBranch [[header:%\w+]]
+; CHECK-NEXT: [[header]] = OpLabel
+; CHECK-NEXT: OpSelectionMerge [[merge:%\w+]]
+; CHECK: [[merge]] = OpLabel
+; CHEKC: OpReturn
+OpCapability Shader
+OpMemoryModel Logical GLSL450
+OpEntryPoint Fragment %func "func"
+%void = OpTypeVoid
+%bool = OpTypeBool
+%functy = OpTypeFunction %void
+%otherfuncty = OpTypeFunction %bool
+%true = OpConstantTrue %bool
+%func = OpFunction %void None %functy
+%1 = OpLabel
+OpBranch %5
+%5 = OpLabel
+OpLoopMerge %8 %7 None
+OpBranch %8
+%7 = OpLabel
+OpBranch %5
+%8 = OpLabel
+OpSelectionMerge %m None
+OpBranchConditional %true %a %m
+%a = OpLabel
+OpBranch %m
+%m = OpLabel
+OpReturn
+OpFunctionEnd
+)";
+
+  SinglePassRunAndMatch<BlockMergePass>(text, true);
+}
 #endif  // SPIRV_EFFCEE
 
 // TODO(greg-lunarg): Add tests to verify handling of these cases: