Progress on new transformation.
diff --git a/source/fuzz/fact_manager.cpp b/source/fuzz/fact_manager.cpp
index ac3ea30..c25d171 100644
--- a/source/fuzz/fact_manager.cpp
+++ b/source/fuzz/fact_manager.cpp
@@ -800,9 +800,37 @@
 // End of data synonym facts
 //==============================
 
+//==============================
+// Dead id facts
+
+// TODO comment.
+class FactManager::DeadIdFacts {
+ public:
+  // See method in FactManager which delegates to this method.
+  void AddFact(const protobufs::FactIdIsDead& fact);
+
+  // See method in FactManager which delegates to this method.
+  bool IdIsDead(uint32_t id) const;
+
+ private:
+  std::set<uint32_t> dead_ids_;
+};
+
+void FactManager::DeadIdFacts::AddFact(const protobufs::FactIdIsDead& fact) {
+  dead_ids_.insert(fact.id());
+}
+
+bool FactManager::DeadIdFacts::IdIsDead(uint32_t id) const {
+  return dead_ids_.count(id) != 0;
+}
+
+// End of dead id facts
+//==============================
+
 FactManager::FactManager()
     : uniform_constant_facts_(MakeUnique<ConstantUniformFacts>()),
-      data_synonym_facts_(MakeUnique<DataSynonymFacts>()) {}
+      data_synonym_facts_(MakeUnique<DataSynonymFacts>()),
+      dead_id_facts_(MakeUnique<DeadIdFacts>()) {}
 
 FactManager::~FactManager() = default;
 
@@ -827,6 +855,9 @@
     case protobufs::Fact::kDataSynonymFact:
       data_synonym_facts_->AddFact(fact.data_synonym_fact(), context);
       return true;
+    case protobufs::Fact::kIdIsDeadFact:
+      dead_id_facts_->AddFact(fact.id_is_dead_fact());
+      return true;
     default:
       assert(false && "Unknown fact type.");
       return false;
@@ -898,5 +929,15 @@
                                            context);
 }
 
+bool FactManager::IdIsDead(uint32_t id) const {
+  return dead_id_facts_->IdIsDead(id);
+}
+
+void FactManager::AddFactIdIsDead(uint32_t id) {
+  protobufs::FactIdIsDead fact;
+  fact.set_id(id);
+  dead_id_facts_->AddFact(fact);
+}
+
 }  // namespace fuzz
 }  // namespace spvtools
diff --git a/source/fuzz/fact_manager.h b/source/fuzz/fact_manager.h
index 62d9dac..fb5ff71 100644
--- a/source/fuzz/fact_manager.h
+++ b/source/fuzz/fact_manager.h
@@ -58,6 +58,9 @@
                           const protobufs::DataDescriptor& data2,
                           opt::IRContext* context);
 
+  // Records the fact that |id| is dead.
+  void AddFactIdIsDead(uint32_t id);
+
   // The fact manager is responsible for managing a few distinct categories of
   // facts. In principle there could be different fact managers for each kind
   // of fact, but in practice providing one 'go to' place for facts is
@@ -130,6 +133,14 @@
   // End of id synonym facts
   //==============================
 
+  //==============================
+  // Querying facts about dead ids
+
+  bool IdIsDead(uint32_t id) const;
+
+  // End of dead id facts
+  //==============================
+
  private:
   // For each distinct kind of fact to be managed, we use a separate opaque
   // class type.
@@ -142,6 +153,10 @@
   class DataSynonymFacts;  // Opaque class for management of data synonym facts.
   std::unique_ptr<DataSynonymFacts>
       data_synonym_facts_;  // Unique pointer to internal data.
+
+  class DeadIdFacts;  // Opaque class for management of dead id facts.
+  std::unique_ptr<DeadIdFacts>
+      dead_id_facts_;  // Unique pointer to internal data.
 };
 
 }  // namespace fuzz
diff --git a/source/fuzz/fuzzer.cpp b/source/fuzz/fuzzer.cpp
index 95913d0..4695b62 100644
--- a/source/fuzz/fuzzer.cpp
+++ b/source/fuzz/fuzzer.cpp
@@ -21,6 +21,7 @@
 #include "fuzzer_pass_adjust_memory_operands_masks.h"
 #include "source/fuzz/fact_manager.h"
 #include "source/fuzz/fuzzer_context.h"
