[llvm] [FixIrreducible][UnifyLoopExits] Support switch statements (PR #206567)

via llvm-commits llvm-commits at lists.llvm.org
Sat Jul 4 01:30:20 PDT 2026


https://github.com/hertelukas updated https://github.com/llvm/llvm-project/pull/206567

>From 3a6b883bc87a2104ed1e03a19d4610d16cc30370 Mon Sep 17 00:00:00 2001
From: Lukas <dev at lukas-hertel.de>
Date: Sun, 28 Jun 2026 17:43:33 +0200
Subject: [PATCH 1/2] [FixIrreducible] Support switch statements

Reuse the approach for callbr terminators for switches. Branches,
entering irreducible loops through switches, are split and replaced
with unconditional branches into the loop.

Assisted-by: LLM (Adapted callbr.ll test structure to switch.ll)
---
 .../llvm/Transforms/Utils/BasicBlockUtils.h   |  23 +-
 llvm/lib/Transforms/Utils/BasicBlockUtils.cpp |  54 +-
 llvm/lib/Transforms/Utils/FixIrreducible.cpp  |  52 +-
 llvm/lib/Transforms/Utils/UnifyLoopExits.cpp  |  38 +-
 llvm/test/Transforms/FixIrreducible/switch.ll | 960 +++++++++++++++++-
 .../FixIrreducible/unsupported-terminator.ll  |  25 +-
 6 files changed, 1032 insertions(+), 120 deletions(-)

diff --git a/llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h b/llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h
index f9bfff09673f0..abf19177bd7da 100644
--- a/llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h
+++ b/llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h
@@ -267,18 +267,17 @@ LLVM_ABI BasicBlock *SplitEdge(BasicBlock *From, BasicBlock *To,
                                MemorySSAUpdater *MSSAU = nullptr,
                                const Twine &BBName = "");
 
-/// \brief Create a new intermediate target block for a callbr edge.
+/// \brief Create a new intermediate target block for a callbr and switch edges.
 ///
-/// Create a new basic block between a callbr instruction and one of its
-/// successors. The new block replaces the original successor in the callbr
-/// instruction and unconditionally branches to the original successor. This
-/// is useful for normalizing control flow, e.g., when transforming
-/// irreducible loops.
+/// Create a new basic block between a callbr or switch instruction and one of
+/// its successors. The new block replaces the original successor in the
+/// callbr/switch instruction and unconditionally branches to the original
+/// successor. This is useful for normalizing control flow, e.g., when
+/// transforming irreducible loops.
 ///
-/// \param CallBrBlock    block containing the callbr instruction
+/// \param MultiBrBlock   block containing the callbr or switch instruction
 /// \param Succ           original successor block
-/// \param SuccIdx        index of the original successor in the callbr
-///                       instruction
+/// \param SuccIdx        index of the original successor in the terminator
 /// \param DTU            optional \p DomTreeUpdater for updating the
 ///                       dominator tree
 /// \param CI             optional \p CycleInfo for updating cycle membership
@@ -291,9 +290,9 @@ LLVM_ABI BasicBlock *SplitEdge(BasicBlock *From, BasicBlock *To,
 /// \note This function updates PHI nodes, dominator tree, loop info, and
 /// cycle info as needed.
 LLVM_ABI BasicBlock *
-SplitCallBrEdge(BasicBlock *CallBrBlock, BasicBlock *Succ, unsigned SuccIdx,
-                DomTreeUpdater *DTU = nullptr, CycleInfo *CI = nullptr,
-                LoopInfo *LI = nullptr, bool *UpdatedLI = nullptr);
+SplitMultiBrEdge(BasicBlock *MultiBrBlock, BasicBlock *Succ, unsigned SuccIdx,
+                 DomTreeUpdater *DTU = nullptr, CycleInfo *CI = nullptr,
+                 LoopInfo *LI = nullptr, bool *UpdatedLI = nullptr);
 
 /// Sets the unwind edge of an instruction to a particular successor.
 LLVM_ABI void setUnwindEdgeTo(Instruction *TI, BasicBlock *Succ);
diff --git a/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp b/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp
index 425faf57f8b63..fbc0ba71b37de 100644
--- a/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp
+++ b/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp
@@ -725,47 +725,47 @@ static bool updateCycleLoopInfo(TI *LCI, BasicBlock *CallBrBlock,
   return true;
 }
 
-BasicBlock *llvm::SplitCallBrEdge(BasicBlock *CallBrBlock, BasicBlock *Succ,
-                                  unsigned SuccIdx, DomTreeUpdater *DTU,
-                                  CycleInfo *CI, LoopInfo *LI,
-                                  bool *UpdatedLI) {
-  CallBrInst *CallBr = dyn_cast<CallBrInst>(CallBrBlock->getTerminator());
-  assert(CallBr && "expected callbr terminator");
-  assert(SuccIdx < CallBr->getNumSuccessors() &&
-         Succ == CallBr->getSuccessor(SuccIdx) && "invalid successor index");
-
-  // Create a new block between callbr and the specified successor.
+BasicBlock *llvm::SplitMultiBrEdge(BasicBlock *MultiBrBlock, BasicBlock *Succ,
+                                   unsigned SuccIdx, DomTreeUpdater *DTU,
+                                   CycleInfo *CI, LoopInfo *LI,
+                                   bool *UpdatedLI) {
+  Instruction *Term = MultiBrBlock->getTerminator();
+  assert(Term && "expected terminator");
+  assert(SuccIdx < Term->getNumSuccessors() &&
+         Succ == Term->getSuccessor(SuccIdx) && "invalid successor index");
+
+  // Create a new block between terminator and the specified successor.
   // splitBlockBefore cannot be re-used here since it cannot split if the split
   // point is a PHI node (because BasicBlock::splitBasicBlockBefore cannot
   // handle that). But we don't need to rewire every part of a potential PHI
-  // node. We only care about the edge between CallBrBlock and the original
+  // node. We only care about the edge between MultiBrBlock and the original
   // successor.
-  BasicBlock *CallBrTarget =
-      BasicBlock::Create(CallBrBlock->getContext(),
-                         CallBrBlock->getName() + ".target." + Succ->getName(),
-                         CallBrBlock->getParent());
+  BasicBlock *BrTarget =
+      BasicBlock::Create(MultiBrBlock->getContext(),
+                         MultiBrBlock->getName() + ".target." + Succ->getName(),
+                         MultiBrBlock->getParent());
   // Rewire control flow from the new target block to the original successor.
-  Succ->replacePhiUsesWith(CallBrBlock, CallBrTarget);
-  // Rewire control flow from callbr to the new target block.
-  CallBr->setSuccessor(SuccIdx, CallBrTarget);
+  Succ->replacePhiUsesWith(MultiBrBlock, BrTarget);
+  // Rewire control flow from the MultiBrBlock to the new target block.
+  Term->setSuccessor(SuccIdx, BrTarget);
   // Jump from the new target block to the original successor.
-  UncondBrInst::Create(Succ, CallBrTarget);
+  UncondBrInst::Create(Succ, BrTarget);
 
   bool Updated =
-      updateCycleLoopInfo<LoopInfo, Loop>(LI, CallBrBlock, CallBrTarget, Succ);
+      updateCycleLoopInfo<LoopInfo, Loop>(LI, MultiBrBlock, BrTarget, Succ);
   if (UpdatedLI)
     *UpdatedLI = Updated;
-  updateCycleLoopInfo<CycleInfo, Cycle>(CI, CallBrBlock, CallBrTarget, Succ);
+  updateCycleLoopInfo<CycleInfo, Cycle>(CI, MultiBrBlock, BrTarget, Succ);
   if (DTU) {
-    DTU->applyUpdates({{DominatorTree::Insert, CallBrBlock, CallBrTarget}});
-    if (DTU->getDomTree().dominates(CallBrBlock, Succ)) {
-      if (!is_contained(successors(CallBrBlock), Succ))
-        DTU->applyUpdates({{DominatorTree::Delete, CallBrBlock, Succ}});
-      DTU->applyUpdates({{DominatorTree::Insert, CallBrTarget, Succ}});
+    DTU->applyUpdates({{DominatorTree::Insert, MultiBrBlock, BrTarget}});
+    if (DTU->getDomTree().dominates(MultiBrBlock, Succ)) {
+      if (!is_contained(successors(MultiBrBlock), Succ))
+        DTU->applyUpdates({{DominatorTree::Delete, MultiBrBlock, Succ}});
+      DTU->applyUpdates({{DominatorTree::Insert, BrTarget, Succ}});
     }
   }
 
-  return CallBrTarget;
+  return BrTarget;
 }
 
 void llvm::setUnwindEdgeTo(Instruction *TI, BasicBlock *Succ) {
diff --git a/llvm/lib/Transforms/Utils/FixIrreducible.cpp b/llvm/lib/Transforms/Utils/FixIrreducible.cpp
index ead39f5991081..3b445492dc564 100644
--- a/llvm/lib/Transforms/Utils/FixIrreducible.cpp
+++ b/llvm/lib/Transforms/Utils/FixIrreducible.cpp
@@ -76,16 +76,15 @@
 // a PHINode in a header. Hence the above handling of PHINodes is sufficient and
 // no further processing is required to restore SSA.
 //
-// Limitation: The pass cannot handle switch statements and indirect
-//             branches. Both must be lowered to plain branches first.
+// Limitation: The pass cannot handle indirect branches. They must be lowered to
+//             plain branches first.
 //
-// CallBr support: CallBr is handled as a more general branch instruction which
-// can have multiple successors. The pass redirects the edges to intermediate
-// target blocks that unconditionally branch to the original callbr target
-// blocks. This allows the control flow hub to know to which of the original
-// target blocks to jump to.
-// Example input CFG:
-//                        Entry (callbr)
+// CallBr and Switch support: CallBr and Switch terminators are handled as a
+// more general branch instruction which can have multiple successors. The pass
+// redirects the edges to intermediate target blocks that unconditionally branch
+// to the original target blocks. This allows the control flow hub to know to
+// which of the original target blocks to jump to. Example input CFG:
+//                        Entry (callbr/switch)
 //                       /     \
 //                      v       v
 //                      H ----> B
@@ -95,7 +94,7 @@
 //                             Exit
 //
 // becomes:
-//                        Entry (callbr)
+//                        Entry (callbr/switch)
 //                       /     \
 //                      v       v
 //                 target.H   target.B
@@ -110,7 +109,7 @@
 // Note
 // OUTPUT CFG: Converted to a natural loop with a new header N.
 //
-//                        Entry (callbr)
+//                        Entry (callbr/switch)
 //                       /     \
 //                      v       v
 //                 target.H   target.B
@@ -132,6 +131,7 @@
 #include "llvm/Analysis/CycleAnalysis.h"
 #include "llvm/Analysis/DomTreeUpdater.h"
 #include "llvm/Analysis/LoopInfo.h"
+#include "llvm/IR/Instructions.h"
 #include "llvm/InitializePasses.h"
 #include "llvm/Pass.h"
 #include "llvm/Support/ErrorHandling.h"
@@ -309,20 +309,23 @@ static bool fixIrreducible(Cycle &C, CycleInfo &CI, DominatorTree &DT,
                         << " -> " << printBasicBlock(Succ0)
                         << (Succ0 && Succ1 ? " " : "") << printBasicBlock(Succ1)
                         << '\n');
-    } else if (CallBrInst *CallBr = dyn_cast<CallBrInst>(P->getTerminator())) {
-      for (unsigned I = 0; I < CallBr->getNumSuccessors(); ++I) {
-        BasicBlock *Succ = CallBr->getSuccessor(I);
+    } else if (isa<CallBrInst>(P->getTerminator()) ||
+               isa<SwitchInst>(P->getTerminator())) {
+      Instruction *Term = P->getTerminator();
+      for (unsigned I = 0; I < Term->getNumSuccessors(); ++I) {
+        BasicBlock *Succ = Term->getSuccessor(I);
         if (Succ != Header)
           continue;
-        BasicBlock *NewSucc = SplitCallBrEdge(P, Succ, I, &DTU, &CI, LI);
+        BasicBlock *NewSucc = SplitMultiBrEdge(P, Succ, I, &DTU, &CI, LI);
         CHub.addBranch(NewSucc, Succ);
         LLVM_DEBUG(dbgs() << "Added internal branch: "
                           << printBasicBlock(NewSucc) << " -> "
                           << printBasicBlock(Succ) << '\n');
       }
     } else {
-      reportFatalUsageError("unsupported block terminator: fix-irreducible "
-                            "only supports br and callbr instructions");
+      reportFatalUsageError(
+          "unsupported block terminator: fix-irreducible "
+          "only supports br, callbr, and switch instructions");
     }
   }
 
@@ -354,20 +357,23 @@ static bool fixIrreducible(Cycle &C, CycleInfo &CI, DominatorTree &DT,
                         << " -> " << printBasicBlock(Succ0)
                         << (Succ0 && Succ1 ? " " : "") << printBasicBlock(Succ1)
                         << '\n');
-    } else if (CallBrInst *CallBr = dyn_cast<CallBrInst>(P->getTerminator())) {
-      for (unsigned I = 0; I < CallBr->getNumSuccessors(); ++I) {
-        BasicBlock *Succ = CallBr->getSuccessor(I);
+    } else if (isa<CallBrInst>(P->getTerminator()) ||
+               isa<SwitchInst>(P->getTerminator())) {
+      Instruction *Term = P->getTerminator();
+      for (unsigned I = 0; I < Term->getNumSuccessors(); ++I) {
+        BasicBlock *Succ = Term->getSuccessor(I);
         if (!C.contains(Succ))
           continue;
-        BasicBlock *NewSucc = SplitCallBrEdge(P, Succ, I, &DTU, &CI, LI);
+        BasicBlock *NewSucc = SplitMultiBrEdge(P, Succ, I, &DTU, &CI, LI);
         CHub.addBranch(NewSucc, Succ);
         LLVM_DEBUG(dbgs() << "Added external branch: "
                           << printBasicBlock(NewSucc) << " -> "
                           << printBasicBlock(Succ) << '\n');
       }
     } else {
-      reportFatalUsageError("unsupported block terminator: fix-irreducible "
-                            "only supports br and callbr instructions");
+      reportFatalUsageError(
+          "unsupported block terminator: fix-irreducible "
+          "only supports br, callbr, and switch instructions");
     }
   }
 
diff --git a/llvm/lib/Transforms/Utils/UnifyLoopExits.cpp b/llvm/lib/Transforms/Utils/UnifyLoopExits.cpp
index 6947cb4f92723..657f407c020a5 100644
--- a/llvm/lib/Transforms/Utils/UnifyLoopExits.cpp
+++ b/llvm/lib/Transforms/Utils/UnifyLoopExits.cpp
@@ -13,10 +13,10 @@
 // Limitation: This assumes that all terminators in the CFG are direct branches
 //             (the "br" instruction). The presence of any other control flow
 //             such as indirectbr or switch will cause an assert.
-//             The callbr terminator is supported by creating intermediate
-//             target blocks that unconditionally branch to the original target
-//             blocks. These intermediate target blocks can then be redirected
-//             through the ControlFlowHub as usual.
+//             The callbr and switch terminators are supported by creating
+//             intermediate target blocks that unconditionally branch to the
+//             original target blocks. These intermediate target blocks can then
+//             be redirected through the ControlFlowHub as usual.
 //
 //===----------------------------------------------------------------------===//
 
@@ -26,6 +26,7 @@
 #include "llvm/Analysis/LoopInfo.h"
 #include "llvm/IR/Constants.h"
 #include "llvm/IR/Dominators.h"
+#include "llvm/IR/Instructions.h"
 #include "llvm/InitializePasses.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Transforms/Utils.h"
@@ -159,7 +160,7 @@ static bool unifyLoopExits(DominatorTree &DT, LoopInfo &LI, Loop *L) {
     return false;
 
   DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Eager);
-  SmallVector<BasicBlock *, 8> CallBrTargetBlocksToFix;
+  SmallVector<BasicBlock *, 8> MultiBrTargetBlocksToFix;
 
   // Redirect exiting edges through a control flow hub.
   ControlFlowHub CHub;
@@ -186,27 +187,30 @@ static bool unifyLoopExits(DominatorTree &DT, LoopInfo &LI, Loop *L) {
                         << " -> " << printBasicBlock(Succ0)
                         << (Succ0 && Succ1 ? " " : "") << printBasicBlock(Succ1)
                         << '\n');
-    } else if (CallBrInst *CallBr = dyn_cast<CallBrInst>(BB->getTerminator())) {
-      for (unsigned J = 0; J < CallBr->getNumSuccessors(); ++J) {
-        BasicBlock *Succ = CallBr->getSuccessor(J);
+    } else if (isa<CallBrInst>(BB->getTerminator()) ||
+               isa<SwitchInst>(BB->getTerminator())) {
+      Instruction *Term = BB->getTerminator();
+      for (unsigned J = 0; J < Term->getNumSuccessors(); ++J) {
+        BasicBlock *Succ = Term->getSuccessor(J);
         if (L->contains(Succ))
           continue;
         bool UpdatedLI = false;
         BasicBlock *NewSucc =
-            SplitCallBrEdge(BB, Succ, J, &DTU, nullptr, &LI, &UpdatedLI);
-        // SplitCallBrEdge modifies the CFG because it creates an intermediate
+            SplitMultiBrEdge(BB, Succ, J, &DTU, nullptr, &LI, &UpdatedLI);
+        // SplitMultiBrEdge modifies the CFG because it creates an intermediate
         // block. So we need to set the changed flag no matter what the
         // ControlFlowHub is going to do later.
         Changed = true;
-        // Even if CallBr and Succ do not have a common parent loop, we need to
-        // add the new target block to the parent loop of the current loop.
+        // Even if the terminator and Succ do not have a common parent loop, we
+        // need to add the new target block to the parent loop of the current
+        // loop.
         if (!UpdatedLI)
-          CallBrTargetBlocksToFix.push_back(NewSucc);
+          MultiBrTargetBlocksToFix.push_back(NewSucc);
         // ExitingBlocks is later used to restore SSA, so we need to make sure
         // that the blocks used for phi nodes in the guard blocks match the
-        // predecessors of the guard blocks, which, in the case of callbr, are
-        // the new intermediate target blocks instead of the callbr blocks
-        // themselves.
+        // predecessors of the guard blocks, which, in the case of a callbr or
+        // switch terminator, are the new intermediate target blocks instead of
+        // the blocks themselves.
         ExitingBlocks[I] = NewSucc;
         CHub.addBranch(NewSucc, Succ);
         LLVM_DEBUG(dbgs() << "Added exiting branch: "
@@ -248,7 +252,7 @@ static bool unifyLoopExits(DominatorTree &DT, LoopInfo &LI, Loop *L) {
     for (auto *G : GuardBlocks) {
       ParentLoop->addBasicBlockToLoop(G, LI);
     }
-    for (auto *C : CallBrTargetBlocksToFix) {
+    for (auto *C : MultiBrTargetBlocksToFix) {
       ParentLoop->addBasicBlockToLoop(C, LI);
     }
     ParentLoop->verifyLoop();
diff --git a/llvm/test/Transforms/FixIrreducible/switch.ll b/llvm/test/Transforms/FixIrreducible/switch.ll
index 4d3d9498b284d..0da0a0d28735c 100644
--- a/llvm/test/Transforms/FixIrreducible/switch.ll
+++ b/llvm/test/Transforms/FixIrreducible/switch.ll
@@ -1,31 +1,145 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt < %s -lowerswitch -fix-irreducible --verify-loop-info -S | FileCheck %s
-; RUN: opt < %s -passes='lower-switch,fix-irreducible,verify<loops>' -S | FileCheck %s
-; RUN: opt < %s -passes='lower-switch,verify<loops>,fix-irreducible,verify<loops>' -S | FileCheck %s
-
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt < %s -passes='fix-irreducible,verify<loops>' -S | FileCheck %s
+; RUN: opt < %s -passes='verify<loops>,fix-irreducible,verify<loops>' -S | FileCheck %s
+; RUN: opt < %s -passes='print<cycles>' -disable-output 2>&1 | FileCheck %s --check-prefix CYCLES-BEFORE
+; RUN: opt < %s -passes='fix-irreducible,print<cycles>' -disable-output 2>&1 | FileCheck %s --check-prefix CYCLES-AFTER
+; CYCLES-BEFORE:      CycleInfo for function: loop_1
+; CYCLES-BEFORE-NEXT:    depth=1: entries(B A)
+; CYCLES-AFTER:       CycleInfo for function: loop_1
+; CYCLES-AFTER-NEXT:     depth=1: entries(irr.guard) B A B.target.B
+;
+; CYCLES-BEFORE-NEXT: CycleInfo for function: switch_entry
+; CYCLES-BEFORE-NEXT:    depth=1: entries(indirect fallthrough)
+; CYCLES-AFTER-NEXT:  CycleInfo for function: switch_entry
+; CYCLES-AFTER-NEXT:     depth=1: entries(irr.guard) indirect fallthrough
+;
+; CYCLES-BEFORE-NEXT: CycleInfo for function: switch_entry_targets_with_phi_nodes
+; CYCLES-BEFORE-NEXT:    depth=1: entries(block1 block)
+; CYCLES-AFTER-NEXT:  CycleInfo for function: switch_entry_targets_with_phi_nodes
+; CYCLES-AFTER-NEXT:     depth=1: entries(irr.guard) block1 block
+;
+; CYCLES-BEFORE-NEXT: CycleInfo for function: switch_entry_multiple_targets
+; CYCLES-BEFORE-NEXT:    depth=1: entries(indirect fallthrough)
+; CYCLES-AFTER-NEXT:  CycleInfo for function: switch_entry_multiple_targets
+; CYCLES-AFTER-NEXT:     depth=1: entries(irr.guard) indirect fallthrough
+;
+; CYCLES-BEFORE-NEXT: CycleInfo for function: switch_entry_multiple_targets1
+; CYCLES-BEFORE-NEXT:    depth=1: entries(indirect1 indirect fallthrough)
+; CYCLES-BEFORE-NEXT:        depth=2: entries(indirect fallthrough)
+; CYCLES-AFTER-NEXT:  CycleInfo for function: switch_entry_multiple_targets1
+; CYCLES-AFTER-NEXT:     depth=1: entries(irr.guard) indirect1 indirect fallthrough irr.guard1 irr.guard2
+; CYCLES-AFTER-NEXT:         depth=2: entries(irr.guard2) indirect fallthrough
+;
+; CYCLES-BEFORE-NEXT: CycleInfo for function: switch_header_no_indirect
+; CYCLES-BEFORE-NEXT:    depth=1: entries(fallthrough switch_bb)
+; CYCLES-AFTER-NEXT:  CycleInfo for function: switch_header_no_indirect
+; CYCLES-AFTER-NEXT:     depth=1: entries(irr.guard) fallthrough switch_bb switch_bb.target.fallthrough
+;
+; CYCLES-BEFORE-NEXT: CycleInfo for function: switch_header
+; CYCLES-BEFORE-NEXT:    depth=1: entries(fallthrough switch_bb)
+; CYCLES-AFTER-NEXT:  CycleInfo for function: switch_header
+; CYCLES-AFTER-NEXT:     depth=1: entries(irr.guard) fallthrough switch_bb switch_bb.target.fallthrough
+;
+; CYCLES-BEFORE-NEXT: CycleInfo for function: switch_header_multiple_targets
+; CYCLES-BEFORE-NEXT:    depth=1: entries(fallthrough switch_bb) indirect1
+; CYCLES-BEFORE-NEXT:        depth=2: entries(switch_bb) indirect1
+; CYCLES-AFTER-NEXT:  CycleInfo for function: switch_header_multiple_targets
+; CYCLES-AFTER-NEXT:     depth=1: entries(irr.guard) fallthrough switch_bb indirect1 switch_bb.target.fallthrough
+; CYCLES-AFTER-NEXT:         depth=2: entries(switch_bb) indirect1
+;
+; CYCLES-BEFORE-NEXT: CycleInfo for function: switch_regular
+; CYCLES-BEFORE-NEXT:    depth=1: entries(fallthrough2 fallthrough1)
+; CYCLES-BEFORE-NEXT:    depth=1: entries(indirect2 indirect1)
+; CYCLES-BEFORE-NEXT:    depth=1: entries(noswitch2 noswitch1)
+; CYCLES-AFTER-NEXT:  CycleInfo for function: switch_regular
+; CYCLES-AFTER-NEXT:     depth=1: entries(irr.guard) fallthrough2 fallthrough1
+; CYCLES-AFTER-NEXT:     depth=1: entries(irr.guard1) indirect2 indirect1
+; CYCLES-AFTER-NEXT:     depth=1: entries(irr.guard2) noswitch2 noswitch1
+;
+; CYCLES-BEFORE-NEXT: CycleInfo for function: switch_regular1
+; CYCLES-BEFORE-NEXT:    depth=1: entries(switch_bb noswitch)
+; CYCLES-AFTER-NEXT:  CycleInfo for function: switch_regular1
+; CYCLES-AFTER-NEXT:     depth=1: entries(irr.guard) switch_bb noswitch
+;
+; CYCLES-BEFORE-NEXT: CycleInfo for function: switch_header_and_regular
+; CYCLES-BEFORE-NEXT:    depth=1: entries(switch_header) switch_regular mid
+; CYCLES-BEFORE-NEXT:        depth=2: entries(switch_regular mid)
+; CYCLES-AFTER-NEXT:  CycleInfo for function: switch_header_and_regular
+; CYCLES-AFTER-NEXT:     depth=1: entries(switch_header) switch_regular mid switch_header.target.mid switch_header.target.switch_regular irr.guard
+; CYCLES-AFTER-NEXT:         depth=2: entries(irr.guard) switch_regular mid
+;
+; CYCLES-BEFORE-NEXT: CycleInfo for function: switch_only
+; CYCLES-BEFORE-NEXT:    depth=1: entries(switch_block switch_header)
+; CYCLES-AFTER-NEXT:  CycleInfo for function: switch_only
+; CYCLES-AFTER-NEXT:     depth=1: entries(irr.guard) switch_block switch_header switch_header.target.switch_block
+;
+; CYCLES-BEFORE-NEXT: CycleInfo for function: entry_multiple_switch
+; CYCLES-BEFORE-NEXT:    depth=1: entries(sw2 block block1)
+; CYCLES-BEFORE-NEXT:        depth=2: entries(block block1)
+; CYCLES-AFTER-NEXT:  CycleInfo for function: entry_multiple_switch
+; CYCLES-AFTER-NEXT:     depth=1: entries(irr.guard) sw2 block block1 irr.guard1 sw2.target.block1 sw2.target.block irr.guard2
+; CYCLES-AFTER-NEXT:         depth=2: entries(irr.guard2) block block1
+;
+; CYCLES-BEFORE-NEXT: CycleInfo for function: switch_exit_with_separate_entries
+; CYCLES-BEFORE-NEXT:    depth=1: entries(l2 l1) sw
+; CYCLES-BEFORE-NEXT:        depth=2: entries(l1 sw)
+; CYCLES-AFTER-NEXT:  CycleInfo for function: switch_exit_with_separate_entries
+; CYCLES-AFTER-NEXT:     depth=1: entries(irr.guard) l2 l1 sw sw.target.l1 irr.guard1
+; CYCLES-AFTER-NEXT:         depth=2: entries(irr.guard1) l1 sw sw.target.l1
+;
+; CYCLES-BEFORE-NEXT: CycleInfo for function: switch_exit_with_separate_entries1
+; CYCLES-BEFORE-NEXT:    depth=1: entries(loop2 loop1) sw
+; CYCLES-AFTER-NEXT:  CycleInfo for function: switch_exit_with_separate_entries1
+; CYCLES-AFTER-NEXT:     depth=1: entries(irr.guard) loop2 loop1 sw sw.target.loop2
+;
+; CYCLES-BEFORE-NEXT: CycleInfo for function: switch_only_multiple
+; CYCLES-BEFORE-NEXT:    depth=1: entries(sw3 sw1 sw2)
+; CYCLES-BEFORE-NEXT:        depth=2: entries(sw1 sw2)
+; CYCLES-AFTER-NEXT:  CycleInfo for function: switch_only_multiple
+; CYCLES-AFTER-NEXT:     depth=1: entries(irr.guard) sw3 sw1 sw2 sw2.target.sw3 sw1.target.sw3 irr.guard1 sw2.target.sw1 sw3.target.sw1 irr.guard2
+; CYCLES-AFTER-NEXT:         depth=2: entries(irr.guard2) sw1 sw2 sw2.target.sw1
+;
+; CYCLES-BEFORE-NEXT: CycleInfo for function: switch_bypass
+; CYCLES-BEFORE-NEXT:    depth=1: entries(l1 sw) l2
+; CYCLES-BEFORE-NEXT:        depth=2: entries(sw l2)
+; CYCLES-AFTER-NEXT:  CycleInfo for function: switch_bypass
+; CYCLES-AFTER-NEXT:     depth=1: entries(irr.guard) l1 sw l2 sw.target.l1 irr.guard1
+; CYCLES-AFTER-NEXT:         depth=2: entries(irr.guard1) sw l2
+;
+; CYCLES-BEFORE-NEXT: CycleInfo for function: switch_multiple_with_exit
+; CYCLES-BEFORE-NEXT:    depth=1: entries(l3 l1 l2)
+; CYCLES-BEFORE-NEXT:        depth=2: entries(l1 l2)
+; CYCLES-AFTER-NEXT:  CycleInfo for function: switch_multiple_with_exit
+; CYCLES-AFTER-NEXT:     depth=1: entries(irr.guard) l3 l1 l2 irr.guard1 irr.guard2
+; CYCLES-AFTER-NEXT:         depth=2: entries(irr.guard2) l1 l2
+;
+; CYCLES-BEFORE-NEXT: CycleInfo for function: switch_nested
+; CYCLES-BEFORE-NEXT:    depth=1: entries(bb bh)
+; CYCLES-BEFORE-NEXT:    depth=1: entries(b h)
+; CYCLES-AFTER-NEXT:  CycleInfo for function: switch_nested
+; CYCLES-AFTER-NEXT:     depth=1: entries(irr.guard) bb bh
+; CYCLES-AFTER-NEXT:     depth=1: entries(irr.guard1) b h
+;
 define void @loop_1(i32 %Value, i1 %PredEntry, i1 %PredD) {
-; CHECK-LABEL: @loop_1(
-; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[PREDENTRY_INV:%.*]] = xor i1 [[PREDENTRY:%.*]], true
-; CHECK-NEXT:    br label [[IRR_GUARD:%.*]]
-; CHECK:       A:
-; CHECK-NEXT:    br label [[IRR_GUARD]]
-; CHECK:       B:
-; CHECK-NEXT:    br label [[NODEBLOCK:%.*]]
-; CHECK:       NodeBlock:
-; CHECK-NEXT:    [[PIVOT:%.*]] = icmp slt i32 [[VALUE:%.*]], 1
-; CHECK-NEXT:    br i1 [[PIVOT]], label [[LEAFBLOCK:%.*]], label [[LEAFBLOCK1:%.*]]
-; CHECK:       LeafBlock1:
-; CHECK-NEXT:    [[SWITCHLEAF2:%.*]] = icmp eq i32 [[VALUE]], 1
-; CHECK-NEXT:    br i1 [[SWITCHLEAF2]], label [[IRR_GUARD]], label [[EXIT:%.*]]
-; CHECK:       LeafBlock:
-; CHECK-NEXT:    [[SWITCHLEAF:%.*]] = icmp eq i32 [[VALUE]], 0
-; CHECK-NEXT:    br i1 [[SWITCHLEAF]], label [[A:%.*]], label [[EXIT]]
-; CHECK:       exit:
-; CHECK-NEXT:    ret void
-; CHECK:       irr.guard:
-; CHECK-NEXT:    [[GUARD_B:%.*]] = phi i1 [ true, [[LEAFBLOCK1]] ], [ true, [[A]] ], [ [[PREDENTRY_INV]], [[ENTRY:%.*]] ]
-; CHECK-NEXT:    br i1 [[GUARD_B]], label [[B:%.*]], label [[A]]
+; CHECK-LABEL: define void @loop_1(
+; CHECK-SAME: i32 [[VALUE:%.*]], i1 [[PREDENTRY:%.*]], i1 [[PREDD:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    [[PREDENTRY_INV:%.*]] = xor i1 [[PREDENTRY]], true
+; CHECK-NEXT:    br label %[[IRR_GUARD:.*]]
+; CHECK:       [[A:.*]]:
+; CHECK-NEXT:    br label %[[IRR_GUARD]]
+; CHECK:       [[B:.*]]:
+; CHECK-NEXT:    switch i32 [[VALUE]], label %[[EXIT:.*]] [
+; CHECK-NEXT:      i32 0, label %[[A]]
+; CHECK-NEXT:      i32 1, label %[[B_TARGET_B:.*]]
+; CHECK-NEXT:    ]
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    ret void
+; CHECK:       [[B_TARGET_B]]:
+; CHECK-NEXT:    br label %[[IRR_GUARD]]
+; CHECK:       [[IRR_GUARD]]:
+; CHECK-NEXT:    [[GUARD_B:%.*]] = phi i1 [ true, %[[B_TARGET_B]] ], [ true, %[[A]] ], [ [[PREDENTRY_INV]], %[[ENTRY]] ]
+; CHECK-NEXT:    br i1 [[GUARD_B]], label %[[B]], label %[[A]]
 ;
 entry:
   br i1 %PredEntry, label %A, label %B
@@ -42,3 +156,795 @@ B:
 exit:
   ret void
 }
+
+define void @switch_entry(i32 %val, i1 %c) {
+; CHECK-LABEL: define void @switch_entry(
+; CHECK-SAME: i32 [[VAL:%.*]], i1 [[C:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    switch i32 [[VAL]], label %[[ENTRY_TARGET_FALLTHROUGH:.*]] [
+; CHECK-NEXT:      i32 0, label %[[ENTRY_TARGET_INDIRECT:.*]]
+; CHECK-NEXT:    ]
+; CHECK:       [[FALLTHROUGH:.*]]:
+; CHECK-NEXT:    br i1 [[C]], label %[[IRR_GUARD:.*]], label %[[RET:.*]]
+; CHECK:       [[INDIRECT:.*]]:
+; CHECK-NEXT:    br label %[[FALLTHROUGH]]
+; CHECK:       [[RET]]:
+; CHECK-NEXT:    ret void
+; CHECK:       [[ENTRY_TARGET_FALLTHROUGH]]:
+; CHECK-NEXT:    br label %[[IRR_GUARD]]
+; CHECK:       [[ENTRY_TARGET_INDIRECT]]:
+; CHECK-NEXT:    br label %[[IRR_GUARD]]
+; CHECK:       [[IRR_GUARD]]:
+; CHECK-NEXT:    [[GUARD_INDIRECT:%.*]] = phi i1 [ true, %[[FALLTHROUGH]] ], [ false, %[[ENTRY_TARGET_FALLTHROUGH]] ], [ true, %[[ENTRY_TARGET_INDIRECT]] ]
+; CHECK-NEXT:    br i1 [[GUARD_INDIRECT]], label %[[INDIRECT]], label %[[FALLTHROUGH]]
+;
+entry:
+  switch i32 %val, label %fallthrough [
+  i32 0, label %indirect
+  ]
+fallthrough:
+  br i1 %c, label %indirect, label %ret
+indirect:
+  br label %fallthrough
+ret:
+  ret void
+}
+
+define i32 @switch_entry_targets_with_phi_nodes(i32 %val, i1 %c) {
+; CHECK-LABEL: define i32 @switch_entry_targets_with_phi_nodes(
+; CHECK-SAME: i32 [[VAL:%.*]], i1 [[C:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    switch i32 [[VAL]], label %[[ENTRY_TARGET_BLOCK:.*]] [
+; CHECK-NEXT:      i32 0, label %[[ENTRY_TARGET_BLOCK1:.*]]
+; CHECK-NEXT:    ]
+; CHECK:       [[BLOCK:.*]]:
+; CHECK-NEXT:    [[A:%.*]] = phi i32 [ 1, %[[BLOCK1:.*]] ], [ [[A_MOVED:%.*]], %[[IRR_GUARD:.*]] ]
+; CHECK-NEXT:    br label %[[IRR_GUARD]]
+; CHECK:       [[BLOCK1]]:
+; CHECK-NEXT:    br i1 [[C]], label %[[BLOCK]], label %[[RET:.*]]
+; CHECK:       [[RET]]:
+; CHECK-NEXT:    ret i32 [[B_MOVED:%.*]]
+; CHECK:       [[ENTRY_TARGET_BLOCK]]:
+; CHECK-NEXT:    br label %[[IRR_GUARD]]
+; CHECK:       [[ENTRY_TARGET_BLOCK1]]:
+; CHECK-NEXT:    br label %[[IRR_GUARD]]
+; CHECK:       [[IRR_GUARD]]:
+; CHECK-NEXT:    [[A_MOVED]] = phi i32 [ poison, %[[BLOCK]] ], [ 42, %[[ENTRY_TARGET_BLOCK]] ], [ poison, %[[ENTRY_TARGET_BLOCK1]] ]
+; CHECK-NEXT:    [[B_MOVED]] = phi i32 [ [[A]], %[[BLOCK]] ], [ poison, %[[ENTRY_TARGET_BLOCK]] ], [ 43, %[[ENTRY_TARGET_BLOCK1]] ]
+; CHECK-NEXT:    [[GUARD_BLOCK1:%.*]] = phi i1 [ true, %[[BLOCK]] ], [ false, %[[ENTRY_TARGET_BLOCK]] ], [ true, %[[ENTRY_TARGET_BLOCK1]] ]
+; CHECK-NEXT:    br i1 [[GUARD_BLOCK1]], label %[[BLOCK1]], label %[[BLOCK]]
+;
+entry:
+  switch i32 %val, label %block [
+  i32 0, label %block1
+  ]
+block:
+  %a = phi i32 [42, %entry], [1, %block1]
+  br label %block1
+block1:
+  %b = phi i32 [43, %entry], [%a, %block]
+  br i1 %c, label %block, label %ret
+ret:
+  ret i32 %b
+}
+
+define void @switch_entry_multiple_targets(i32 %val, i1 %c) {
+; CHECK-LABEL: define void @switch_entry_multiple_targets(
+; CHECK-SAME: i32 [[VAL:%.*]], i1 [[C:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    switch i32 [[VAL]], label %[[ENTRY_TARGET_FALLTHROUGH:.*]] [
+; CHECK-NEXT:      i32 0, label %[[ENTRY_TARGET_INDIRECT:.*]]
+; CHECK-NEXT:      i32 1, label %[[INDIRECT1:.*]]
+; CHECK-NEXT:      i32 2, label %[[INDIRECT2:.*]]
+; CHECK-NEXT:    ]
+; CHECK:       [[FALLTHROUGH:.*]]:
+; CHECK-NEXT:    br i1 [[C]], label %[[IRR_GUARD:.*]], label %[[RET:.*]]
+; CHECK:       [[INDIRECT:.*]]:
+; CHECK-NEXT:    br label %[[FALLTHROUGH]]
+; CHECK:       [[INDIRECT1]]:
+; CHECK-NEXT:    br label %[[IRR_GUARD]]
+; CHECK:       [[INDIRECT2]]:
+; CHECK-NEXT:    br label %[[RET]]
+; CHECK:       [[RET]]:
+; CHECK-NEXT:    ret void
+; CHECK:       [[ENTRY_TARGET_FALLTHROUGH]]:
+; CHECK-NEXT:    br label %[[IRR_GUARD]]
+; CHECK:       [[ENTRY_TARGET_INDIRECT]]:
+; CHECK-NEXT:    br label %[[IRR_GUARD]]
+; CHECK:       [[IRR_GUARD]]:
+; CHECK-NEXT:    [[GUARD_INDIRECT:%.*]] = phi i1 [ true, %[[FALLTHROUGH]] ], [ true, %[[INDIRECT1]] ], [ false, %[[ENTRY_TARGET_FALLTHROUGH]] ], [ true, %[[ENTRY_TARGET_INDIRECT]] ]
+; CHECK-NEXT:    br i1 [[GUARD_INDIRECT]], label %[[INDIRECT]], label %[[FALLTHROUGH]]
+;
+entry:
+  switch i32 %val, label %fallthrough [
+  i32 0, label %indirect
+  i32 1, label %indirect1
+  i32 2, label %indirect2
+  ]
+fallthrough:
+  br i1 %c, label %indirect, label %ret
+indirect:
+  br label %fallthrough
+indirect1:
+  br label %indirect
+indirect2:
+  br label %ret
+ret:
+  ret void
+}
+
+define void @switch_entry_multiple_targets1(i32 %val, i1 %c, i1 %d) {
+; CHECK-LABEL: define void @switch_entry_multiple_targets1(
+; CHECK-SAME: i32 [[VAL:%.*]], i1 [[C:%.*]], i1 [[D:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    switch i32 [[VAL]], label %[[ENTRY_TARGET_FALLTHROUGH:.*]] [
+; CHECK-NEXT:      i32 0, label %[[ENTRY_TARGET_INDIRECT:.*]]
+; CHECK-NEXT:      i32 1, label %[[ENTRY_TARGET_INDIRECT1:.*]]
+; CHECK-NEXT:      i32 2, label %[[INDIRECT2:.*]]
+; CHECK-NEXT:    ]
+; CHECK:       [[FALLTHROUGH:.*]]:
+; CHECK-NEXT:    br i1 [[C]], label %[[IRR_GUARD2:.*]], label %[[RET:.*]]
+; CHECK:       [[INDIRECT:.*]]:
+; CHECK-NEXT:    br i1 [[D]], label %[[FALLTHROUGH]], label %[[IRR_GUARD:.*]]
+; CHECK:       [[INDIRECT1:.*]]:
+; CHECK-NEXT:    br label %[[IRR_GUARD2]]
+; CHECK:       [[INDIRECT2]]:
+; CHECK-NEXT:    br label %[[RET]]
+; CHECK:       [[RET]]:
+; CHECK-NEXT:    ret void
+; CHECK:       [[ENTRY_TARGET_FALLTHROUGH]]:
+; CHECK-NEXT:    br label %[[IRR_GUARD]]
+; CHECK:       [[ENTRY_TARGET_INDIRECT]]:
+; CHECK-NEXT:    br label %[[IRR_GUARD]]
+; CHECK:       [[ENTRY_TARGET_INDIRECT1]]:
+; CHECK-NEXT:    br label %[[IRR_GUARD]]
+; CHECK:       [[IRR_GUARD]]:
+; CHECK-NEXT:    [[GUARD_INDIRECT1:%.*]] = phi i1 [ true, %[[INDIRECT]] ], [ false, %[[ENTRY_TARGET_FALLTHROUGH]] ], [ false, %[[ENTRY_TARGET_INDIRECT]] ], [ true, %[[ENTRY_TARGET_INDIRECT1]] ]
+; CHECK-NEXT:    [[GUARD_FALLTHROUGH:%.*]] = phi i1 [ false, %[[INDIRECT]] ], [ true, %[[ENTRY_TARGET_FALLTHROUGH]] ], [ false, %[[ENTRY_TARGET_INDIRECT]] ], [ false, %[[ENTRY_TARGET_INDIRECT1]] ]
+; CHECK-NEXT:    [[GUARD_FALLTHROUGH_INV:%.*]] = xor i1 [[GUARD_FALLTHROUGH]], true
+; CHECK-NEXT:    br i1 [[GUARD_INDIRECT1]], label %[[INDIRECT1]], label %[[IRR_GUARD1:.*]]
+; CHECK:       [[IRR_GUARD1]]:
+; CHECK-NEXT:    br label %[[IRR_GUARD2]]
+; CHECK:       [[IRR_GUARD2]]:
+; CHECK-NEXT:    [[GUARD_INDIRECT:%.*]] = phi i1 [ true, %[[FALLTHROUGH]] ], [ [[GUARD_FALLTHROUGH_INV]], %[[IRR_GUARD1]] ], [ true, %[[INDIRECT1]] ]
+; CHECK-NEXT:    br i1 [[GUARD_INDIRECT]], label %[[INDIRECT]], label %[[FALLTHROUGH]]
+;
+entry:
+  switch i32 %val, label %fallthrough [
+  i32 0, label %indirect
+  i32 1, label %indirect1
+  i32 2, label %indirect2
+  ]
+fallthrough:
+  br i1 %c, label %indirect, label %ret
+indirect:
+  br i1 %d, label %fallthrough, label %indirect1
+indirect1:
+  br label %indirect
+indirect2:
+  br label %ret
+ret:
+  ret void
+}
+
+define void @switch_header_no_indirect(i32 %val, i1 %c, i1 %d) {
+; CHECK-LABEL: define void @switch_header_no_indirect(
+; CHECK-SAME: i32 [[VAL:%.*]], i1 [[C:%.*]], i1 [[D:%.*]]) {
+; CHECK-NEXT:    [[D_INV:%.*]] = xor i1 [[D]], true
+; CHECK-NEXT:    br label %[[IRR_GUARD:.*]]
+; CHECK:       [[SWITCH_BB:.*]]:
+; CHECK-NEXT:    switch i32 [[VAL]], label %[[SWITCH_BB_TARGET_FALLTHROUGH:.*]] [
+; CHECK-NEXT:    ]
+; CHECK:       [[FALLTHROUGH:.*]]:
+; CHECK-NEXT:    br i1 [[C]], label %[[SWITCH_BB]], label %[[RET:.*]]
+; CHECK:       [[RET]]:
+; CHECK-NEXT:    ret void
+; CHECK:       [[SWITCH_BB_TARGET_FALLTHROUGH]]:
+; CHECK-NEXT:    br label %[[IRR_GUARD]]
+; CHECK:       [[IRR_GUARD]]:
+; CHECK-NEXT:    [[GUARD_FALLTHROUGH:%.*]] = phi i1 [ true, %[[SWITCH_BB_TARGET_FALLTHROUGH]] ], [ [[D_INV]], [[TMP0:%.*]] ]
+; CHECK-NEXT:    br i1 [[GUARD_FALLTHROUGH]], label %[[FALLTHROUGH]], label %[[SWITCH_BB]]
+;
+  br i1 %d, label %switch_bb, label %fallthrough
+switch_bb:
+  switch i32 %val, label %fallthrough []
+fallthrough:
+  br i1 %c, label %switch_bb, label %ret
+ret:
+  ret void
+}
+
+define void @switch_header(i32 %val, i1 %c, i1 %d) {
+; CHECK-LABEL: define void @switch_header(
+; CHECK-SAME: i32 [[VAL:%.*]], i1 [[C:%.*]], i1 [[D:%.*]]) {
+; CHECK-NEXT:    [[D_INV:%.*]] = xor i1 [[D]], true
+; CHECK-NEXT:    br label %[[IRR_GUARD:.*]]
+; CHECK:       [[SWITCH_BB:.*]]:
+; CHECK-NEXT:    switch i32 [[VAL]], label %[[SWITCH_BB_TARGET_FALLTHROUGH:.*]] [
+; CHECK-NEXT:      i32 0, label %[[INDIRECT:.*]]
+; CHECK-NEXT:    ]
+; CHECK:       [[INDIRECT]]:
+; CHECK-NEXT:    br label %[[RET:.*]]
+; CHECK:       [[FALLTHROUGH:.*]]:
+; CHECK-NEXT:    br i1 [[C]], label %[[SWITCH_BB]], label %[[RET]]
+; CHECK:       [[RET]]:
+; CHECK-NEXT:    ret void
+; CHECK:       [[SWITCH_BB_TARGET_FALLTHROUGH]]:
+; CHECK-NEXT:    br label %[[IRR_GUARD]]
+; CHECK:       [[IRR_GUARD]]:
+; CHECK-NEXT:    [[GUARD_FALLTHROUGH:%.*]] = phi i1 [ true, %[[SWITCH_BB_TARGET_FALLTHROUGH]] ], [ [[D_INV]], [[TMP0:%.*]] ]
+; CHECK-NEXT:    br i1 [[GUARD_FALLTHROUGH]], label %[[FALLTHROUGH]], label %[[SWITCH_BB]]
+;
+  br i1 %d, label %switch_bb, label %fallthrough
+switch_bb:
+  switch i32 %val, label %fallthrough [
+  i32 0, label %indirect
+  ]
+indirect:
+  br label %ret
+fallthrough:
+  br i1 %c, label %switch_bb, label %ret
+ret:
+  ret void
+}
+
+define void @switch_header_multiple_targets(i32 %val, i1 %c, i1 %d) {
+; CHECK-LABEL: define void @switch_header_multiple_targets(
+; CHECK-SAME: i32 [[VAL:%.*]], i1 [[C:%.*]], i1 [[D:%.*]]) {
+; CHECK-NEXT:    [[D_INV:%.*]] = xor i1 [[D]], true
+; CHECK-NEXT:    br label %[[IRR_GUARD:.*]]
+; CHECK:       [[SWITCH_BB:.*]]:
+; CHECK-NEXT:    switch i32 [[VAL]], label %[[SWITCH_BB_TARGET_FALLTHROUGH:.*]] [
+; CHECK-NEXT:      i32 0, label %[[INDIRECT:.*]]
+; CHECK-NEXT:      i32 1, label %[[INDIRECT1:.*]]
+; CHECK-NEXT:    ]
+; CHECK:       [[INDIRECT]]:
+; CHECK-NEXT:    br label %[[RET:.*]]
+; CHECK:       [[INDIRECT1]]:
+; CHECK-NEXT:    br label %[[SWITCH_BB]]
+; CHECK:       [[FALLTHROUGH:.*]]:
+; CHECK-NEXT:    br i1 [[C]], label %[[SWITCH_BB]], label %[[RET]]
+; CHECK:       [[RET]]:
+; CHECK-NEXT:    ret void
+; CHECK:       [[SWITCH_BB_TARGET_FALLTHROUGH]]:
+; CHECK-NEXT:    br label %[[IRR_GUARD]]
+; CHECK:       [[IRR_GUARD]]:
+; CHECK-NEXT:    [[GUARD_FALLTHROUGH:%.*]] = phi i1 [ true, %[[SWITCH_BB_TARGET_FALLTHROUGH]] ], [ [[D_INV]], [[TMP0:%.*]] ]
+; CHECK-NEXT:    br i1 [[GUARD_FALLTHROUGH]], label %[[FALLTHROUGH]], label %[[SWITCH_BB]]
+;
+  br i1 %d, label %switch_bb, label %fallthrough
+switch_bb:
+  switch i32 %val, label %fallthrough [
+  i32 0, label %indirect
+  i32 1, label %indirect1
+  ]
+indirect:
+  br label %ret
+indirect1:
+  br label %switch_bb
+fallthrough:
+  br i1 %c, label %switch_bb, label %ret
+ret:
+  ret void
+}
+
+define void @switch_regular(i32 %val, i1 %c, i1 %d) {
+; CHECK-LABEL: define void @switch_regular(
+; CHECK-SAME: i32 [[VAL:%.*]], i1 [[C:%.*]], i1 [[D:%.*]]) {
+; CHECK-NEXT:    [[C_INV:%.*]] = xor i1 [[C]], true
+; CHECK-NEXT:    br i1 [[D]], label %[[SWITCH_BB:.*]], label %[[NOSWITCH:.*]]
+; CHECK:       [[SWITCH_BB]]:
+; CHECK-NEXT:    switch i32 [[VAL]], label %[[FALLTHROUGH:.*]] [
+; CHECK-NEXT:      i32 0, label %[[INDIRECT:.*]]
+; CHECK-NEXT:    ]
+; CHECK:       [[FALLTHROUGH]]:
+; CHECK-NEXT:    br label %[[IRR_GUARD:.*]]
+; CHECK:       [[FALLTHROUGH1:.*]]:
+; CHECK-NEXT:    br label %[[IRR_GUARD]]
+; CHECK:       [[FALLTHROUGH2:.*]]:
+; CHECK-NEXT:    br i1 [[D]], label %[[FALLTHROUGH1]], label %[[RET:.*]]
+; CHECK:       [[INDIRECT]]:
+; CHECK-NEXT:    br label %[[IRR_GUARD1:.*]]
+; CHECK:       [[INDIRECT1:.*]]:
+; CHECK-NEXT:    br label %[[IRR_GUARD1]]
+; CHECK:       [[INDIRECT2:.*]]:
+; CHECK-NEXT:    br i1 [[D]], label %[[INDIRECT1]], label %[[RET]]
+; CHECK:       [[NOSWITCH]]:
+; CHECK-NEXT:    br label %[[IRR_GUARD2:.*]]
+; CHECK:       [[NOSWITCH1:.*]]:
+; CHECK-NEXT:    br label %[[IRR_GUARD2]]
+; CHECK:       [[NOSWITCH2:.*]]:
+; CHECK-NEXT:    br i1 [[D]], label %[[NOSWITCH1]], label %[[RET]]
+; CHECK:       [[RET]]:
+; CHECK-NEXT:    ret void
+; CHECK:       [[IRR_GUARD]]:
+; CHECK-NEXT:    [[GUARD_FALLTHROUGH2:%.*]] = phi i1 [ true, %[[FALLTHROUGH1]] ], [ [[C_INV]], %[[FALLTHROUGH]] ]
+; CHECK-NEXT:    br i1 [[GUARD_FALLTHROUGH2]], label %[[FALLTHROUGH2]], label %[[FALLTHROUGH1]]
+; CHECK:       [[IRR_GUARD1]]:
+; CHECK-NEXT:    [[GUARD_INDIRECT2:%.*]] = phi i1 [ true, %[[INDIRECT1]] ], [ [[C_INV]], %[[INDIRECT]] ]
+; CHECK-NEXT:    br i1 [[GUARD_INDIRECT2]], label %[[INDIRECT2]], label %[[INDIRECT1]]
+; CHECK:       [[IRR_GUARD2]]:
+; CHECK-NEXT:    [[GUARD_NOSWITCH2:%.*]] = phi i1 [ true, %[[NOSWITCH1]] ], [ [[C_INV]], %[[NOSWITCH]] ]
+; CHECK-NEXT:    br i1 [[GUARD_NOSWITCH2]], label %[[NOSWITCH2]], label %[[NOSWITCH1]]
+;
+  br i1 %d, label %switch_bb, label %noswitch
+switch_bb:
+  switch i32 %val, label %fallthrough [
+  i32 0, label %indirect
+  ]
+fallthrough:
+  br i1 %c, label %fallthrough1, label %fallthrough2
+fallthrough1:
+  br label %fallthrough2
+fallthrough2:
+  br i1 %d, label %fallthrough1, label %ret
+indirect:
+  br i1 %c, label %indirect1, label %indirect2
+indirect1:
+  br label %indirect2
+indirect2:
+  br i1 %d, label %indirect1, label %ret
+noswitch:
+  br i1 %c, label %noswitch1, label %noswitch2
+noswitch1:
+  br label %noswitch2
+noswitch2:
+  br i1 %d, label %noswitch1, label %ret
+ret:
+  ret void
+}
+
+define void @switch_regular1(i32 %val, i1 %c) {
+; CHECK-LABEL: define void @switch_regular1(
+; CHECK-SAME: i32 [[VAL:%.*]], i1 [[C:%.*]]) {
+; CHECK-NEXT:    [[C_INV:%.*]] = xor i1 [[C]], true
+; CHECK-NEXT:    br label %[[IRR_GUARD:.*]]
+; CHECK:       [[NOSWITCH:.*]]:
+; CHECK-NEXT:    br label %[[IRR_GUARD]]
+; CHECK:       [[SWITCH_BB:.*]]:
+; CHECK-NEXT:    switch i32 [[VAL]], label %[[RET:.*]] [
+; CHECK-NEXT:      i32 0, label %[[NOSWITCH]]
+; CHECK-NEXT:    ]
+; CHECK:       [[RET]]:
+; CHECK-NEXT:    ret void
+; CHECK:       [[IRR_GUARD]]:
+; CHECK-NEXT:    [[GUARD_SWITCH_BB:%.*]] = phi i1 [ true, %[[NOSWITCH]] ], [ [[C_INV]], [[TMP0:%.*]] ]
+; CHECK-NEXT:    br i1 [[GUARD_SWITCH_BB]], label %[[SWITCH_BB]], label %[[NOSWITCH]]
+;
+  br i1 %c, label %noswitch, label %switch_bb
+noswitch:
+  br label %switch_bb
+switch_bb:
+  switch i32 %val, label %ret [
+  i32 0, label %noswitch
+  ]
+ret:
+  ret void
+}
+
+define void @switch_header_and_regular(i32 %val, i1 %c) {
+; CHECK-LABEL: define void @switch_header_and_regular(
+; CHECK-SAME: i32 [[VAL:%.*]], i1 [[C:%.*]]) {
+; CHECK-NEXT:    br label %[[SWITCH_HEADER:.*]]
+; CHECK:       [[SWITCH_HEADER]]:
+; CHECK-NEXT:    switch i32 [[VAL]], label %[[SWITCH_HEADER_TARGET_MID:.*]] [
+; CHECK-NEXT:      i32 0, label %[[SWITCH_HEADER_TARGET_SWITCH_REGULAR:.*]]
+; CHECK-NEXT:    ]
+; CHECK:       [[MID:.*]]:
+; CHECK-NEXT:    br i1 [[C]], label %[[IRR_GUARD:.*]], label %[[RET:.*]]
+; CHECK:       [[SWITCH_REGULAR:.*]]:
+; CHECK-NEXT:    switch i32 [[VAL]], label %[[SWITCH_HEADER]] [
+; CHECK-NEXT:      i32 0, label %[[MID]]
+; CHECK-NEXT:    ]
+; CHECK:       [[RET]]:
+; CHECK-NEXT:    ret void
+; CHECK:       [[SWITCH_HEADER_TARGET_MID]]:
+; CHECK-NEXT:    br label %[[IRR_GUARD]]
+; CHECK:       [[SWITCH_HEADER_TARGET_SWITCH_REGULAR]]:
+; CHECK-NEXT:    br label %[[IRR_GUARD]]
+; CHECK:       [[IRR_GUARD]]:
+; CHECK-NEXT:    [[GUARD_SWITCH_REGULAR:%.*]] = phi i1 [ true, %[[MID]] ], [ false, %[[SWITCH_HEADER_TARGET_MID]] ], [ true, %[[SWITCH_HEADER_TARGET_SWITCH_REGULAR]] ]
+; CHECK-NEXT:    br i1 [[GUARD_SWITCH_REGULAR]], label %[[SWITCH_REGULAR]], label %[[MID]]
+;
+  br label %switch_header
+switch_header:
+  switch i32 %val, label %mid [
+  i32 0, label %switch_regular
+  ]
+mid:
+  br i1 %c, label %switch_regular, label %ret
+switch_regular:
+  switch i32 %val, label %switch_header [
+  i32 0, label %mid
+  ]
+ret:
+  ret void
+}
+
+define void @switch_only(i32 %val, i1 %c) {
+; CHECK-LABEL: define void @switch_only(
+; CHECK-SAME: i32 [[VAL:%.*]], i1 [[C:%.*]]) {
+; CHECK-NEXT:  [[SWITCH_ENTRY:.*:]]
+; CHECK-NEXT:    switch i32 [[VAL]], label %[[SWITCH_ENTRY_TARGET_SWITCH_HEADER:.*]] [
+; CHECK-NEXT:      i32 0, label %[[SWITCH_ENTRY_TARGET_SWITCH_BLOCK:.*]]
+; CHECK-NEXT:    ]
+; CHECK:       [[SWITCH_HEADER:.*]]:
+; CHECK-NEXT:    switch i32 [[VAL]], label %[[SWITCH_HEADER_TARGET_SWITCH_BLOCK:.*]] [
+; CHECK-NEXT:    ]
+; CHECK:       [[SWITCH_BLOCK:.*]]:
+; CHECK-NEXT:    switch i32 [[VAL]], label %[[SWITCH_HEADER]] [
+; CHECK-NEXT:      i32 0, label %[[RET:.*]]
+; CHECK-NEXT:    ]
+; CHECK:       [[RET]]:
+; CHECK-NEXT:    ret void
+; CHECK:       [[SWITCH_HEADER_TARGET_SWITCH_BLOCK]]:
+; CHECK-NEXT:    br label %[[IRR_GUARD:.*]]
+; CHECK:       [[SWITCH_ENTRY_TARGET_SWITCH_HEADER]]:
+; CHECK-NEXT:    br label %[[IRR_GUARD]]
+; CHECK:       [[SWITCH_ENTRY_TARGET_SWITCH_BLOCK]]:
+; CHECK-NEXT:    br label %[[IRR_GUARD]]
+; CHECK:       [[IRR_GUARD]]:
+; CHECK-NEXT:    [[GUARD_SWITCH_BLOCK:%.*]] = phi i1 [ true, %[[SWITCH_HEADER_TARGET_SWITCH_BLOCK]] ], [ false, %[[SWITCH_ENTRY_TARGET_SWITCH_HEADER]] ], [ true, %[[SWITCH_ENTRY_TARGET_SWITCH_BLOCK]] ]
+; CHECK-NEXT:    br i1 [[GUARD_SWITCH_BLOCK]], label %[[SWITCH_BLOCK]], label %[[SWITCH_HEADER]]
+;
+switch_entry:
+  switch i32 %val, label %switch_header [
+  i32 0, label %switch_block
+  ]
+switch_header:
+  switch i32 %val, label %switch_block []
+switch_block:
+  switch i32 %val, label %switch_header [
+  i32 0, label %ret
+  ]
+ret:
+  ret void
+}
+
+define void @entry_multiple_switch(i32 %val, i1 %a, i1 %b, i1 %c) {
+; CHECK-LABEL: define void @entry_multiple_switch(
+; CHECK-SAME: i32 [[VAL:%.*]], i1 [[A:%.*]], i1 [[B:%.*]], i1 [[C:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    br i1 [[A]], label %[[SW1:.*]], label %[[IRR_GUARD:.*]]
+; CHECK:       [[SW1]]:
+; CHECK-NEXT:    switch i32 [[VAL]], label %[[SW1_TARGET_BLOCK:.*]] [
+; CHECK-NEXT:      i32 0, label %[[SW1_TARGET_SW2:.*]]
+; CHECK-NEXT:      i32 1, label %[[SW1_TARGET_BLOCK1:.*]]
+; CHECK-NEXT:    ]
+; CHECK:       [[BLOCK:.*]]:
+; CHECK-NEXT:    br i1 [[B]], label %[[IRR_GUARD]], label %[[BLOCK1:.*]]
+; CHECK:       [[SW2:.*]]:
+; CHECK-NEXT:    switch i32 [[VAL]], label %[[SW2_TARGET_BLOCK1:.*]] [
+; CHECK-NEXT:      i32 0, label %[[SW2_TARGET_BLOCK:.*]]
+; CHECK-NEXT:    ]
+; CHECK:       [[BLOCK1]]:
+; CHECK-NEXT:    br i1 [[C]], label %[[IRR_GUARD2:.*]], label %[[EXIT:.*]]
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    ret void
+; CHECK:       [[SW1_TARGET_BLOCK]]:
+; CHECK-NEXT:    br label %[[IRR_GUARD]]
+; CHECK:       [[SW1_TARGET_SW2]]:
+; CHECK-NEXT:    br label %[[IRR_GUARD]]
+; CHECK:       [[SW1_TARGET_BLOCK1]]:
+; CHECK-NEXT:    br label %[[IRR_GUARD]]
+; CHECK:       [[IRR_GUARD]]:
+; CHECK-NEXT:    [[GUARD_SW2:%.*]] = phi i1 [ true, %[[BLOCK]] ], [ false, %[[SW1_TARGET_BLOCK]] ], [ true, %[[SW1_TARGET_SW2]] ], [ false, %[[SW1_TARGET_BLOCK1]] ], [ true, %[[ENTRY]] ]
+; CHECK-NEXT:    [[GUARD_BLOCK:%.*]] = phi i1 [ false, %[[BLOCK]] ], [ true, %[[SW1_TARGET_BLOCK]] ], [ false, %[[SW1_TARGET_SW2]] ], [ false, %[[SW1_TARGET_BLOCK1]] ], [ false, %[[ENTRY]] ]
+; CHECK-NEXT:    br i1 [[GUARD_SW2]], label %[[SW2]], label %[[IRR_GUARD1:.*]]
+; CHECK:       [[IRR_GUARD1]]:
+; CHECK-NEXT:    br label %[[IRR_GUARD2]]
+; CHECK:       [[SW2_TARGET_BLOCK1]]:
+; CHECK-NEXT:    br label %[[IRR_GUARD2]]
+; CHECK:       [[SW2_TARGET_BLOCK]]:
+; CHECK-NEXT:    br label %[[IRR_GUARD2]]
+; CHECK:       [[IRR_GUARD2]]:
+; CHECK-NEXT:    [[GUARD_BLOCK3:%.*]] = phi i1 [ true, %[[BLOCK1]] ], [ [[GUARD_BLOCK]], %[[IRR_GUARD1]] ], [ false, %[[SW2_TARGET_BLOCK1]] ], [ true, %[[SW2_TARGET_BLOCK]] ]
+; CHECK-NEXT:    br i1 [[GUARD_BLOCK3]], label %[[BLOCK]], label %[[BLOCK1]]
+;
+entry:
+  br i1 %a, label %sw1, label %sw2
+sw1:
+  switch i32 %val, label %block [
+  i32 0, label %sw2
+  i32 1, label %block1
+  ]
+block:
+  br i1 %b, label %sw2, label %block1
+sw2:
+  switch i32 %val, label %block1 [
+  i32 0, label %block
+  ]
+block1:
+  br i1 %c, label %block, label %exit
+exit:
+  ret void
+}
+
+define void @switch_exit_with_separate_entries(i32 %val, i1 %a, i1 %b, i1 %c) {
+; CHECK-LABEL: define void @switch_exit_with_separate_entries(
+; CHECK-SAME: i32 [[VAL:%.*]], i1 [[A:%.*]], i1 [[B:%.*]], i1 [[C:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    [[C_INV:%.*]] = xor i1 [[C]], true
+; CHECK-NEXT:    [[A_INV:%.*]] = xor i1 [[A]], true
+; CHECK-NEXT:    br label %[[IRR_GUARD:.*]]
+; CHECK:       [[L1:.*]]:
+; CHECK-NEXT:    br i1 [[B]], label %[[SW:.*]], label %[[IRR_GUARD]]
+; CHECK:       [[L2:.*]]:
+; CHECK-NEXT:    br label %[[IRR_GUARD1:.*]]
+; CHECK:       [[SW]]:
+; CHECK-NEXT:    switch i32 [[VAL]], label %[[EXIT:.*]] [
+; CHECK-NEXT:      i32 0, label %[[SW_TARGET_L1:.*]]
+; CHECK-NEXT:    ]
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    ret void
+; CHECK:       [[IRR_GUARD]]:
+; CHECK-NEXT:    [[GUARD_L2:%.*]] = phi i1 [ true, %[[L1]] ], [ [[A_INV]], %[[ENTRY]] ]
+; CHECK-NEXT:    br i1 [[GUARD_L2]], label %[[L2]], label %[[IRR_GUARD1]]
+; CHECK:       [[SW_TARGET_L1]]:
+; CHECK-NEXT:    br label %[[IRR_GUARD1]]
+; CHECK:       [[IRR_GUARD1]]:
+; CHECK-NEXT:    [[GUARD_L1:%.*]] = phi i1 [ true, %[[SW_TARGET_L1]] ], [ true, %[[IRR_GUARD]] ], [ [[C_INV]], %[[L2]] ]
+; CHECK-NEXT:    br i1 [[GUARD_L1]], label %[[L1]], label %[[SW]]
+;
+entry:
+  br i1 %a, label %l1, label %l2
+l1:
+  br i1 %b, label %sw, label %l2
+l2:
+  br i1 %c, label %sw, label %l1
+sw:
+  switch i32 %val, label %exit [
+  i32 0, label %l1
+  ]
+exit:
+  ret void
+}
+
+define void @switch_exit_with_separate_entries1(i32 %val, i1 %a, i1 %b) {
+; CHECK-LABEL: define void @switch_exit_with_separate_entries1(
+; CHECK-SAME: i32 [[VAL:%.*]], i1 [[A:%.*]], i1 [[B:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    [[A_INV:%.*]] = xor i1 [[A]], true
+; CHECK-NEXT:    br label %[[IRR_GUARD:.*]]
+; CHECK:       [[LOOP1:.*]]:
+; CHECK-NEXT:    br i1 [[B]], label %[[SW:.*]], label %[[IRR_GUARD]]
+; CHECK:       [[LOOP2:.*]]:
+; CHECK-NEXT:    br label %[[LOOP1]]
+; CHECK:       [[SW]]:
+; CHECK-NEXT:    switch i32 [[VAL]], label %[[EXIT:.*]] [
+; CHECK-NEXT:      i32 0, label %[[SW_TARGET_LOOP2:.*]]
+; CHECK-NEXT:    ]
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    ret void
+; CHECK:       [[SW_TARGET_LOOP2]]:
+; CHECK-NEXT:    br label %[[IRR_GUARD]]
+; CHECK:       [[IRR_GUARD]]:
+; CHECK-NEXT:    [[GUARD_LOOP2:%.*]] = phi i1 [ true, %[[SW_TARGET_LOOP2]] ], [ true, %[[LOOP1]] ], [ [[A_INV]], %[[ENTRY]] ]
+; CHECK-NEXT:    br i1 [[GUARD_LOOP2]], label %[[LOOP2]], label %[[LOOP1]]
+;
+entry:
+  br i1 %a, label %loop1, label %loop2
+loop1:
+  br i1 %b, label %sw, label %loop2
+loop2:
+  br label %loop1
+sw:
+  switch i32 %val, label %exit [
+  i32 0, label %loop2
+  ]
+exit:
+  ret void
+}
+
+define void @switch_only_multiple(i32 %val, i1 %a, i1 %b, i1 %c) {
+; CHECK-LABEL: define void @switch_only_multiple(
+; CHECK-SAME: i32 [[VAL:%.*]], i1 [[A:%.*]], i1 [[B:%.*]], i1 [[C:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    switch i32 [[VAL]], label %[[ENTRY_TARGET_SW1:.*]] [
+; CHECK-NEXT:      i32 0, label %[[ENTRY_TARGET_SW2:.*]]
+; CHECK-NEXT:      i32 1, label %[[ENTRY_TARGET_SW3:.*]]
+; CHECK-NEXT:    ]
+; CHECK:       [[SW1:.*]]:
+; CHECK-NEXT:    switch i32 [[VAL]], label %[[SW2:.*]] [
+; CHECK-NEXT:      i32 0, label %[[SW1_TARGET_SW3:.*]]
+; CHECK-NEXT:    ]
+; CHECK:       [[SW2]]:
+; CHECK-NEXT:    switch i32 [[VAL]], label %[[SW2_TARGET_SW3:.*]] [
+; CHECK-NEXT:      i32 0, label %[[SW2_TARGET_SW1:.*]]
+; CHECK-NEXT:    ]
+; CHECK:       [[SW3:.*]]:
+; CHECK-NEXT:    switch i32 [[VAL]], label %[[SW3_TARGET_SW1:.*]] [
+; CHECK-NEXT:      i32 0, label %[[EXIT:.*]]
+; CHECK-NEXT:    ]
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    ret void
+; CHECK:       [[SW2_TARGET_SW3]]:
+; CHECK-NEXT:    br label %[[IRR_GUARD:.*]]
+; CHECK:       [[SW1_TARGET_SW3]]:
+; CHECK-NEXT:    br label %[[IRR_GUARD]]
+; CHECK:       [[ENTRY_TARGET_SW1]]:
+; CHECK-NEXT:    br label %[[IRR_GUARD]]
+; CHECK:       [[ENTRY_TARGET_SW2]]:
+; CHECK-NEXT:    br label %[[IRR_GUARD]]
+; CHECK:       [[ENTRY_TARGET_SW3]]:
+; CHECK-NEXT:    br label %[[IRR_GUARD]]
+; CHECK:       [[IRR_GUARD]]:
+; CHECK-NEXT:    [[GUARD_SW3:%.*]] = phi i1 [ true, %[[SW2_TARGET_SW3]] ], [ true, %[[SW1_TARGET_SW3]] ], [ false, %[[ENTRY_TARGET_SW1]] ], [ false, %[[ENTRY_TARGET_SW2]] ], [ true, %[[ENTRY_TARGET_SW3]] ]
+; CHECK-NEXT:    [[GUARD_SW1:%.*]] = phi i1 [ false, %[[SW2_TARGET_SW3]] ], [ false, %[[SW1_TARGET_SW3]] ], [ true, %[[ENTRY_TARGET_SW1]] ], [ false, %[[ENTRY_TARGET_SW2]] ], [ false, %[[ENTRY_TARGET_SW3]] ]
+; CHECK-NEXT:    br i1 [[GUARD_SW3]], label %[[SW3]], label %[[IRR_GUARD1:.*]]
+; CHECK:       [[IRR_GUARD1]]:
+; CHECK-NEXT:    br label %[[IRR_GUARD2:.*]]
+; CHECK:       [[SW2_TARGET_SW1]]:
+; CHECK-NEXT:    br label %[[IRR_GUARD2]]
+; CHECK:       [[SW3_TARGET_SW1]]:
+; CHECK-NEXT:    br label %[[IRR_GUARD2]]
+; CHECK:       [[IRR_GUARD2]]:
+; CHECK-NEXT:    [[GUARD_SW13:%.*]] = phi i1 [ true, %[[SW2_TARGET_SW1]] ], [ [[GUARD_SW1]], %[[IRR_GUARD1]] ], [ true, %[[SW3_TARGET_SW1]] ]
+; CHECK-NEXT:    br i1 [[GUARD_SW13]], label %[[SW1]], label %[[SW2]]
+;
+entry:
+  switch i32 %val, label %sw1 [
+  i32 0, label %sw2
+  i32 1, label %sw3
+  ]
+sw1:
+  switch i32 %val, label %sw2 [
+  i32 0, label %sw3
+  ]
+sw2:
+  switch i32 %val, label %sw3 [
+  i32 0, label %sw1
+  ]
+sw3:
+  switch i32 %val, label %sw1 [
+  i32 0, label %exit
+  ]
+exit:
+  ret void
+}
+
+define void @switch_bypass(i32 %val, i1 %a, i1 %b, i1 %c) {
+; CHECK-LABEL: define void @switch_bypass(
+; CHECK-SAME: i32 [[VAL:%.*]], i1 [[A:%.*]], i1 [[B:%.*]], i1 [[C:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    [[B_INV:%.*]] = xor i1 [[B]], true
+; CHECK-NEXT:    [[A_INV:%.*]] = xor i1 [[A]], true
+; CHECK-NEXT:    br label %[[IRR_GUARD:.*]]
+; CHECK:       [[SW:.*]]:
+; CHECK-NEXT:    switch i32 [[VAL]], label %[[L2:.*]] [
+; CHECK-NEXT:      i32 0, label %[[SW_TARGET_L1:.*]]
+; CHECK-NEXT:    ]
+; CHECK:       [[L1:.*]]:
+; CHECK-NEXT:    br label %[[IRR_GUARD1:.*]]
+; CHECK:       [[L2]]:
+; CHECK-NEXT:    br i1 [[C]], label %[[IRR_GUARD1]], label %[[EXIT:.*]]
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    ret void
+; CHECK:       [[SW_TARGET_L1]]:
+; CHECK-NEXT:    br label %[[IRR_GUARD]]
+; CHECK:       [[IRR_GUARD]]:
+; CHECK-NEXT:    [[GUARD_L1:%.*]] = phi i1 [ true, %[[SW_TARGET_L1]] ], [ [[A_INV]], %[[ENTRY]] ]
+; CHECK-NEXT:    br i1 [[GUARD_L1]], label %[[L1]], label %[[IRR_GUARD1]]
+; CHECK:       [[IRR_GUARD1]]:
+; CHECK-NEXT:    [[GUARD_SW:%.*]] = phi i1 [ true, %[[L2]] ], [ true, %[[IRR_GUARD]] ], [ [[B_INV]], %[[L1]] ]
+; CHECK-NEXT:    br i1 [[GUARD_SW]], label %[[SW]], label %[[L2]]
+;
+entry:
+  br i1 %a, label %sw, label %l1
+sw:
+  switch i32 %val, label %l2 [
+  i32 0, label %l1
+  ]
+l1:
+  br i1 %b, label %l2, label %sw
+l2:
+  br i1 %c, label %sw, label %exit
+exit:
+  ret void
+}
+
+define void @switch_multiple_with_exit(i32 %val, i1 %a, i1 %b, i1 %c) {
+; CHECK-LABEL: define void @switch_multiple_with_exit(
+; CHECK-SAME: i32 [[VAL:%.*]], i1 [[A:%.*]], i1 [[B:%.*]], i1 [[C:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    switch i32 [[VAL]], label %[[ENTRY_TARGET_L1:.*]] [
+; CHECK-NEXT:      i32 0, label %[[ENTRY_TARGET_L2:.*]]
+; CHECK-NEXT:      i32 1, label %[[EXIT:.*]]
+; CHECK-NEXT:      i32 2, label %[[ENTRY_TARGET_L3:.*]]
+; CHECK-NEXT:    ]
+; CHECK:       [[L1:.*]]:
+; CHECK-NEXT:    br i1 [[A]], label %[[L2:.*]], label %[[IRR_GUARD:.*]]
+; CHECK:       [[L2]]:
+; CHECK-NEXT:    br i1 [[B]], label %[[IRR_GUARD2:.*]], label %[[EXIT]]
+; CHECK:       [[L3:.*]]:
+; CHECK-NEXT:    br i1 [[C]], label %[[IRR_GUARD2]], label %[[EXIT]]
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    ret void
+; CHECK:       [[ENTRY_TARGET_L1]]:
+; CHECK-NEXT:    br label %[[IRR_GUARD]]
+; CHECK:       [[ENTRY_TARGET_L2]]:
+; CHECK-NEXT:    br label %[[IRR_GUARD]]
+; CHECK:       [[ENTRY_TARGET_L3]]:
+; CHECK-NEXT:    br label %[[IRR_GUARD]]
+; CHECK:       [[IRR_GUARD]]:
+; CHECK-NEXT:    [[GUARD_L3:%.*]] = phi i1 [ true, %[[L1]] ], [ false, %[[ENTRY_TARGET_L1]] ], [ false, %[[ENTRY_TARGET_L2]] ], [ true, %[[ENTRY_TARGET_L3]] ]
+; CHECK-NEXT:    [[GUARD_L1:%.*]] = phi i1 [ false, %[[L1]] ], [ true, %[[ENTRY_TARGET_L1]] ], [ false, %[[ENTRY_TARGET_L2]] ], [ false, %[[ENTRY_TARGET_L3]] ]
+; CHECK-NEXT:    br i1 [[GUARD_L3]], label %[[L3]], label %[[IRR_GUARD1:.*]]
+; CHECK:       [[IRR_GUARD1]]:
+; CHECK-NEXT:    br label %[[IRR_GUARD2]]
+; CHECK:       [[IRR_GUARD2]]:
+; CHECK-NEXT:    [[GUARD_L13:%.*]] = phi i1 [ true, %[[L2]] ], [ [[GUARD_L1]], %[[IRR_GUARD1]] ], [ true, %[[L3]] ]
+; CHECK-NEXT:    br i1 [[GUARD_L13]], label %[[L1]], label %[[L2]]
+;
+entry:
+  switch i32 %val, label %l1 [
+  i32 0, label %l2
+  i32 1, label %exit
+  i32 2, label %l3
+  ]
+l1:
+  br i1 %a, label %l2, label %l3
+l2:
+  br i1 %b, label %l1, label %exit
+l3:
+  br i1 %c, label %l1, label %exit
+exit:
+  ret void
+}
+
+define void @switch_nested(i32 %val, i1 %c, i1 %d) {
+; CHECK-LABEL: define void @switch_nested(
+; CHECK-SAME: i32 [[VAL:%.*]], i1 [[C:%.*]], i1 [[D:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    switch i32 [[VAL]], label %[[ENTRY_TARGET_H:.*]] [
+; CHECK-NEXT:      i32 0, label %[[ENTRY_TARGET_B:.*]]
+; CHECK-NEXT:    ]
+; CHECK:       [[H:.*]]:
+; CHECK-NEXT:    br label %[[IRR_GUARD1:.*]]
+; CHECK:       [[B:.*]]:
+; CHECK-NEXT:    switch i32 [[VAL]], label %[[H]] [
+; CHECK-NEXT:      i32 0, label %[[B_TARGET_BH:.*]]
+; CHECK-NEXT:      i32 1, label %[[B_TARGET_BB:.*]]
+; CHECK-NEXT:    ]
+; CHECK:       [[BH:.*]]:
+; CHECK-NEXT:    br label %[[IRR_GUARD:.*]]
+; CHECK:       [[BB:.*]]:
+; CHECK-NEXT:    br i1 [[C]], label %[[BH]], label %[[RET:.*]]
+; CHECK:       [[RET]]:
+; CHECK-NEXT:    ret void
+; CHECK:       [[B_TARGET_BH]]:
+; CHECK-NEXT:    br label %[[IRR_GUARD]]
+; CHECK:       [[B_TARGET_BB]]:
+; CHECK-NEXT:    br label %[[IRR_GUARD]]
+; CHECK:       [[IRR_GUARD]]:
+; CHECK-NEXT:    [[GUARD_BB:%.*]] = phi i1 [ true, %[[BH]] ], [ false, %[[B_TARGET_BH]] ], [ true, %[[B_TARGET_BB]] ]
+; CHECK-NEXT:    br i1 [[GUARD_BB]], label %[[BB]], label %[[BH]]
+; CHECK:       [[ENTRY_TARGET_H]]:
+; CHECK-NEXT:    br label %[[IRR_GUARD1]]
+; CHECK:       [[ENTRY_TARGET_B]]:
+; CHECK-NEXT:    br label %[[IRR_GUARD1]]
+; CHECK:       [[IRR_GUARD1]]:
+; CHECK-NEXT:    [[GUARD_B:%.*]] = phi i1 [ true, %[[H]] ], [ false, %[[ENTRY_TARGET_H]] ], [ true, %[[ENTRY_TARGET_B]] ]
+; CHECK-NEXT:    br i1 [[GUARD_B]], label %[[B]], label %[[H]]
+;
+entry:
+  switch i32 %val, label %h [
+  i32 0, label %b
+  ]
+h:
+  br label %b
+b:
+  switch i32 %val, label %h [
+  i32 0, label %bh
+  i32 1, label %bb
+  ]
+bh:
+  br label %bb
+bb:
+  br i1 %c, label %bh, label %ret
+ret:
+  ret void
+}
+;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
+; CYCLES-AFTER: {{.*}}
+; CYCLES-BEFORE: {{.*}}
diff --git a/llvm/test/Transforms/FixIrreducible/unsupported-terminator.ll b/llvm/test/Transforms/FixIrreducible/unsupported-terminator.ll
index f1be342c3d324..02a4ec802cd33 100644
--- a/llvm/test/Transforms/FixIrreducible/unsupported-terminator.ll
+++ b/llvm/test/Transforms/FixIrreducible/unsupported-terminator.ll
@@ -1,19 +1,16 @@
 ; RUN: not opt < %s -passes=fix-irreducible -S 2>&1 | FileCheck %s
-; CHECK: LLVM ERROR: unsupported block terminator: fix-irreducible only supports br and callbr instructions
+; CHECK: LLVM ERROR: unsupported block terminator: fix-irreducible only supports br, callbr, and switch instructions
 
-define void @loop_1(i32 %Value, i1 %PredEntry) {
+define i32 @test(i1 %cond) {
 entry:
-  br i1 %PredEntry, label %A, label %B
+  %target = select i1 %cond,
+                   ptr blockaddress(@test, %then),
+                   ptr blockaddress(@test, %else)
+  indirectbr ptr %target, [label %then, label %else]
 
-A:
-  br label %B
+then:
+  br label %else
 
-B:
-  switch i32 %Value, label %exit [
-    i32 0, label %A
-    i32 1, label %B
-  ]
-
-exit:
-  ret void
-}
+else:
+  br label %then
+}
\ No newline at end of file

>From ab0ee818fbaf181373bd3258b70ec3592e86d640 Mon Sep 17 00:00:00 2001
From: Lukas <dev at lukas-hertel.de>
Date: Sat, 4 Jul 2026 10:29:28 +0200
Subject: [PATCH 2/2] Address review feedback and add switch tests

---
 .../llvm/Transforms/Utils/BasicBlockUtils.h   |   2 +-
 .../Transforms/FixIrreducible/bug45623.ll     | 131 ++-
 llvm/test/Transforms/FixIrreducible/nested.ll | 869 ++++++++++++++++--
 .../Transforms/FixIrreducible/unreachable.ll  |  23 +
 .../FixIrreducible/unsupported-terminator.ll  |   2 +-
 llvm/test/Transforms/UnifyLoopExits/basic.ll  | 170 +++-
 .../UnifyLoopExits/integer_guards.ll          | 503 +++++++++-
 llvm/test/Transforms/UnifyLoopExits/nested.ll | 168 +++-
 .../Transforms/UnifyLoopExits/restore-ssa.ll  | 275 +++++-
 llvm/test/Transforms/UnifyLoopExits/switch.ll |  29 +
 .../Transforms/UnifyLoopExits/undef-phis.ll   |  81 +-
 11 files changed, 2109 insertions(+), 144 deletions(-)

diff --git a/llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h b/llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h
index abf19177bd7da..cc6b13cf28714 100644
--- a/llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h
+++ b/llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h
@@ -267,7 +267,7 @@ LLVM_ABI BasicBlock *SplitEdge(BasicBlock *From, BasicBlock *To,
                                MemorySSAUpdater *MSSAU = nullptr,
                                const Twine &BBName = "");
 
-/// \brief Create a new intermediate target block for a callbr and switch edges.
+/// \brief Create a new intermediate target block for a callbr or switch edge.
 ///
 /// Create a new basic block between a callbr or switch instruction and one of
 /// its successors. The new block replaces the original successor in the
diff --git a/llvm/test/Transforms/FixIrreducible/bug45623.ll b/llvm/test/Transforms/FixIrreducible/bug45623.ll
index b6dd6fb9e6fcb..d03d1a1aaf9a9 100644
--- a/llvm/test/Transforms/FixIrreducible/bug45623.ll
+++ b/llvm/test/Transforms/FixIrreducible/bug45623.ll
@@ -98,16 +98,16 @@ define void @tre_tnfa_run_backtrack_callbr(i1 %arg) {
 ; CHECK-NEXT:            to label [[RETRY:%.*]] []
 ; CHECK:       retry:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[ARG:%.*]])
-; CHECK-NEXT:            to label [[RETRY_TARGET_BACKTRACK:%.*]] [label %retry.target.while.body248]
+; CHECK-NEXT:            to label [[RETRY_TARGET_BACKTRACK:%.*]] [label [[RETRY_TARGET_WHILE_BODY248:%.*]]]
 ; CHECK:       while.body248:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[ARG]])
-; CHECK-NEXT:            to label [[IF_THEN250:%.*]] [label %if.end275]
+; CHECK-NEXT:            to label [[IF_THEN250:%.*]] [label [[IF_END275:%.*]]]
 ; CHECK:       if.then250:
 ; CHECK-NEXT:    callbr void asm "", ""()
 ; CHECK-NEXT:            to label [[FOR_COND264:%.*]] []
 ; CHECK:       for.cond264:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[ARG]])
-; CHECK-NEXT:            to label [[FOR_BODY267:%.*]] [label %backtrack]
+; CHECK-NEXT:            to label [[FOR_BODY267:%.*]] [label [[BACKTRACK:%.*]]]
 ; CHECK:       for.body267:
 ; CHECK-NEXT:    callbr void asm "", ""()
 ; CHECK-NEXT:            to label [[FOR_COND264]] []
@@ -116,22 +116,22 @@ define void @tre_tnfa_run_backtrack_callbr(i1 %arg) {
 ; CHECK-NEXT:            to label [[FOR_COND342:%.*]] []
 ; CHECK:       for.cond342:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[ARG]])
-; CHECK-NEXT:            to label [[FOR_BODY345:%.*]] [label %for.end580]
+; CHECK-NEXT:            to label [[FOR_BODY345:%.*]] [label [[FOR_END580:%.*]]]
 ; CHECK:       for.body345:
 ; CHECK-NEXT:    callbr void asm "", ""()
 ; CHECK-NEXT:            to label [[FOR_COND342]] []
 ; CHECK:       for.end580:
 ; CHECK-NEXT:    callbr void asm "", ""()
-; CHECK-NEXT:            to label [[BACKTRACK:%.*]] []
+; CHECK-NEXT:            to label [[BACKTRACK]] []
 ; CHECK:       backtrack:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[ARG]])
-; CHECK-NEXT:            to label [[IF_THEN595:%.*]] [label %if.else629]
+; CHECK-NEXT:            to label [[IF_THEN595:%.*]] [label [[IF_ELSE629:%.*]]]
 ; CHECK:       if.then595:
 ; CHECK-NEXT:    callbr void asm "", ""()
 ; CHECK-NEXT:            to label [[FOR_COND616:%.*]] []
 ; CHECK:       for.cond616:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[ARG]])
-; CHECK-NEXT:            to label [[FOR_BODY619:%.*]] [label %for.end626]
+; CHECK-NEXT:            to label [[FOR_BODY619:%.*]] [label [[FOR_END626:%.*]]]
 ; CHECK:       for.body619:
 ; CHECK-NEXT:    callbr void asm "", ""()
 ; CHECK-NEXT:            to label [[FOR_COND616]] []
@@ -148,7 +148,7 @@ define void @tre_tnfa_run_backtrack_callbr(i1 %arg) {
 ; CHECK:       retry.target.while.body248:
 ; CHECK-NEXT:    br label [[IRR_GUARD]]
 ; CHECK:       irr.guard:
-; CHECK-NEXT:    [[GUARD_WHILE_BODY248:%.*]] = phi i1 [ true, [[FOR_END626_TARGET_WHILE_BODY248]] ], [ false, [[RETRY_TARGET_BACKTRACK]] ], [ true, [[RETRY_TARGET_WHILE_BODY248:%.*]] ]
+; CHECK-NEXT:    [[GUARD_WHILE_BODY248:%.*]] = phi i1 [ true, [[FOR_END626_TARGET_WHILE_BODY248]] ], [ false, [[RETRY_TARGET_BACKTRACK]] ], [ true, [[RETRY_TARGET_WHILE_BODY248]] ]
 ; CHECK-NEXT:    br i1 [[GUARD_WHILE_BODY248]], label [[WHILE_BODY248:%.*]], label [[BACKTRACK]]
 ;
 entry:
@@ -199,3 +199,118 @@ for.end626:                                       ; preds = %for.cond616
 if.else629:                                       ; preds = %backtrack
   callbr void asm "", ""() to label %retry []
 }
+
+define void @tre_tnfa_run_backtrack_switch(i32 %arg) {
+; CHECK-LABEL: @tre_tnfa_run_backtrack_switch(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    switch i32 [[ARG:%.*]], label [[RETRY:%.*]] [
+; CHECK-NEXT:    ]
+; CHECK:       retry:
+; CHECK-NEXT:    switch i32 [[ARG]], label [[RETRY_TARGET_BACKTRACK:%.*]] [
+; CHECK-NEXT:      i32 0, label [[RETRY_TARGET_WHILE_BODY248:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       while.body248:
+; CHECK-NEXT:    switch i32 [[ARG]], label [[IF_THEN250:%.*]] [
+; CHECK-NEXT:      i32 0, label [[IF_END275:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       if.then250:
+; CHECK-NEXT:    switch i32 [[ARG]], label [[FOR_COND264:%.*]] [
+; CHECK-NEXT:    ]
+; CHECK:       for.cond264:
+; CHECK-NEXT:    switch i32 [[ARG]], label [[FOR_BODY267:%.*]] [
+; CHECK-NEXT:      i32 0, label [[BACKTRACK:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       for.body267:
+; CHECK-NEXT:    switch i32 [[ARG]], label [[FOR_COND264]] [
+; CHECK-NEXT:    ]
+; CHECK:       if.end275:
+; CHECK-NEXT:    switch i32 [[ARG]], label [[FOR_COND342:%.*]] [
+; CHECK-NEXT:    ]
+; CHECK:       for.cond342:
+; CHECK-NEXT:    switch i32 [[ARG]], label [[FOR_BODY345:%.*]] [
+; CHECK-NEXT:      i32 0, label [[FOR_END580:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       for.body345:
+; CHECK-NEXT:    switch i32 [[ARG]], label [[FOR_COND342]] [
+; CHECK-NEXT:    ]
+; CHECK:       for.end580:
+; CHECK-NEXT:    switch i32 [[ARG]], label [[BACKTRACK]] [
+; CHECK-NEXT:    ]
+; CHECK:       backtrack:
+; CHECK-NEXT:    switch i32 [[ARG]], label [[IF_THEN595:%.*]] [
+; CHECK-NEXT:      i32 0, label [[IF_ELSE629:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       if.then595:
+; CHECK-NEXT:    switch i32 [[ARG]], label [[FOR_COND616:%.*]] [
+; CHECK-NEXT:    ]
+; CHECK:       for.cond616:
+; CHECK-NEXT:    switch i32 [[ARG]], label [[FOR_BODY619:%.*]] [
+; CHECK-NEXT:      i32 0, label [[FOR_END626:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       for.body619:
+; CHECK-NEXT:    switch i32 [[ARG]], label [[FOR_COND616]] [
+; CHECK-NEXT:    ]
+; CHECK:       for.end626:
+; CHECK-NEXT:    switch i32 [[ARG]], label [[FOR_END626_TARGET_WHILE_BODY248:%.*]] [
+; CHECK-NEXT:    ]
+; CHECK:       if.else629:
+; CHECK-NEXT:    switch i32 [[ARG]], label [[RETRY]] [
+; CHECK-NEXT:    ]
+; CHECK:       for.end626.target.while.body248:
+; CHECK-NEXT:    br label [[IRR_GUARD:%.*]]
+; CHECK:       retry.target.backtrack:
+; CHECK-NEXT:    br label [[IRR_GUARD]]
+; CHECK:       retry.target.while.body248:
+; CHECK-NEXT:    br label [[IRR_GUARD]]
+; CHECK:       irr.guard:
+; CHECK-NEXT:    [[GUARD_WHILE_BODY248:%.*]] = phi i1 [ true, [[FOR_END626_TARGET_WHILE_BODY248]] ], [ false, [[RETRY_TARGET_BACKTRACK]] ], [ true, [[RETRY_TARGET_WHILE_BODY248]] ]
+; CHECK-NEXT:    br i1 [[GUARD_WHILE_BODY248]], label [[WHILE_BODY248:%.*]], label [[BACKTRACK]]
+;
+entry:
+  switch i32 %arg, label %retry []
+
+retry:
+  switch i32 %arg, label %backtrack [ i32 0, label %while.body248 ]
+
+while.body248:                                    ; preds = %for.end626, %retry
+  switch i32 %arg, label %if.then250 [ i32 0, label %if.end275 ]
+
+if.then250:                                       ; preds = %while.body248
+  switch i32 %arg, label %for.cond264 []
+
+for.cond264:                                      ; preds = %for.body267, %if.then250
+  switch i32 %arg, label %for.body267 [ i32 0, label %backtrack ]
+
+for.body267:                                      ; preds = %for.cond264
+  switch i32 %arg, label %for.cond264 []
+
+if.end275:                                        ; preds = %while.body248
+  switch i32 %arg, label %for.cond342 []
+
+for.cond342:                                      ; preds = %for.body345, %if.end275
+  switch i32 %arg, label %for.body345 [ i32 0, label %for.end580 ]
+
+for.body345:                                      ; preds = %for.cond342
+  switch i32 %arg, label %for.cond342 []
+
+for.end580:                                       ; preds = %for.cond342
+  switch i32 %arg, label %backtrack []
+
+backtrack:                                        ; preds = %for.end580, %for.cond264, %retry
+  switch i32 %arg, label %if.then595 [ i32 0, label %if.else629 ]
+
+if.then595:                                       ; preds = %backtrack
+  switch i32 %arg, label %for.cond616 []
+
+for.cond616:                                      ; preds = %for.body619, %if.then595
+  switch i32 %arg, label %for.body619 [ i32 0, label %for.end626 ]
+
+for.body619:                                      ; preds = %for.cond616
+  switch i32 %arg, label %for.cond616 []
+
+for.end626:                                       ; preds = %for.cond616
+  switch i32 %arg, label %while.body248 []
+
+if.else629:                                       ; preds = %backtrack
+  switch i32 %arg, label %retry []
+}
diff --git a/llvm/test/Transforms/FixIrreducible/nested.ll b/llvm/test/Transforms/FixIrreducible/nested.ll
index c9161cc14f208..a739d093f5583 100644
--- a/llvm/test/Transforms/FixIrreducible/nested.ll
+++ b/llvm/test/Transforms/FixIrreducible/nested.ll
@@ -54,22 +54,22 @@ define void @nested_irr_top_level_callbr(i1 %Pred0, i1 %Pred1, i1 %Pred2, i1 %Pr
 ; CHECK-LABEL: @nested_irr_top_level_callbr(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[PRED0:%.*]])
-; CHECK-NEXT:            to label [[ENTRY_TARGET_A1:%.*]] [label %entry.target.A2]
+; CHECK-NEXT:            to label [[ENTRY_TARGET_A1:%.*]] [label [[ENTRY_TARGET_A2:%.*]]]
 ; CHECK:       A1:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[PRED1:%.*]])
-; CHECK-NEXT:            to label [[A1_TARGET_B1:%.*]] [label %A1.target.B2]
+; CHECK-NEXT:            to label [[A1_TARGET_B1:%.*]] [label [[A1_TARGET_B2:%.*]]]
 ; CHECK:       B1:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[PRED2:%.*]])
-; CHECK-NEXT:            to label [[B1_TARGET_B2:%.*]] [label %A3]
+; CHECK-NEXT:            to label [[B1_TARGET_B2:%.*]] [label [[A3:%.*]]]
 ; CHECK:       B2:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[PRED3:%.*]])
-; CHECK-NEXT:            to label [[B1:%.*]] [label %A3]
+; CHECK-NEXT:            to label [[B1:%.*]] [label [[A3]]]
 ; CHECK:       A3:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[PRED4:%.*]])
-; CHECK-NEXT:            to label [[A3_TARGET_A2:%.*]] [label %exit]
+; CHECK-NEXT:            to label [[A3_TARGET_A2:%.*]] [label [[EXIT:%.*]]]
 ; CHECK:       A2:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[PRED5:%.*]])
-; CHECK-NEXT:            to label [[A1:%.*]] [label %exit]
+; CHECK-NEXT:            to label [[A1:%.*]] [label [[EXIT]]]
 ; CHECK:       exit:
 ; CHECK-NEXT:    ret void
 ; CHECK:       A3.target.A2:
@@ -79,7 +79,7 @@ define void @nested_irr_top_level_callbr(i1 %Pred0, i1 %Pred1, i1 %Pred2, i1 %Pr
 ; CHECK:       entry.target.A2:
 ; CHECK-NEXT:    br label [[IRR_GUARD]]
 ; CHECK:       irr.guard:
-; CHECK-NEXT:    [[GUARD_A2:%.*]] = phi i1 [ true, [[A3_TARGET_A2]] ], [ false, [[ENTRY_TARGET_A1]] ], [ true, [[ENTRY_TARGET_A2:%.*]] ]
+; CHECK-NEXT:    [[GUARD_A2:%.*]] = phi i1 [ true, [[A3_TARGET_A2]] ], [ false, [[ENTRY_TARGET_A1]] ], [ true, [[ENTRY_TARGET_A2]] ]
 ; CHECK-NEXT:    br i1 [[GUARD_A2]], label [[A2:%.*]], label [[A1]]
 ; CHECK:       B1.target.B2:
 ; CHECK-NEXT:    br label [[IRR_GUARD1:%.*]]
@@ -88,7 +88,7 @@ define void @nested_irr_top_level_callbr(i1 %Pred0, i1 %Pred1, i1 %Pred2, i1 %Pr
 ; CHECK:       A1.target.B2:
 ; CHECK-NEXT:    br label [[IRR_GUARD1]]
 ; CHECK:       irr.guard1:
-; CHECK-NEXT:    [[GUARD_B2:%.*]] = phi i1 [ true, [[B1_TARGET_B2]] ], [ false, [[A1_TARGET_B1]] ], [ true, [[A1_TARGET_B2:%.*]] ]
+; CHECK-NEXT:    [[GUARD_B2:%.*]] = phi i1 [ true, [[B1_TARGET_B2]] ], [ false, [[A1_TARGET_B1]] ], [ true, [[A1_TARGET_B2]] ]
 ; CHECK-NEXT:    br i1 [[GUARD_B2]], label [[B2:%.*]], label [[B1]]
 ;
 entry:
@@ -113,6 +113,75 @@ exit:
   ret void
 }
 
+define void @nested_irr_top_level_switch(i1 %Pred0, i1 %Pred1, i1 %Pred2, i1 %Pred3, i1 %Pred4, i1 %Pred5) {
+; CHECK-LABEL: @nested_irr_top_level_switch(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    switch i1 [[PRED0:%.*]], label [[ENTRY_TARGET_A1:%.*]] [
+; CHECK-NEXT:      i1 false, label [[ENTRY_TARGET_A2:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       A1:
+; CHECK-NEXT:    switch i1 [[PRED1:%.*]], label [[A1_TARGET_B1:%.*]] [
+; CHECK-NEXT:      i1 false, label [[A1_TARGET_B2:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       B1:
+; CHECK-NEXT:    switch i1 [[PRED2:%.*]], label [[B1_TARGET_B2:%.*]] [
+; CHECK-NEXT:      i1 false, label [[A3:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       B2:
+; CHECK-NEXT:    switch i1 [[PRED3:%.*]], label [[B1:%.*]] [
+; CHECK-NEXT:      i1 false, label [[A3]]
+; CHECK-NEXT:    ]
+; CHECK:       A3:
+; CHECK-NEXT:    switch i1 [[PRED4:%.*]], label [[A3_TARGET_A2:%.*]] [
+; CHECK-NEXT:      i1 false, label [[EXIT:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       A2:
+; CHECK-NEXT:    switch i1 [[PRED5:%.*]], label [[A1:%.*]] [
+; CHECK-NEXT:      i1 false, label [[EXIT]]
+; CHECK-NEXT:    ]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+; CHECK:       A3.target.A2:
+; CHECK-NEXT:    br label [[IRR_GUARD:%.*]]
+; CHECK:       entry.target.A1:
+; CHECK-NEXT:    br label [[IRR_GUARD]]
+; CHECK:       entry.target.A2:
+; CHECK-NEXT:    br label [[IRR_GUARD]]
+; CHECK:       irr.guard:
+; CHECK-NEXT:    [[GUARD_A2:%.*]] = phi i1 [ true, [[A3_TARGET_A2]] ], [ false, [[ENTRY_TARGET_A1]] ], [ true, [[ENTRY_TARGET_A2]] ]
+; CHECK-NEXT:    br i1 [[GUARD_A2]], label [[A2:%.*]], label [[A1]]
+; CHECK:       B1.target.B2:
+; CHECK-NEXT:    br label [[IRR_GUARD1:%.*]]
+; CHECK:       A1.target.B1:
+; CHECK-NEXT:    br label [[IRR_GUARD1]]
+; CHECK:       A1.target.B2:
+; CHECK-NEXT:    br label [[IRR_GUARD1]]
+; CHECK:       irr.guard1:
+; CHECK-NEXT:    [[GUARD_B2:%.*]] = phi i1 [ true, [[B1_TARGET_B2]] ], [ false, [[A1_TARGET_B1]] ], [ true, [[A1_TARGET_B2]] ]
+; CHECK-NEXT:    br i1 [[GUARD_B2]], label [[B2:%.*]], label [[B1]]
+;
+entry:
+  switch i1 %Pred0, label %A1 [ i1 0, label %A2 ]
+
+A1:
+  switch i1 %Pred1, label %B1 [ i1 0, label %B2 ]
+
+B1:
+  switch i1 %Pred2, label %B2 [ i1 0, label %A3 ]
+
+B2:
+  switch i1 %Pred3, label %B1 [ i1 0, label %A3 ]
+
+A3:
+  switch i1 %Pred4, label %A2 [ i1 0, label %exit ]
+
+A2:
+  switch i1 %Pred5, label %A1 [ i1 0, label %exit ]
+
+exit:
+  ret void
+}
+
 define void @nested_irr_in_loop(i1 %Pred0, i1 %Pred1, i1 %Pred2, i1 %Pred3, i1 %Pred4, i1 %Pred5, i1 %Pred6) {
 ; CHECK-LABEL: @nested_irr_in_loop(
 ; CHECK-NEXT:  entry:
@@ -176,25 +245,25 @@ define void @nested_irr_in_loop_callbr(i1 %Pred0, i1 %Pred1, i1 %Pred2, i1 %Pred
 ; CHECK-NEXT:    br label [[H1:%.*]]
 ; CHECK:       H1:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[PRED0:%.*]])
-; CHECK-NEXT:            to label [[H1_TARGET_A1:%.*]] [label %H1.target.A2]
+; CHECK-NEXT:            to label [[H1_TARGET_A1:%.*]] [label [[H1_TARGET_A2:%.*]]]
 ; CHECK:       A1:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[PRED1:%.*]])
-; CHECK-NEXT:            to label [[A1_TARGET_B1:%.*]] [label %A1.target.B2]
+; CHECK-NEXT:            to label [[A1_TARGET_B1:%.*]] [label [[A1_TARGET_B2:%.*]]]
 ; CHECK:       B1:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[PRED2:%.*]])
-; CHECK-NEXT:            to label [[B1_TARGET_B2:%.*]] [label %A3]
+; CHECK-NEXT:            to label [[B1_TARGET_B2:%.*]] [label [[A3:%.*]]]
 ; CHECK:       B2:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[PRED3:%.*]])
-; CHECK-NEXT:            to label [[B1:%.*]] [label %A3]
+; CHECK-NEXT:            to label [[B1:%.*]] [label [[A3]]]
 ; CHECK:       A3:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[PRED4:%.*]])
-; CHECK-NEXT:            to label [[A3_TARGET_A2:%.*]] [label %L1]
+; CHECK-NEXT:            to label [[A3_TARGET_A2:%.*]] [label [[L1:%.*]]]
 ; CHECK:       A2:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[PRED5:%.*]])
-; CHECK-NEXT:            to label [[A1:%.*]] [label %L1]
+; CHECK-NEXT:            to label [[A1:%.*]] [label [[L1]]]
 ; CHECK:       L1:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[PRED6:%.*]])
-; CHECK-NEXT:            to label [[EXIT:%.*]] [label %H1]
+; CHECK-NEXT:            to label [[EXIT:%.*]] [label [[H1]]]
 ; CHECK:       exit:
 ; CHECK-NEXT:    ret void
 ; CHECK:       A3.target.A2:
@@ -204,7 +273,7 @@ define void @nested_irr_in_loop_callbr(i1 %Pred0, i1 %Pred1, i1 %Pred2, i1 %Pred
 ; CHECK:       H1.target.A2:
 ; CHECK-NEXT:    br label [[IRR_GUARD]]
 ; CHECK:       irr.guard:
-; CHECK-NEXT:    [[GUARD_A2:%.*]] = phi i1 [ true, [[A3_TARGET_A2]] ], [ false, [[H1_TARGET_A1]] ], [ true, [[H1_TARGET_A2:%.*]] ]
+; CHECK-NEXT:    [[GUARD_A2:%.*]] = phi i1 [ true, [[A3_TARGET_A2]] ], [ false, [[H1_TARGET_A1]] ], [ true, [[H1_TARGET_A2]] ]
 ; CHECK-NEXT:    br i1 [[GUARD_A2]], label [[A2:%.*]], label [[A1]]
 ; CHECK:       B1.target.B2:
 ; CHECK-NEXT:    br label [[IRR_GUARD1:%.*]]
@@ -213,7 +282,7 @@ define void @nested_irr_in_loop_callbr(i1 %Pred0, i1 %Pred1, i1 %Pred2, i1 %Pred
 ; CHECK:       A1.target.B2:
 ; CHECK-NEXT:    br label [[IRR_GUARD1]]
 ; CHECK:       irr.guard1:
-; CHECK-NEXT:    [[GUARD_B2:%.*]] = phi i1 [ true, [[B1_TARGET_B2]] ], [ false, [[A1_TARGET_B1]] ], [ true, [[A1_TARGET_B2:%.*]] ]
+; CHECK-NEXT:    [[GUARD_B2:%.*]] = phi i1 [ true, [[B1_TARGET_B2]] ], [ false, [[A1_TARGET_B1]] ], [ true, [[A1_TARGET_B2]] ]
 ; CHECK-NEXT:    br i1 [[GUARD_B2]], label [[B2:%.*]], label [[B1]]
 ;
 entry:
@@ -244,6 +313,87 @@ exit:
   ret void
 }
 
+define void @nested_irr_in_loop_switch(i1 %Pred0, i1 %Pred1, i1 %Pred2, i1 %Pred3, i1 %Pred4, i1 %Pred5, i1 %Pred6) {
+; CHECK-LABEL: @nested_irr_in_loop_switch(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label [[H1:%.*]]
+; CHECK:       H1:
+; CHECK-NEXT:    switch i1 [[PRED0:%.*]], label [[H1_TARGET_A1:%.*]] [
+; CHECK-NEXT:      i1 false, label [[H1_TARGET_A2:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       A1:
+; CHECK-NEXT:    switch i1 [[PRED1:%.*]], label [[A1_TARGET_B1:%.*]] [
+; CHECK-NEXT:      i1 false, label [[A1_TARGET_B2:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       B1:
+; CHECK-NEXT:    switch i1 [[PRED2:%.*]], label [[B1_TARGET_B2:%.*]] [
+; CHECK-NEXT:      i1 false, label [[A3:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       B2:
+; CHECK-NEXT:    switch i1 [[PRED3:%.*]], label [[B1:%.*]] [
+; CHECK-NEXT:      i1 false, label [[A3]]
+; CHECK-NEXT:    ]
+; CHECK:       A3:
+; CHECK-NEXT:    switch i1 [[PRED4:%.*]], label [[A3_TARGET_A2:%.*]] [
+; CHECK-NEXT:      i1 false, label [[L1:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       A2:
+; CHECK-NEXT:    switch i1 [[PRED5:%.*]], label [[A1:%.*]] [
+; CHECK-NEXT:      i1 false, label [[L1]]
+; CHECK-NEXT:    ]
+; CHECK:       L1:
+; CHECK-NEXT:    switch i1 [[PRED6:%.*]], label [[EXIT:%.*]] [
+; CHECK-NEXT:      i1 false, label [[H1]]
+; CHECK-NEXT:    ]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+; CHECK:       A3.target.A2:
+; CHECK-NEXT:    br label [[IRR_GUARD:%.*]]
+; CHECK:       H1.target.A1:
+; CHECK-NEXT:    br label [[IRR_GUARD]]
+; CHECK:       H1.target.A2:
+; CHECK-NEXT:    br label [[IRR_GUARD]]
+; CHECK:       irr.guard:
+; CHECK-NEXT:    [[GUARD_A2:%.*]] = phi i1 [ true, [[A3_TARGET_A2]] ], [ false, [[H1_TARGET_A1]] ], [ true, [[H1_TARGET_A2]] ]
+; CHECK-NEXT:    br i1 [[GUARD_A2]], label [[A2:%.*]], label [[A1]]
+; CHECK:       B1.target.B2:
+; CHECK-NEXT:    br label [[IRR_GUARD1:%.*]]
+; CHECK:       A1.target.B1:
+; CHECK-NEXT:    br label [[IRR_GUARD1]]
+; CHECK:       A1.target.B2:
+; CHECK-NEXT:    br label [[IRR_GUARD1]]
+; CHECK:       irr.guard1:
+; CHECK-NEXT:    [[GUARD_B2:%.*]] = phi i1 [ true, [[B1_TARGET_B2]] ], [ false, [[A1_TARGET_B1]] ], [ true, [[A1_TARGET_B2]] ]
+; CHECK-NEXT:    br i1 [[GUARD_B2]], label [[B2:%.*]], label [[B1]]
+;
+entry:
+  br label %H1
+
+H1:
+  switch i1 %Pred0, label %A1 [ i1 0, label %A2 ]
+
+A1:
+  switch i1 %Pred1, label %B1 [ i1 0, label %B2 ]
+
+B1:
+  switch i1 %Pred2, label %B2 [ i1 0, label %A3 ]
+
+B2:
+  switch i1 %Pred3, label %B1 [ i1 0, label %A3 ]
+
+A3:
+  switch i1 %Pred4, label %A2 [ i1 0, label %L1 ]
+
+A2:
+  switch i1 %Pred5, label %A1 [ i1 0, label %L1 ]
+
+L1:
+  switch i1 %Pred6, label %exit [ i1 0, label %H1 ]
+
+exit:
+  ret void
+}
+
 define void @loop_in_irr(i1 %Pred0, i1 %Pred1, i1 %Pred2) {
 ; CHECK-LABEL: @loop_in_irr(
 ; CHECK-NEXT:  entry:
@@ -291,7 +441,7 @@ define void @loop_in_irr_callbr(i1 %Pred0, i1 %Pred1, i1 %Pred2) {
 ; CHECK-LABEL: @loop_in_irr_callbr(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[PRED0:%.*]])
-; CHECK-NEXT:            to label [[ENTRY_TARGET_A1:%.*]] [label %entry.target.A2]
+; CHECK-NEXT:            to label [[ENTRY_TARGET_A1:%.*]] [label [[ENTRY_TARGET_A2:%.*]]]
 ; CHECK:       A1:
 ; CHECK-NEXT:    callbr void asm "", ""()
 ; CHECK-NEXT:            to label [[H1:%.*]] []
@@ -300,10 +450,10 @@ define void @loop_in_irr_callbr(i1 %Pred0, i1 %Pred1, i1 %Pred2) {
 ; CHECK-NEXT:            to label [[L1:%.*]] []
 ; CHECK:       L1:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[PRED1:%.*]])
-; CHECK-NEXT:            to label [[H1]] [label %A3]
+; CHECK-NEXT:            to label [[H1]] [label [[A3:%.*]]]
 ; CHECK:       A3:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[PRED2:%.*]])
-; CHECK-NEXT:            to label [[A3_TARGET_A2:%.*]] [label %exit]
+; CHECK-NEXT:            to label [[A3_TARGET_A2:%.*]] [label [[EXIT:%.*]]]
 ; CHECK:       A2:
 ; CHECK-NEXT:    callbr void asm "", ""()
 ; CHECK-NEXT:            to label [[A1:%.*]] []
@@ -316,7 +466,7 @@ define void @loop_in_irr_callbr(i1 %Pred0, i1 %Pred1, i1 %Pred2) {
 ; CHECK:       entry.target.A2:
 ; CHECK-NEXT:    br label [[IRR_GUARD]]
 ; CHECK:       irr.guard:
-; CHECK-NEXT:    [[GUARD_A2:%.*]] = phi i1 [ true, [[A3_TARGET_A2]] ], [ false, [[ENTRY_TARGET_A1]] ], [ true, [[ENTRY_TARGET_A2:%.*]] ]
+; CHECK-NEXT:    [[GUARD_A2:%.*]] = phi i1 [ true, [[A3_TARGET_A2]] ], [ false, [[ENTRY_TARGET_A1]] ], [ true, [[ENTRY_TARGET_A2]] ]
 ; CHECK-NEXT:    br i1 [[GUARD_A2]], label [[A2:%.*]], label [[A1]]
 ;
 entry:
@@ -341,6 +491,63 @@ exit:
   ret void
 }
 
+define void @loop_in_irr_switch(i1 %Pred0, i1 %Pred1, i1 %Pred2) {
+; CHECK-LABEL: @loop_in_irr_switch(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    switch i1 [[PRED0:%.*]], label [[ENTRY_TARGET_A1:%.*]] [
+; CHECK-NEXT:      i1 false, label [[ENTRY_TARGET_A2:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       A1:
+; CHECK-NEXT:    switch i1 [[PRED0]], label [[H1:%.*]] [
+; CHECK-NEXT:    ]
+; CHECK:       H1:
+; CHECK-NEXT:    switch i1 [[PRED0]], label [[L1:%.*]] [
+; CHECK-NEXT:    ]
+; CHECK:       L1:
+; CHECK-NEXT:    switch i1 [[PRED1:%.*]], label [[H1]] [
+; CHECK-NEXT:      i1 false, label [[A3:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       A3:
+; CHECK-NEXT:    switch i1 [[PRED2:%.*]], label [[A3_TARGET_A2:%.*]] [
+; CHECK-NEXT:      i1 false, label [[EXIT:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       A2:
+; CHECK-NEXT:    switch i1 [[PRED0]], label [[A1:%.*]] [
+; CHECK-NEXT:    ]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+; CHECK:       A3.target.A2:
+; CHECK-NEXT:    br label [[IRR_GUARD:%.*]]
+; CHECK:       entry.target.A1:
+; CHECK-NEXT:    br label [[IRR_GUARD]]
+; CHECK:       entry.target.A2:
+; CHECK-NEXT:    br label [[IRR_GUARD]]
+; CHECK:       irr.guard:
+; CHECK-NEXT:    [[GUARD_A2:%.*]] = phi i1 [ true, [[A3_TARGET_A2]] ], [ false, [[ENTRY_TARGET_A1]] ], [ true, [[ENTRY_TARGET_A2]] ]
+; CHECK-NEXT:    br i1 [[GUARD_A2]], label [[A2:%.*]], label [[A1]]
+;
+entry:
+  switch i1 %Pred0, label %A1 [ i1 0, label %A2 ]
+
+A1:
+  switch i1 %Pred0, label %H1 []
+
+H1:
+  switch i1 %Pred0, label %L1 []
+
+L1:
+  switch i1 %Pred1, label %H1 [ i1 0, label %A3 ]
+
+A3:
+  switch i1 %Pred2, label %A2 [ i1 0, label %exit ]
+
+A2:
+  switch i1 %Pred0, label %A1 []
+
+exit:
+  ret void
+}
+
 define void @loop_in_irr_shared_entry(i1 %Pred0, i1 %Pred1, i1 %Pred2) {
 ; CHECK-LABEL: @loop_in_irr_shared_entry(
 ; CHECK-NEXT:  entry:
@@ -383,16 +590,16 @@ define void @loop_in_irr_shared_entry_callbr(i1 %Pred0, i1 %Pred1, i1 %Pred2) {
 ; CHECK-LABEL: @loop_in_irr_shared_entry_callbr(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[PRED0:%.*]])
-; CHECK-NEXT:            to label [[ENTRY_TARGET_H1:%.*]] [label %entry.target.A2]
+; CHECK-NEXT:            to label [[ENTRY_TARGET_H1:%.*]] [label [[ENTRY_TARGET_A2:%.*]]]
 ; CHECK:       H1:
 ; CHECK-NEXT:    callbr void asm "", ""()
 ; CHECK-NEXT:            to label [[L1:%.*]] []
 ; CHECK:       L1:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[PRED1:%.*]])
-; CHECK-NEXT:            to label [[H1:%.*]] [label %A3]
+; CHECK-NEXT:            to label [[H1:%.*]] [label [[A3:%.*]]]
 ; CHECK:       A3:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[PRED2:%.*]])
-; CHECK-NEXT:            to label [[A3_TARGET_A2:%.*]] [label %exit]
+; CHECK-NEXT:            to label [[A3_TARGET_A2:%.*]] [label [[EXIT:%.*]]]
 ; CHECK:       A2:
 ; CHECK-NEXT:    callbr void asm "", ""()
 ; CHECK-NEXT:            to label [[H1]] []
@@ -405,7 +612,7 @@ define void @loop_in_irr_shared_entry_callbr(i1 %Pred0, i1 %Pred1, i1 %Pred2) {
 ; CHECK:       entry.target.A2:
 ; CHECK-NEXT:    br label [[IRR_GUARD]]
 ; CHECK:       irr.guard:
-; CHECK-NEXT:    [[GUARD_A2:%.*]] = phi i1 [ true, [[A3_TARGET_A2]] ], [ false, [[ENTRY_TARGET_H1]] ], [ true, [[ENTRY_TARGET_A2:%.*]] ]
+; CHECK-NEXT:    [[GUARD_A2:%.*]] = phi i1 [ true, [[A3_TARGET_A2]] ], [ false, [[ENTRY_TARGET_H1]] ], [ true, [[ENTRY_TARGET_A2]] ]
 ; CHECK-NEXT:    br i1 [[GUARD_A2]], label [[A2:%.*]], label [[H1]]
 ;
 entry:
@@ -427,6 +634,57 @@ exit:
   ret void
 }
 
+define void @loop_in_irr_shared_entry_switch(i1 %Pred0, i1 %Pred1, i1 %Pred2) {
+; CHECK-LABEL: @loop_in_irr_shared_entry_switch(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    switch i1 [[PRED0:%.*]], label [[ENTRY_TARGET_H1:%.*]] [
+; CHECK-NEXT:      i1 false, label [[ENTRY_TARGET_A2:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       H1:
+; CHECK-NEXT:    switch i1 [[PRED0]], label [[L1:%.*]] [
+; CHECK-NEXT:    ]
+; CHECK:       L1:
+; CHECK-NEXT:    switch i1 [[PRED1:%.*]], label [[H1:%.*]] [
+; CHECK-NEXT:      i1 false, label [[A3:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       A3:
+; CHECK-NEXT:    switch i1 [[PRED2:%.*]], label [[A3_TARGET_A2:%.*]] [
+; CHECK-NEXT:      i1 false, label [[EXIT:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       A2:
+; CHECK-NEXT:    switch i1 [[PRED0]], label [[H1]] [
+; CHECK-NEXT:    ]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+; CHECK:       A3.target.A2:
+; CHECK-NEXT:    br label [[IRR_GUARD:%.*]]
+; CHECK:       entry.target.H1:
+; CHECK-NEXT:    br label [[IRR_GUARD]]
+; CHECK:       entry.target.A2:
+; CHECK-NEXT:    br label [[IRR_GUARD]]
+; CHECK:       irr.guard:
+; CHECK-NEXT:    [[GUARD_A2:%.*]] = phi i1 [ true, [[A3_TARGET_A2]] ], [ false, [[ENTRY_TARGET_H1]] ], [ true, [[ENTRY_TARGET_A2]] ]
+; CHECK-NEXT:    br i1 [[GUARD_A2]], label [[A2:%.*]], label [[H1]]
+;
+entry:
+  switch i1 %Pred0, label %H1 [ i1 0, label %A2 ]
+
+H1:
+  switch i1 %Pred0, label %L1 []
+
+L1:
+  switch i1 %Pred1, label %H1 [ i1 0, label %A3 ]
+
+A3:
+  switch i1 %Pred2, label %A2 [ i1 0, label %exit ]
+
+A2:
+  switch i1 %Pred0, label %H1 []
+
+exit:
+  ret void
+}
+
 define void @loop_in_irr_shared_header(i1 %Pred0, i1 %Pred1, i1 %Pred2) {
 ; CHECK-LABEL: @loop_in_irr_shared_header(
 ; CHECK-NEXT:  entry:
@@ -469,16 +727,16 @@ define void @loop_in_irr_shared_header_callbr(i1 %Pred0, i1 %Pred1, i1 %Pred2) {
 ; CHECK-LABEL: @loop_in_irr_shared_header_callbr(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[PRED0:%.*]])
-; CHECK-NEXT:            to label [[ENTRY_TARGET_A2:%.*]] [label %entry.target.H1]
+; CHECK-NEXT:            to label [[ENTRY_TARGET_A2:%.*]] [label [[ENTRY_TARGET_H1:%.*]]]
 ; CHECK:       H1:
 ; CHECK-NEXT:    callbr void asm "", ""()
 ; CHECK-NEXT:            to label [[L1:%.*]] []
 ; CHECK:       L1:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[PRED1:%.*]])
-; CHECK-NEXT:            to label [[L1_TARGET_H1:%.*]] [label %A3]
+; CHECK-NEXT:            to label [[L1_TARGET_H1:%.*]] [label [[A3:%.*]]]
 ; CHECK:       A3:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[PRED2:%.*]])
-; CHECK-NEXT:            to label [[A2:%.*]] [label %exit]
+; CHECK-NEXT:            to label [[A2:%.*]] [label [[EXIT:%.*]]]
 ; CHECK:       A2:
 ; CHECK-NEXT:    callbr void asm "", ""()
 ; CHECK-NEXT:            to label [[A2_TARGET_H1:%.*]] []
@@ -493,7 +751,7 @@ define void @loop_in_irr_shared_header_callbr(i1 %Pred0, i1 %Pred1, i1 %Pred2) {
 ; CHECK:       entry.target.H1:
 ; CHECK-NEXT:    br label [[IRR_GUARD]]
 ; CHECK:       irr.guard:
-; CHECK-NEXT:    [[GUARD_H1:%.*]] = phi i1 [ true, [[A2_TARGET_H1]] ], [ true, [[L1_TARGET_H1]] ], [ false, [[ENTRY_TARGET_A2]] ], [ true, [[ENTRY_TARGET_H1:%.*]] ]
+; CHECK-NEXT:    [[GUARD_H1:%.*]] = phi i1 [ true, [[A2_TARGET_H1]] ], [ true, [[L1_TARGET_H1]] ], [ false, [[ENTRY_TARGET_A2]] ], [ true, [[ENTRY_TARGET_H1]] ]
 ; CHECK-NEXT:    br i1 [[GUARD_H1]], label [[H1:%.*]], label [[A2]]
 ;
 entry:
@@ -515,6 +773,59 @@ exit:
   ret void
 }
 
+define void @loop_in_irr_shared_header_switch(i1 %Pred0, i1 %Pred1, i1 %Pred2) {
+; CHECK-LABEL: @loop_in_irr_shared_header_switch(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    switch i1 [[PRED0:%.*]], label [[ENTRY_TARGET_A2:%.*]] [
+; CHECK-NEXT:      i1 false, label [[ENTRY_TARGET_H1:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       H1:
+; CHECK-NEXT:    switch i1 [[PRED0]], label [[L1:%.*]] [
+; CHECK-NEXT:    ]
+; CHECK:       L1:
+; CHECK-NEXT:    switch i1 [[PRED1:%.*]], label [[L1_TARGET_H1:%.*]] [
+; CHECK-NEXT:      i1 false, label [[A3:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       A3:
+; CHECK-NEXT:    switch i1 [[PRED2:%.*]], label [[A2:%.*]] [
+; CHECK-NEXT:      i1 false, label [[EXIT:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       A2:
+; CHECK-NEXT:    switch i1 [[PRED0]], label [[A2_TARGET_H1:%.*]] [
+; CHECK-NEXT:    ]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+; CHECK:       A2.target.H1:
+; CHECK-NEXT:    br label [[IRR_GUARD:%.*]]
+; CHECK:       L1.target.H1:
+; CHECK-NEXT:    br label [[IRR_GUARD]]
+; CHECK:       entry.target.A2:
+; CHECK-NEXT:    br label [[IRR_GUARD]]
+; CHECK:       entry.target.H1:
+; CHECK-NEXT:    br label [[IRR_GUARD]]
+; CHECK:       irr.guard:
+; CHECK-NEXT:    [[GUARD_H1:%.*]] = phi i1 [ true, [[A2_TARGET_H1]] ], [ true, [[L1_TARGET_H1]] ], [ false, [[ENTRY_TARGET_A2]] ], [ true, [[ENTRY_TARGET_H1]] ]
+; CHECK-NEXT:    br i1 [[GUARD_H1]], label [[H1:%.*]], label [[A2]]
+;
+entry:
+  switch i1 %Pred0, label %A2 [ i1 0, label %H1 ]
+
+H1:
+  switch i1 %Pred0, label %L1 []
+
+L1:
+  switch i1 %Pred1, label %H1 [ i1 0, label %A3 ]
+
+A3:
+  switch i1 %Pred2, label %A2 [ i1 0, label %exit ]
+
+A2:
+  switch i1 %Pred0, label %H1 []
+
+exit:
+  ret void
+}
+
 define void @loop_irr_loop_shared_header(i1 %Pred0, i1 %Pred1, i1 %Pred2, i1 %Pred3) {
 ; CHECK-LABEL: @loop_irr_loop_shared_header(
 ; CHECK-NEXT:  entry:
@@ -565,19 +876,19 @@ define void @loop_irr_loop_shared_header_callbr(i1 %Pred0, i1 %Pred1, i1 %Pred2,
 ; CHECK-NEXT:            to label [[H2:%.*]] []
 ; CHECK:       H2:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[PRED0:%.*]])
-; CHECK-NEXT:            to label [[H2_TARGET_A2:%.*]] [label %H2.target.H1]
+; CHECK-NEXT:            to label [[H2_TARGET_A2:%.*]] [label [[H2_TARGET_H1:%.*]]]
 ; CHECK:       H1:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[PRED1:%.*]])
-; CHECK-NEXT:            to label [[A3:%.*]] [label %H1.target.H1]
+; CHECK-NEXT:            to label [[A3:%.*]] [label [[H1_TARGET_H1:%.*]]]
 ; CHECK:       A3:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[PRED2:%.*]])
-; CHECK-NEXT:            to label [[A2:%.*]] [label %L2]
+; CHECK-NEXT:            to label [[A2:%.*]] [label [[L2:%.*]]]
 ; CHECK:       A2:
 ; CHECK-NEXT:    callbr void asm "", ""()
 ; CHECK-NEXT:            to label [[A2_TARGET_H1:%.*]] []
 ; CHECK:       L2:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[PRED3:%.*]])
-; CHECK-NEXT:            to label [[H2]] [label %exit]
+; CHECK-NEXT:            to label [[H2]] [label [[EXIT:%.*]]]
 ; CHECK:       exit:
 ; CHECK-NEXT:    ret void
 ; CHECK:       A2.target.H1:
@@ -589,7 +900,7 @@ define void @loop_irr_loop_shared_header_callbr(i1 %Pred0, i1 %Pred1, i1 %Pred2,
 ; CHECK:       H2.target.H1:
 ; CHECK-NEXT:    br label [[IRR_GUARD]]
 ; CHECK:       irr.guard:
-; CHECK-NEXT:    [[GUARD_H1:%.*]] = phi i1 [ true, [[A2_TARGET_H1]] ], [ true, [[H1_TARGET_H1:%.*]] ], [ false, [[H2_TARGET_A2]] ], [ true, [[H2_TARGET_H1:%.*]] ]
+; CHECK-NEXT:    [[GUARD_H1:%.*]] = phi i1 [ true, [[A2_TARGET_H1]] ], [ true, [[H1_TARGET_H1]] ], [ false, [[H2_TARGET_A2]] ], [ true, [[H2_TARGET_H1]] ]
 ; CHECK-NEXT:    br i1 [[GUARD_H1]], label [[H1:%.*]], label [[A2]]
 ;
 entry:
@@ -614,6 +925,66 @@ exit:
   ret void
 }
 
+define void @loop_irr_loop_shared_header_switch(i1 %Pred0, i1 %Pred1, i1 %Pred2, i1 %Pred3) {
+; CHECK-LABEL: @loop_irr_loop_shared_header_switch(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    switch i1 [[PRED0:%.*]], label [[H2:%.*]] [
+; CHECK-NEXT:    ]
+; CHECK:       H2:
+; CHECK-NEXT:    switch i1 [[PRED0]], label [[H2_TARGET_A2:%.*]] [
+; CHECK-NEXT:      i1 false, label [[H2_TARGET_H1:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       H1:
+; CHECK-NEXT:    switch i1 [[PRED1:%.*]], label [[A3:%.*]] [
+; CHECK-NEXT:      i1 false, label [[H1_TARGET_H1:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       A3:
+; CHECK-NEXT:    switch i1 [[PRED2:%.*]], label [[A2:%.*]] [
+; CHECK-NEXT:      i1 false, label [[L2:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       A2:
+; CHECK-NEXT:    switch i1 [[PRED0]], label [[A2_TARGET_H1:%.*]] [
+; CHECK-NEXT:    ]
+; CHECK:       L2:
+; CHECK-NEXT:    switch i1 [[PRED3:%.*]], label [[H2]] [
+; CHECK-NEXT:      i1 false, label [[EXIT:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+; CHECK:       A2.target.H1:
+; CHECK-NEXT:    br label [[IRR_GUARD:%.*]]
+; CHECK:       H1.target.H1:
+; CHECK-NEXT:    br label [[IRR_GUARD]]
+; CHECK:       H2.target.A2:
+; CHECK-NEXT:    br label [[IRR_GUARD]]
+; CHECK:       H2.target.H1:
+; CHECK-NEXT:    br label [[IRR_GUARD]]
+; CHECK:       irr.guard:
+; CHECK-NEXT:    [[GUARD_H1:%.*]] = phi i1 [ true, [[A2_TARGET_H1]] ], [ true, [[H1_TARGET_H1]] ], [ false, [[H2_TARGET_A2]] ], [ true, [[H2_TARGET_H1]] ]
+; CHECK-NEXT:    br i1 [[GUARD_H1]], label [[H1:%.*]], label [[A2]]
+;
+entry:
+  switch i1 %Pred0, label %H2 []
+
+H2:
+  switch i1 %Pred0, label %A2 [ i1 0, label %H1 ]
+
+H1:
+  switch i1 %Pred1, label %A3 [ i1 0, label %H1 ]
+
+A3:
+  switch i1 %Pred2, label %A2 [ i1 0, label %L2 ]
+
+A2:
+  switch i1 %Pred0, label %H1 []
+
+L2:
+  switch i1 %Pred3, label %H2 [ i1 0, label %exit ]
+
+exit:
+  ret void
+}
+
 define void @siblings_top_level(i1 %Pred0, i1 %Pred1, i1 %Pred2, i1 %Pred3, i1 %Pred4, i1 %Pred5, i1 %Pred6) {
 ; CHECK-LABEL: @siblings_top_level(
 ; CHECK-NEXT:  entry:
@@ -685,22 +1056,22 @@ define void @siblings_top_level_callbr(i1 %Pred0, i1 %Pred1, i1 %Pred2, i1 %Pred
 ; CHECK-LABEL: @siblings_top_level_callbr(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[PRED0:%.*]])
-; CHECK-NEXT:            to label [[H1:%.*]] [label %fork1]
+; CHECK-NEXT:            to label [[H1:%.*]] [label [[FORK1:%.*]]]
 ; CHECK:       H1:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[PRED1:%.*]])
-; CHECK-NEXT:            to label [[H1_TARGET_A1:%.*]] [label %H1.target.A2]
+; CHECK-NEXT:            to label [[H1_TARGET_A1:%.*]] [label [[H1_TARGET_A2:%.*]]]
 ; CHECK:       A1:
 ; CHECK-NEXT:    callbr void asm "", ""()
 ; CHECK-NEXT:            to label [[A1_TARGET_A2:%.*]] []
 ; CHECK:       A2:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[PRED2:%.*]])
-; CHECK-NEXT:            to label [[A1:%.*]] [label %L1]
+; CHECK-NEXT:            to label [[A1:%.*]] [label [[L1:%.*]]]
 ; CHECK:       L1:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[PRED3:%.*]])
-; CHECK-NEXT:            to label [[H1]] [label %exit]
+; CHECK-NEXT:            to label [[H1]] [label [[EXIT:%.*]]]
 ; CHECK:       fork1:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[PRED4:%.*]])
-; CHECK-NEXT:            to label [[FORK1_TARGET_B1:%.*]] [label %fork1.target.B2]
+; CHECK-NEXT:            to label [[FORK1_TARGET_B1:%.*]] [label [[FORK1_TARGET_B2:%.*]]]
 ; CHECK:       B1:
 ; CHECK-NEXT:    callbr void asm "", ""()
 ; CHECK-NEXT:            to label [[H2:%.*]] []
@@ -709,10 +1080,10 @@ define void @siblings_top_level_callbr(i1 %Pred0, i1 %Pred1, i1 %Pred2, i1 %Pred
 ; CHECK-NEXT:            to label [[L2:%.*]] []
 ; CHECK:       L2:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[PRED5:%.*]])
-; CHECK-NEXT:            to label [[H2]] [label %L2.target.B2]
+; CHECK-NEXT:            to label [[H2]] [label [[L2_TARGET_B2:%.*]]]
 ; CHECK:       B2:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[PRED6:%.*]])
-; CHECK-NEXT:            to label [[B1:%.*]] [label %exit]
+; CHECK-NEXT:            to label [[B1:%.*]] [label [[EXIT]]]
 ; CHECK:       exit:
 ; CHECK-NEXT:    ret void
 ; CHECK:       A1.target.A2:
@@ -722,7 +1093,7 @@ define void @siblings_top_level_callbr(i1 %Pred0, i1 %Pred1, i1 %Pred2, i1 %Pred
 ; CHECK:       H1.target.A2:
 ; CHECK-NEXT:    br label [[IRR_GUARD]]
 ; CHECK:       irr.guard:
-; CHECK-NEXT:    [[GUARD_A2:%.*]] = phi i1 [ true, [[A1_TARGET_A2]] ], [ false, [[H1_TARGET_A1]] ], [ true, [[H1_TARGET_A2:%.*]] ]
+; CHECK-NEXT:    [[GUARD_A2:%.*]] = phi i1 [ true, [[A1_TARGET_A2]] ], [ false, [[H1_TARGET_A1]] ], [ true, [[H1_TARGET_A2]] ]
 ; CHECK-NEXT:    br i1 [[GUARD_A2]], label [[A2:%.*]], label [[A1]]
 ; CHECK:       L2.target.B2:
 ; CHECK-NEXT:    br label [[IRR_GUARD1:%.*]]
@@ -731,7 +1102,7 @@ define void @siblings_top_level_callbr(i1 %Pred0, i1 %Pred1, i1 %Pred2, i1 %Pred
 ; CHECK:       fork1.target.B2:
 ; CHECK-NEXT:    br label [[IRR_GUARD1]]
 ; CHECK:       irr.guard1:
-; CHECK-NEXT:    [[GUARD_B2:%.*]] = phi i1 [ true, [[L2_TARGET_B2:%.*]] ], [ false, [[FORK1_TARGET_B1]] ], [ true, [[FORK1_TARGET_B2:%.*]] ]
+; CHECK-NEXT:    [[GUARD_B2:%.*]] = phi i1 [ true, [[L2_TARGET_B2]] ], [ false, [[FORK1_TARGET_B1]] ], [ true, [[FORK1_TARGET_B2]] ]
 ; CHECK-NEXT:    br i1 [[GUARD_B2]], label [[B2:%.*]], label [[B1]]
 ;
 entry:
@@ -768,6 +1139,100 @@ exit:
   ret void
 }
 
+define void @siblings_top_level_switch(i1 %Pred0, i1 %Pred1, i1 %Pred2, i1 %Pred3, i1 %Pred4, i1 %Pred5, i1 %Pred6) {
+; CHECK-LABEL: @siblings_top_level_switch(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    switch i1 [[PRED0:%.*]], label [[H1:%.*]] [
+; CHECK-NEXT:      i1 false, label [[FORK1:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       H1:
+; CHECK-NEXT:    switch i1 [[PRED1:%.*]], label [[H1_TARGET_A1:%.*]] [
+; CHECK-NEXT:      i1 false, label [[H1_TARGET_A2:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       A1:
+; CHECK-NEXT:    switch i1 [[PRED0]], label [[A1_TARGET_A2:%.*]] [
+; CHECK-NEXT:    ]
+; CHECK:       A2:
+; CHECK-NEXT:    switch i1 [[PRED2:%.*]], label [[A1:%.*]] [
+; CHECK-NEXT:      i1 false, label [[L1:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       L1:
+; CHECK-NEXT:    switch i1 [[PRED3:%.*]], label [[H1]] [
+; CHECK-NEXT:      i1 false, label [[EXIT:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       fork1:
+; CHECK-NEXT:    switch i1 [[PRED4:%.*]], label [[FORK1_TARGET_B1:%.*]] [
+; CHECK-NEXT:      i1 false, label [[FORK1_TARGET_B2:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       B1:
+; CHECK-NEXT:    switch i1 [[PRED0]], label [[H2:%.*]] [
+; CHECK-NEXT:    ]
+; CHECK:       H2:
+; CHECK-NEXT:    switch i1 [[PRED0]], label [[L2:%.*]] [
+; CHECK-NEXT:    ]
+; CHECK:       L2:
+; CHECK-NEXT:    switch i1 [[PRED5:%.*]], label [[H2]] [
+; CHECK-NEXT:      i1 false, label [[L2_TARGET_B2:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       B2:
+; CHECK-NEXT:    switch i1 [[PRED6:%.*]], label [[B1:%.*]] [
+; CHECK-NEXT:      i1 false, label [[EXIT]]
+; CHECK-NEXT:    ]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+; CHECK:       A1.target.A2:
+; CHECK-NEXT:    br label [[IRR_GUARD:%.*]]
+; CHECK:       H1.target.A1:
+; CHECK-NEXT:    br label [[IRR_GUARD]]
+; CHECK:       H1.target.A2:
+; CHECK-NEXT:    br label [[IRR_GUARD]]
+; CHECK:       irr.guard:
+; CHECK-NEXT:    [[GUARD_A2:%.*]] = phi i1 [ true, [[A1_TARGET_A2]] ], [ false, [[H1_TARGET_A1]] ], [ true, [[H1_TARGET_A2]] ]
+; CHECK-NEXT:    br i1 [[GUARD_A2]], label [[A2:%.*]], label [[A1]]
+; CHECK:       L2.target.B2:
+; CHECK-NEXT:    br label [[IRR_GUARD1:%.*]]
+; CHECK:       fork1.target.B1:
+; CHECK-NEXT:    br label [[IRR_GUARD1]]
+; CHECK:       fork1.target.B2:
+; CHECK-NEXT:    br label [[IRR_GUARD1]]
+; CHECK:       irr.guard1:
+; CHECK-NEXT:    [[GUARD_B2:%.*]] = phi i1 [ true, [[L2_TARGET_B2]] ], [ false, [[FORK1_TARGET_B1]] ], [ true, [[FORK1_TARGET_B2]] ]
+; CHECK-NEXT:    br i1 [[GUARD_B2]], label [[B2:%.*]], label [[B1]]
+;
+entry:
+  switch i1 %Pred0, label %H1 [ i1 0, label %fork1 ]
+
+H1:
+  switch i1 %Pred1, label %A1 [ i1 0, label %A2 ]
+
+A1:
+  switch i1 %Pred0, label %A2 []
+
+A2:
+  switch i1 %Pred2, label %A1 [ i1 0, label %L1 ]
+
+L1:
+  switch i1 %Pred3, label %H1 [ i1 0, label %exit ]
+
+fork1:
+  switch i1 %Pred4, label %B1 [ i1 0, label %B2 ]
+
+B1:
+  switch i1 %Pred0, label %H2 []
+
+H2:
+  switch i1 %Pred0, label %L2 []
+
+L2:
+  switch i1 %Pred5, label %H2 [ i1 0, label %B2 ]
+
+B2:
+  switch i1 %Pred6, label %B1 [ i1 0, label %exit ]
+
+exit:
+  ret void
+}
+
 define void @siblings_in_loop(i1 %Pred0, i1 %Pred1, i1 %Pred2, i1 %Pred3, i1 %Pred4, i1 %Pred5, i1 %Pred6, i1 %Pred7) {
 ; CHECK-LABEL: @siblings_in_loop(
 ; CHECK-NEXT:  entry:
@@ -852,22 +1317,22 @@ define void @siblings_in_loop_callbr(i1 %Pred0, i1 %Pred1, i1 %Pred2, i1 %Pred3,
 ; CHECK-NEXT:            to label [[H0:%.*]] []
 ; CHECK:       H0:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[PRED0:%.*]])
-; CHECK-NEXT:            to label [[H1:%.*]] [label %fork1]
+; CHECK-NEXT:            to label [[H1:%.*]] [label [[FORK1:%.*]]]
 ; CHECK:       H1:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[PRED1:%.*]])
-; CHECK-NEXT:            to label [[H1_TARGET_A1:%.*]] [label %H1.target.A2]
+; CHECK-NEXT:            to label [[H1_TARGET_A1:%.*]] [label [[H1_TARGET_A2:%.*]]]
 ; CHECK:       A1:
 ; CHECK-NEXT:    callbr void asm "", ""()
 ; CHECK-NEXT:            to label [[A1_TARGET_A2:%.*]] []
 ; CHECK:       A2:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[PRED2:%.*]])
-; CHECK-NEXT:            to label [[A1:%.*]] [label %L1]
+; CHECK-NEXT:            to label [[A1:%.*]] [label [[L1:%.*]]]
 ; CHECK:       L1:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[PRED3:%.*]])
-; CHECK-NEXT:            to label [[H1]] [label %L0]
+; CHECK-NEXT:            to label [[H1]] [label [[L0:%.*]]]
 ; CHECK:       fork1:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[PRED4:%.*]])
-; CHECK-NEXT:            to label [[FORK1_TARGET_B1:%.*]] [label %fork1.target.B2]
+; CHECK-NEXT:            to label [[FORK1_TARGET_B1:%.*]] [label [[FORK1_TARGET_B2:%.*]]]
 ; CHECK:       B1:
 ; CHECK-NEXT:    callbr void asm "", ""()
 ; CHECK-NEXT:            to label [[H2:%.*]] []
@@ -876,13 +1341,13 @@ define void @siblings_in_loop_callbr(i1 %Pred0, i1 %Pred1, i1 %Pred2, i1 %Pred3,
 ; CHECK-NEXT:            to label [[L2:%.*]] []
 ; CHECK:       L2:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[PRED5:%.*]])
-; CHECK-NEXT:            to label [[H2]] [label %L2.target.B2]
+; CHECK-NEXT:            to label [[H2]] [label [[L2_TARGET_B2:%.*]]]
 ; CHECK:       B2:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[PRED6:%.*]])
-; CHECK-NEXT:            to label [[B1:%.*]] [label %L0]
+; CHECK-NEXT:            to label [[B1:%.*]] [label [[L0]]]
 ; CHECK:       L0:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[PRED7:%.*]])
-; CHECK-NEXT:            to label [[EXIT:%.*]] [label %H0]
+; CHECK-NEXT:            to label [[EXIT:%.*]] [label [[H0]]]
 ; CHECK:       exit:
 ; CHECK-NEXT:    ret void
 ; CHECK:       A1.target.A2:
@@ -892,7 +1357,7 @@ define void @siblings_in_loop_callbr(i1 %Pred0, i1 %Pred1, i1 %Pred2, i1 %Pred3,
 ; CHECK:       H1.target.A2:
 ; CHECK-NEXT:    br label [[IRR_GUARD]]
 ; CHECK:       irr.guard:
-; CHECK-NEXT:    [[GUARD_A2:%.*]] = phi i1 [ true, [[A1_TARGET_A2]] ], [ false, [[H1_TARGET_A1]] ], [ true, [[H1_TARGET_A2:%.*]] ]
+; CHECK-NEXT:    [[GUARD_A2:%.*]] = phi i1 [ true, [[A1_TARGET_A2]] ], [ false, [[H1_TARGET_A1]] ], [ true, [[H1_TARGET_A2]] ]
 ; CHECK-NEXT:    br i1 [[GUARD_A2]], label [[A2:%.*]], label [[A1]]
 ; CHECK:       L2.target.B2:
 ; CHECK-NEXT:    br label [[IRR_GUARD1:%.*]]
@@ -901,7 +1366,7 @@ define void @siblings_in_loop_callbr(i1 %Pred0, i1 %Pred1, i1 %Pred2, i1 %Pred3,
 ; CHECK:       fork1.target.B2:
 ; CHECK-NEXT:    br label [[IRR_GUARD1]]
 ; CHECK:       irr.guard1:
-; CHECK-NEXT:    [[GUARD_B2:%.*]] = phi i1 [ true, [[L2_TARGET_B2:%.*]] ], [ false, [[FORK1_TARGET_B1]] ], [ true, [[FORK1_TARGET_B2:%.*]] ]
+; CHECK-NEXT:    [[GUARD_B2:%.*]] = phi i1 [ true, [[L2_TARGET_B2]] ], [ false, [[FORK1_TARGET_B1]] ], [ true, [[FORK1_TARGET_B2]] ]
 ; CHECK-NEXT:    br i1 [[GUARD_B2]], label [[B2:%.*]], label [[B1]]
 ;
 entry:
@@ -944,6 +1409,113 @@ exit:
   ret void
 }
 
+define void @siblings_in_loop_switch(i1 %Pred0, i1 %Pred1, i1 %Pred2, i1 %Pred3, i1 %Pred4, i1 %Pred5, i1 %Pred6, i1 %Pred7) {
+; CHECK-LABEL: @siblings_in_loop_switch(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    switch i1 [[PRED0:%.*]], label [[H0:%.*]] [
+; CHECK-NEXT:    ]
+; CHECK:       H0:
+; CHECK-NEXT:    switch i1 [[PRED0]], label [[H1:%.*]] [
+; CHECK-NEXT:      i1 false, label [[FORK1:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       H1:
+; CHECK-NEXT:    switch i1 [[PRED1:%.*]], label [[H1_TARGET_A1:%.*]] [
+; CHECK-NEXT:      i1 false, label [[H1_TARGET_A2:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       A1:
+; CHECK-NEXT:    switch i1 [[PRED0]], label [[A1_TARGET_A2:%.*]] [
+; CHECK-NEXT:    ]
+; CHECK:       A2:
+; CHECK-NEXT:    switch i1 [[PRED2:%.*]], label [[A1:%.*]] [
+; CHECK-NEXT:      i1 false, label [[L1:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       L1:
+; CHECK-NEXT:    switch i1 [[PRED3:%.*]], label [[H1]] [
+; CHECK-NEXT:      i1 false, label [[L0:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       fork1:
+; CHECK-NEXT:    switch i1 [[PRED4:%.*]], label [[FORK1_TARGET_B1:%.*]] [
+; CHECK-NEXT:      i1 false, label [[FORK1_TARGET_B2:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       B1:
+; CHECK-NEXT:    switch i1 [[PRED0]], label [[H2:%.*]] [
+; CHECK-NEXT:    ]
+; CHECK:       H2:
+; CHECK-NEXT:    switch i1 [[PRED0]], label [[L2:%.*]] [
+; CHECK-NEXT:    ]
+; CHECK:       L2:
+; CHECK-NEXT:    switch i1 [[PRED5:%.*]], label [[H2]] [
+; CHECK-NEXT:      i1 false, label [[L2_TARGET_B2:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       B2:
+; CHECK-NEXT:    switch i1 [[PRED6:%.*]], label [[B1:%.*]] [
+; CHECK-NEXT:      i1 false, label [[L0]]
+; CHECK-NEXT:    ]
+; CHECK:       L0:
+; CHECK-NEXT:    switch i1 [[PRED7:%.*]], label [[EXIT:%.*]] [
+; CHECK-NEXT:      i1 false, label [[H0]]
+; CHECK-NEXT:    ]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+; CHECK:       A1.target.A2:
+; CHECK-NEXT:    br label [[IRR_GUARD:%.*]]
+; CHECK:       H1.target.A1:
+; CHECK-NEXT:    br label [[IRR_GUARD]]
+; CHECK:       H1.target.A2:
+; CHECK-NEXT:    br label [[IRR_GUARD]]
+; CHECK:       irr.guard:
+; CHECK-NEXT:    [[GUARD_A2:%.*]] = phi i1 [ true, [[A1_TARGET_A2]] ], [ false, [[H1_TARGET_A1]] ], [ true, [[H1_TARGET_A2]] ]
+; CHECK-NEXT:    br i1 [[GUARD_A2]], label [[A2:%.*]], label [[A1]]
+; CHECK:       L2.target.B2:
+; CHECK-NEXT:    br label [[IRR_GUARD1:%.*]]
+; CHECK:       fork1.target.B1:
+; CHECK-NEXT:    br label [[IRR_GUARD1]]
+; CHECK:       fork1.target.B2:
+; CHECK-NEXT:    br label [[IRR_GUARD1]]
+; CHECK:       irr.guard1:
+; CHECK-NEXT:    [[GUARD_B2:%.*]] = phi i1 [ true, [[L2_TARGET_B2]] ], [ false, [[FORK1_TARGET_B1]] ], [ true, [[FORK1_TARGET_B2]] ]
+; CHECK-NEXT:    br i1 [[GUARD_B2]], label [[B2:%.*]], label [[B1]]
+;
+entry:
+  switch i1 %Pred0, label %H0 []
+
+H0:
+  switch i1 %Pred0, label %H1 [ i1 0, label %fork1 ]
+
+H1:
+  switch i1 %Pred1, label %A1 [ i1 0, label %A2 ]
+
+A1:
+  switch i1 %Pred0, label %A2 []
+
+A2:
+  switch i1 %Pred2, label %A1 [ i1 0, label %L1 ]
+
+L1:
+  switch i1 %Pred3, label %H1 [ i1 0, label %L0 ]
+
+fork1:
+  switch i1 %Pred4, label %B1 [ i1 0, label %B2 ]
+
+B1:
+  switch i1 %Pred0, label %H2 []
+
+H2:
+  switch i1 %Pred0, label %L2 []
+
+L2:
+  switch i1 %Pred5, label %H2 [ i1 0, label %B2 ]
+
+B2:
+  switch i1 %Pred6, label %B1 [ i1 0, label %L0 ]
+
+L0:
+  switch i1 %Pred7, label %exit [ i1 0, label %H0 ]
+
+exit:
+  ret void
+}
+
 define void @irr_in_irr_shared_entry(i1 %Pred0, i1 %Pred1, i1 %Pred2, i1 %Pred3, i1 %Pred4, i1 %Pred5, i1 %Pred6, i1 %Pred7, i1 %Pred8, i1 %Pred9, i1 %Pred10, i1 %Pred11, i1 %Pred12, i1 %Pred13) {
 ; CHECK-LABEL: @irr_in_irr_shared_entry(
 ; CHECK-NEXT:  entry:
@@ -1063,10 +1635,10 @@ define void @irr_in_irr_shared_entry_callbr(i1 %Pred0, i1 %Pred1, i1 %Pred2, i1
 ; CHECK-LABEL: @irr_in_irr_shared_entry_callbr(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[PRED0:%.*]])
-; CHECK-NEXT:            to label [[IF_END:%.*]] [label %if.then]
+; CHECK-NEXT:            to label [[IF_END:%.*]] [label [[IF_THEN:%.*]]]
 ; CHECK:       if.end:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[PRED1:%.*]])
-; CHECK-NEXT:            to label [[IF_THEN7:%.*]] [label %if.else]
+; CHECK-NEXT:            to label [[IF_THEN7:%.*]] [label [[IF_ELSE:%.*]]]
 ; CHECK:       if.then7:
 ; CHECK-NEXT:    callbr void asm "", ""()
 ; CHECK-NEXT:            to label [[IF_END16:%.*]] []
@@ -1075,49 +1647,49 @@ define void @irr_in_irr_shared_entry_callbr(i1 %Pred0, i1 %Pred1, i1 %Pred2, i1
 ; CHECK-NEXT:            to label [[IF_END16]] []
 ; CHECK:       if.end16:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[PRED2:%.*]])
-; CHECK-NEXT:            to label [[WHILE_COND_PREHEADER:%.*]] [label %if.then39]
+; CHECK-NEXT:            to label [[WHILE_COND_PREHEADER:%.*]] [label [[IF_THEN39:%.*]]]
 ; CHECK:       while.cond.preheader:
 ; CHECK-NEXT:    callbr void asm "", ""()
 ; CHECK-NEXT:            to label [[WHILE_COND:%.*]] []
 ; CHECK:       while.cond:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[PRED3:%.*]])
-; CHECK-NEXT:            to label [[WHILE_COND_TARGET_COND_TRUE49:%.*]] [label %lor.rhs]
+; CHECK-NEXT:            to label [[WHILE_COND_TARGET_COND_TRUE49:%.*]] [label [[LOR_RHS:%.*]]]
 ; CHECK:       cond.true49:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[PRED4:%.*]])
-; CHECK-NEXT:            to label [[IF_THEN69:%.*]] [label %cond.true49.target.while.body63]
+; CHECK-NEXT:            to label [[IF_THEN69:%.*]] [label [[COND_TRUE49_TARGET_WHILE_BODY63:%.*]]]
 ; CHECK:       while.body63:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[PRED5:%.*]])
-; CHECK-NEXT:            to label [[EXIT:%.*]] [label %while.cond47]
+; CHECK-NEXT:            to label [[EXIT:%.*]] [label [[WHILE_COND47:%.*]]]
 ; CHECK:       while.cond47:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[PRED6:%.*]])
-; CHECK-NEXT:            to label [[COND_TRUE49:%.*]] [label %while.cond47.target.cond.end61]
+; CHECK-NEXT:            to label [[COND_TRUE49:%.*]] [label [[WHILE_COND47_TARGET_COND_END61:%.*]]]
 ; CHECK:       cond.end61:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[PRED7:%.*]])
-; CHECK-NEXT:            to label [[COND_END61_TARGET_WHILE_BODY63:%.*]] [label %while.cond]
+; CHECK-NEXT:            to label [[COND_END61_TARGET_WHILE_BODY63:%.*]] [label [[WHILE_COND]]]
 ; CHECK:       if.then69:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[PRED8:%.*]])
-; CHECK-NEXT:            to label [[EXIT]] [label %while.cond]
+; CHECK-NEXT:            to label [[EXIT]] [label [[WHILE_COND]]]
 ; CHECK:       lor.rhs:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[PRED9:%.*]])
-; CHECK-NEXT:            to label [[LOR_RHS_TARGET_COND_END61:%.*]] [label %while.end76]
+; CHECK-NEXT:            to label [[LOR_RHS_TARGET_COND_END61:%.*]] [label [[WHILE_END76:%.*]]]
 ; CHECK:       while.end76:
 ; CHECK-NEXT:    callbr void asm "", ""()
 ; CHECK-NEXT:            to label [[EXIT]] []
 ; CHECK:       if.then39:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[PRED10:%.*]])
-; CHECK-NEXT:            to label [[EXIT]] [label %if.end.i145]
+; CHECK-NEXT:            to label [[EXIT]] [label [[IF_END_I145:%.*]]]
 ; CHECK:       if.end.i145:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[PRED11:%.*]])
-; CHECK-NEXT:            to label [[EXIT]] [label %if.end8.i149]
+; CHECK-NEXT:            to label [[EXIT]] [label [[IF_END8_I149:%.*]]]
 ; CHECK:       if.end8.i149:
 ; CHECK-NEXT:    callbr void asm "", ""()
 ; CHECK-NEXT:            to label [[EXIT]] []
 ; CHECK:       if.then:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[PRED12:%.*]])
-; CHECK-NEXT:            to label [[EXIT]] [label %if.end.i]
+; CHECK-NEXT:            to label [[EXIT]] [label [[IF_END_I:%.*]]]
 ; CHECK:       if.end.i:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[PRED13:%.*]])
-; CHECK-NEXT:            to label [[EXIT]] [label %if.end8.i]
+; CHECK-NEXT:            to label [[EXIT]] [label [[IF_END8_I:%.*]]]
 ; CHECK:       if.end8.i:
 ; CHECK-NEXT:    callbr void asm "", ""()
 ; CHECK-NEXT:            to label [[EXIT]] []
@@ -1130,14 +1702,14 @@ define void @irr_in_irr_shared_entry_callbr(i1 %Pred0, i1 %Pred1, i1 %Pred2, i1
 ; CHECK:       while.cond.target.cond.true49:
 ; CHECK-NEXT:    br label [[IRR_GUARD]]
 ; CHECK:       irr.guard:
-; CHECK-NEXT:    [[GUARD_COND_END61:%.*]] = phi i1 [ true, [[WHILE_COND47_TARGET_COND_END61:%.*]] ], [ true, [[LOR_RHS_TARGET_COND_END61]] ], [ false, [[WHILE_COND_TARGET_COND_TRUE49]] ]
+; CHECK-NEXT:    [[GUARD_COND_END61:%.*]] = phi i1 [ true, [[WHILE_COND47_TARGET_COND_END61]] ], [ true, [[LOR_RHS_TARGET_COND_END61]] ], [ false, [[WHILE_COND_TARGET_COND_TRUE49]] ]
 ; CHECK-NEXT:    br i1 [[GUARD_COND_END61]], label [[COND_END61:%.*]], label [[IRR_GUARD1:%.*]]
 ; CHECK:       cond.true49.target.while.body63:
 ; CHECK-NEXT:    br label [[IRR_GUARD1]]
 ; CHECK:       cond.end61.target.while.body63:
 ; CHECK-NEXT:    br label [[IRR_GUARD1]]
 ; CHECK:       irr.guard1:
-; CHECK-NEXT:    [[GUARD_WHILE_BODY63:%.*]] = phi i1 [ true, [[COND_TRUE49_TARGET_WHILE_BODY63:%.*]] ], [ true, [[COND_END61_TARGET_WHILE_BODY63]] ], [ false, [[IRR_GUARD]] ]
+; CHECK-NEXT:    [[GUARD_WHILE_BODY63:%.*]] = phi i1 [ true, [[COND_TRUE49_TARGET_WHILE_BODY63]] ], [ true, [[COND_END61_TARGET_WHILE_BODY63]] ], [ false, [[IRR_GUARD]] ]
 ; CHECK-NEXT:    br i1 [[GUARD_WHILE_BODY63]], label [[WHILE_BODY63:%.*]], label [[COND_TRUE49]]
 ;
 entry:
@@ -1203,3 +1775,162 @@ if.end8.i:
 exit:
   ret void
 }
+
+define void @irr_in_irr_shared_entry_switch(i1 %Pred0, i1 %Pred1, i1 %Pred2, i1 %Pred3, i1 %Pred4, i1 %Pred5, i1 %Pred6, i1 %Pred7, i1 %Pred8, i1 %Pred9, i1 %Pred10, i1 %Pred11, i1 %Pred12, i1 %Pred13) {
+; CHECK-LABEL: @irr_in_irr_shared_entry_switch(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    switch i1 [[PRED0:%.*]], label [[IF_END:%.*]] [
+; CHECK-NEXT:      i1 false, label [[IF_THEN:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       if.end:
+; CHECK-NEXT:    switch i1 [[PRED1:%.*]], label [[IF_THEN7:%.*]] [
+; CHECK-NEXT:      i1 false, label [[IF_ELSE:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       if.then7:
+; CHECK-NEXT:    switch i1 [[PRED0]], label [[IF_END16:%.*]] [
+; CHECK-NEXT:    ]
+; CHECK:       if.else:
+; CHECK-NEXT:    switch i1 [[PRED0]], label [[IF_END16]] [
+; CHECK-NEXT:    ]
+; CHECK:       if.end16:
+; CHECK-NEXT:    switch i1 [[PRED2:%.*]], label [[WHILE_COND_PREHEADER:%.*]] [
+; CHECK-NEXT:      i1 false, label [[IF_THEN39:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       while.cond.preheader:
+; CHECK-NEXT:    switch i1 [[PRED0]], label [[WHILE_COND:%.*]] [
+; CHECK-NEXT:    ]
+; CHECK:       while.cond:
+; CHECK-NEXT:    switch i1 [[PRED3:%.*]], label [[WHILE_COND_TARGET_COND_TRUE49:%.*]] [
+; CHECK-NEXT:      i1 false, label [[LOR_RHS:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       cond.true49:
+; CHECK-NEXT:    switch i1 [[PRED4:%.*]], label [[IF_THEN69:%.*]] [
+; CHECK-NEXT:      i1 false, label [[COND_TRUE49_TARGET_WHILE_BODY63:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       while.body63:
+; CHECK-NEXT:    switch i1 [[PRED5:%.*]], label [[EXIT:%.*]] [
+; CHECK-NEXT:      i1 false, label [[WHILE_COND47:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       while.cond47:
+; CHECK-NEXT:    switch i1 [[PRED6:%.*]], label [[COND_TRUE49:%.*]] [
+; CHECK-NEXT:      i1 false, label [[WHILE_COND47_TARGET_COND_END61:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       cond.end61:
+; CHECK-NEXT:    switch i1 [[PRED7:%.*]], label [[COND_END61_TARGET_WHILE_BODY63:%.*]] [
+; CHECK-NEXT:      i1 false, label [[WHILE_COND]]
+; CHECK-NEXT:    ]
+; CHECK:       if.then69:
+; CHECK-NEXT:    switch i1 [[PRED8:%.*]], label [[EXIT]] [
+; CHECK-NEXT:      i1 false, label [[WHILE_COND]]
+; CHECK-NEXT:    ]
+; CHECK:       lor.rhs:
+; CHECK-NEXT:    switch i1 [[PRED9:%.*]], label [[LOR_RHS_TARGET_COND_END61:%.*]] [
+; CHECK-NEXT:      i1 false, label [[WHILE_END76:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       while.end76:
+; CHECK-NEXT:    switch i1 [[PRED0]], label [[EXIT]] [
+; CHECK-NEXT:    ]
+; CHECK:       if.then39:
+; CHECK-NEXT:    switch i1 [[PRED10:%.*]], label [[EXIT]] [
+; CHECK-NEXT:      i1 false, label [[IF_END_I145:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       if.end.i145:
+; CHECK-NEXT:    switch i1 [[PRED11:%.*]], label [[EXIT]] [
+; CHECK-NEXT:      i1 false, label [[IF_END8_I149:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       if.end8.i149:
+; CHECK-NEXT:    switch i1 [[PRED0]], label [[EXIT]] [
+; CHECK-NEXT:    ]
+; CHECK:       if.then:
+; CHECK-NEXT:    switch i1 [[PRED12:%.*]], label [[EXIT]] [
+; CHECK-NEXT:      i1 false, label [[IF_END_I:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       if.end.i:
+; CHECK-NEXT:    switch i1 [[PRED13:%.*]], label [[EXIT]] [
+; CHECK-NEXT:      i1 false, label [[IF_END8_I:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       if.end8.i:
+; CHECK-NEXT:    switch i1 [[PRED0]], label [[EXIT]] [
+; CHECK-NEXT:    ]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+; CHECK:       while.cond47.target.cond.end61:
+; CHECK-NEXT:    br label [[IRR_GUARD:%.*]]
+; CHECK:       lor.rhs.target.cond.end61:
+; CHECK-NEXT:    br label [[IRR_GUARD]]
+; CHECK:       while.cond.target.cond.true49:
+; CHECK-NEXT:    br label [[IRR_GUARD]]
+; CHECK:       irr.guard:
+; CHECK-NEXT:    [[GUARD_COND_END61:%.*]] = phi i1 [ true, [[WHILE_COND47_TARGET_COND_END61]] ], [ true, [[LOR_RHS_TARGET_COND_END61]] ], [ false, [[WHILE_COND_TARGET_COND_TRUE49]] ]
+; CHECK-NEXT:    br i1 [[GUARD_COND_END61]], label [[COND_END61:%.*]], label [[IRR_GUARD1:%.*]]
+; CHECK:       cond.true49.target.while.body63:
+; CHECK-NEXT:    br label [[IRR_GUARD1]]
+; CHECK:       cond.end61.target.while.body63:
+; CHECK-NEXT:    br label [[IRR_GUARD1]]
+; CHECK:       irr.guard1:
+; CHECK-NEXT:    [[GUARD_WHILE_BODY63:%.*]] = phi i1 [ true, [[COND_TRUE49_TARGET_WHILE_BODY63]] ], [ true, [[COND_END61_TARGET_WHILE_BODY63]] ], [ false, [[IRR_GUARD]] ]
+; CHECK-NEXT:    br i1 [[GUARD_WHILE_BODY63]], label [[WHILE_BODY63:%.*]], label [[COND_TRUE49]]
+;
+entry:
+  switch i1 %Pred0, label %if.end [ i1 0, label %if.then ]
+
+if.end:
+  switch i1 %Pred1, label %if.then7 [ i1 0, label %if.else ]
+
+if.then7:
+  switch i1 %Pred0, label %if.end16 []
+
+if.else:
+  switch i1 %Pred0, label %if.end16 []
+
+if.end16:
+  switch i1 %Pred2, label %while.cond.preheader [ i1 0, label %if.then39 ]
+
+while.cond.preheader:
+  switch i1 %Pred0, label %while.cond []
+
+while.cond:
+  switch i1 %Pred3, label %cond.true49 [ i1 0, label %lor.rhs ]
+
+cond.true49:
+  switch i1 %Pred4, label %if.then69 [ i1 0, label %while.body63 ]
+
+while.body63:
+  switch i1 %Pred5, label %exit [ i1 0, label %while.cond47 ]
+
+while.cond47:
+  switch i1 %Pred6, label %cond.true49 [ i1 0, label %cond.end61 ]
+
+cond.end61:
+  switch i1 %Pred7, label %while.body63 [ i1 0, label %while.cond ]
+
+if.then69:
+  switch i1 %Pred8, label %exit [ i1 0, label %while.cond ]
+
+lor.rhs:
+  switch i1 %Pred9, label %cond.end61 [ i1 0, label %while.end76 ]
+
+while.end76:
+  switch i1 %Pred0, label %exit []
+
+if.then39:
+  switch i1 %Pred10, label %exit [ i1 0, label %if.end.i145 ]
+
+if.end.i145:
+  switch i1 %Pred11, label %exit [ i1 0, label %if.end8.i149 ]
+
+if.end8.i149:
+  switch i1 %Pred0, label %exit []
+
+if.then:
+  switch i1 %Pred12, label %exit [ i1 0, label %if.end.i ]
+
+if.end.i:
+  switch i1 %Pred13, label %exit [ i1 0, label %if.end8.i ]
+
+if.end8.i:
+  switch i1 %Pred0, label %exit []
+
+exit:
+  ret void
+}
diff --git a/llvm/test/Transforms/FixIrreducible/unreachable.ll b/llvm/test/Transforms/FixIrreducible/unreachable.ll
index 845cf507c7fc0..02a23a97380f8 100644
--- a/llvm/test/Transforms/FixIrreducible/unreachable.ll
+++ b/llvm/test/Transforms/FixIrreducible/unreachable.ll
@@ -48,3 +48,26 @@ loop.latch:
 loop.exit:
   ret void
 }
+
+; CHECK-LABEL: @unreachable_switch(
+; CHECK: entry:
+; CHECK-NOT: irr.guard:
+define void @unreachable_switch(i32 %n, i1 %arg) {
+entry:
+  switch i32 %n, label %loop.body []
+
+loop.body:
+  switch i32 %n, label %inner.block []
+
+unreachable.block:
+  switch i32 %n, label %inner.block []
+
+inner.block:
+  switch i1 %arg, label %loop.exit [ i1 0, label %loop.latch ]
+
+loop.latch:
+  switch i32 %n, label %loop.body []
+
+loop.exit:
+  ret void
+}
diff --git a/llvm/test/Transforms/FixIrreducible/unsupported-terminator.ll b/llvm/test/Transforms/FixIrreducible/unsupported-terminator.ll
index 02a4ec802cd33..80711a8ddaedf 100644
--- a/llvm/test/Transforms/FixIrreducible/unsupported-terminator.ll
+++ b/llvm/test/Transforms/FixIrreducible/unsupported-terminator.ll
@@ -13,4 +13,4 @@ then:
 
 else:
   br label %then
-}
\ No newline at end of file
+}
diff --git a/llvm/test/Transforms/UnifyLoopExits/basic.ll b/llvm/test/Transforms/UnifyLoopExits/basic.ll
index a1c4814883c93..0ab4b34b13d11 100644
--- a/llvm/test/Transforms/UnifyLoopExits/basic.ll
+++ b/llvm/test/Transforms/UnifyLoopExits/basic.ll
@@ -1,5 +1,5 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt < %s -passes='lower-switch,unify-loop-exits' -S | FileCheck %s
+; RUN: opt < %s -passes='unify-loop-exits' -S | FileCheck %s
 
 define void @loop_1(i1 %PredEntry, i1 %PredB, i1 %PredC, i1 %PredD) {
 ; CHECK-LABEL: @loop_1(
@@ -73,7 +73,7 @@ define void @loop_1_callbr(i1 %PredEntry, i1 %PredB, i1 %PredC, i1 %PredD) {
 ; CHECK:       F:
 ; CHECK-NEXT:    br label [[EXIT]]
 ; CHECK:       G:
-; CHECK-NEXT:    br label [[Y:%.*]]
+; CHECK-NEXT:    br label [[F:%.*]]
 ; CHECK:       exit:
 ; CHECK-NEXT:    ret void
 ; CHECK:       B.target.E:
@@ -83,8 +83,8 @@ define void @loop_1_callbr(i1 %PredEntry, i1 %PredB, i1 %PredC, i1 %PredD) {
 ; CHECK:       D.target.F:
 ; CHECK-NEXT:    br label [[LOOP_EXIT_GUARD]]
 ; CHECK:       loop.exit.guard:
-; CHECK-NEXT:    [[GUARD_X:%.*]] = phi i1 [ true, [[B_TARGET_E]] ], [ false, [[C_TARGET_F]] ], [ false, [[D_TARGET_F]] ]
-; CHECK-NEXT:    br i1 [[GUARD_X]], label [[X:%.*]], label [[Y]]
+; CHECK-NEXT:    [[GUARD_E:%.*]] = phi i1 [ true, [[B_TARGET_E]] ], [ false, [[C_TARGET_F]] ], [ false, [[D_TARGET_F]] ]
+; CHECK-NEXT:    br i1 [[GUARD_E]], label [[E:%.*]], label [[F]]
 ;
 entry:
   br i1 %PredEntry, label %A, label %G
@@ -114,6 +114,72 @@ exit:
   ret void
 }
 
+define void @loop_1_switch(i1 %PredEntry, i1 %PredB, i1 %PredC, i1 %PredD) {
+; CHECK-LABEL: @loop_1_switch(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    switch i1 [[PREDENTRY:%.*]], label [[A:%.*]] [
+; CHECK-NEXT:      i1 false, label [[G:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       A:
+; CHECK-NEXT:    br label [[B:%.*]]
+; CHECK:       B:
+; CHECK-NEXT:    switch i1 [[PREDB:%.*]], label [[C:%.*]] [
+; CHECK-NEXT:      i1 false, label [[B_TARGET_E:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       C:
+; CHECK-NEXT:    switch i1 [[PREDC:%.*]], label [[D:%.*]] [
+; CHECK-NEXT:      i1 false, label [[C_TARGET_F:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       D:
+; CHECK-NEXT:    switch i1 [[PREDD:%.*]], label [[A]] [
+; CHECK-NEXT:      i1 false, label [[D_TARGET_F:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       E:
+; CHECK-NEXT:    br label [[EXIT:%.*]]
+; CHECK:       F:
+; CHECK-NEXT:    br label [[EXIT]]
+; CHECK:       G:
+; CHECK-NEXT:    br label [[F:%.*]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+; CHECK:       B.target.E:
+; CHECK-NEXT:    br label [[LOOP_EXIT_GUARD:%.*]]
+; CHECK:       C.target.F:
+; CHECK-NEXT:    br label [[LOOP_EXIT_GUARD]]
+; CHECK:       D.target.F:
+; CHECK-NEXT:    br label [[LOOP_EXIT_GUARD]]
+; CHECK:       loop.exit.guard:
+; CHECK-NEXT:    [[GUARD_E:%.*]] = phi i1 [ true, [[B_TARGET_E]] ], [ false, [[C_TARGET_F]] ], [ false, [[D_TARGET_F]] ]
+; CHECK-NEXT:    br i1 [[GUARD_E]], label [[E:%.*]], label [[F]]
+;
+entry:
+  switch i1 %PredEntry, label %A [ i1 0, label %G ]
+
+A:
+  br label %B
+
+B:
+  switch i1 %PredB, label %C [ i1 0, label %E ]
+
+C:
+  switch i1 %PredC, label %D [ i1 0, label %F ]
+
+D:
+  switch i1 %PredD, label %A [ i1 0, label %F ]
+
+E:
+  br label %exit
+
+F:
+  br label %exit
+
+G:
+  br label %F
+
+exit:
+  ret void
+}
+
 define void @loop_2(i1 %PredA, i1 %PredB, i1 %PredC) {
 ; CHECK-LABEL: @loop_2(
 ; CHECK-NEXT:  entry:
@@ -233,6 +299,73 @@ exit:
   ret void
 }
 
+define void @loop_2_switch(i1 %PredA, i1 %PredB, i1 %PredC) {
+; CHECK-LABEL: @loop_2_switch(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label [[A:%.*]]
+; CHECK:       A:
+; CHECK-NEXT:    switch i1 [[PREDA:%.*]], label [[B:%.*]] [
+; CHECK-NEXT:      i1 false, label [[A_TARGET_X:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       B:
+; CHECK-NEXT:    switch i1 [[PREDB:%.*]], label [[C:%.*]] [
+; CHECK-NEXT:      i1 false, label [[B_TARGET_Y:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       C:
+; CHECK-NEXT:    switch i1 [[PREDC:%.*]], label [[D:%.*]] [
+; CHECK-NEXT:      i1 false, label [[C_TARGET_Z:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       D:
+; CHECK-NEXT:    br label [[A]]
+; CHECK:       X:
+; CHECK-NEXT:    br label [[EXIT:%.*]]
+; CHECK:       Y:
+; CHECK-NEXT:    br label [[EXIT]]
+; CHECK:       Z:
+; CHECK-NEXT:    br label [[EXIT]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+; CHECK:       A.target.X:
+; CHECK-NEXT:    br label [[LOOP_EXIT_GUARD:%.*]]
+; CHECK:       B.target.Y:
+; CHECK-NEXT:    br label [[LOOP_EXIT_GUARD]]
+; CHECK:       C.target.Z:
+; CHECK-NEXT:    br label [[LOOP_EXIT_GUARD]]
+; CHECK:       loop.exit.guard:
+; CHECK-NEXT:    [[GUARD_X:%.*]] = phi i1 [ true, [[A_TARGET_X]] ], [ false, [[B_TARGET_Y]] ], [ false, [[C_TARGET_Z]] ]
+; CHECK-NEXT:    [[GUARD_Y:%.*]] = phi i1 [ false, [[A_TARGET_X]] ], [ true, [[B_TARGET_Y]] ], [ false, [[C_TARGET_Z]] ]
+; CHECK-NEXT:    br i1 [[GUARD_X]], label [[X:%.*]], label [[LOOP_EXIT_GUARD1:%.*]]
+; CHECK:       loop.exit.guard1:
+; CHECK-NEXT:    br i1 [[GUARD_Y]], label [[Y:%.*]], label [[Z:%.*]]
+;
+entry:
+  br label %A
+
+A:
+  switch i1 %PredA, label %B [ i1 0, label %X ]
+
+B:
+  switch i1 %PredB, label %C [ i1 0, label %Y ]
+
+C:
+  switch i1 %PredC, label %D [ i1 0, label %Z ]
+
+D:
+  br label %A
+
+X:
+  br label %exit
+
+Y:
+  br label %exit
+
+Z:
+  br label %exit
+
+exit:
+  ret void
+}
+
 ; Test that UnifyLoopExits handles callbr with duplicate successors correctly.
 ; The exit block appears twice as a successor of the callbr instruction.
 define void @callbr_duplicate_successors() {
@@ -259,3 +392,32 @@ loop:
 exit:
   ret void
 }
+
+define void @switch_duplicate_successors(i1 %Pred) {
+; CHECK-LABEL: @switch_duplicate_successors(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label [[LOOP:%.*]]
+; CHECK:       loop:
+; CHECK-NEXT:    switch i1 [[PRED:%.*]], label [[LOOP_TARGET_EXIT:%.*]] [
+; CHECK-NEXT:      i1 false, label [[LOOP]]
+; CHECK-NEXT:      i1 true, label [[LOOP_TARGET_EXIT1:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+; CHECK:       loop.target.exit:
+; CHECK-NEXT:    br label [[EXIT:%.*]]
+; CHECK:       loop.target.exit1:
+; CHECK-NEXT:    br label [[EXIT]]
+;
+entry:
+  br label %loop
+
+loop:
+  switch i1 %Pred, label %exit [
+  i1 0, label %loop
+  i1 1, label %exit
+  ]
+
+exit:
+  ret void
+}
diff --git a/llvm/test/Transforms/UnifyLoopExits/integer_guards.ll b/llvm/test/Transforms/UnifyLoopExits/integer_guards.ll
index be982d5d043f9..5cded19c06d97 100644
--- a/llvm/test/Transforms/UnifyLoopExits/integer_guards.ll
+++ b/llvm/test/Transforms/UnifyLoopExits/integer_guards.ll
@@ -78,7 +78,7 @@ define void @loop_two_exits_callbr(i1 %PredEntry, i1 %PredA) {
 ; CHECK:       A:
 ; CHECK-NEXT:    [[INC1:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC2:%.*]], [[C:%.*]] ]
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[PREDA:%.*]])
-; CHECK-NEXT:            to label [[A_TARGET_B:%.*]] [label %C]
+; CHECK-NEXT:            to label [[A_TARGET_B:%.*]] [label [[C]]]
 ; CHECK:       B:
 ; CHECK-NEXT:    tail call fastcc void @check(i32 1) #[[ATTR0]]
 ; CHECK-NEXT:    br label [[D:%.*]]
@@ -86,7 +86,7 @@ define void @loop_two_exits_callbr(i1 %PredEntry, i1 %PredA) {
 ; CHECK-NEXT:    [[INC2]] = add i32 [[INC1]], 1
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[INC2]], 10
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[CMP]])
-; CHECK-NEXT:            to label [[A]] [label %C.target.E]
+; CHECK-NEXT:            to label [[A]] [label [[C_TARGET_E:%.*]]]
 ; CHECK:       D:
 ; CHECK-NEXT:    unreachable
 ; CHECK:       E:
@@ -96,7 +96,7 @@ define void @loop_two_exits_callbr(i1 %PredEntry, i1 %PredA) {
 ; CHECK:       C.target.E:
 ; CHECK-NEXT:    br label [[LOOP_EXIT_GUARD]]
 ; CHECK:       loop.exit.guard:
-; CHECK-NEXT:    [[MERGED_BB_IDX:%.*]] = phi i32 [ 0, [[A_TARGET_B]] ], [ 1, [[C_TARGET_E:%.*]] ]
+; CHECK-NEXT:    [[MERGED_BB_IDX:%.*]] = phi i32 [ 0, [[A_TARGET_B]] ], [ 1, [[C_TARGET_E]] ]
 ; CHECK-NEXT:    [[B_PREDICATE:%.*]] = icmp eq i32 [[MERGED_BB_IDX]], 0
 ; CHECK-NEXT:    br i1 [[B_PREDICATE]], label [[B:%.*]], label [[E]]
 ;
@@ -106,7 +106,7 @@ define void @loop_two_exits_callbr(i1 %PredEntry, i1 %PredA) {
 ; BOOLEAN:       A:
 ; BOOLEAN-NEXT:    [[INC1:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC2:%.*]], [[C:%.*]] ]
 ; BOOLEAN-NEXT:    callbr void asm "", "r,!i"(i1 [[PREDA:%.*]])
-; BOOLEAN-NEXT:            to label [[A_TARGET_B:%.*]] [label %C]
+; BOOLEAN-NEXT:            to label [[A_TARGET_B:%.*]] [label [[C]]]
 ; BOOLEAN:       B:
 ; BOOLEAN-NEXT:    tail call fastcc void @check(i32 1) #[[ATTR0]]
 ; BOOLEAN-NEXT:    br label [[D:%.*]]
@@ -114,7 +114,7 @@ define void @loop_two_exits_callbr(i1 %PredEntry, i1 %PredA) {
 ; BOOLEAN-NEXT:    [[INC2]] = add i32 [[INC1]], 1
 ; BOOLEAN-NEXT:    [[CMP:%.*]] = icmp ult i32 [[INC2]], 10
 ; BOOLEAN-NEXT:    callbr void asm "", "r,!i"(i1 [[CMP]])
-; BOOLEAN-NEXT:            to label [[A]] [label %C.target.E]
+; BOOLEAN-NEXT:            to label [[A]] [label [[C_TARGET_E:%.*]]]
 ; BOOLEAN:       D:
 ; BOOLEAN-NEXT:    unreachable
 ; BOOLEAN:       E:
@@ -124,7 +124,7 @@ define void @loop_two_exits_callbr(i1 %PredEntry, i1 %PredA) {
 ; BOOLEAN:       C.target.E:
 ; BOOLEAN-NEXT:    br label [[LOOP_EXIT_GUARD]]
 ; BOOLEAN:       loop.exit.guard:
-; BOOLEAN-NEXT:    [[GUARD_B:%.*]] = phi i1 [ true, [[A_TARGET_B]] ], [ false, [[C_TARGET_E:%.*]] ]
+; BOOLEAN-NEXT:    [[GUARD_B:%.*]] = phi i1 [ true, [[A_TARGET_B]] ], [ false, [[C_TARGET_E]] ]
 ; BOOLEAN-NEXT:    br i1 [[GUARD_B]], label [[B:%.*]], label [[E]]
 ;
 entry:
@@ -150,6 +150,93 @@ E:
   ret void
 }
 
+define void @loop_two_exits_switch(i1 %PredEntry, i1 %PredA) {
+; CHECK-LABEL: @loop_two_exits_switch(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    switch i1 [[PREDENTRY:%.*]], label [[A:%.*]] [
+; CHECK-NEXT:      i1 false, label [[E:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       A:
+; CHECK-NEXT:    [[INC1:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC2:%.*]], [[C:%.*]] ]
+; CHECK-NEXT:    switch i1 [[PREDA:%.*]], label [[A_TARGET_B:%.*]] [
+; CHECK-NEXT:      i1 false, label [[C]]
+; CHECK-NEXT:    ]
+; CHECK:       B:
+; CHECK-NEXT:    tail call fastcc void @check(i32 1) #[[ATTR0]]
+; CHECK-NEXT:    br label [[D:%.*]]
+; CHECK:       C:
+; CHECK-NEXT:    [[INC2]] = add i32 [[INC1]], 1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[INC2]], 10
+; CHECK-NEXT:    switch i1 [[CMP]], label [[A]] [
+; CHECK-NEXT:      i1 false, label [[C_TARGET_E:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       D:
+; CHECK-NEXT:    unreachable
+; CHECK:       E:
+; CHECK-NEXT:    ret void
+; CHECK:       A.target.B:
+; CHECK-NEXT:    br label [[LOOP_EXIT_GUARD:%.*]]
+; CHECK:       C.target.E:
+; CHECK-NEXT:    br label [[LOOP_EXIT_GUARD]]
+; CHECK:       loop.exit.guard:
+; CHECK-NEXT:    [[MERGED_BB_IDX:%.*]] = phi i32 [ 0, [[A_TARGET_B]] ], [ 1, [[C_TARGET_E]] ]
+; CHECK-NEXT:    [[B_PREDICATE:%.*]] = icmp eq i32 [[MERGED_BB_IDX]], 0
+; CHECK-NEXT:    br i1 [[B_PREDICATE]], label [[B:%.*]], label [[E]]
+;
+; BOOLEAN-LABEL: @loop_two_exits_switch(
+; BOOLEAN-NEXT:  entry:
+; BOOLEAN-NEXT:    switch i1 [[PREDENTRY:%.*]], label [[A:%.*]] [
+; BOOLEAN-NEXT:      i1 false, label [[E:%.*]]
+; BOOLEAN-NEXT:    ]
+; BOOLEAN:       A:
+; BOOLEAN-NEXT:    [[INC1:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC2:%.*]], [[C:%.*]] ]
+; BOOLEAN-NEXT:    switch i1 [[PREDA:%.*]], label [[A_TARGET_B:%.*]] [
+; BOOLEAN-NEXT:      i1 false, label [[C]]
+; BOOLEAN-NEXT:    ]
+; BOOLEAN:       B:
+; BOOLEAN-NEXT:    tail call fastcc void @check(i32 1) #[[ATTR0]]
+; BOOLEAN-NEXT:    br label [[D:%.*]]
+; BOOLEAN:       C:
+; BOOLEAN-NEXT:    [[INC2]] = add i32 [[INC1]], 1
+; BOOLEAN-NEXT:    [[CMP:%.*]] = icmp ult i32 [[INC2]], 10
+; BOOLEAN-NEXT:    switch i1 [[CMP]], label [[A]] [
+; BOOLEAN-NEXT:      i1 false, label [[C_TARGET_E:%.*]]
+; BOOLEAN-NEXT:    ]
+; BOOLEAN:       D:
+; BOOLEAN-NEXT:    unreachable
+; BOOLEAN:       E:
+; BOOLEAN-NEXT:    ret void
+; BOOLEAN:       A.target.B:
+; BOOLEAN-NEXT:    br label [[LOOP_EXIT_GUARD:%.*]]
+; BOOLEAN:       C.target.E:
+; BOOLEAN-NEXT:    br label [[LOOP_EXIT_GUARD]]
+; BOOLEAN:       loop.exit.guard:
+; BOOLEAN-NEXT:    [[GUARD_B:%.*]] = phi i1 [ true, [[A_TARGET_B]] ], [ false, [[C_TARGET_E]] ]
+; BOOLEAN-NEXT:    br i1 [[GUARD_B]], label [[B:%.*]], label [[E]]
+;
+entry:
+  switch i1 %PredEntry, label %A [ i1 0, label %E ]
+
+A:
+  %inc1 = phi i32 [ 0, %entry ], [ %inc2, %C ]
+  switch i1 %PredA, label %B [ i1 0, label %C ]
+
+B:
+  tail call fastcc void @check(i32 1) #0
+  br label %D
+
+C:
+  %inc2 = add i32 %inc1, 1
+  %cmp = icmp ult i32 %inc2, 10
+  switch i1 %cmp, label %A [ i1 0, label %E ]
+
+D:
+  unreachable
+
+E:
+  ret void
+}
+
 ; The loop exit blocks appear in an inner loop.
 
 define void @inner_loop(i1 %PredEntry, i1 %PredA, i1 %PredB) {
@@ -285,13 +372,13 @@ define void @inner_loop_callbr(i1 %PredEntry, i1 %PredA, i1 %PredB) {
 ; CHECK:       B:
 ; CHECK-NEXT:    [[INNER1:%.*]] = phi i32 [ 0, [[A]] ], [ [[INNER2:%.*]], [[F:%.*]] ]
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[PREDA:%.*]])
-; CHECK-NEXT:            to label [[D:%.*]] [label %B.target.B.target.C]
+; CHECK-NEXT:            to label [[D:%.*]] [label [[B_TARGET_B_TARGET_C:%.*]]]
 ; CHECK:       C:
 ; CHECK-NEXT:    tail call fastcc void @check(i32 1) #[[ATTR0]]
 ; CHECK-NEXT:    br label [[H:%.*]]
 ; CHECK:       D:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[PREDB:%.*]])
-; CHECK-NEXT:            to label [[D_TARGET_D_TARGET_E:%.*]] [label %F]
+; CHECK-NEXT:            to label [[D_TARGET_D_TARGET_E:%.*]] [label [[F]]]
 ; CHECK:       E:
 ; CHECK-NEXT:    tail call fastcc void @check(i32 2) #[[ATTR0]]
 ; CHECK-NEXT:    br label [[H]]
@@ -299,12 +386,12 @@ define void @inner_loop_callbr(i1 %PredEntry, i1 %PredA, i1 %PredB) {
 ; CHECK-NEXT:    [[INNER2]] = add i32 [[INNER1]], 1
 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp ult i32 [[INNER2]], 20
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[CMP1]])
-; CHECK-NEXT:            to label [[B]] [label %F.target.G]
+; CHECK-NEXT:            to label [[B]] [label [[F_TARGET_G:%.*]]]
 ; CHECK:       G:
 ; CHECK-NEXT:    [[OUTER2]] = add i32 [[OUTER1]], 1
 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp ult i32 [[OUTER2]], 10
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[CMP2]])
-; CHECK-NEXT:            to label [[A]] [label %G.target.I]
+; CHECK-NEXT:            to label [[A]] [label [[G_TARGET_I:%.*]]]
 ; CHECK:       H:
 ; CHECK-NEXT:    unreachable
 ; CHECK:       I:
@@ -316,7 +403,7 @@ define void @inner_loop_callbr(i1 %PredEntry, i1 %PredA, i1 %PredB) {
 ; CHECK:       G.target.I:
 ; CHECK-NEXT:    br label [[LOOP_EXIT_GUARD]]
 ; CHECK:       loop.exit.guard:
-; CHECK-NEXT:    [[MERGED_BB_IDX:%.*]] = phi i32 [ 0, [[B_TARGET_C:%.*]] ], [ 1, [[D_TARGET_E:%.*]] ], [ 2, [[G_TARGET_I:%.*]] ]
+; CHECK-NEXT:    [[MERGED_BB_IDX:%.*]] = phi i32 [ 0, [[B_TARGET_C:%.*]] ], [ 1, [[D_TARGET_E:%.*]] ], [ 2, [[G_TARGET_I]] ]
 ; CHECK-NEXT:    [[C_PREDICATE:%.*]] = icmp eq i32 [[MERGED_BB_IDX]], 0
 ; CHECK-NEXT:    br i1 [[C_PREDICATE]], label [[C:%.*]], label [[LOOP_EXIT_GUARD1:%.*]]
 ; CHECK:       loop.exit.guard1:
@@ -329,7 +416,7 @@ define void @inner_loop_callbr(i1 %PredEntry, i1 %PredA, i1 %PredB) {
 ; CHECK:       F.target.G:
 ; CHECK-NEXT:    br label [[LOOP_EXIT_GUARD2]]
 ; CHECK:       loop.exit.guard2:
-; CHECK-NEXT:    [[MERGED_BB_IDX4:%.*]] = phi i32 [ 0, [[B_TARGET_B_TARGET_C:%.*]] ], [ 1, [[D_TARGET_D_TARGET_E]] ], [ 2, [[F_TARGET_G:%.*]] ]
+; CHECK-NEXT:    [[MERGED_BB_IDX4:%.*]] = phi i32 [ 0, [[B_TARGET_B_TARGET_C]] ], [ 1, [[D_TARGET_D_TARGET_E]] ], [ 2, [[F_TARGET_G]] ]
 ; CHECK-NEXT:    [[B_TARGET_C_PREDICATE:%.*]] = icmp eq i32 [[MERGED_BB_IDX4]], 0
 ; CHECK-NEXT:    br i1 [[B_TARGET_C_PREDICATE]], label [[B_TARGET_C]], label [[LOOP_EXIT_GUARD3:%.*]]
 ; CHECK:       loop.exit.guard3:
@@ -345,13 +432,13 @@ define void @inner_loop_callbr(i1 %PredEntry, i1 %PredA, i1 %PredB) {
 ; BOOLEAN:       B:
 ; BOOLEAN-NEXT:    [[INNER1:%.*]] = phi i32 [ 0, [[A]] ], [ [[INNER2:%.*]], [[F:%.*]] ]
 ; BOOLEAN-NEXT:    callbr void asm "", "r,!i"(i1 [[PREDA:%.*]])
-; BOOLEAN-NEXT:            to label [[D:%.*]] [label %B.target.B.target.C]
+; BOOLEAN-NEXT:            to label [[D:%.*]] [label [[B_TARGET_B_TARGET_C:%.*]]]
 ; BOOLEAN:       C:
 ; BOOLEAN-NEXT:    tail call fastcc void @check(i32 1) #[[ATTR0]]
 ; BOOLEAN-NEXT:    br label [[H:%.*]]
 ; BOOLEAN:       D:
 ; BOOLEAN-NEXT:    callbr void asm "", "r,!i"(i1 [[PREDB:%.*]])
-; BOOLEAN-NEXT:            to label [[D_TARGET_D_TARGET_E:%.*]] [label %F]
+; BOOLEAN-NEXT:            to label [[D_TARGET_D_TARGET_E:%.*]] [label [[F]]]
 ; BOOLEAN:       E:
 ; BOOLEAN-NEXT:    tail call fastcc void @check(i32 2) #[[ATTR0]]
 ; BOOLEAN-NEXT:    br label [[H]]
@@ -359,12 +446,12 @@ define void @inner_loop_callbr(i1 %PredEntry, i1 %PredA, i1 %PredB) {
 ; BOOLEAN-NEXT:    [[INNER2]] = add i32 [[INNER1]], 1
 ; BOOLEAN-NEXT:    [[CMP1:%.*]] = icmp ult i32 [[INNER2]], 20
 ; BOOLEAN-NEXT:    callbr void asm "", "r,!i"(i1 [[CMP1]])
-; BOOLEAN-NEXT:            to label [[B]] [label %F.target.G]
+; BOOLEAN-NEXT:            to label [[B]] [label [[F_TARGET_G:%.*]]]
 ; BOOLEAN:       G:
 ; BOOLEAN-NEXT:    [[OUTER2]] = add i32 [[OUTER1]], 1
 ; BOOLEAN-NEXT:    [[CMP2:%.*]] = icmp ult i32 [[OUTER2]], 10
 ; BOOLEAN-NEXT:    callbr void asm "", "r,!i"(i1 [[CMP2]])
-; BOOLEAN-NEXT:            to label [[A]] [label %G.target.I]
+; BOOLEAN-NEXT:            to label [[A]] [label [[G_TARGET_I:%.*]]]
 ; BOOLEAN:       H:
 ; BOOLEAN-NEXT:    unreachable
 ; BOOLEAN:       I:
@@ -376,7 +463,7 @@ define void @inner_loop_callbr(i1 %PredEntry, i1 %PredA, i1 %PredB) {
 ; BOOLEAN:       G.target.I:
 ; BOOLEAN-NEXT:    br label [[LOOP_EXIT_GUARD]]
 ; BOOLEAN:       loop.exit.guard:
-; BOOLEAN-NEXT:    [[GUARD_C:%.*]] = phi i1 [ true, [[B_TARGET_C:%.*]] ], [ false, [[D_TARGET_E:%.*]] ], [ false, [[G_TARGET_I:%.*]] ]
+; BOOLEAN-NEXT:    [[GUARD_C:%.*]] = phi i1 [ true, [[B_TARGET_C:%.*]] ], [ false, [[D_TARGET_E:%.*]] ], [ false, [[G_TARGET_I]] ]
 ; BOOLEAN-NEXT:    [[GUARD_E:%.*]] = phi i1 [ false, [[B_TARGET_C]] ], [ true, [[D_TARGET_E]] ], [ false, [[G_TARGET_I]] ]
 ; BOOLEAN-NEXT:    br i1 [[GUARD_C]], label [[C:%.*]], label [[LOOP_EXIT_GUARD1:%.*]]
 ; BOOLEAN:       loop.exit.guard1:
@@ -388,7 +475,7 @@ define void @inner_loop_callbr(i1 %PredEntry, i1 %PredA, i1 %PredB) {
 ; BOOLEAN:       F.target.G:
 ; BOOLEAN-NEXT:    br label [[LOOP_EXIT_GUARD2]]
 ; BOOLEAN:       loop.exit.guard2:
-; BOOLEAN-NEXT:    [[GUARD_B_TARGET_C:%.*]] = phi i1 [ true, [[B_TARGET_B_TARGET_C:%.*]] ], [ false, [[D_TARGET_D_TARGET_E]] ], [ false, [[F_TARGET_G:%.*]] ]
+; BOOLEAN-NEXT:    [[GUARD_B_TARGET_C:%.*]] = phi i1 [ true, [[B_TARGET_B_TARGET_C]] ], [ false, [[D_TARGET_D_TARGET_E]] ], [ false, [[F_TARGET_G]] ]
 ; BOOLEAN-NEXT:    [[GUARD_D_TARGET_E:%.*]] = phi i1 [ false, [[B_TARGET_B_TARGET_C]] ], [ true, [[D_TARGET_D_TARGET_E]] ], [ false, [[F_TARGET_G]] ]
 ; BOOLEAN-NEXT:    br i1 [[GUARD_B_TARGET_C]], label [[B_TARGET_C]], label [[LOOP_EXIT_GUARD3:%.*]]
 ; BOOLEAN:       loop.exit.guard3:
@@ -433,6 +520,176 @@ I:
   ret void
 }
 
+define void @inner_loop_switch(i1 %PredEntry, i1 %PredA, i1 %PredB) {
+; CHECK-LABEL: @inner_loop_switch(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    switch i1 [[PREDENTRY:%.*]], label [[A:%.*]] [
+; CHECK-NEXT:      i1 false, label [[I:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       A:
+; CHECK-NEXT:    [[OUTER1:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[OUTER2:%.*]], [[G:%.*]] ]
+; CHECK-NEXT:    br label [[B:%.*]]
+; CHECK:       B:
+; CHECK-NEXT:    [[INNER1:%.*]] = phi i32 [ 0, [[A]] ], [ [[INNER2:%.*]], [[F:%.*]] ]
+; CHECK-NEXT:    switch i1 [[PREDA:%.*]], label [[D:%.*]] [
+; CHECK-NEXT:      i1 false, label [[B_TARGET_B_TARGET_C:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       C:
+; CHECK-NEXT:    tail call fastcc void @check(i32 1) #[[ATTR0]]
+; CHECK-NEXT:    br label [[H:%.*]]
+; CHECK:       D:
+; CHECK-NEXT:    switch i1 [[PREDB:%.*]], label [[D_TARGET_D_TARGET_E:%.*]] [
+; CHECK-NEXT:      i1 false, label [[F]]
+; CHECK-NEXT:    ]
+; CHECK:       E:
+; CHECK-NEXT:    tail call fastcc void @check(i32 2) #[[ATTR0]]
+; CHECK-NEXT:    br label [[H]]
+; CHECK:       F:
+; CHECK-NEXT:    [[INNER2]] = add i32 [[INNER1]], 1
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp ult i32 [[INNER2]], 20
+; CHECK-NEXT:    switch i1 [[CMP1]], label [[B]] [
+; CHECK-NEXT:      i1 false, label [[F_TARGET_G:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       G:
+; CHECK-NEXT:    [[OUTER2]] = add i32 [[OUTER1]], 1
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ult i32 [[OUTER2]], 10
+; CHECK-NEXT:    switch i1 [[CMP2]], label [[A]] [
+; CHECK-NEXT:      i1 false, label [[G_TARGET_I:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       H:
+; CHECK-NEXT:    unreachable
+; CHECK:       I:
+; CHECK-NEXT:    ret void
+; CHECK:       B.target.C:
+; CHECK-NEXT:    br label [[LOOP_EXIT_GUARD:%.*]]
+; CHECK:       D.target.E:
+; CHECK-NEXT:    br label [[LOOP_EXIT_GUARD]]
+; CHECK:       G.target.I:
+; CHECK-NEXT:    br label [[LOOP_EXIT_GUARD]]
+; CHECK:       loop.exit.guard:
+; CHECK-NEXT:    [[MERGED_BB_IDX:%.*]] = phi i32 [ 0, [[B_TARGET_C:%.*]] ], [ 1, [[D_TARGET_E:%.*]] ], [ 2, [[G_TARGET_I]] ]
+; CHECK-NEXT:    [[C_PREDICATE:%.*]] = icmp eq i32 [[MERGED_BB_IDX]], 0
+; CHECK-NEXT:    br i1 [[C_PREDICATE]], label [[C:%.*]], label [[LOOP_EXIT_GUARD1:%.*]]
+; CHECK:       loop.exit.guard1:
+; CHECK-NEXT:    [[E_PREDICATE:%.*]] = icmp eq i32 [[MERGED_BB_IDX]], 1
+; CHECK-NEXT:    br i1 [[E_PREDICATE]], label [[E:%.*]], label [[I]]
+; CHECK:       B.target.B.target.C:
+; CHECK-NEXT:    br label [[LOOP_EXIT_GUARD2:%.*]]
+; CHECK:       D.target.D.target.E:
+; CHECK-NEXT:    br label [[LOOP_EXIT_GUARD2]]
+; CHECK:       F.target.G:
+; CHECK-NEXT:    br label [[LOOP_EXIT_GUARD2]]
+; CHECK:       loop.exit.guard2:
+; CHECK-NEXT:    [[MERGED_BB_IDX4:%.*]] = phi i32 [ 0, [[B_TARGET_B_TARGET_C]] ], [ 1, [[D_TARGET_D_TARGET_E]] ], [ 2, [[F_TARGET_G]] ]
+; CHECK-NEXT:    [[B_TARGET_C_PREDICATE:%.*]] = icmp eq i32 [[MERGED_BB_IDX4]], 0
+; CHECK-NEXT:    br i1 [[B_TARGET_C_PREDICATE]], label [[B_TARGET_C]], label [[LOOP_EXIT_GUARD3:%.*]]
+; CHECK:       loop.exit.guard3:
+; CHECK-NEXT:    [[D_TARGET_E_PREDICATE:%.*]] = icmp eq i32 [[MERGED_BB_IDX4]], 1
+; CHECK-NEXT:    br i1 [[D_TARGET_E_PREDICATE]], label [[D_TARGET_E]], label [[G]]
+;
+; BOOLEAN-LABEL: @inner_loop_switch(
+; BOOLEAN-NEXT:  entry:
+; BOOLEAN-NEXT:    switch i1 [[PREDENTRY:%.*]], label [[A:%.*]] [
+; BOOLEAN-NEXT:      i1 false, label [[I:%.*]]
+; BOOLEAN-NEXT:    ]
+; BOOLEAN:       A:
+; BOOLEAN-NEXT:    [[OUTER1:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[OUTER2:%.*]], [[G:%.*]] ]
+; BOOLEAN-NEXT:    br label [[B:%.*]]
+; BOOLEAN:       B:
+; BOOLEAN-NEXT:    [[INNER1:%.*]] = phi i32 [ 0, [[A]] ], [ [[INNER2:%.*]], [[F:%.*]] ]
+; BOOLEAN-NEXT:    switch i1 [[PREDA:%.*]], label [[D:%.*]] [
+; BOOLEAN-NEXT:      i1 false, label [[B_TARGET_B_TARGET_C:%.*]]
+; BOOLEAN-NEXT:    ]
+; BOOLEAN:       C:
+; BOOLEAN-NEXT:    tail call fastcc void @check(i32 1) #[[ATTR0]]
+; BOOLEAN-NEXT:    br label [[H:%.*]]
+; BOOLEAN:       D:
+; BOOLEAN-NEXT:    switch i1 [[PREDB:%.*]], label [[D_TARGET_D_TARGET_E:%.*]] [
+; BOOLEAN-NEXT:      i1 false, label [[F]]
+; BOOLEAN-NEXT:    ]
+; BOOLEAN:       E:
+; BOOLEAN-NEXT:    tail call fastcc void @check(i32 2) #[[ATTR0]]
+; BOOLEAN-NEXT:    br label [[H]]
+; BOOLEAN:       F:
+; BOOLEAN-NEXT:    [[INNER2]] = add i32 [[INNER1]], 1
+; BOOLEAN-NEXT:    [[CMP1:%.*]] = icmp ult i32 [[INNER2]], 20
+; BOOLEAN-NEXT:    switch i1 [[CMP1]], label [[B]] [
+; BOOLEAN-NEXT:      i1 false, label [[F_TARGET_G:%.*]]
+; BOOLEAN-NEXT:    ]
+; BOOLEAN:       G:
+; BOOLEAN-NEXT:    [[OUTER2]] = add i32 [[OUTER1]], 1
+; BOOLEAN-NEXT:    [[CMP2:%.*]] = icmp ult i32 [[OUTER2]], 10
+; BOOLEAN-NEXT:    switch i1 [[CMP2]], label [[A]] [
+; BOOLEAN-NEXT:      i1 false, label [[G_TARGET_I:%.*]]
+; BOOLEAN-NEXT:    ]
+; BOOLEAN:       H:
+; BOOLEAN-NEXT:    unreachable
+; BOOLEAN:       I:
+; BOOLEAN-NEXT:    ret void
+; BOOLEAN:       B.target.C:
+; BOOLEAN-NEXT:    br label [[LOOP_EXIT_GUARD:%.*]]
+; BOOLEAN:       D.target.E:
+; BOOLEAN-NEXT:    br label [[LOOP_EXIT_GUARD]]
+; BOOLEAN:       G.target.I:
+; BOOLEAN-NEXT:    br label [[LOOP_EXIT_GUARD]]
+; BOOLEAN:       loop.exit.guard:
+; BOOLEAN-NEXT:    [[GUARD_C:%.*]] = phi i1 [ true, [[B_TARGET_C:%.*]] ], [ false, [[D_TARGET_E:%.*]] ], [ false, [[G_TARGET_I]] ]
+; BOOLEAN-NEXT:    [[GUARD_E:%.*]] = phi i1 [ false, [[B_TARGET_C]] ], [ true, [[D_TARGET_E]] ], [ false, [[G_TARGET_I]] ]
+; BOOLEAN-NEXT:    br i1 [[GUARD_C]], label [[C:%.*]], label [[LOOP_EXIT_GUARD1:%.*]]
+; BOOLEAN:       loop.exit.guard1:
+; BOOLEAN-NEXT:    br i1 [[GUARD_E]], label [[E:%.*]], label [[I]]
+; BOOLEAN:       B.target.B.target.C:
+; BOOLEAN-NEXT:    br label [[LOOP_EXIT_GUARD2:%.*]]
+; BOOLEAN:       D.target.D.target.E:
+; BOOLEAN-NEXT:    br label [[LOOP_EXIT_GUARD2]]
+; BOOLEAN:       F.target.G:
+; BOOLEAN-NEXT:    br label [[LOOP_EXIT_GUARD2]]
+; BOOLEAN:       loop.exit.guard2:
+; BOOLEAN-NEXT:    [[GUARD_B_TARGET_C:%.*]] = phi i1 [ true, [[B_TARGET_B_TARGET_C]] ], [ false, [[D_TARGET_D_TARGET_E]] ], [ false, [[F_TARGET_G]] ]
+; BOOLEAN-NEXT:    [[GUARD_D_TARGET_E:%.*]] = phi i1 [ false, [[B_TARGET_B_TARGET_C]] ], [ true, [[D_TARGET_D_TARGET_E]] ], [ false, [[F_TARGET_G]] ]
+; BOOLEAN-NEXT:    br i1 [[GUARD_B_TARGET_C]], label [[B_TARGET_C]], label [[LOOP_EXIT_GUARD3:%.*]]
+; BOOLEAN:       loop.exit.guard3:
+; BOOLEAN-NEXT:    br i1 [[GUARD_D_TARGET_E]], label [[D_TARGET_E]], label [[G]]
+;
+entry:
+  switch i1 %PredEntry, label %A [ i1 0, label %I ]
+
+A:
+  %outer1 = phi i32 [ 0, %entry ], [ %outer2, %G ]
+  br label %B
+
+B:
+  %inner1 = phi i32 [ 0, %A ], [ %inner2, %F ]
+  switch i1 %PredA, label %D [ i1 0, label %C ]
+
+C:
+  tail call fastcc void @check(i32 1) #0
+  br label %H
+
+D:
+  switch i1 %PredB, label %E [ i1 0, label %F ]
+
+E:
+  tail call fastcc void @check(i32 2) #0
+  br label %H
+
+F:
+  %inner2 = add i32 %inner1, 1
+  %cmp1 = icmp ult i32 %inner2, 20
+  switch i1 %cmp1, label %B [ i1 0, label %G ]
+
+G:
+  %outer2 = add i32 %outer1, 1
+  %cmp2 = icmp ult i32 %outer2, 10
+  switch i1 %cmp2, label %A [ i1 0, label %I ]
+
+H:
+  unreachable
+
+I:
+  ret void
+}
+
 ; A loop with more exit blocks.
 
 define void @loop_five_exits(i1 %PredEntry, i1 %PredA, i1 %PredB, i1 %PredC, i1 %PredD) {
@@ -585,25 +842,25 @@ define void @loop_five_exits_callbr(i1 %PredEntry, i1 %PredA, i1 %PredB, i1 %Pre
 ; CHECK:       A:
 ; CHECK-NEXT:    [[INC1:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC2:%.*]], [[I:%.*]] ]
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[PREDA:%.*]])
-; CHECK-NEXT:            to label [[A_TARGET_B:%.*]] [label %C]
+; CHECK-NEXT:            to label [[A_TARGET_B:%.*]] [label [[C:%.*]]]
 ; CHECK:       B:
 ; CHECK-NEXT:    tail call fastcc void @check(i32 1) #[[ATTR0]]
 ; CHECK-NEXT:    br label [[J:%.*]]
 ; CHECK:       C:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[PREDB:%.*]])
-; CHECK-NEXT:            to label [[C_TARGET_D:%.*]] [label %E]
+; CHECK-NEXT:            to label [[C_TARGET_D:%.*]] [label [[E:%.*]]]
 ; CHECK:       D:
 ; CHECK-NEXT:    tail call fastcc void @check(i32 2) #[[ATTR0]]
 ; CHECK-NEXT:    br label [[J]]
 ; CHECK:       E:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[PREDC:%.*]])
-; CHECK-NEXT:            to label [[E_TARGET_F:%.*]] [label %G]
+; CHECK-NEXT:            to label [[E_TARGET_F:%.*]] [label [[G:%.*]]]
 ; CHECK:       F:
 ; CHECK-NEXT:    tail call fastcc void @check(i32 3) #[[ATTR0]]
 ; CHECK-NEXT:    br label [[K:%.*]]
 ; CHECK:       G:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[PREDD:%.*]])
-; CHECK-NEXT:            to label [[G_TARGET_H:%.*]] [label %I]
+; CHECK-NEXT:            to label [[G_TARGET_H:%.*]] [label [[I]]]
 ; CHECK:       H:
 ; CHECK-NEXT:    tail call fastcc void @check(i32 4) #[[ATTR0]]
 ; CHECK-NEXT:    br label [[K]]
@@ -611,7 +868,7 @@ define void @loop_five_exits_callbr(i1 %PredEntry, i1 %PredA, i1 %PredB, i1 %Pre
 ; CHECK-NEXT:    [[INC2]] = add i32 [[INC1]], 1
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[INC2]], 10
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[CMP]])
-; CHECK-NEXT:            to label [[A]] [label %I.target.L]
+; CHECK-NEXT:            to label [[A]] [label [[I_TARGET_L:%.*]]]
 ; CHECK:       J:
 ; CHECK-NEXT:    br label [[L]]
 ; CHECK:       K:
@@ -629,7 +886,7 @@ define void @loop_five_exits_callbr(i1 %PredEntry, i1 %PredA, i1 %PredB, i1 %Pre
 ; CHECK:       I.target.L:
 ; CHECK-NEXT:    br label [[LOOP_EXIT_GUARD]]
 ; CHECK:       loop.exit.guard:
-; CHECK-NEXT:    [[MERGED_BB_IDX:%.*]] = phi i32 [ 0, [[A_TARGET_B]] ], [ 1, [[C_TARGET_D]] ], [ 2, [[E_TARGET_F]] ], [ 3, [[G_TARGET_H]] ], [ 4, [[I_TARGET_L:%.*]] ]
+; CHECK-NEXT:    [[MERGED_BB_IDX:%.*]] = phi i32 [ 0, [[A_TARGET_B]] ], [ 1, [[C_TARGET_D]] ], [ 2, [[E_TARGET_F]] ], [ 3, [[G_TARGET_H]] ], [ 4, [[I_TARGET_L]] ]
 ; CHECK-NEXT:    [[B_PREDICATE:%.*]] = icmp eq i32 [[MERGED_BB_IDX]], 0
 ; CHECK-NEXT:    br i1 [[B_PREDICATE]], label [[B:%.*]], label [[LOOP_EXIT_GUARD1:%.*]]
 ; CHECK:       loop.exit.guard1:
@@ -648,25 +905,25 @@ define void @loop_five_exits_callbr(i1 %PredEntry, i1 %PredA, i1 %PredB, i1 %Pre
 ; BOOLEAN:       A:
 ; BOOLEAN-NEXT:    [[INC1:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC2:%.*]], [[I:%.*]] ]
 ; BOOLEAN-NEXT:    callbr void asm "", "r,!i"(i1 [[PREDA:%.*]])
-; BOOLEAN-NEXT:            to label [[A_TARGET_B:%.*]] [label %C]
+; BOOLEAN-NEXT:            to label [[A_TARGET_B:%.*]] [label [[C:%.*]]]
 ; BOOLEAN:       B:
 ; BOOLEAN-NEXT:    tail call fastcc void @check(i32 1) #[[ATTR0]]
 ; BOOLEAN-NEXT:    br label [[J:%.*]]
 ; BOOLEAN:       C:
 ; BOOLEAN-NEXT:    callbr void asm "", "r,!i"(i1 [[PREDB:%.*]])
-; BOOLEAN-NEXT:            to label [[C_TARGET_D:%.*]] [label %E]
+; BOOLEAN-NEXT:            to label [[C_TARGET_D:%.*]] [label [[E:%.*]]]
 ; BOOLEAN:       D:
 ; BOOLEAN-NEXT:    tail call fastcc void @check(i32 2) #[[ATTR0]]
 ; BOOLEAN-NEXT:    br label [[J]]
 ; BOOLEAN:       E:
 ; BOOLEAN-NEXT:    callbr void asm "", "r,!i"(i1 [[PREDC:%.*]])
-; BOOLEAN-NEXT:            to label [[E_TARGET_F:%.*]] [label %G]
+; BOOLEAN-NEXT:            to label [[E_TARGET_F:%.*]] [label [[G:%.*]]]
 ; BOOLEAN:       F:
 ; BOOLEAN-NEXT:    tail call fastcc void @check(i32 3) #[[ATTR0]]
 ; BOOLEAN-NEXT:    br label [[K:%.*]]
 ; BOOLEAN:       G:
 ; BOOLEAN-NEXT:    callbr void asm "", "r,!i"(i1 [[PREDD:%.*]])
-; BOOLEAN-NEXT:            to label [[G_TARGET_H:%.*]] [label %I]
+; BOOLEAN-NEXT:            to label [[G_TARGET_H:%.*]] [label [[I]]]
 ; BOOLEAN:       H:
 ; BOOLEAN-NEXT:    tail call fastcc void @check(i32 4) #[[ATTR0]]
 ; BOOLEAN-NEXT:    br label [[K]]
@@ -674,7 +931,7 @@ define void @loop_five_exits_callbr(i1 %PredEntry, i1 %PredA, i1 %PredB, i1 %Pre
 ; BOOLEAN-NEXT:    [[INC2]] = add i32 [[INC1]], 1
 ; BOOLEAN-NEXT:    [[CMP:%.*]] = icmp ult i32 [[INC2]], 10
 ; BOOLEAN-NEXT:    callbr void asm "", "r,!i"(i1 [[CMP]])
-; BOOLEAN-NEXT:            to label [[A]] [label %I.target.L]
+; BOOLEAN-NEXT:            to label [[A]] [label [[I_TARGET_L:%.*]]]
 ; BOOLEAN:       J:
 ; BOOLEAN-NEXT:    br label [[L]]
 ; BOOLEAN:       K:
@@ -692,7 +949,7 @@ define void @loop_five_exits_callbr(i1 %PredEntry, i1 %PredA, i1 %PredB, i1 %Pre
 ; BOOLEAN:       I.target.L:
 ; BOOLEAN-NEXT:    br label [[LOOP_EXIT_GUARD]]
 ; BOOLEAN:       loop.exit.guard:
-; BOOLEAN-NEXT:    [[GUARD_B:%.*]] = phi i1 [ true, [[A_TARGET_B]] ], [ false, [[C_TARGET_D]] ], [ false, [[E_TARGET_F]] ], [ false, [[G_TARGET_H]] ], [ false, [[I_TARGET_L:%.*]] ]
+; BOOLEAN-NEXT:    [[GUARD_B:%.*]] = phi i1 [ true, [[A_TARGET_B]] ], [ false, [[C_TARGET_D]] ], [ false, [[E_TARGET_F]] ], [ false, [[G_TARGET_H]] ], [ false, [[I_TARGET_L]] ]
 ; BOOLEAN-NEXT:    [[GUARD_D:%.*]] = phi i1 [ false, [[A_TARGET_B]] ], [ true, [[C_TARGET_D]] ], [ false, [[E_TARGET_F]] ], [ false, [[G_TARGET_H]] ], [ false, [[I_TARGET_L]] ]
 ; BOOLEAN-NEXT:    [[GUARD_F:%.*]] = phi i1 [ false, [[A_TARGET_B]] ], [ false, [[C_TARGET_D]] ], [ true, [[E_TARGET_F]] ], [ false, [[G_TARGET_H]] ], [ false, [[I_TARGET_L]] ]
 ; BOOLEAN-NEXT:    [[GUARD_H:%.*]] = phi i1 [ false, [[A_TARGET_B]] ], [ false, [[C_TARGET_D]] ], [ false, [[E_TARGET_F]] ], [ true, [[G_TARGET_H]] ], [ false, [[I_TARGET_L]] ]
@@ -751,6 +1008,192 @@ L:
   ret void
 }
 
+define void @loop_five_exits_switch(i1 %PredEntry, i1 %PredA, i1 %PredB, i1 %PredC, i1 %PredD) {
+; CHECK-LABEL: @loop_five_exits_switch(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    switch i1 [[PREDENTRY:%.*]], label [[A:%.*]] [
+; CHECK-NEXT:      i1 false, label [[L:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       A:
+; CHECK-NEXT:    [[INC1:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC2:%.*]], [[I:%.*]] ]
+; CHECK-NEXT:    switch i1 [[PREDA:%.*]], label [[A_TARGET_B:%.*]] [
+; CHECK-NEXT:      i1 false, label [[C:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       B:
+; CHECK-NEXT:    tail call fastcc void @check(i32 1) #[[ATTR0]]
+; CHECK-NEXT:    br label [[J:%.*]]
+; CHECK:       C:
+; CHECK-NEXT:    switch i1 [[PREDB:%.*]], label [[C_TARGET_D:%.*]] [
+; CHECK-NEXT:      i1 false, label [[E:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       D:
+; CHECK-NEXT:    tail call fastcc void @check(i32 2) #[[ATTR0]]
+; CHECK-NEXT:    br label [[J]]
+; CHECK:       E:
+; CHECK-NEXT:    switch i1 [[PREDC:%.*]], label [[E_TARGET_F:%.*]] [
+; CHECK-NEXT:      i1 false, label [[G:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       F:
+; CHECK-NEXT:    tail call fastcc void @check(i32 3) #[[ATTR0]]
+; CHECK-NEXT:    br label [[K:%.*]]
+; CHECK:       G:
+; CHECK-NEXT:    switch i1 [[PREDD:%.*]], label [[G_TARGET_H:%.*]] [
+; CHECK-NEXT:      i1 false, label [[I]]
+; CHECK-NEXT:    ]
+; CHECK:       H:
+; CHECK-NEXT:    tail call fastcc void @check(i32 4) #[[ATTR0]]
+; CHECK-NEXT:    br label [[K]]
+; CHECK:       I:
+; CHECK-NEXT:    [[INC2]] = add i32 [[INC1]], 1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[INC2]], 10
+; CHECK-NEXT:    switch i1 [[CMP]], label [[A]] [
+; CHECK-NEXT:      i1 false, label [[I_TARGET_L:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       J:
+; CHECK-NEXT:    br label [[L]]
+; CHECK:       K:
+; CHECK-NEXT:    br label [[L]]
+; CHECK:       L:
+; CHECK-NEXT:    ret void
+; CHECK:       A.target.B:
+; CHECK-NEXT:    br label [[LOOP_EXIT_GUARD:%.*]]
+; CHECK:       C.target.D:
+; CHECK-NEXT:    br label [[LOOP_EXIT_GUARD]]
+; CHECK:       E.target.F:
+; CHECK-NEXT:    br label [[LOOP_EXIT_GUARD]]
+; CHECK:       G.target.H:
+; CHECK-NEXT:    br label [[LOOP_EXIT_GUARD]]
+; CHECK:       I.target.L:
+; CHECK-NEXT:    br label [[LOOP_EXIT_GUARD]]
+; CHECK:       loop.exit.guard:
+; CHECK-NEXT:    [[MERGED_BB_IDX:%.*]] = phi i32 [ 0, [[A_TARGET_B]] ], [ 1, [[C_TARGET_D]] ], [ 2, [[E_TARGET_F]] ], [ 3, [[G_TARGET_H]] ], [ 4, [[I_TARGET_L]] ]
+; CHECK-NEXT:    [[B_PREDICATE:%.*]] = icmp eq i32 [[MERGED_BB_IDX]], 0
+; CHECK-NEXT:    br i1 [[B_PREDICATE]], label [[B:%.*]], label [[LOOP_EXIT_GUARD1:%.*]]
+; CHECK:       loop.exit.guard1:
+; CHECK-NEXT:    [[D_PREDICATE:%.*]] = icmp eq i32 [[MERGED_BB_IDX]], 1
+; CHECK-NEXT:    br i1 [[D_PREDICATE]], label [[D:%.*]], label [[LOOP_EXIT_GUARD2:%.*]]
+; CHECK:       loop.exit.guard2:
+; CHECK-NEXT:    [[F_PREDICATE:%.*]] = icmp eq i32 [[MERGED_BB_IDX]], 2
+; CHECK-NEXT:    br i1 [[F_PREDICATE]], label [[F:%.*]], label [[LOOP_EXIT_GUARD3:%.*]]
+; CHECK:       loop.exit.guard3:
+; CHECK-NEXT:    [[H_PREDICATE:%.*]] = icmp eq i32 [[MERGED_BB_IDX]], 3
+; CHECK-NEXT:    br i1 [[H_PREDICATE]], label [[H:%.*]], label [[L]]
+;
+; BOOLEAN-LABEL: @loop_five_exits_switch(
+; BOOLEAN-NEXT:  entry:
+; BOOLEAN-NEXT:    switch i1 [[PREDENTRY:%.*]], label [[A:%.*]] [
+; BOOLEAN-NEXT:      i1 false, label [[L:%.*]]
+; BOOLEAN-NEXT:    ]
+; BOOLEAN:       A:
+; BOOLEAN-NEXT:    [[INC1:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC2:%.*]], [[I:%.*]] ]
+; BOOLEAN-NEXT:    switch i1 [[PREDA:%.*]], label [[A_TARGET_B:%.*]] [
+; BOOLEAN-NEXT:      i1 false, label [[C:%.*]]
+; BOOLEAN-NEXT:    ]
+; BOOLEAN:       B:
+; BOOLEAN-NEXT:    tail call fastcc void @check(i32 1) #[[ATTR0]]
+; BOOLEAN-NEXT:    br label [[J:%.*]]
+; BOOLEAN:       C:
+; BOOLEAN-NEXT:    switch i1 [[PREDB:%.*]], label [[C_TARGET_D:%.*]] [
+; BOOLEAN-NEXT:      i1 false, label [[E:%.*]]
+; BOOLEAN-NEXT:    ]
+; BOOLEAN:       D:
+; BOOLEAN-NEXT:    tail call fastcc void @check(i32 2) #[[ATTR0]]
+; BOOLEAN-NEXT:    br label [[J]]
+; BOOLEAN:       E:
+; BOOLEAN-NEXT:    switch i1 [[PREDC:%.*]], label [[E_TARGET_F:%.*]] [
+; BOOLEAN-NEXT:      i1 false, label [[G:%.*]]
+; BOOLEAN-NEXT:    ]
+; BOOLEAN:       F:
+; BOOLEAN-NEXT:    tail call fastcc void @check(i32 3) #[[ATTR0]]
+; BOOLEAN-NEXT:    br label [[K:%.*]]
+; BOOLEAN:       G:
+; BOOLEAN-NEXT:    switch i1 [[PREDD:%.*]], label [[G_TARGET_H:%.*]] [
+; BOOLEAN-NEXT:      i1 false, label [[I]]
+; BOOLEAN-NEXT:    ]
+; BOOLEAN:       H:
+; BOOLEAN-NEXT:    tail call fastcc void @check(i32 4) #[[ATTR0]]
+; BOOLEAN-NEXT:    br label [[K]]
+; BOOLEAN:       I:
+; BOOLEAN-NEXT:    [[INC2]] = add i32 [[INC1]], 1
+; BOOLEAN-NEXT:    [[CMP:%.*]] = icmp ult i32 [[INC2]], 10
+; BOOLEAN-NEXT:    switch i1 [[CMP]], label [[A]] [
+; BOOLEAN-NEXT:      i1 false, label [[I_TARGET_L:%.*]]
+; BOOLEAN-NEXT:    ]
+; BOOLEAN:       J:
+; BOOLEAN-NEXT:    br label [[L]]
+; BOOLEAN:       K:
+; BOOLEAN-NEXT:    br label [[L]]
+; BOOLEAN:       L:
+; BOOLEAN-NEXT:    ret void
+; BOOLEAN:       A.target.B:
+; BOOLEAN-NEXT:    br label [[LOOP_EXIT_GUARD:%.*]]
+; BOOLEAN:       C.target.D:
+; BOOLEAN-NEXT:    br label [[LOOP_EXIT_GUARD]]
+; BOOLEAN:       E.target.F:
+; BOOLEAN-NEXT:    br label [[LOOP_EXIT_GUARD]]
+; BOOLEAN:       G.target.H:
+; BOOLEAN-NEXT:    br label [[LOOP_EXIT_GUARD]]
+; BOOLEAN:       I.target.L:
+; BOOLEAN-NEXT:    br label [[LOOP_EXIT_GUARD]]
+; BOOLEAN:       loop.exit.guard:
+; BOOLEAN-NEXT:    [[GUARD_B:%.*]] = phi i1 [ true, [[A_TARGET_B]] ], [ false, [[C_TARGET_D]] ], [ false, [[E_TARGET_F]] ], [ false, [[G_TARGET_H]] ], [ false, [[I_TARGET_L]] ]
+; BOOLEAN-NEXT:    [[GUARD_D:%.*]] = phi i1 [ false, [[A_TARGET_B]] ], [ true, [[C_TARGET_D]] ], [ false, [[E_TARGET_F]] ], [ false, [[G_TARGET_H]] ], [ false, [[I_TARGET_L]] ]
+; BOOLEAN-NEXT:    [[GUARD_F:%.*]] = phi i1 [ false, [[A_TARGET_B]] ], [ false, [[C_TARGET_D]] ], [ true, [[E_TARGET_F]] ], [ false, [[G_TARGET_H]] ], [ false, [[I_TARGET_L]] ]
+; BOOLEAN-NEXT:    [[GUARD_H:%.*]] = phi i1 [ false, [[A_TARGET_B]] ], [ false, [[C_TARGET_D]] ], [ false, [[E_TARGET_F]] ], [ true, [[G_TARGET_H]] ], [ false, [[I_TARGET_L]] ]
+; BOOLEAN-NEXT:    br i1 [[GUARD_B]], label [[B:%.*]], label [[LOOP_EXIT_GUARD1:%.*]]
+; BOOLEAN:       loop.exit.guard1:
+; BOOLEAN-NEXT:    br i1 [[GUARD_D]], label [[D:%.*]], label [[LOOP_EXIT_GUARD2:%.*]]
+; BOOLEAN:       loop.exit.guard2:
+; BOOLEAN-NEXT:    br i1 [[GUARD_F]], label [[F:%.*]], label [[LOOP_EXIT_GUARD3:%.*]]
+; BOOLEAN:       loop.exit.guard3:
+; BOOLEAN-NEXT:    br i1 [[GUARD_H]], label [[H:%.*]], label [[L]]
+;
+entry:
+  switch i1 %PredEntry, label %A [ i1 0, label %L ]
+
+A:
+  %inc1 = phi i32 [ 0, %entry ], [ %inc2, %I ]
+  switch i1 %PredA, label %B [ i1 0, label %C ]
+
+B:
+  tail call fastcc void @check(i32 1) #0
+  br label %J
+
+C:
+  switch i1 %PredB, label %D [ i1 0, label %E ]
+
+D:
+  tail call fastcc void @check(i32 2) #0
+  br label %J
+
+E:
+  switch i1 %PredC, label %F [ i1 0, label %G ]
+
+F:
+  tail call fastcc void @check(i32 3) #0
+  br label %K
+
+G:
+  switch i1 %PredD, label %H [ i1 0, label %I ]
+
+H:
+  tail call fastcc void @check(i32 4) #0
+  br label %K
+
+I:
+  %inc2 = add i32 %inc1, 1
+  %cmp = icmp ult i32 %inc2, 10
+  switch i1 %cmp, label %A [ i1 0, label %L ]
+
+J:
+  br label %L
+
+K:
+  br label %L
+
+L:
+  ret void
+}
 
 declare void @check(i32 noundef %i) #0
 
diff --git a/llvm/test/Transforms/UnifyLoopExits/nested.ll b/llvm/test/Transforms/UnifyLoopExits/nested.ll
index 2ec576a2efa89..2383667b434a0 100644
--- a/llvm/test/Transforms/UnifyLoopExits/nested.ll
+++ b/llvm/test/Transforms/UnifyLoopExits/nested.ll
@@ -1,5 +1,5 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt < %s -passes='lower-switch,unify-loop-exits' -S | FileCheck %s
+; RUN: opt < %s -passes='unify-loop-exits' -S | FileCheck %s
 
 define void @nested(i1 %PredB3, i1 %PredB4, i1 %PredA4, i1 %PredA3, i32 %X, i32 %Y, i32 %Z) {
 ; CHECK-LABEL: @nested(
@@ -92,10 +92,10 @@ define void @nested_callbr(i1 %PredB3, i1 %PredB4, i1 %PredA4, i1 %PredA3, i32 %
 ; CHECK-NEXT:    br label [[B3:%.*]]
 ; CHECK:       B3:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[PREDB3:%.*]])
-; CHECK-NEXT:            to label [[B4:%.*]] [label %B3.target.A3]
+; CHECK-NEXT:            to label [[B4:%.*]] [label [[B3_TARGET_A3:%.*]]]
 ; CHECK:       B4:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[PREDB4:%.*]])
-; CHECK-NEXT:            to label [[B1]] [label %B4.target.A2]
+; CHECK-NEXT:            to label [[B1]] [label [[B4_TARGET_A2:%.*]]]
 ; CHECK:       A2:
 ; CHECK-NEXT:    br label [[A4:%.*]]
 ; CHECK:       A3:
@@ -103,10 +103,10 @@ define void @nested_callbr(i1 %PredB3, i1 %PredB4, i1 %PredA4, i1 %PredA3, i32 %
 ; CHECK:       A4:
 ; CHECK-NEXT:    [[A4_PHI:%.*]] = phi i32 [ [[Y:%.*]], [[A3:%.*]] ], [ [[X_INC_MOVED:%.*]], [[A2:%.*]] ]
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[PREDA4:%.*]])
-; CHECK-NEXT:            to label [[A4_TARGET_C:%.*]] [label %A5]
+; CHECK-NEXT:            to label [[A4_TARGET_C:%.*]] [label [[A5:%.*]]]
 ; CHECK:       A5:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[PREDA3:%.*]])
-; CHECK-NEXT:            to label [[A5_TARGET_EXIT:%.*]] [label %A1]
+; CHECK-NEXT:            to label [[A5_TARGET_EXIT:%.*]] [label [[A1]]]
 ; CHECK:       C:
 ; CHECK-NEXT:    br label [[EXIT:%.*]]
 ; CHECK:       exit:
@@ -125,7 +125,7 @@ define void @nested_callbr(i1 %PredB3, i1 %PredB4, i1 %PredA4, i1 %PredA3, i32 %
 ; CHECK:       B4.target.A2:
 ; CHECK-NEXT:    br label [[LOOP_EXIT_GUARD1]]
 ; CHECK:       loop.exit.guard1:
-; CHECK-NEXT:    [[X_INC_MOVED]] = phi i32 [ [[X_INC]], [[B3_TARGET_A3:%.*]] ], [ [[X_INC]], [[B4_TARGET_A2:%.*]] ]
+; CHECK-NEXT:    [[X_INC_MOVED]] = phi i32 [ [[X_INC]], [[B3_TARGET_A3]] ], [ [[X_INC]], [[B4_TARGET_A2]] ]
 ; CHECK-NEXT:    [[GUARD_A3:%.*]] = phi i1 [ true, [[B3_TARGET_A3]] ], [ false, [[B4_TARGET_A2]] ]
 ; CHECK-NEXT:    br i1 [[GUARD_A3]], label [[A3]], label [[A2]]
 ;
@@ -169,6 +169,100 @@ exit:
   ret void
 }
 
+define void @nested_switch(i1 %PredB3, i1 %PredB4, i1 %PredA4, i1 %PredA3, i32 %X, i32 %Y, i32 %Z) {
+; CHECK-LABEL: @nested_switch(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label [[A1:%.*]]
+; CHECK:       A1:
+; CHECK-NEXT:    br label [[B1:%.*]]
+; CHECK:       B1:
+; CHECK-NEXT:    br label [[B2:%.*]]
+; CHECK:       B2:
+; CHECK-NEXT:    [[X_INC:%.*]] = add i32 [[X:%.*]], 1
+; CHECK-NEXT:    br label [[B3:%.*]]
+; CHECK:       B3:
+; CHECK-NEXT:    switch i1 [[PREDB3:%.*]], label [[B4:%.*]] [
+; CHECK-NEXT:      i1 false, label [[B3_TARGET_A3:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       B4:
+; CHECK-NEXT:    switch i1 [[PREDB4:%.*]], label [[B1]] [
+; CHECK-NEXT:      i1 false, label [[B4_TARGET_A2:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       A2:
+; CHECK-NEXT:    br label [[A4:%.*]]
+; CHECK:       A3:
+; CHECK-NEXT:    br label [[A4]]
+; CHECK:       A4:
+; CHECK-NEXT:    [[A4_PHI:%.*]] = phi i32 [ [[Y:%.*]], [[A3:%.*]] ], [ [[X_INC_MOVED:%.*]], [[A2:%.*]] ]
+; CHECK-NEXT:    switch i1 [[PREDA4:%.*]], label [[A4_TARGET_C:%.*]] [
+; CHECK-NEXT:      i1 false, label [[A5:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       A5:
+; CHECK-NEXT:    switch i1 [[PREDA3:%.*]], label [[A5_TARGET_EXIT:%.*]] [
+; CHECK-NEXT:      i1 false, label [[A1]]
+; CHECK-NEXT:    ]
+; CHECK:       C:
+; CHECK-NEXT:    br label [[EXIT:%.*]]
+; CHECK:       exit:
+; CHECK-NEXT:    [[EXIT_PHI:%.*]] = phi i32 [ [[Z:%.*]], [[C:%.*]] ], [ [[EXIT_PHI_MOVED:%.*]], [[LOOP_EXIT_GUARD:%.*]] ]
+; CHECK-NEXT:    ret void
+; CHECK:       A4.target.C:
+; CHECK-NEXT:    br label [[LOOP_EXIT_GUARD]]
+; CHECK:       A5.target.exit:
+; CHECK-NEXT:    br label [[LOOP_EXIT_GUARD]]
+; CHECK:       loop.exit.guard:
+; CHECK-NEXT:    [[EXIT_PHI_MOVED]] = phi i32 [ poison, [[A4_TARGET_C]] ], [ [[A4_PHI]], [[A5_TARGET_EXIT]] ]
+; CHECK-NEXT:    [[GUARD_C:%.*]] = phi i1 [ true, [[A4_TARGET_C]] ], [ false, [[A5_TARGET_EXIT]] ]
+; CHECK-NEXT:    br i1 [[GUARD_C]], label [[C]], label [[EXIT]]
+; CHECK:       B3.target.A3:
+; CHECK-NEXT:    br label [[LOOP_EXIT_GUARD1:%.*]]
+; CHECK:       B4.target.A2:
+; CHECK-NEXT:    br label [[LOOP_EXIT_GUARD1]]
+; CHECK:       loop.exit.guard1:
+; CHECK-NEXT:    [[X_INC_MOVED]] = phi i32 [ [[X_INC]], [[B3_TARGET_A3]] ], [ [[X_INC]], [[B4_TARGET_A2]] ]
+; CHECK-NEXT:    [[GUARD_A3:%.*]] = phi i1 [ true, [[B3_TARGET_A3]] ], [ false, [[B4_TARGET_A2]] ]
+; CHECK-NEXT:    br i1 [[GUARD_A3]], label [[A3]], label [[A2]]
+;
+entry:
+  br label %A1
+
+A1:
+  br label %B1
+
+B1:
+  br label %B2
+
+B2:
+  %X.inc = add i32 %X, 1
+  br label %B3
+
+B3:
+  switch i1 %PredB3, label %B4 [ i1 0, label %A3 ]
+
+B4:
+  switch i1 %PredB4, label %B1 [ i1 0, label %A2 ]
+
+A2:
+  br label %A4
+
+A3:
+  br label %A4
+
+A4:
+  %A4.phi = phi i32 [%Y, %A3], [%X.inc, %A2]
+  switch i1 %PredA4, label %C [ i1 0, label %A5 ]
+
+A5:
+  switch i1 %PredA3, label %exit [ i1 0, label %A1 ]
+
+C:
+  br label %exit
+
+exit:
+  %exit.phi = phi i32 [%A4.phi, %A5], [%Z, %C]
+  ret void
+}
+
 ; Here, the newly created target loop that connects b to r1 needs to be part of
 ; the parent loop (the outer loop b participates in). Otherwise, it will be
 ; regarded as an additional loop entry point to this outer loop.
@@ -180,13 +274,13 @@ define void @nested_callbr_multiple_exits() {
 ; CHECK-NEXT:            to label [[B:%.*]] []
 ; CHECK:       b:
 ; CHECK-NEXT:    callbr void asm "", "!i"()
-; CHECK-NEXT:            to label [[C:%.*]] [label %b.target.b.target.r1]
+; CHECK-NEXT:            to label [[C:%.*]] [label [[B_TARGET_B_TARGET_R1:%.*]]]
 ; CHECK:       c:
 ; CHECK-NEXT:    callbr void asm "", "!i"()
-; CHECK-NEXT:            to label [[C_TARGET_E:%.*]] [label %b]
+; CHECK-NEXT:            to label [[C_TARGET_E:%.*]] [label [[B]]]
 ; CHECK:       e:
 ; CHECK-NEXT:    callbr void asm "", "!i"()
-; CHECK-NEXT:            to label [[A]] [label %e.target.r2]
+; CHECK-NEXT:            to label [[A]] [label [[E_TARGET_R2:%.*]]]
 ; CHECK:       r1:
 ; CHECK-NEXT:    ret void
 ; CHECK:       r2:
@@ -196,14 +290,14 @@ define void @nested_callbr_multiple_exits() {
 ; CHECK:       e.target.r2:
 ; CHECK-NEXT:    br label [[LOOP_EXIT_GUARD]]
 ; CHECK:       loop.exit.guard:
-; CHECK-NEXT:    [[GUARD_R1:%.*]] = phi i1 [ true, [[B_TARGET_R1:%.*]] ], [ false, [[E_TARGET_R2:%.*]] ]
+; CHECK-NEXT:    [[GUARD_R1:%.*]] = phi i1 [ true, [[B_TARGET_R1:%.*]] ], [ false, [[E_TARGET_R2]] ]
 ; CHECK-NEXT:    br i1 [[GUARD_R1]], label [[R1:%.*]], label [[R2:%.*]]
 ; CHECK:       b.target.b.target.r1:
 ; CHECK-NEXT:    br label [[LOOP_EXIT_GUARD1:%.*]]
 ; CHECK:       c.target.e:
 ; CHECK-NEXT:    br label [[LOOP_EXIT_GUARD1]]
 ; CHECK:       loop.exit.guard1:
-; CHECK-NEXT:    [[GUARD_B_TARGET_R1:%.*]] = phi i1 [ true, [[B_TARGET_B_TARGET_R1:%.*]] ], [ false, [[C_TARGET_E]] ]
+; CHECK-NEXT:    [[GUARD_B_TARGET_R1:%.*]] = phi i1 [ true, [[B_TARGET_B_TARGET_R1]] ], [ false, [[C_TARGET_E]] ]
 ; CHECK-NEXT:    br i1 [[GUARD_B_TARGET_R1]], label [[B_TARGET_R1]], label [[E:%.*]]
 ;
   br label %a
@@ -220,3 +314,55 @@ r1:
 r2:
   ret void
 }
+
+define void @nested_switch_multiple_exits(i1 %PredA, i1 %PredB, i1 %PredC, i1 %PredE) {
+; CHECK-LABEL: @nested_switch_multiple_exits(
+; CHECK-NEXT:    br label [[A:%.*]]
+; CHECK:       a:
+; CHECK-NEXT:    switch i1 [[PREDA:%.*]], label [[B:%.*]] [
+; CHECK-NEXT:    ]
+; CHECK:       b:
+; CHECK-NEXT:    switch i1 [[PREDB:%.*]], label [[C:%.*]] [
+; CHECK-NEXT:      i1 false, label [[B_TARGET_B_TARGET_R1:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       c:
+; CHECK-NEXT:    switch i1 [[PREDC:%.*]], label [[C_TARGET_E:%.*]] [
+; CHECK-NEXT:      i1 false, label [[B]]
+; CHECK-NEXT:    ]
+; CHECK:       e:
+; CHECK-NEXT:    switch i1 [[PREDE:%.*]], label [[A]] [
+; CHECK-NEXT:      i1 false, label [[E_TARGET_R2:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       r1:
+; CHECK-NEXT:    ret void
+; CHECK:       r2:
+; CHECK-NEXT:    ret void
+; CHECK:       b.target.r1:
+; CHECK-NEXT:    br label [[LOOP_EXIT_GUARD:%.*]]
+; CHECK:       e.target.r2:
+; CHECK-NEXT:    br label [[LOOP_EXIT_GUARD]]
+; CHECK:       loop.exit.guard:
+; CHECK-NEXT:    [[GUARD_R1:%.*]] = phi i1 [ true, [[B_TARGET_R1:%.*]] ], [ false, [[E_TARGET_R2]] ]
+; CHECK-NEXT:    br i1 [[GUARD_R1]], label [[R1:%.*]], label [[R2:%.*]]
+; CHECK:       b.target.b.target.r1:
+; CHECK-NEXT:    br label [[LOOP_EXIT_GUARD1:%.*]]
+; CHECK:       c.target.e:
+; CHECK-NEXT:    br label [[LOOP_EXIT_GUARD1]]
+; CHECK:       loop.exit.guard1:
+; CHECK-NEXT:    [[GUARD_B_TARGET_R1:%.*]] = phi i1 [ true, [[B_TARGET_B_TARGET_R1]] ], [ false, [[C_TARGET_E]] ]
+; CHECK-NEXT:    br i1 [[GUARD_B_TARGET_R1]], label [[B_TARGET_R1]], label [[E:%.*]]
+;
+  br label %a
+a:
+  switch i1 %PredA, label %b []
+b:
+  switch i1 %PredB, label %c [ i1 0, label %r1 ]
+c:
+  switch i1 %PredC, label %e [ i1 0, label %b ]
+e:
+  switch i1 %PredE, label %a [ i1 0, label %r2 ]
+r1:
+  ret void
+r2:
+  ret void
+}
diff --git a/llvm/test/Transforms/UnifyLoopExits/restore-ssa.ll b/llvm/test/Transforms/UnifyLoopExits/restore-ssa.ll
index ffe8026a535c0..5e8202eca56f3 100644
--- a/llvm/test/Transforms/UnifyLoopExits/restore-ssa.ll
+++ b/llvm/test/Transforms/UnifyLoopExits/restore-ssa.ll
@@ -1,5 +1,5 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt < %s -passes='lower-switch,unify-loop-exits' -S | FileCheck %s
+; RUN: opt < %s -passes='unify-loop-exits' -S | FileCheck %s
 
 ; Loop consists of A and B:
 ; - A is the header
@@ -66,12 +66,12 @@ define i32 @exiting-used-in-exit_callbr(ptr %arg1, ptr %arg2) local_unnamed_addr
 ; CHECK-NEXT:    [[MYTMP42:%.*]] = load i32, ptr [[ARG1:%.*]], align 4
 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[MYTMP42]], 0
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[CMP1]])
-; CHECK-NEXT:            to label [[B:%.*]] [label %A.target.return]
+; CHECK-NEXT:            to label [[B:%.*]] [label [[A_TARGET_RETURN:%.*]]]
 ; CHECK:       B:
 ; CHECK-NEXT:    [[MYTMP41:%.*]] = load i32, ptr [[ARG2:%.*]], align 4
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[MYTMP41]], 0
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[CMP]])
-; CHECK-NEXT:            to label [[A]] [label %B.target.C]
+; CHECK-NEXT:            to label [[A]] [label [[B_TARGET_C:%.*]]]
 ; CHECK:       C:
 ; CHECK-NEXT:    [[INC:%.*]] = add i32 [[MYTMP41_MOVED:%.*]], 1
 ; CHECK-NEXT:    callbr void asm "", ""()
@@ -84,7 +84,7 @@ define i32 @exiting-used-in-exit_callbr(ptr %arg1, ptr %arg2) local_unnamed_addr
 ; CHECK:       B.target.C:
 ; CHECK-NEXT:    br label [[LOOP_EXIT_GUARD]]
 ; CHECK:       loop.exit.guard:
-; CHECK-NEXT:    [[MYTMP41_MOVED]] = phi i32 [ poison, [[A_TARGET_RETURN:%.*]] ], [ [[MYTMP41]], [[B_TARGET_C:%.*]] ]
+; CHECK-NEXT:    [[MYTMP41_MOVED]] = phi i32 [ poison, [[A_TARGET_RETURN]] ], [ [[MYTMP41]], [[B_TARGET_C]] ]
 ; CHECK-NEXT:    [[PHI_MOVED]] = phi i32 [ [[MYTMP42]], [[A_TARGET_RETURN]] ], [ poison, [[B_TARGET_C]] ]
 ; CHECK-NEXT:    [[GUARD_RETURN:%.*]] = phi i1 [ true, [[A_TARGET_RETURN]] ], [ false, [[B_TARGET_C]] ]
 ; CHECK-NEXT:    br i1 [[GUARD_RETURN]], label [[RETURN]], label [[C]]
@@ -111,6 +111,62 @@ return:
   ret i32 %phi
 }
 
+define i32 @exiting-used-in-exit_switch(ptr %arg1, ptr %arg2, i1 %Pred) local_unnamed_addr align 2 {
+; CHECK-LABEL: @exiting-used-in-exit_switch(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    switch i1 [[PRED:%.*]], label [[A:%.*]] [
+; CHECK-NEXT:    ]
+; CHECK:       A:
+; CHECK-NEXT:    [[MYTMP42:%.*]] = load i32, ptr [[ARG1:%.*]], align 4
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[MYTMP42]], 0
+; CHECK-NEXT:    switch i1 [[CMP1]], label [[B:%.*]] [
+; CHECK-NEXT:      i1 false, label [[A_TARGET_RETURN:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       B:
+; CHECK-NEXT:    [[MYTMP41:%.*]] = load i32, ptr [[ARG2:%.*]], align 4
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[MYTMP41]], 0
+; CHECK-NEXT:    switch i1 [[CMP]], label [[A]] [
+; CHECK-NEXT:      i1 false, label [[B_TARGET_C:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       C:
+; CHECK-NEXT:    [[INC:%.*]] = add i32 [[MYTMP41_MOVED:%.*]], 1
+; CHECK-NEXT:    switch i1 [[PRED]], label [[RETURN:%.*]] [
+; CHECK-NEXT:    ]
+; CHECK:       return:
+; CHECK-NEXT:    [[PHI:%.*]] = phi i32 [ [[INC]], [[C:%.*]] ], [ [[PHI_MOVED:%.*]], [[LOOP_EXIT_GUARD:%.*]] ]
+; CHECK-NEXT:    ret i32 [[PHI]]
+; CHECK:       A.target.return:
+; CHECK-NEXT:    br label [[LOOP_EXIT_GUARD]]
+; CHECK:       B.target.C:
+; CHECK-NEXT:    br label [[LOOP_EXIT_GUARD]]
+; CHECK:       loop.exit.guard:
+; CHECK-NEXT:    [[MYTMP41_MOVED]] = phi i32 [ poison, [[A_TARGET_RETURN]] ], [ [[MYTMP41]], [[B_TARGET_C]] ]
+; CHECK-NEXT:    [[PHI_MOVED]] = phi i32 [ [[MYTMP42]], [[A_TARGET_RETURN]] ], [ poison, [[B_TARGET_C]] ]
+; CHECK-NEXT:    [[GUARD_RETURN:%.*]] = phi i1 [ true, [[A_TARGET_RETURN]] ], [ false, [[B_TARGET_C]] ]
+; CHECK-NEXT:    br i1 [[GUARD_RETURN]], label [[RETURN]], label [[C]]
+;
+entry:
+  switch i1 %Pred, label %A []
+
+A:
+  %mytmp42 = load i32, ptr %arg1, align 4
+  %cmp1 = icmp slt i32 %mytmp42, 0
+  switch i1 %cmp1, label %B [ i1 0, label %return ]
+
+B:
+  %mytmp41 = load i32, ptr %arg2, align 4
+  %cmp = icmp slt i32 %mytmp41, 0
+  switch i1 %cmp, label %A [ i1 0, label %C ]
+
+C:
+  %inc = add i32 %mytmp41, 1
+  switch i1 %Pred, label %return []
+
+return:
+  %phi = phi i32 [ %inc, %C ], [ %mytmp42, %A ]
+  ret i32 %phi
+}
+
 ; Loop consists of A, B and C:
 ; - A is the header
 ; - A and C are exiting blocks
@@ -175,7 +231,7 @@ define i32 @internal-used-in-exit_callbr(ptr %arg1, ptr %arg2) local_unnamed_add
 ; CHECK:       A:
 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[MYTMP42]], 0
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[CMP1]])
-; CHECK-NEXT:            to label [[B:%.*]] [label %A.target.return]
+; CHECK-NEXT:            to label [[B:%.*]] [label [[A_TARGET_RETURN:%.*]]]
 ; CHECK:       B:
 ; CHECK-NEXT:    [[MYTMP41:%.*]] = load i32, ptr [[ARG2:%.*]], align 4
 ; CHECK-NEXT:    callbr void asm "", ""()
@@ -183,7 +239,7 @@ define i32 @internal-used-in-exit_callbr(ptr %arg1, ptr %arg2) local_unnamed_add
 ; CHECK:       C:
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[MYTMP42]], 0
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[CMP]])
-; CHECK-NEXT:            to label [[A]] [label %C.target.D]
+; CHECK-NEXT:            to label [[A]] [label [[C_TARGET_D:%.*]]]
 ; CHECK:       D:
 ; CHECK-NEXT:    [[INC:%.*]] = add i32 [[MYTMP41_MOVED:%.*]], 1
 ; CHECK-NEXT:    callbr void asm "", ""()
@@ -195,7 +251,7 @@ define i32 @internal-used-in-exit_callbr(ptr %arg1, ptr %arg2) local_unnamed_add
 ; CHECK:       C.target.D:
 ; CHECK-NEXT:    br label [[LOOP_EXIT_GUARD]]
 ; CHECK:       loop.exit.guard:
-; CHECK-NEXT:    [[MYTMP41_MOVED]] = phi i32 [ poison, [[A_TARGET_RETURN:%.*]] ], [ [[MYTMP41]], [[C_TARGET_D:%.*]] ]
+; CHECK-NEXT:    [[MYTMP41_MOVED]] = phi i32 [ poison, [[A_TARGET_RETURN]] ], [ [[MYTMP41]], [[C_TARGET_D]] ]
 ; CHECK-NEXT:    [[GUARD_RETURN:%.*]] = phi i1 [ true, [[A_TARGET_RETURN]] ], [ false, [[C_TARGET_D]] ]
 ; CHECK-NEXT:    br i1 [[GUARD_RETURN]], label [[RETURN]], label [[D:%.*]]
 ;
@@ -223,6 +279,65 @@ return:
   ret i32 0
 }
 
+define i32 @internal-used-in-exit_switch(ptr %arg1, ptr %arg2, i1 %Pred) local_unnamed_addr align 2 {
+; CHECK-LABEL: @internal-used-in-exit_switch(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[MYTMP42:%.*]] = load i32, ptr [[ARG1:%.*]], align 4
+; CHECK-NEXT:    switch i1 [[PRED:%.*]], label [[A:%.*]] [
+; CHECK-NEXT:    ]
+; CHECK:       A:
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[MYTMP42]], 0
+; CHECK-NEXT:    switch i1 [[CMP1]], label [[B:%.*]] [
+; CHECK-NEXT:      i1 false, label [[A_TARGET_RETURN:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       B:
+; CHECK-NEXT:    [[MYTMP41:%.*]] = load i32, ptr [[ARG2:%.*]], align 4
+; CHECK-NEXT:    switch i1 [[PRED]], label [[C:%.*]] [
+; CHECK-NEXT:    ]
+; CHECK:       C:
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[MYTMP42]], 0
+; CHECK-NEXT:    switch i1 [[CMP]], label [[A]] [
+; CHECK-NEXT:      i1 false, label [[C_TARGET_D:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       D:
+; CHECK-NEXT:    [[INC:%.*]] = add i32 [[MYTMP41_MOVED:%.*]], 1
+; CHECK-NEXT:    switch i1 [[PRED]], label [[RETURN:%.*]] [
+; CHECK-NEXT:    ]
+; CHECK:       return:
+; CHECK-NEXT:    ret i32 0
+; CHECK:       A.target.return:
+; CHECK-NEXT:    br label [[LOOP_EXIT_GUARD:%.*]]
+; CHECK:       C.target.D:
+; CHECK-NEXT:    br label [[LOOP_EXIT_GUARD]]
+; CHECK:       loop.exit.guard:
+; CHECK-NEXT:    [[MYTMP41_MOVED]] = phi i32 [ poison, [[A_TARGET_RETURN]] ], [ [[MYTMP41]], [[C_TARGET_D]] ]
+; CHECK-NEXT:    [[GUARD_RETURN:%.*]] = phi i1 [ true, [[A_TARGET_RETURN]] ], [ false, [[C_TARGET_D]] ]
+; CHECK-NEXT:    br i1 [[GUARD_RETURN]], label [[RETURN]], label [[D:%.*]]
+;
+entry:
+  %mytmp42 = load i32, ptr %arg1, align 4
+  switch i1 %Pred, label %A []
+
+A:
+  %cmp1 = icmp slt i32 %mytmp42, 0
+  switch i1 %cmp1, label %B [ i1 0, label %return ]
+
+B:
+  %mytmp41 = load i32, ptr %arg2, align 4
+  switch i1 %Pred, label %C []
+
+C:
+  %cmp = icmp slt i32 %mytmp42, 0
+  switch i1 %cmp, label %A [ i1 0, label %D ]
+
+D:
+  %inc = add i32 %mytmp41, 1
+  switch i1 %Pred, label %return []
+
+return:
+  ret i32 0
+}
+
 ; Loop consists of A, B and C:
 ; - A is the header
 ; - A and C are exiting blocks
@@ -289,12 +404,12 @@ define i32 @mixed-use-in-exit_callbr(ptr %arg1, ptr %arg2) local_unnamed_addr al
 ; CHECK-NEXT:    [[MYTMP42:%.*]] = load i32, ptr [[ARG1:%.*]], align 4
 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i32 [[MYTMP42]], 0
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[CMP2]])
-; CHECK-NEXT:            to label [[A:%.*]] [label %return]
+; CHECK-NEXT:            to label [[A:%.*]] [label [[RETURN:%.*]]]
 ; CHECK:       A:
 ; CHECK-NEXT:    [[MYTMP43:%.*]] = add i32 [[MYTMP42]], 1
 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[MYTMP42]], 0
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[CMP1]])
-; CHECK-NEXT:            to label [[B:%.*]] [label %A.target.return]
+; CHECK-NEXT:            to label [[B:%.*]] [label [[A_TARGET_RETURN:%.*]]]
 ; CHECK:       B:
 ; CHECK-NEXT:    [[MYTMP41:%.*]] = load i32, ptr [[ARG2:%.*]], align 4
 ; CHECK-NEXT:    callbr void asm "", ""()
@@ -302,10 +417,10 @@ define i32 @mixed-use-in-exit_callbr(ptr %arg1, ptr %arg2) local_unnamed_addr al
 ; CHECK:       C:
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[MYTMP42]], 0
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[CMP]])
-; CHECK-NEXT:            to label [[A]] [label %C.target.D]
+; CHECK-NEXT:            to label [[A]] [label [[C_TARGET_D:%.*]]]
 ; CHECK:       D:
 ; CHECK-NEXT:    callbr void asm "", ""()
-; CHECK-NEXT:            to label [[RETURN:%.*]] []
+; CHECK-NEXT:            to label [[RETURN]] []
 ; CHECK:       return:
 ; CHECK-NEXT:    [[PHI:%.*]] = phi i32 [ [[MYTMP41_MOVED:%.*]], [[D:%.*]] ], [ [[MYTMP42]], [[ENTRY:%.*]] ], [ [[PHI_MOVED:%.*]], [[LOOP_EXIT_GUARD:%.*]] ]
 ; CHECK-NEXT:    ret i32 [[PHI]]
@@ -314,7 +429,7 @@ define i32 @mixed-use-in-exit_callbr(ptr %arg1, ptr %arg2) local_unnamed_addr al
 ; CHECK:       C.target.D:
 ; CHECK-NEXT:    br label [[LOOP_EXIT_GUARD]]
 ; CHECK:       loop.exit.guard:
-; CHECK-NEXT:    [[MYTMP41_MOVED]] = phi i32 [ poison, [[A_TARGET_RETURN:%.*]] ], [ [[MYTMP41]], [[C_TARGET_D:%.*]] ]
+; CHECK-NEXT:    [[MYTMP41_MOVED]] = phi i32 [ poison, [[A_TARGET_RETURN]] ], [ [[MYTMP41]], [[C_TARGET_D]] ]
 ; CHECK-NEXT:    [[PHI_MOVED]] = phi i32 [ [[MYTMP43]], [[A_TARGET_RETURN]] ], [ poison, [[C_TARGET_D]] ]
 ; CHECK-NEXT:    [[GUARD_RETURN:%.*]] = phi i1 [ true, [[A_TARGET_RETURN]] ], [ false, [[C_TARGET_D]] ]
 ; CHECK-NEXT:    br i1 [[GUARD_RETURN]], label [[RETURN]], label [[D]]
@@ -345,6 +460,71 @@ return:
   ret i32 %phi
 }
 
+define i32 @mixed-use-in-exit_switch(ptr %arg1, ptr %arg2, i1 %Pred) local_unnamed_addr align 2 {
+; CHECK-LABEL: @mixed-use-in-exit_switch(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[MYTMP42:%.*]] = load i32, ptr [[ARG1:%.*]], align 4
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i32 [[MYTMP42]], 0
+; CHECK-NEXT:    switch i1 [[CMP2]], label [[A:%.*]] [
+; CHECK-NEXT:      i1 false, label [[RETURN:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       A:
+; CHECK-NEXT:    [[MYTMP43:%.*]] = add i32 [[MYTMP42]], 1
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[MYTMP42]], 0
+; CHECK-NEXT:    switch i1 [[CMP1]], label [[B:%.*]] [
+; CHECK-NEXT:      i1 false, label [[A_TARGET_RETURN:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       B:
+; CHECK-NEXT:    [[MYTMP41:%.*]] = load i32, ptr [[ARG2:%.*]], align 4
+; CHECK-NEXT:    switch i1 [[PRED:%.*]], label [[C:%.*]] [
+; CHECK-NEXT:    ]
+; CHECK:       C:
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[MYTMP42]], 0
+; CHECK-NEXT:    switch i1 [[CMP]], label [[A]] [
+; CHECK-NEXT:      i1 false, label [[C_TARGET_D:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       D:
+; CHECK-NEXT:    switch i1 [[PRED]], label [[RETURN]] [
+; CHECK-NEXT:    ]
+; CHECK:       return:
+; CHECK-NEXT:    [[PHI:%.*]] = phi i32 [ [[MYTMP41_MOVED:%.*]], [[D:%.*]] ], [ [[MYTMP42]], [[ENTRY:%.*]] ], [ [[PHI_MOVED:%.*]], [[LOOP_EXIT_GUARD:%.*]] ]
+; CHECK-NEXT:    ret i32 [[PHI]]
+; CHECK:       A.target.return:
+; CHECK-NEXT:    br label [[LOOP_EXIT_GUARD]]
+; CHECK:       C.target.D:
+; CHECK-NEXT:    br label [[LOOP_EXIT_GUARD]]
+; CHECK:       loop.exit.guard:
+; CHECK-NEXT:    [[MYTMP41_MOVED]] = phi i32 [ poison, [[A_TARGET_RETURN]] ], [ [[MYTMP41]], [[C_TARGET_D]] ]
+; CHECK-NEXT:    [[PHI_MOVED]] = phi i32 [ [[MYTMP43]], [[A_TARGET_RETURN]] ], [ poison, [[C_TARGET_D]] ]
+; CHECK-NEXT:    [[GUARD_RETURN:%.*]] = phi i1 [ true, [[A_TARGET_RETURN]] ], [ false, [[C_TARGET_D]] ]
+; CHECK-NEXT:    br i1 [[GUARD_RETURN]], label [[RETURN]], label [[D]]
+;
+entry:
+  %mytmp42 = load i32, ptr %arg1, align 4
+  %cmp2 = icmp slt i32 %mytmp42, 0
+  switch i1 %cmp2, label %A [ i1 0, label %return ]
+
+A:
+  %mytmp43 = add i32 %mytmp42, 1
+  %cmp1 = icmp slt i32 %mytmp42, 0
+  switch i1 %cmp1, label %B [ i1 0, label %return ]
+
+B:
+  %mytmp41 = load i32, ptr %arg2, align 4
+  switch i1 %Pred, label %C []
+
+C:
+  %cmp = icmp slt i32 %mytmp42, 0
+  switch i1 %cmp, label %A [ i1 0, label %D ]
+
+D:
+  switch i1 %Pred, label %return []
+
+return:
+  %phi = phi i32 [ %mytmp41, %D ], [ %mytmp43, %A ], [%mytmp42, %entry]
+  ret i32 %phi
+}
+
 ; Loop consists of A, B and C:
 ; - A is the header
 ; - A and C are exiting blocks
@@ -419,7 +599,7 @@ define i32 @phi-via-external-block_callbr(ptr %arg1, ptr %arg2) local_unnamed_ad
 ; CHECK:       A:
 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[MYTMP42]], 0
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[CMP1]])
-; CHECK-NEXT:            to label [[B:%.*]] [label %A.target.E]
+; CHECK-NEXT:            to label [[B:%.*]] [label [[A_TARGET_E:%.*]]]
 ; CHECK:       B:
 ; CHECK-NEXT:    [[MYTMP41:%.*]] = load i32, ptr [[ARG2:%.*]], align 4
 ; CHECK-NEXT:    callbr void asm "", ""()
@@ -427,7 +607,7 @@ define i32 @phi-via-external-block_callbr(ptr %arg1, ptr %arg2) local_unnamed_ad
 ; CHECK:       C:
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[MYTMP42]], 0
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[CMP]])
-; CHECK-NEXT:            to label [[A]] [label %C.target.D]
+; CHECK-NEXT:            to label [[A]] [label [[C_TARGET_D:%.*]]]
 ; CHECK:       D:
 ; CHECK-NEXT:    callbr void asm "", ""()
 ; CHECK-NEXT:            to label [[RETURN:%.*]] []
@@ -442,7 +622,7 @@ define i32 @phi-via-external-block_callbr(ptr %arg1, ptr %arg2) local_unnamed_ad
 ; CHECK:       C.target.D:
 ; CHECK-NEXT:    br label [[LOOP_EXIT_GUARD]]
 ; CHECK:       loop.exit.guard:
-; CHECK-NEXT:    [[MYTMP41_MOVED]] = phi i32 [ poison, [[A_TARGET_E:%.*]] ], [ [[MYTMP41]], [[C_TARGET_D:%.*]] ]
+; CHECK-NEXT:    [[MYTMP41_MOVED]] = phi i32 [ poison, [[A_TARGET_E]] ], [ [[MYTMP41]], [[C_TARGET_D]] ]
 ; CHECK-NEXT:    [[GUARD_E:%.*]] = phi i1 [ true, [[A_TARGET_E]] ], [ false, [[C_TARGET_D]] ]
 ; CHECK-NEXT:    br i1 [[GUARD_E]], label [[E]], label [[D]]
 ;
@@ -472,3 +652,68 @@ return:
   %phi = phi i32 [ %mytmp41, %D ], [ %mytmp42, %E ]
   ret i32 %phi
 }
+
+define i32 @phi-via-external-block_switch(ptr %arg1, ptr %arg2, i1 %Pred) local_unnamed_addr align 2 {
+; CHECK-LABEL: @phi-via-external-block_switch(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[MYTMP42:%.*]] = load i32, ptr [[ARG1:%.*]], align 4
+; CHECK-NEXT:    switch i1 [[PRED:%.*]], label [[A:%.*]] [
+; CHECK-NEXT:    ]
+; CHECK:       A:
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[MYTMP42]], 0
+; CHECK-NEXT:    switch i1 [[CMP1]], label [[B:%.*]] [
+; CHECK-NEXT:      i1 false, label [[A_TARGET_E:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       B:
+; CHECK-NEXT:    [[MYTMP41:%.*]] = load i32, ptr [[ARG2:%.*]], align 4
+; CHECK-NEXT:    switch i1 [[PRED]], label [[C:%.*]] [
+; CHECK-NEXT:    ]
+; CHECK:       C:
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[MYTMP42]], 0
+; CHECK-NEXT:    switch i1 [[CMP]], label [[A]] [
+; CHECK-NEXT:      i1 false, label [[C_TARGET_D:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       D:
+; CHECK-NEXT:    switch i1 [[PRED]], label [[RETURN:%.*]] [
+; CHECK-NEXT:    ]
+; CHECK:       E:
+; CHECK-NEXT:    switch i1 [[PRED]], label [[RETURN]] [
+; CHECK-NEXT:    ]
+; CHECK:       return:
+; CHECK-NEXT:    [[PHI:%.*]] = phi i32 [ [[MYTMP41_MOVED:%.*]], [[D:%.*]] ], [ [[MYTMP42]], [[E:%.*]] ]
+; CHECK-NEXT:    ret i32 [[PHI]]
+; CHECK:       A.target.E:
+; CHECK-NEXT:    br label [[LOOP_EXIT_GUARD:%.*]]
+; CHECK:       C.target.D:
+; CHECK-NEXT:    br label [[LOOP_EXIT_GUARD]]
+; CHECK:       loop.exit.guard:
+; CHECK-NEXT:    [[MYTMP41_MOVED]] = phi i32 [ poison, [[A_TARGET_E]] ], [ [[MYTMP41]], [[C_TARGET_D]] ]
+; CHECK-NEXT:    [[GUARD_E:%.*]] = phi i1 [ true, [[A_TARGET_E]] ], [ false, [[C_TARGET_D]] ]
+; CHECK-NEXT:    br i1 [[GUARD_E]], label [[E]], label [[D]]
+;
+entry:
+  %mytmp42 = load i32, ptr %arg1, align 4
+  switch i1 %Pred, label %A []
+
+A:
+  %cmp1 = icmp slt i32 %mytmp42, 0
+  switch i1 %cmp1, label %B [ i1 0, label %E ]
+
+B:
+  %mytmp41 = load i32, ptr %arg2, align 4
+  switch i1 %Pred, label %C []
+
+C:
+  %cmp = icmp slt i32 %mytmp42, 0
+  switch i1 %cmp, label %A [ i1 0, label %D ]
+
+D:
+  switch i1 %Pred, label %return []
+
+E:
+  switch i1 %Pred, label %return []
+
+return:
+  %phi = phi i32 [ %mytmp41, %D ], [ %mytmp42, %E ]
+  ret i32 %phi
+}
diff --git a/llvm/test/Transforms/UnifyLoopExits/switch.ll b/llvm/test/Transforms/UnifyLoopExits/switch.ll
index 887a6f5d08e9b..7ab6de7651bd9 100644
--- a/llvm/test/Transforms/UnifyLoopExits/switch.ll
+++ b/llvm/test/Transforms/UnifyLoopExits/switch.ll
@@ -1,5 +1,6 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
 ; RUN: opt < %s -passes='lower-switch,unify-loop-exits' -S | FileCheck %s
+; RUN: opt < %s -passes='unify-loop-exits' -S | FileCheck %s --check-prefix=NOLOWER
 
 define void @loop_1(i32 %Value, i1 %PredEntry, i1 %PredD) {
 ; CHECK-LABEL: @loop_1(
@@ -34,6 +35,34 @@ define void @loop_1(i32 %Value, i1 %PredEntry, i1 %PredD) {
 ; CHECK-NEXT:    [[GUARD_X:%.*]] = phi i1 [ true, [[LEAFBLOCK1]] ], [ true, [[LEAFBLOCK]] ], [ false, [[D]] ]
 ; CHECK-NEXT:    br i1 [[GUARD_X]], label [[X:%.*]], label [[Y:%.*]]
 ;
+; NOLOWER-LABEL: @loop_1(
+; NOLOWER-NEXT:  entry:
+; NOLOWER-NEXT:    br i1 [[PREDENTRY:%.*]], label [[A:%.*]], label [[G:%.*]]
+; NOLOWER:       A:
+; NOLOWER-NEXT:    br label [[B:%.*]]
+; NOLOWER:       B:
+; NOLOWER-NEXT:    switch i32 [[VALUE:%.*]], label [[B_TARGET_X:%.*]] [
+; NOLOWER-NEXT:      i32 0, label [[C:%.*]]
+; NOLOWER-NEXT:      i32 1, label [[D:%.*]]
+; NOLOWER-NEXT:    ]
+; NOLOWER:       C:
+; NOLOWER-NEXT:    br label [[D]]
+; NOLOWER:       D:
+; NOLOWER-NEXT:    br i1 [[PREDD:%.*]], label [[A]], label [[LOOP_EXIT_GUARD:%.*]]
+; NOLOWER:       X:
+; NOLOWER-NEXT:    br label [[EXIT:%.*]]
+; NOLOWER:       Y:
+; NOLOWER-NEXT:    br label [[EXIT]]
+; NOLOWER:       G:
+; NOLOWER-NEXT:    br label [[EXIT]]
+; NOLOWER:       exit:
+; NOLOWER-NEXT:    ret void
+; NOLOWER:       B.target.X:
+; NOLOWER-NEXT:    br label [[LOOP_EXIT_GUARD]]
+; NOLOWER:       loop.exit.guard:
+; NOLOWER-NEXT:    [[GUARD_X:%.*]] = phi i1 [ true, [[B_TARGET_X]] ], [ false, [[D]] ]
+; NOLOWER-NEXT:    br i1 [[GUARD_X]], label [[X:%.*]], label [[Y:%.*]]
+;
 entry:
   br i1 %PredEntry, label %A, label %G
 
diff --git a/llvm/test/Transforms/UnifyLoopExits/undef-phis.ll b/llvm/test/Transforms/UnifyLoopExits/undef-phis.ll
index e65e2549a21c8..af7d1a912be70 100644
--- a/llvm/test/Transforms/UnifyLoopExits/undef-phis.ll
+++ b/llvm/test/Transforms/UnifyLoopExits/undef-phis.ll
@@ -70,28 +70,28 @@ define fastcc void @undef_phi_callbr(i64 %i5247, i1 %i4530, i1 %i4936.not) {
 ; CHECK-NEXT:    [[TMP0:%.*]] = trunc i64 [[I5247]] to i32
 ; CHECK-NEXT:    [[I5290:%.*]] = icmp eq i32 [[TMP0]], 0
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[I5290]])
-; CHECK-NEXT:            to label %[[MBB3932]] [label %mbb4321.target.mbb5291]
+; CHECK-NEXT:            to label %[[MBB3932]] [label %[[MBB4321_TARGET_MBB5291:.*]]]
 ; CHECK:       [[MBB4454]]:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[I4530]])
-; CHECK-NEXT:            to label %[[MBB4535:.*]] [label %mbb4454.target.mbb4454.target.mbb4531]
+; CHECK-NEXT:            to label %[[MBB4535:.*]] [label %[[MBB4454_TARGET_MBB4454_TARGET_MBB4531:.*]]]
 ; CHECK:       [[MBB4531:.*]]:
 ; CHECK-NEXT:    ret void
 ; CHECK:       [[MBB4535]]:
 ; CHECK-NEXT:    callbr void asm "", "r,!i"(i1 [[I4936_NOT]])
-; CHECK-NEXT:            to label %[[MBB4535_TARGET_MBB4321:.*]] [label %mbb4454]
+; CHECK-NEXT:            to label %[[MBB4535_TARGET_MBB4321:.*]] [label %[[MBB4454]]]
 ; CHECK:       [[MBB5291:.*]]:
 ; CHECK-NEXT:    [[I5293:%.*]] = insertvalue [2 x i32] zeroinitializer, i32 [[DOTMOVED:%.*]], 1
 ; CHECK-NEXT:    store volatile [2 x i32] [[I5293]], ptr addrspace(5) null, align 4
 ; CHECK-NEXT:    ret void
 ; CHECK:       [[MBB4454_TARGET_MBB4531:.*]]:
 ; CHECK-NEXT:    br label %[[LOOP_EXIT_GUARD:.*]]
-; CHECK:       [[MBB4321_TARGET_MBB5291:.*]]:
+; CHECK:       [[MBB4321_TARGET_MBB5291]]:
 ; CHECK-NEXT:    br label %[[LOOP_EXIT_GUARD]]
 ; CHECK:       [[LOOP_EXIT_GUARD]]:
 ; CHECK-NEXT:    [[DOTMOVED]] = phi i32 [ poison, %[[MBB4454_TARGET_MBB4531]] ], [ [[TMP0]], %[[MBB4321_TARGET_MBB5291]] ]
 ; CHECK-NEXT:    [[GUARD_MBB4531:%.*]] = phi i1 [ true, %[[MBB4454_TARGET_MBB4531]] ], [ false, %[[MBB4321_TARGET_MBB5291]] ]
 ; CHECK-NEXT:    br i1 [[GUARD_MBB4531]], label %[[MBB4531]], label %[[MBB5291]]
-; CHECK:       [[MBB4454_TARGET_MBB4454_TARGET_MBB4531:.*]]:
+; CHECK:       [[MBB4454_TARGET_MBB4454_TARGET_MBB4531]]:
 ; CHECK-NEXT:    br label %[[LOOP_EXIT_GUARD1:.*]]
 ; CHECK:       [[MBB4535_TARGET_MBB4321]]:
 ; CHECK-NEXT:    br label %[[LOOP_EXIT_GUARD1]]
@@ -124,3 +124,74 @@ mbb5291:                                           ; preds = %mbb4321
   store volatile [2 x i32] %i5293, ptr addrspace(5) null, align 4
   ret void
 }
+
+define fastcc void @undef_phi_switch(i64 %i5247, i1 %i4530, i1 %i4936.not, i1 %Pred) {
+; CHECK-LABEL: define fastcc void @undef_phi_switch(
+; CHECK-SAME: i64 [[I5247:%.*]], i1 [[I4530:%.*]], i1 [[I4936_NOT:%.*]], i1 [[PRED:%.*]]) {
+; CHECK-NEXT:  [[MBB:.*:]]
+; CHECK-NEXT:    switch i1 [[PRED]], label %[[MBB3932:.*]] [
+; CHECK-NEXT:    ]
+; CHECK:       [[MBB3932]]:
+; CHECK-NEXT:    switch i1 [[PRED]], label %[[MBB4454:.*]] [
+; CHECK-NEXT:    ]
+; CHECK:       [[MBB4321:.*]]:
+; CHECK-NEXT:    [[TMP0:%.*]] = trunc i64 [[I5247]] to i32
+; CHECK-NEXT:    [[I5290:%.*]] = icmp eq i32 [[TMP0]], 0
+; CHECK-NEXT:    switch i1 [[I5290]], label %[[MBB3932]] [
+; CHECK-NEXT:      i1 false, label %[[MBB4321_TARGET_MBB5291:.*]]
+; CHECK-NEXT:    ]
+; CHECK:       [[MBB4454]]:
+; CHECK-NEXT:    switch i1 [[I4530]], label %[[MBB4535:.*]] [
+; CHECK-NEXT:      i1 false, label %[[MBB4454_TARGET_MBB4454_TARGET_MBB4531:.*]]
+; CHECK-NEXT:    ]
+; CHECK:       [[MBB4531:.*]]:
+; CHECK-NEXT:    ret void
+; CHECK:       [[MBB4535]]:
+; CHECK-NEXT:    switch i1 [[I4936_NOT]], label %[[MBB4535_TARGET_MBB4321:.*]] [
+; CHECK-NEXT:      i1 false, label %[[MBB4454]]
+; CHECK-NEXT:    ]
+; CHECK:       [[MBB5291:.*]]:
+; CHECK-NEXT:    [[I5293:%.*]] = insertvalue [2 x i32] zeroinitializer, i32 [[DOTMOVED:%.*]], 1
+; CHECK-NEXT:    store volatile [2 x i32] [[I5293]], ptr addrspace(5) null, align 4
+; CHECK-NEXT:    ret void
+; CHECK:       [[MBB4454_TARGET_MBB4531:.*]]:
+; CHECK-NEXT:    br label %[[LOOP_EXIT_GUARD:.*]]
+; CHECK:       [[MBB4321_TARGET_MBB5291]]:
+; CHECK-NEXT:    br label %[[LOOP_EXIT_GUARD]]
+; CHECK:       [[LOOP_EXIT_GUARD]]:
+; CHECK-NEXT:    [[DOTMOVED]] = phi i32 [ poison, %[[MBB4454_TARGET_MBB4531]] ], [ [[TMP0]], %[[MBB4321_TARGET_MBB5291]] ]
+; CHECK-NEXT:    [[GUARD_MBB4531:%.*]] = phi i1 [ true, %[[MBB4454_TARGET_MBB4531]] ], [ false, %[[MBB4321_TARGET_MBB5291]] ]
+; CHECK-NEXT:    br i1 [[GUARD_MBB4531]], label %[[MBB4531]], label %[[MBB5291]]
+; CHECK:       [[MBB4454_TARGET_MBB4454_TARGET_MBB4531]]:
+; CHECK-NEXT:    br label %[[LOOP_EXIT_GUARD1:.*]]
+; CHECK:       [[MBB4535_TARGET_MBB4321]]:
+; CHECK-NEXT:    br label %[[LOOP_EXIT_GUARD1]]
+; CHECK:       [[LOOP_EXIT_GUARD1]]:
+; CHECK-NEXT:    [[GUARD_MBB4454_TARGET_MBB4531:%.*]] = phi i1 [ true, %[[MBB4454_TARGET_MBB4454_TARGET_MBB4531]] ], [ false, %[[MBB4535_TARGET_MBB4321]] ]
+; CHECK-NEXT:    br i1 [[GUARD_MBB4454_TARGET_MBB4531]], label %[[MBB4454_TARGET_MBB4531]], label %[[MBB4321]]
+;
+mbb:
+  switch i1 %Pred, label %mbb3932 []
+
+mbb3932:                                           ; preds = %mbb4321, %mbb
+  switch i1 %Pred, label %mbb4454 []
+
+mbb4321:                                           ; preds = %mbb4535
+  %0 = trunc i64 %i5247 to i32
+  %i5290 = icmp eq i32 %0, 0
+  switch i1 %i5290, label %mbb3932 [ i1 0, label %mbb5291 ]
+
+mbb4454:                                           ; preds = %mbb4535, %mbb3932
+  switch i1 %i4530, label %mbb4535 [ i1 0, label %mbb4531 ]
+
+mbb4531:                                           ; preds = %mbb4454
+  ret void
+
+mbb4535:                                           ; preds = %mbb4454
+  switch i1 %i4936.not, label %mbb4321 [ i1 0, label %mbb4454 ]
+
+mbb5291:                                           ; preds = %mbb4321
+  %i5293 = insertvalue [2 x i32] zeroinitializer, i32 %0, 1
+  store volatile [2 x i32] %i5293, ptr addrspace(5) null, align 4
+  ret void
+}



More information about the llvm-commits mailing list