[llvm] [SimplifyCFG] Simplify identical predessors (PR #173022)

Kunqiu Chen via llvm-commits llvm-commits at lists.llvm.org
Fri Dec 19 08:29:48 PST 2025


https://github.com/Camsyn updated https://github.com/llvm/llvm-project/pull/173022

>From c7f61f7ad65524ec6825c7cf38392f10e88c43a4 Mon Sep 17 00:00:00 2001
From: Camsyn <camsyn at foxmail.com>
Date: Fri, 19 Dec 2025 23:27:13 +0800
Subject: [PATCH 1/4] before-commit test

---
 llvm/test/Transforms/SimplifyCFG/dup-preds.ll | 55 +++++++++++++++++++
 1 file changed, 55 insertions(+)
 create mode 100644 llvm/test/Transforms/SimplifyCFG/dup-preds.ll

diff --git a/llvm/test/Transforms/SimplifyCFG/dup-preds.ll b/llvm/test/Transforms/SimplifyCFG/dup-preds.ll
new file mode 100644
index 0000000000000..859ef2a64e394
--- /dev/null
+++ b/llvm/test/Transforms/SimplifyCFG/dup-preds.ll
@@ -0,0 +1,55 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S | FileCheck %s -check-prefix=SIMPLIFY-CFG
+
+define i8 @foo(i8 %v1, i8 %v2) {
+; SIMPLIFY-CFG-LABEL: @foo(
+; SIMPLIFY-CFG-NEXT:  entry:
+; SIMPLIFY-CFG-NEXT:    switch i8 [[V1:%.*]], label [[EXIT:%.*]] [
+; SIMPLIFY-CFG-NEXT:      i8 0, label [[THEN:%.*]]
+; SIMPLIFY-CFG-NEXT:      i8 1, label [[ELSE:%.*]]
+; SIMPLIFY-CFG-NEXT:    ]
+; SIMPLIFY-CFG:       then:
+; SIMPLIFY-CFG-NEXT:    switch i8 [[V2:%.*]], label [[EXIT]] [
+; SIMPLIFY-CFG-NEXT:      i8 0, label [[SWITCH_CASE_0:%.*]]
+; SIMPLIFY-CFG-NEXT:      i8 1, label [[SWITCH_CASE_1:%.*]]
+; SIMPLIFY-CFG-NEXT:      i8 2, label [[SWITCH_CASE_1]]
+; SIMPLIFY-CFG-NEXT:    ]
+; SIMPLIFY-CFG:       switch.case.0:
+; SIMPLIFY-CFG-NEXT:    br label [[EXIT]]
+; SIMPLIFY-CFG:       switch.case.1:
+; SIMPLIFY-CFG-NEXT:    br label [[EXIT]]
+; SIMPLIFY-CFG:       else:
+; SIMPLIFY-CFG-NEXT:    br label [[EXIT]]
+; SIMPLIFY-CFG:       exit:
+; SIMPLIFY-CFG-NEXT:    [[RET:%.*]] = phi i8 [ 0, [[ELSE]] ], [ 0, [[SWITCH_CASE_0]] ], [ 1, [[SWITCH_CASE_1]] ], [ 2, [[THEN]] ], [ 3, [[ENTRY:%.*]] ]
+; SIMPLIFY-CFG-NEXT:    ret i8 [[RET]]
+;
+entry:
+  switch i8 %v1, label %exit [
+  i8 0, label %then
+  i8 1, label %else
+  ]
+
+then:                                             ; preds = %entry
+  switch i8 %v2, label %exit [
+  i8 0, label %switch.case.0
+  i8 1, label %switch.case.1
+  i8 2, label %switch.case.2
+  ]
+
+switch.case.0:                                    ; preds = %then
+  br label %exit
+
+switch.case.1:                                    ; preds = %then
+  br label %exit
+
+switch.case.2:                                    ; preds = %then
+  br label %exit
+
+else:                                             ; preds = %entry
+  br label %exit
+
+exit:                                             ; preds = %else, %switch.case.2, %switch.case.1, %switch.case.0, %then, %entry
+  %ret = phi i8 [ 0, %else ], [ 0, %switch.case.0 ], [ 1, %switch.case.1 ], [ 1, %switch.case.2 ], [ 2, %then ], [ 3, %entry ]
+  ret i8 %ret
+}

>From 9968d1f1186e01006407a3ad921fadbf95e76c12 Mon Sep 17 00:00:00 2001
From: Camsyn <camsyn at foxmail.com>
Date: Fri, 19 Dec 2025 23:20:33 +0800
Subject: [PATCH 2/4] feat: impl generic dup preds merging

---
 llvm/lib/Transforms/Utils/SimplifyCFG.cpp | 214 +++++++++++++++++++++-
 1 file changed, 212 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index 4fac5d36ddb3f..dae3a10beabdb 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -315,6 +315,7 @@ class SimplifyCFGOpt {
   bool simplifySwitchOnSelect(SwitchInst *SI, SelectInst *Select);
   bool simplifyIndirectBrOnSelect(IndirectBrInst *IBI, SelectInst *SI);
   bool turnSwitchRangeIntoICmp(SwitchInst *SI, IRBuilder<> &Builder);
+  bool simplifyDuplicatePredecessors(BasicBlock *Succ, DomTreeUpdater *DTU);
 
 public:
   SimplifyCFGOpt(const TargetTransformInfo &TTI, DomTreeUpdater *DTU,
@@ -8435,6 +8436,212 @@ bool SimplifyCFGOpt::simplifyCondBranch(BranchInst *BI, IRBuilder<> &Builder) {
 
   return false;
 }
+/// Checking whether two BBs are equal depends on the contents of the
+/// BasicBlock and the incoming values of their successor PHINodes.
+/// PHINode::getIncomingValueForBlock is O(|Preds|), so we'd like to avoid
+/// calling this function on each BasicBlock every time isEqual is called,
+/// especially since the same BasicBlock may be passed as an argument multiple
+/// times. To do this, we can precompute a map of PHINode -> Pred BasicBlock ->
+/// IncomingValue and add it in the Wrapper so isEqual can do O(1) checking
+/// of the incoming values.
+struct EqualBBWrapper {
+  BasicBlock *BB;
+
+  // One Phi usually has < 8 incoming values.
+  using BB2ValueMap = SmallDenseMap<BasicBlock *, Value *, 8>;
+  using Phi2IVsMap = DenseMap<PHINode *, BB2ValueMap>;
+  Phi2IVsMap *PhiPredIVs;
+};
+
+template <> struct llvm::DenseMapInfo<const EqualBBWrapper *> {
+  static const EqualBBWrapper *getEmptyKey() {
+    return static_cast<EqualBBWrapper *>(DenseMapInfo<void *>::getEmptyKey());
+  }
+  static const EqualBBWrapper *getTombstoneKey() {
+    return static_cast<EqualBBWrapper *>(
+        DenseMapInfo<void *>::getTombstoneKey());
+  }
+  static unsigned getHashValue(const EqualBBWrapper *SSW) {
+    BasicBlock *BB = SSW->BB;
+    BranchInst *BI = cast<BranchInst>(BB->getTerminator());
+    assert(BI->isUnconditional() &&
+           "Only supporting unconditional branches for now");
+    assert(BI->getNumSuccessors() == 1 &&
+           "Expected unconditional branches to have one successor");
+    assert(BB->size() == 1 && "Expected just a single branch in the BB");
+
+    // Since we assume the BB is just a single BranchInst with a single
+    // successor, we hash as the BB and the incoming Values of its successor
+    // PHIs. Initially, we tried to just use the successor BB as the hash, but
+    // including the incoming PHI values leads to better performance.
+    // We also tried to build a map from BB -> Succs.IncomingValues ahead of
+    // time and passing it in SwitchSuccWrapper, but this slowed down the
+    // average compile time without having any impact on the worst case compile
+    // time.
+    BasicBlock *Succ = BI->getSuccessor(0);
+    auto PhiValsForBB = map_range(
+        BB->phis(), [BB, &PhiPredIVs = *SSW->PhiPredIVs](PHINode &Phi) {
+          return PhiPredIVs[&Phi][BB];
+        });
+    return hash_combine(Succ, hash_combine_range(PhiValsForBB));
+  }
+  static bool isEqual(const EqualBBWrapper *LHS, const EqualBBWrapper *RHS) {
+    auto *EKey = DenseMapInfo<EqualBBWrapper *>::getEmptyKey();
+    auto *TKey = DenseMapInfo<EqualBBWrapper *>::getTombstoneKey();
+    if (LHS == EKey || RHS == EKey || LHS == TKey || RHS == TKey)
+      return LHS == RHS;
+
+    BasicBlock *A = LHS->BB;
+    BasicBlock *B = RHS->BB;
+
+    // FIXME: we checked that the size of A and B are both 1 in
+    // simplifyDuplicateSwitchArms to make the Case list smaller to
+    // improve performance. If we decide to support BasicBlocks with more
+    // than just a single instruction, we need to check that A.size() ==
+    // B.size() here, and we need to check more than just the BranchInsts
+    // for equality.
+
+    BranchInst *ABI = cast<BranchInst>(A->getTerminator());
+    BranchInst *BBI = cast<BranchInst>(B->getTerminator());
+    assert(ABI->isUnconditional() && BBI->isUnconditional() &&
+           "Only supporting unconditional branches for now");
+    if (ABI->getSuccessor(0) != BBI->getSuccessor(0))
+      return false;
+
+    // Need to check that PHIs in successor have matching values
+    BasicBlock *Succ = ABI->getSuccessor(0);
+    auto IfPhiIVMatch = [A, B, &PhiPredIVs = *LHS->PhiPredIVs](PHINode &Phi) {
+      // Replace O(|Pred|) Phi.getIncomingValueForBlock with this O(1) hashmap
+      // query
+      auto &PredIVs = PhiPredIVs[&Phi];
+      return PredIVs[A] == PredIVs[B];
+    };
+    return all_of(Succ->phis(), IfPhiIVMatch);
+  }
+};
+
+bool SimplifyCFGOpt::simplifyDuplicatePredecessors(BasicBlock *Succ,
+                                                   DomTreeUpdater *DTU) {
+  // Need at least 2 predecessors to do anything.
+  if (!Succ || pred_empty(Succ))
+    return false;
+  // Precompute PHI incoming values in Succ for all candidate preds.
+  // PhiPredIVs[Phi][Pred] = incoming value
+  EqualBBWrapper::Phi2IVsMap PhiPredIVs;
+
+  // We only handle a single successor "Succ"; caller can iterate blocks.
+  // Collect candidate predecessors P with:
+  // - terminator unconditional br to Succ,
+  // - does not have address taken / weird control.
+  auto Filter = [Succ](BasicBlock *Pred) {
+    // Single successor and must be Succ.
+    auto *BI = dyn_cast<BranchInst>(Pred->getTerminator());
+    if (!BI || !BI->isUnconditional())
+      return false;
+
+    // Avoid blocks that are "address-taken" (blockaddress) or have unusual
+    // uses.
+    if (Pred->hasAddressTaken())
+      return false;
+    if (Pred->isLandingPad())
+      return false;
+
+    // TODO: should we support Pred with >1 instructions?
+    if (Pred->size() != 1)
+      return false;
+
+    // Avoid self-loop predecessor merging for now.
+    if (Pred == Succ)
+      return false;
+
+    return true;
+  };
+
+  auto FilteredPreds = make_filter_range(predecessors(Succ), Filter);
+
+  SmallVector<EqualBBWrapper> Preds(
+      map_range(FilteredPreds, [&PhiPredIVs](BasicBlock *Pred) {
+        return EqualBBWrapper{Pred, &PhiPredIVs};
+      }));
+
+  if (Preds.size() < 2)
+    return false;
+
+  SmallVector<PHINode *, 8> Phis(make_pointer_range(Succ->phis()));
+
+  PhiPredIVs.reserve(Phis.size());
+  for (PHINode *Phi : Phis) {
+    auto &IVs =
+        PhiPredIVs.try_emplace(Phi, Phi->getNumIncomingValues()).first->second;
+    // Pre-fill all incoming for O(1) lookup as Phi.getIncomingValueForBlock is
+    // O(|Pred|).
+    for (auto &IV : Phi->incoming_values())
+      IVs.insert({Phi->getIncomingBlock(IV), IV.get()});
+  }
+
+  // Group duplicates using DenseSet with custom equality/hashing.
+  DenseSet<const EqualBBWrapper *> Keep;
+  Keep.reserve(Preds.size());
+
+  SmallVector<DominatorTree::UpdateType> Updates;
+  Updates.reserve(Preds.size() * 2);
+
+  bool MadeChange = false;
+
+  // Helper: redirect all edges X -> DeadPred to X -> LivePred.
+  auto RedirectIncomingEdges = [&](BasicBlock *DeadPred, BasicBlock *LivePred) {
+    // Replace successors in all predecessors of DeadPred.
+    SmallSetVector<BasicBlock *, 8> DeadPredPreds(llvm::from_range,
+                                                  predecessors(DeadPred));
+    if (DTU) {
+      // All predecessors of DeadPred (except the common predecessor) will be
+      // moved to LivePred.
+      Updates.reserve(Updates.size() + DeadPredPreds.size() * 2);
+      SmallPtrSet<BasicBlock *, 16> LivePredPreds(llvm::from_range,
+                                                  predecessors(LivePred));
+      for (BasicBlock *PP : DeadPredPreds) {
+        // Do not modify those common predecessors of DeadPred and LivePred
+        if (!LivePredPreds.contains(PP))
+          Updates.push_back({DominatorTree::Insert, PP, LivePred});
+        Updates.push_back({DominatorTree::Delete, PP, DeadPred});
+      }
+    }
+    for (BasicBlock *PP : DeadPredPreds) {
+      Instruction *T = PP->getTerminator();
+      T->replaceSuccessorWith(DeadPred, LivePred);
+    }
+  };
+
+  // Try to canonicalize duplicates.
+  for (const auto &Pred : Preds) {
+    // Pred is a candidate for simplification. If we find a duplicate BB,
+    // replace it.
+    const auto [It, Inserted] = Keep.insert(&Pred);
+    if (Inserted)
+      continue;
+
+    // Found duplicate: merge P into canonical predecessor It->Pred.
+    BasicBlock *KeepPred = (*It)->BB;
+    BasicBlock *DeadPred = Pred.BB;
+
+    // Avoid merging if either is the other's predecessor in weird ways.
+    if (KeepPred == DeadPred)
+      continue;
+
+    // Redirect all edges into DeadPred to KeepPred.
+    RedirectIncomingEdges(DeadPred, KeepPred);
+
+    // Now DeadPred should become unreachable; leave DCE to later,
+    // but we can try to simplify it if it only branches to Succ.
+    // (We won't erase here to keep the routine simple and DT-safe.)
+    MadeChange = true;
+  }
+
+  if (DTU && !Updates.empty())
+    DTU->applyUpdates(Updates);
+
+  return MadeChange;
+}
 
 /// Check if passing a value to an instruction will cause undefined behavior.
 static bool passingValueIsAlwaysUndefined(Value *V, Instruction *I, bool PtrValueMayBeModified) {
@@ -8681,8 +8888,6 @@ bool SimplifyCFGOpt::simplifyOnce(BasicBlock *BB) {
       return true;
     }
 
-  IRBuilder<> Builder(BB);
-
   if (Options.SpeculateBlocks &&
       !BB->getParent()->hasFnAttribute(Attribute::OptForFuzzing)) {
     // If there is a trivial two-entry PHI node in this basic block, and we can
@@ -8694,6 +8899,11 @@ bool SimplifyCFGOpt::simplifyOnce(BasicBlock *BB) {
           return true;
   }
 
+  // Merge identical predecessors of this block
+  if (simplifyDuplicatePredecessors(BB, DTU))
+    return true;
+
+  IRBuilder<> Builder(BB);
   Instruction *Terminator = BB->getTerminator();
   Builder.SetInsertPoint(Terminator);
   switch (Terminator->getOpcode()) {

>From 139623f4112c6252cc92e6a5de6f8948166a0c2b Mon Sep 17 00:00:00 2001
From: Camsyn <camsyn at foxmail.com>
Date: Sat, 20 Dec 2025 00:24:37 +0800
Subject: [PATCH 3/4] Regenerate some existing tests

---
 .../Transforms/LoopDeletion/simplify-then-delete.ll |  5 +++++
 .../SimplifyCFG/X86/switch-to-lookup-globals.ll     | 13 +++----------
 .../SimplifyCFG/X86/switch_to_lookup_table.ll       |  2 +-
 llvm/test/Transforms/SimplifyCFG/switch-dup-bbs.ll  | 10 ++++------
 4 files changed, 13 insertions(+), 17 deletions(-)

diff --git a/llvm/test/Transforms/LoopDeletion/simplify-then-delete.ll b/llvm/test/Transforms/LoopDeletion/simplify-then-delete.ll
index 529ee8919bdb3..869fea650f49f 100644
--- a/llvm/test/Transforms/LoopDeletion/simplify-then-delete.ll
+++ b/llvm/test/Transforms/LoopDeletion/simplify-then-delete.ll
@@ -11,6 +11,11 @@ define i32 @pmat(i32 %m, i32 %n, ptr %y, i1 %arg) nounwind {
 ; CHECK-LABEL: @pmat(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[CMP4:%.*]] = icmp sgt i32 [[M:%.*]], 0
+; CHECK-NEXT:    br i1 [[CMP4]], label [[BB_N10:%.*]], label [[W_E12:%.*]]
+; CHECK:       bb.n10:
+; CHECK-NEXT:    [[CMP51:%.*]] = icmp sgt i32 [[N:%.*]], 0
+; CHECK-NEXT:    br label [[W_E12]]
+; CHECK:       w.e12:
 ; CHECK-NEXT:    ret i32 0
 ;
 entry:
diff --git a/llvm/test/Transforms/SimplifyCFG/X86/switch-to-lookup-globals.ll b/llvm/test/Transforms/SimplifyCFG/X86/switch-to-lookup-globals.ll
index 4f8dc5c0a274f..4745cd0f7ea3a 100644
--- a/llvm/test/Transforms/SimplifyCFG/X86/switch-to-lookup-globals.ll
+++ b/llvm/test/Transforms/SimplifyCFG/X86/switch-to-lookup-globals.ll
@@ -10,16 +10,9 @@ target triple = "x86_64-unknown-linux-gnu"
 define i1 @zot(i32 %arg) {
 ; CHECK-LABEL: @zot(
 ; CHECK-NEXT:  bb:
-; CHECK-NEXT:    %0 = icmp ult i32 %arg, 3
-; CHECK-NEXT:    br i1 %0, label %switch.lookup, label %bb6
-; CHECK:       switch.lookup:
-; CHECK-NEXT:    %1 = zext nneg i32 %arg to i64
-; CHECK-NEXT:    %switch.gep = getelementptr inbounds [3 x ptr], ptr @switch.table.zot, i64 0, i64 %1
-; CHECK-NEXT:    %switch.load = load ptr, ptr %switch.gep, align 8
-; CHECK-NEXT:    br label %bb6
-; CHECK:       bb6:
-; CHECK-NEXT:    %tmp7 = phi ptr [ %switch.load, %switch.lookup ], [ null, %bb ]
-; CHECK-NEXT:    %tmp8 = icmp eq ptr %tmp7, getelementptr inbounds ([75 x { i32, i32, i32, i8, i8 }], ptr @global, i64 1, i64 0, i32 0)
+; CHECK-NEXT:    %cond = icmp eq i32 %arg, 1
+; CHECK-NEXT:    %spec.select = select i1 %cond, ptr getelementptr inbounds ([75 x { i32, i32, i32, i8, i8 }], ptr @global, i64 0, i64 6, i32 0), ptr null
+; CHECK-NEXT:    %tmp8 = icmp eq ptr %spec.select, getelementptr inbounds ([75 x { i32, i32, i32, i8, i8 }], ptr @global, i64 1, i64 0, i32 0)
 ; CHECK-NEXT:    ret i1 %tmp8
 ;
 bb:
diff --git a/llvm/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll b/llvm/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll
index bee6b375ea11a..d35396cfe6688 100644
--- a/llvm/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll
+++ b/llvm/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll
@@ -1609,7 +1609,7 @@ define i32 @PR26308(i1 %B, i64 %load) {
 ; CHECK-LABEL: @PR26308(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    br label [[CLEANUP4:%.*]]
-; CHECK:       cleanup4:
+; CHECK:       while.body:
 ; CHECK-NEXT:    br label [[CLEANUP4]]
 ;
 entry:
diff --git a/llvm/test/Transforms/SimplifyCFG/switch-dup-bbs.ll b/llvm/test/Transforms/SimplifyCFG/switch-dup-bbs.ll
index d2d917de11897..dfc9dbea3dc7c 100644
--- a/llvm/test/Transforms/SimplifyCFG/switch-dup-bbs.ll
+++ b/llvm/test/Transforms/SimplifyCFG/switch-dup-bbs.ll
@@ -72,16 +72,14 @@ define i32 @switch_duplicate_arms_multipred(i1 %0, i32 %1, i32 %2, i32 %3, i32 %
 ; SIMPLIFY-CFG-SAME: i1 [[TMP0:%.*]], i32 [[TMP1:%.*]], i32 [[TMP2:%.*]], i32 [[TMP3:%.*]], i32 [[TMP4:%.*]]) {
 ; SIMPLIFY-CFG-NEXT:    br i1 [[TMP0]], label %[[BB6:.*]], label %[[BB7:.*]]
 ; SIMPLIFY-CFG:       [[BB6]]:
-; SIMPLIFY-CFG-NEXT:    switch i32 [[TMP2]], label %[[BB9:.*]] [
+; SIMPLIFY-CFG-NEXT:    switch i32 [[TMP2]], label %[[BB8:.*]] [
 ; SIMPLIFY-CFG-NEXT:      i32 0, label %[[BB7]]
-; SIMPLIFY-CFG-NEXT:      i32 1, label %[[BB8:.*]]
+; SIMPLIFY-CFG-NEXT:      i32 1, label %[[BB7]]
 ; SIMPLIFY-CFG-NEXT:    ]
 ; SIMPLIFY-CFG:       [[BB7]]:
-; SIMPLIFY-CFG-NEXT:    br label %[[BB9]]
+; SIMPLIFY-CFG-NEXT:    br label %[[BB8]]
 ; SIMPLIFY-CFG:       [[BB8]]:
-; SIMPLIFY-CFG-NEXT:    br label %[[BB9]]
-; SIMPLIFY-CFG:       [[BB9]]:
-; SIMPLIFY-CFG-NEXT:    [[TMP10:%.*]] = phi i32 [ [[TMP4]], %[[BB6]] ], [ [[TMP3]], %[[BB8]] ], [ [[TMP3]], %[[BB7]] ]
+; SIMPLIFY-CFG-NEXT:    [[TMP10:%.*]] = phi i32 [ [[TMP4]], %[[BB6]] ], [ [[TMP3]], %[[BB7]] ]
 ; SIMPLIFY-CFG-NEXT:    ret i32 [[TMP10]]
 ;
   br i1 %0, label %6, label %7

>From be1c9642f43d54e44c09c94b6e2eeb45638720c8 Mon Sep 17 00:00:00 2001
From: Camsyn <camsyn at foxmail.com>
Date: Sat, 20 Dec 2025 00:28:36 +0800
Subject: [PATCH 4/4] after-commit test

---
 llvm/test/Transforms/SimplifyCFG/dup-preds.ll | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/llvm/test/Transforms/SimplifyCFG/dup-preds.ll b/llvm/test/Transforms/SimplifyCFG/dup-preds.ll
index 859ef2a64e394..590e28fb1e67b 100644
--- a/llvm/test/Transforms/SimplifyCFG/dup-preds.ll
+++ b/llvm/test/Transforms/SimplifyCFG/dup-preds.ll
@@ -10,18 +10,16 @@ define i8 @foo(i8 %v1, i8 %v2) {
 ; SIMPLIFY-CFG-NEXT:    ]
 ; SIMPLIFY-CFG:       then:
 ; SIMPLIFY-CFG-NEXT:    switch i8 [[V2:%.*]], label [[EXIT]] [
-; SIMPLIFY-CFG-NEXT:      i8 0, label [[SWITCH_CASE_0:%.*]]
+; SIMPLIFY-CFG-NEXT:      i8 0, label [[ELSE]]
 ; SIMPLIFY-CFG-NEXT:      i8 1, label [[SWITCH_CASE_1:%.*]]
 ; SIMPLIFY-CFG-NEXT:      i8 2, label [[SWITCH_CASE_1]]
 ; SIMPLIFY-CFG-NEXT:    ]
-; SIMPLIFY-CFG:       switch.case.0:
-; SIMPLIFY-CFG-NEXT:    br label [[EXIT]]
 ; SIMPLIFY-CFG:       switch.case.1:
 ; SIMPLIFY-CFG-NEXT:    br label [[EXIT]]
 ; SIMPLIFY-CFG:       else:
 ; SIMPLIFY-CFG-NEXT:    br label [[EXIT]]
 ; SIMPLIFY-CFG:       exit:
-; SIMPLIFY-CFG-NEXT:    [[RET:%.*]] = phi i8 [ 0, [[ELSE]] ], [ 0, [[SWITCH_CASE_0]] ], [ 1, [[SWITCH_CASE_1]] ], [ 2, [[THEN]] ], [ 3, [[ENTRY:%.*]] ]
+; SIMPLIFY-CFG-NEXT:    [[RET:%.*]] = phi i8 [ 0, [[ELSE]] ], [ 1, [[SWITCH_CASE_1]] ], [ 2, [[THEN]] ], [ 3, [[ENTRY:%.*]] ]
 ; SIMPLIFY-CFG-NEXT:    ret i8 [[RET]]
 ;
 entry:



More information about the llvm-commits mailing list