+#include "source/fuzz/fuzzer_pass_add_dead_blocks.h"
 #include "source/fuzz/fuzzer_pass_add_dead_breaks.h"
 #include "source/fuzz/fuzzer_pass_add_dead_continues.h"
 #include "source/fuzz/fuzzer_pass_add_no_contraction_decorations.h"
@@ -169,6 +170,9 @@
   // Apply some semantics-preserving passes.
   std::vector<std::unique_ptr<FuzzerPass>> passes;
   while (passes.empty()) {
+    MaybeAddPass<FuzzerPassAddDeadBlocks>(&passes, ir_context.get(),
+                                          &fact_manager, &fuzzer_context,
+                                          transformation_sequence_out);
     MaybeAddPass<FuzzerPassAddDeadBreaks>(&passes, ir_context.get(),
                                           &fact_manager, &fuzzer_context,
                                           transformation_sequence_out);
diff --git a/source/fuzz/fuzzer_context.cpp b/source/fuzz/fuzzer_context.cpp
index 98585d9..f2db42a 100644
--- a/source/fuzz/fuzzer_context.cpp
+++ b/source/fuzz/fuzzer_context.cpp
@@ -23,6 +23,7 @@
 // Default <minimum, maximum> pairs of probabilities for applying various
 // transformations. All values are percentages. Keep them in alphabetical order.
 
+const std::pair<uint32_t, uint32_t> kChanceOfAddingDeadBlock = {20, 90};
 const std::pair<uint32_t, uint32_t> kChanceOfAddingDeadBreak = {5, 80};
 const std::pair<uint32_t, uint32_t> kChanceOfAddingDeadContinue = {5, 80};
 const std::pair<uint32_t, uint32_t> kChanceOfAddingNoContractionDecoration = {
@@ -66,6 +67,8 @@
       next_fresh_id_(min_fresh_id),
       go_deeper_in_constant_obfuscation_(
           kDefaultGoDeeperInConstantObfuscation) {
+  chance_of_adding_dead_block_ =
+      ChooseBetweenMinAndMax(kChanceOfAddingDeadBlock);
   chance_of_adding_dead_break_ =
       ChooseBetweenMinAndMax(kChanceOfAddingDeadBreak);
   chance_of_adding_dead_continue_ =
diff --git a/source/fuzz/fuzzer_context.h b/source/fuzz/fuzzer_context.h
index 619c131..42ac320 100644
--- a/source/fuzz/fuzzer_context.h
+++ b/source/fuzz/fuzzer_context.h
@@ -58,6 +58,7 @@
 
   // Probabilities associated with applying various transformations.
   // Keep them in alphabetical order.
+  uint32_t GetChanceOfAddingDeadBlock() { return chance_of_adding_dead_block_; }
   uint32_t GetChanceOfAddingDeadBreak() { return chance_of_adding_dead_break_; }
   uint32_t GetChanceOfAddingDeadContinue() {
     return chance_of_adding_dead_continue_;
@@ -114,6 +115,7 @@
 
   // Probabilities associated with applying various transformations.
   // Keep them in alphabetical order.
+  uint32_t chance_of_adding_dead_block_;
   uint32_t chance_of_adding_dead_break_;
   uint32_t chance_of_adding_dead_continue_;
   uint32_t chance_of_adding_no_contraction_decoration_;
diff --git a/source/fuzz/fuzzer_pass_add_dead_blocks.cpp b/source/fuzz/fuzzer_pass_add_dead_blocks.cpp
index f964146..ac2aef3 100644
--- a/source/fuzz/fuzzer_pass_add_dead_blocks.cpp
+++ b/source/fuzz/fuzzer_pass_add_dead_blocks.cpp
@@ -14,6 +14,9 @@
 
 #include "source/fuzz/fuzzer_pass_add_dead_blocks.h"
 
+#include "source/fuzz/fuzzer_util.h"
+#include "source/fuzz/transformation_add_dead_block.h"
+
 namespace spvtools {
 namespace fuzz {
 
@@ -26,7 +29,40 @@
 FuzzerPassAddDeadBlocks::~FuzzerPassAddDeadBlocks() = default;
 
 void FuzzerPassAddDeadBlocks::Apply() {
-  assert(false && "Implement");
+  std::vector<opt::BasicBlock*> candidate_blocks;
+  for (auto& function : *GetIRContext()->module()) {
+    for (auto& block : function) {
+      if (!GetFuzzerContext()->ChoosePercentage(
+              GetFuzzerContext()->GetChanceOfAddingDeadBlock())) {
+        continue;
+      }
+      if (block.IsLoopHeader()) {
+        continue;
+      }
+      if (block.terminator()->opcode() != SpvOpBranch) {
+        continue;
+      }
+      if (fuzzerutil::IsMergeOrContinue(
+              GetIRContext(), block.terminator()->GetSingleWordInOperand(0))) {
+        continue;
+      }
+      // TODO think about OpPhi here
+      candidate_blocks.push_back(&block);
+    }
+  }
+  while (!candidate_blocks.empty()) {
+    uint32_t index = GetFuzzerContext()->RandomIndex(candidate_blocks);
+    auto block = candidate_blocks.at(index);
+    candidate_blocks.erase(candidate_blocks.begin() + index);
+    // TODO: address OpPhi situation
+    TransformationAddDeadBlock transformation(
+        GetFuzzerContext()->GetFreshId(), block->id(),
+        GetFuzzerContext()->ChooseEven(), {});
+    if (transformation.IsApplicable(GetIRContext(), *GetFactManager())) {
+      transformation.Apply(GetIRContext(), GetFactManager());
+      *GetTransformations()->add_transformation() = transformation.ToMessage();
+    }
+  }
 }
 
 }  // namespace fuzz
diff --git a/source/fuzz/fuzzer_pass_add_dead_blocks.h b/source/fuzz/fuzzer_pass_add_dead_blocks.h
index 0577151..9ebb2f3 100644
--- a/source/fuzz/fuzzer_pass_add_dead_blocks.h
+++ b/source/fuzz/fuzzer_pass_add_dead_blocks.h
@@ -24,8 +24,8 @@
 class FuzzerPassAddDeadBlocks : public FuzzerPass {
  public:
   FuzzerPassAddDeadBlocks(opt::IRContext* ir_context, FactManager* fact_manager,
-                        FuzzerContext* fuzzer_context,
-                        protobufs::TransformationSequence* transformations);
+                          FuzzerContext* fuzzer_context,
+                          protobufs::TransformationSequence* transformations);
 
   ~FuzzerPassAddDeadBlocks();
 
diff --git a/source/fuzz/fuzzer_util.cpp b/source/fuzz/fuzzer_util.cpp
index a6e3657..82d761c 100644
--- a/source/fuzz/fuzzer_util.cpp
+++ b/source/fuzz/fuzzer_util.cpp
@@ -112,14 +112,14 @@
 uint32_t MaybeGetBoolConstantId(opt::IRContext* context, bool value) {
   opt::analysis::Bool bool_type;
   auto registered_bool_type =
-          context->get_type_mgr()->GetRegisteredType(&bool_type);
+      context->get_type_mgr()->GetRegisteredType(&bool_type);
   if (!registered_bool_type) {
     return 0;
   }
   opt::analysis::BoolConstant bool_constant(registered_bool_type->AsBool(),
-          value);
+                                            value);
   return context->get_constant_mgr()->FindDeclaredConstant(
-          &bool_constant, context->get_type_mgr()->GetId(&bool_type));
+      &bool_constant, context->get_type_mgr()->GetId(&bool_type));
 }
 
 void AddUnreachableEdgeAndUpdateOpPhis(
@@ -133,7 +133,9 @@
 
   // Get the id of the boolean constant to be used as the condition.
   uint32_t bool_id = MaybeGetBoolConstantId(context, condition_value);
-  assert(bool_id && "Precondition that condition value must be available is not satisfied");
+  assert(
+      bool_id &&
+      "Precondition that condition value must be available is not satisfied");
 
   const bool from_to_edge_already_exists = bb_from->IsSuccessor(bb_to);
   auto successor = bb_from->terminator()->GetSingleWordInOperand(0);
@@ -330,19 +332,18 @@
 bool IsMergeOrContinue(opt::IRContext* ir_context, uint32_t block_id) {
   bool result = false;
   ir_context->get_def_use_mgr()->WhileEachUse(
-          block_id,
-          [&result](
-                  const opt::Instruction* use_instruction,
-                  uint32_t /*unused*/) -> bool {
-              switch (use_instruction->opcode()) {
-                case SpvOpLoopMerge:
-                case SpvOpSelectionMerge:
-                  result = true;
-                  return false;
-                default:
-                  return true;
-              }
-          });
+      block_id,
+      [&result](const opt::Instruction* use_instruction,
+                uint32_t /*unused*/) -> bool {
+        switch (use_instruction->opcode()) {
+          case SpvOpLoopMerge:
+          case SpvOpSelectionMerge:
+            result = true;
+            return false;
+          default:
+            return true;
+        }
+      });
   return result;
 }
 
diff --git a/source/fuzz/protobufs/spvtoolsfuzz.proto b/source/fuzz/protobufs/spvtoolsfuzz.proto
index ef8074e..a0efd6e 100644
--- a/source/fuzz/protobufs/spvtoolsfuzz.proto
+++ b/source/fuzz/protobufs/spvtoolsfuzz.proto
@@ -166,6 +166,7 @@
     // Order the fact options by numeric id (rather than alphabetically).
     FactConstantUniform constant_uniform_fact = 1;
     FactDataSynonym data_synonym_fact = 2;
+    FactIdIsDead id_is_dead_fact = 3;
   }
 }
 
@@ -200,6 +201,16 @@
 
 }
 
+message FactIdIsDead {
+
+  // Records the fact that a block label instruction, or an instruction inside
+  // a block, is guaranteed to be dynamically unreachable.  This is useful
+  // because it informs the fuzzer that rather arbitrary changes can be made
+  // in relation to this instruction.
+
+  uint32 id = 1;
+}
+
 message TransformationSequence {
   repeated Transformation transformation = 1;
 }
diff --git a/source/fuzz/transformation.cpp b/source/fuzz/transformation.cpp
index 3f5375e..c7aae58 100644
--- a/source/fuzz/transformation.cpp
+++ b/source/fuzz/transformation.cpp
@@ -70,8 +70,7 @@
       return MakeUnique<TransformationAddConstantScalar>(
           message.add_constant_scalar());
     case protobufs::Transformation::TransformationCase::kAddDeadBlock:
-      return MakeUnique<TransformationAddDeadBlock>(
-          message.add_dead_block());
+      return MakeUnique<TransformationAddDeadBlock>(message.add_dead_block());
     case protobufs::Transformation::TransformationCase::kAddDeadBreak:
       return MakeUnique<TransformationAddDeadBreak>(message.add_dead_break());
     case protobufs::Transformation::TransformationCase::kAddDeadContinue:
diff --git a/source/fuzz/transformation_add_dead_block.cpp b/source/fuzz/transformation_add_dead_block.cpp
index ff9cebc..0d6b2f7 100644
--- a/source/fuzz/transformation_add_dead_block.cpp
+++ b/source/fuzz/transformation_add_dead_block.cpp
@@ -24,9 +24,8 @@
     : message_(message) {}
 
 TransformationAddDeadBlock::TransformationAddDeadBlock(
-        uint32_t fresh_id, uint32_t existing_block,
-bool condition_value,
-        std::vector<uint32_t> phi_id) {
+    uint32_t fresh_id, uint32_t existing_block, bool condition_value,
+    std::vector<uint32_t> phi_id) {
   message_.set_fresh_id(fresh_id);
   message_.set_existing_block(existing_block);
   message_.set_condition_value(condition_value);
@@ -45,14 +44,16 @@
 
   // First, we check that a constant with the same value as
   // |message_.condition_value| is present.
-  if (!fuzzerutil::MaybeGetBoolConstantId(context, message_.condition_value())) {
+  if (!fuzzerutil::MaybeGetBoolConstantId(context,
+                                          message_.condition_value())) {
     // The required constant is not present, so the transformation cannot be
     // applied.
     return false;
   }
 
   // The existing block must indeed exist.
-  auto existing_block = fuzzerutil::MaybeFindBlock(context, message_.existing_block());
+  auto existing_block =
+      fuzzerutil::MaybeFindBlock(context, message_.existing_block());
   if (!existing_block) {
     return false;
   }
@@ -68,32 +69,54 @@
   }
 
   // Its successor must not be a merge block nor continue target.
-  if (fuzzerutil::IsMergeOrContinue(context, existing_block->terminator()->GetSingleWordInOperand(0))) {
+  if (fuzzerutil::IsMergeOrContinue(
+          context, existing_block->terminator()->GetSingleWordInOperand(0))) {
     return false;
   }
   return true;
 }
 
 void TransformationAddDeadBlock::Apply(
-    opt::IRContext* context, spvtools::fuzz::FactManager* /*unused*/) const {
+    opt::IRContext* context, spvtools::fuzz::FactManager* fact_manager) const {
   // TODO comment
   fuzzerutil::UpdateModuleIdBound(context, message_.fresh_id());
   auto existing_block = context->cfg()->block(message_.existing_block());
-  auto successor_block_id = existing_block->terminator()->GetSingleWordInOperand(0);
-  auto bool_id = fuzzerutil::MaybeGetBoolConstantId(context, message_.condition_value());
+  auto successor_block_id =
+      existing_block->terminator()->GetSingleWordInOperand(0);
+  auto bool_id =
+      fuzzerutil::MaybeGetBoolConstantId(context, message_.condition_value());
 
   auto enclosing_function = existing_block->GetParent();
-  std::unique_ptr<opt::BasicBlock> new_block =
-          MakeUnique<opt::BasicBlock>(MakeUnique<opt::Instruction>(
-                  context, SpvOpLabel, 0, message_.fresh_id(), opt::Instruction::OperandList()));
+  std::unique_ptr<opt::BasicBlock> new_block = MakeUnique<opt::BasicBlock>(
+      MakeUnique<opt::Instruction>(context, SpvOpLabel, 0, message_.fresh_id(),
+                                   opt::Instruction::OperandList()));
   new_block->SetParent(enclosing_function);
-  new_block->AddInstruction(MakeUnique<opt::Instruction>(context, SpvOpBranch, 0, 0, opt::Instruction::OperandList({{SPV_OPERAND_TYPE_ID, {successor_block_id}}})));
+  new_block->AddInstruction(MakeUnique<opt::Instruction>(
+      context, SpvOpBranch, 0, 0,
+      opt::Instruction::OperandList(
+          {{SPV_OPERAND_TYPE_ID, {successor_block_id}}})));
+
+  existing_block->terminator()->InsertBefore(MakeUnique<opt::Instruction>(
+      context, SpvOpSelectionMerge, 0, 0,
+      opt::Instruction::OperandList(
+          {{SPV_OPERAND_TYPE_ID, {successor_block_id}},
+           {SPV_OPERAND_TYPE_SELECTION_CONTROL,
+            {SpvSelectionControlMaskNone}}})));
+
   existing_block->terminator()->SetOpcode(SpvOpBranchConditional);
   existing_block->terminator()->SetInOperands(
-          {{SPV_OPERAND_TYPE_ID, {bool_id}},
-           {SPV_OPERAND_TYPE_ID, {message_.condition_value() ? successor_block_id : message_.fresh_id()}},
-           {SPV_OPERAND_TYPE_ID, {message_.condition_value() ? message_.fresh_id() : successor_block_id}}});
-  enclosing_function->InsertBasicBlockAfter(std::move(new_block), existing_block);
+      {{SPV_OPERAND_TYPE_ID, {bool_id}},
+       {SPV_OPERAND_TYPE_ID,
+        {message_.condition_value() ? successor_block_id
+                                    : message_.fresh_id()}},
+       {SPV_OPERAND_TYPE_ID,
+        {message_.condition_value() ? message_.fresh_id()
+                                    : successor_block_id}}});
+  enclosing_function->InsertBasicBlockAfter(std::move(new_block),
+                                            existing_block);
+
+  fact_manager->AddFactIdIsDead(message_.fresh_id());
+
   context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
 }
 
diff --git a/source/fuzz/transformation_add_dead_block.h b/source/fuzz/transformation_add_dead_block.h
index 203b9a9..3c85615 100644
--- a/source/fuzz/transformation_add_dead_block.h
+++ b/source/fuzz/transformation_add_dead_block.h
@@ -28,8 +28,7 @@
   explicit TransformationAddDeadBlock(
       const protobufs::TransformationAddDeadBlock& message);
 
-  TransformationAddDeadBlock(uint32_t fresh_id,
-                             uint32_t existing_block,
+  TransformationAddDeadBlock(uint32_t fresh_id, uint32_t existing_block,
                              bool condition_value,
                              std::vector<uint32_t> phi_id);
 
diff --git a/source/fuzz/transformation_add_dead_break.cpp b/source/fuzz/transformation_add_dead_break.cpp
index 9fa2df6..43847fa 100644
--- a/source/fuzz/transformation_add_dead_break.cpp
+++ b/source/fuzz/transformation_add_dead_break.cpp
@@ -111,7 +111,8 @@
     opt::IRContext* context, const FactManager& /*unused*/) const {
   // First, we check that a constant with the same value as
   // |message_.break_condition_value| is present.
-  if (!fuzzerutil::MaybeGetBoolConstantId(context, message_.break_condition_value())) {
+  if (!fuzzerutil::MaybeGetBoolConstantId(context,
+                                          message_.break_condition_value())) {
     // The required constant is not present, so the transformation cannot be
     // applied.
     return false;
diff --git a/source/fuzz/transformation_add_dead_continue.cpp b/source/fuzz/transformation_add_dead_continue.cpp
index b614a23..ffa182e 100644
--- a/source/fuzz/transformation_add_dead_continue.cpp
+++ b/source/fuzz/transformation_add_dead_continue.cpp
@@ -37,7 +37,8 @@
     opt::IRContext* context, const FactManager& /*unused*/) const {
   // First, we check that a constant with the same value as
   // |message_.continue_condition_value| is present.
-  if (!fuzzerutil::MaybeGetBoolConstantId(context, message_.continue_condition_value())) {
+  if (!fuzzerutil::MaybeGetBoolConstantId(
+          context, message_.continue_condition_value())) {
     // The required constant is not present, so the transformation cannot be
     // applied.
     return false;
diff --git a/source/fuzz/transformation_split_block.cpp b/source/fuzz/transformation_split_block.cpp
index 9f6da7c..f05e77b 100644
--- a/source/fuzz/transformation_split_block.cpp
+++ b/source/fuzz/transformation_split_block.cpp
@@ -80,7 +80,7 @@
 }
 
 void TransformationSplitBlock::Apply(opt::IRContext* context,
-                                     FactManager* /*unused*/) const {
+                                     FactManager* fact_manager) const {
   opt::Instruction* instruction_to_split_before =
       FindInstruction(message_.instruction_to_split_before(), context);
   opt::BasicBlock* block_to_split =
@@ -114,6 +114,13 @@
            "one predecessor.");
     phi_inst->SetInOperand(1, {block_to_split->id()});
   });
+
+  // If the block being split was dead, the new block arising from the split is
+  // also dead.
+  if (fact_manager->IdIsDead(block_to_split->id())) {
+    fact_manager->AddFactIdIsDead(message_.fresh_id());
+  }
+
   // Invalidate all analyses
   context->InvalidateAnalysesExceptFor(opt::IRContext::Analysis::kAnalysisNone);
 }
diff --git a/test/fuzz/transformation_add_dead_block_test.cpp b/test/fuzz/transformation_add_dead_block_test.cpp
index 1044647..fbb9c3e 100644
--- a/test/fuzz/transformation_add_dead_block_test.cpp
+++ b/test/fuzz/transformation_add_dead_block_test.cpp
@@ -48,16 +48,20 @@
   FactManager fact_manager;
 
   // Id 4 is already in use
-  ASSERT_FALSE(TransformationAddDeadBlock(4, 5, true, {}).IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(TransformationAddDeadBlock(4, 5, true, {})
+                   .IsApplicable(context.get(), fact_manager));
 
   // Id 7 is not a block
-  ASSERT_FALSE(TransformationAddDeadBlock(100, 7, true, {}).IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(TransformationAddDeadBlock(100, 7, true, {})
+                   .IsApplicable(context.get(), fact_manager));
 
   TransformationAddDeadBlock transformation(100, 5, true, {});
   ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
   transformation.Apply(context.get(), &fact_manager);
   ASSERT_TRUE(IsValid(env, context.get()));
 
+  ASSERT_TRUE(fact_manager.IdIsDead(100));
+
   std::string after_transformation = R"(
                OpCapability Shader
           %1 = OpExtInstImport "GLSL.std.450"
@@ -72,7 +76,7 @@
           %7 = OpConstantTrue %6
           %4 = OpFunction %2 None %3
           %5 = OpLabel
-               OpSelectionMerge %8
+               OpSelectionMerge %8 None
                OpBranchConditional %7 %8 %100
         %100 = OpLabel
                OpBranch %8
@@ -83,11 +87,12 @@
   ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
 }
 
-// Target block must not be merge or continue
+// TODO Target block must not be merge or continue
 
-// Source block must not be loop head
+// TODO Source block must not be loop head
 
-// Target block can start with OpPhi; need to give suitable ids in that case
+// TODO Target block can start with OpPhi; need to give suitable ids in that
+//  case
 
 }  // namespace
 }  // namespace fuzz
diff --git a/test/fuzz/transformation_split_block_test.cpp b/test/fuzz/transformation_split_block_test.cpp
index d162e07..8c46bda 100644
--- a/test/fuzz/transformation_split_block_test.cpp
+++ b/test/fuzz/transformation_split_block_test.cpp
@@ -774,6 +774,77 @@
   ASSERT_TRUE(IsEqual(env, after_split, context.get()));
 }
 
+TEST(TransformationSplitBlockTest, DeadBlockShouldSplitToTwoDeadBlocks) {
+  // This checks that if a block B is marked as dead, it should split into a
+  // pair of dead blocks.
+  std::string shader = R"(
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %4 "main"
+               OpExecutionMode %4 OriginUpperLeft
+               OpSource ESSL 310
+               OpName %4 "main"
+          %2 = OpTypeVoid
+          %3 = OpTypeFunction %2
+          %6 = OpTypeBool
+          %7 = OpConstantFalse %6
+          %4 = OpFunction %2 None %3
+          %5 = OpLabel
+               OpSelectionMerge %9 None
+               OpBranchConditional %7 %8 %9
+          %8 = OpLabel
+               OpBranch %9
+          %9 = OpLabel
+               OpReturn
+               OpFunctionEnd
+  )";
+
+  const auto env = SPV_ENV_UNIVERSAL_1_3;
+  const auto consumer = nullptr;
+  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
+
+  FactManager fact_manager;
+
+  // Record the fact that block 8 is dead.
+  fact_manager.AddFactIdIsDead(8);
+
+  auto split = TransformationSplitBlock(
+      MakeInstructionDescriptor(8, SpvOpBranch, 0), 100);
+  ASSERT_TRUE(split.IsApplicable(context.get(), fact_manager));
+  split.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(IsValid(env, context.get()));
+
+  ASSERT_TRUE(fact_manager.IdIsDead(8));
+  ASSERT_TRUE(fact_manager.IdIsDead(100));
+
+  std::string after_split = R"(
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %4 "main"
+               OpExecutionMode %4 OriginUpperLeft
+               OpSource ESSL 310
+               OpName %4 "main"
+          %2 = OpTypeVoid
+          %3 = OpTypeFunction %2
+          %6 = OpTypeBool
+          %7 = OpConstantFalse %6
+          %4 = OpFunction %2 None %3
+          %5 = OpLabel
+               OpSelectionMerge %9 None
+               OpBranchConditional %7 %8 %9
+          %8 = OpLabel
+               OpBranch %100
+        %100 = OpLabel
+               OpBranch %9
+          %9 = OpLabel
+               OpReturn
+               OpFunctionEnd
+  )";
+  ASSERT_TRUE(IsEqual(env, after_split, context.get()));
+}
+
 }  // namespace
 }  // namespace fuzz
 }  // namespace spvtools