[llvm] [SimplifyCFG] Fold pairs of entries in multiple-entry phi (PR #73674)

via llvm-commits llvm-commits at lists.llvm.org
Tue Nov 28 09:44:13 PST 2023


https://github.com/XChy created https://github.com/llvm/llvm-project/pull/73674

Resolves #73380.
In this PR, I've done:
- Add tests for #73380.
- Refactor logic of FoldTwoEntryPHINode in SimplifyCFG, so that we can easily fold such pattern based on both dominant and merge point of the if-region.
- Add logic for folding one of entry pair in multiple-entry phi based on both dominant.

Somehow this PR causes some regressions for doing such fold in incorrect order, I don't know where to place it now and it may take some time to find the place to do fold.

>From f484fcbccb90db42573314aefec5583a1252fb95 Mon Sep 17 00:00:00 2001
From: XChy <xxs_chy at outlook.com>
Date: Tue, 28 Nov 2023 21:21:41 +0800
Subject: [PATCH 1/3] [SimplifyCFG][NFC] Precommit tests for folding multiple
 entry phi

---
 .../SimplifyCFG/fold-multiple-entry-phi.ll    | 226 ++++++++++++++++++
 1 file changed, 226 insertions(+)
 create mode 100644 llvm/test/Transforms/SimplifyCFG/fold-multiple-entry-phi.ll

diff --git a/llvm/test/Transforms/SimplifyCFG/fold-multiple-entry-phi.ll b/llvm/test/Transforms/SimplifyCFG/fold-multiple-entry-phi.ll
new file mode 100644
index 000000000000000..c86f20164ebc525
--- /dev/null
+++ b/llvm/test/Transforms/SimplifyCFG/fold-multiple-entry-phi.ll
@@ -0,0 +1,226 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 3
+; RUN: opt -S -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1 -two-entry-phi-node-folding-threshold=4 -phi-node-folding-threshold=0 < %s | FileCheck %s
+
+define i32 @three_entry_test(i32 %x, i32 %y, i1 %cond){
+; CHECK-LABEL: define i32 @three_entry_test(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]], i1 [[COND:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br i1 [[COND]], label [[END:%.*]], label [[THEN:%.*]]
+; CHECK:       then:
+; CHECK-NEXT:    [[SUB:%.*]] = add i32 [[X]], -1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[X]], [[Y]]
+; CHECK-NEXT:    br i1 [[CMP]], label [[END]], label [[B:%.*]]
+; CHECK:       b:
+; CHECK-NEXT:    [[ADD:%.*]] = add i32 [[X]], 1
+; CHECK-NEXT:    br label [[END]]
+; CHECK:       end:
+; CHECK-NEXT:    [[RET_0:%.*]] = phi i32 [ [[SUB]], [[THEN]] ], [ [[ADD]], [[B]] ], [ 0, [[ENTRY:%.*]] ]
+; CHECK-NEXT:    ret i32 [[RET_0]]
+;
+entry:
+  br i1 %cond, label %if.then, label %then
+
+if.then:
+  br label %end
+
+then:
+  %sub = add i32 %x, -1
+  %cmp = icmp sgt i32 %x, %y
+  br i1 %cmp, label %end, label %b
+
+b:
+  %add = add i32 %x, 1
+  br label %end
+
+end:
+  %ret.0 = phi i32 [ 0, %if.then ], [ %sub, %then ], [ %add, %b ]
+  ret i32 %ret.0
+}
+
+define i32 @three_entry_test_diamond(i32 %x, i32 %y, i1 %cond){
+; CHECK-LABEL: define i32 @three_entry_test_diamond(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]], i1 [[COND:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br i1 [[COND]], label [[END:%.*]], label [[THEN:%.*]]
+; CHECK:       then:
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[X]], [[Y]]
+; CHECK-NEXT:    br i1 [[CMP]], label [[B1:%.*]], label [[B2:%.*]]
+; CHECK:       b1:
+; CHECK-NEXT:    [[SUB:%.*]] = add i32 [[X]], -1
+; CHECK-NEXT:    br label [[END]]
+; CHECK:       b2:
+; CHECK-NEXT:    [[ADD:%.*]] = add i32 [[X]], 1
+; CHECK-NEXT:    br label [[END]]
+; CHECK:       end:
+; CHECK-NEXT:    [[RET_0:%.*]] = phi i32 [ [[SUB]], [[B1]] ], [ [[ADD]], [[B2]] ], [ 0, [[ENTRY:%.*]] ]
+; CHECK-NEXT:    ret i32 [[RET_0]]
+;
+entry:
+  br i1 %cond, label %if.then, label %then
+
+if.then:
+  br label %end
+
+then:
+  %cmp = icmp sgt i32 %x, %y
+  br i1 %cmp, label %b1, label %b2
+
+b1:
+  %sub = add i32 %x, -1
+  br label %end
+
+b2:
+  %add = add i32 %x, 1
+  br label %end
+
+end:
+  %ret.0 = phi i32 [ 0, %if.then ], [ %sub, %b1 ], [ %add, %b2 ]
+  ret i32 %ret.0
+}
+
+
+
+define i32 @four_entry_test(i32 %x, i32 %y, i1 %cond, i1 %cond1){
+; CHECK-LABEL: define i32 @four_entry_test(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]], i1 [[COND:%.*]], i1 [[COND1:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br i1 [[COND]], label [[IF_THEN:%.*]], label [[THEN1:%.*]]
+; CHECK:       if.then:
+; CHECK-NEXT:    br i1 [[COND1]], label [[THEN:%.*]], label [[END:%.*]]
+; CHECK:       then:
+; CHECK-NEXT:    br label [[END]]
+; CHECK:       then1:
+; CHECK-NEXT:    [[SUB:%.*]] = add i32 [[X]], -1
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp sgt i32 [[X]], [[Y]]
+; CHECK-NEXT:    br i1 [[CMP1]], label [[END]], label [[B:%.*]]
+; CHECK:       b:
+; CHECK-NEXT:    [[ADD:%.*]] = add i32 [[X]], 1
+; CHECK-NEXT:    br label [[END]]
+; CHECK:       end:
+; CHECK-NEXT:    [[RET_0:%.*]] = phi i32 [ 0, [[IF_THEN]] ], [ 1, [[THEN]] ], [ [[SUB]], [[THEN1]] ], [ [[ADD]], [[B]] ]
+; CHECK-NEXT:    ret i32 [[RET_0]]
+;
+entry:
+  br i1 %cond, label %if.then, label %then1
+
+if.then:
+  br i1 %cond1, label %then, label %end
+
+then:
+  br label %end
+
+then1:
+  %sub = add i32 %x, -1
+  %cmp1 = icmp sgt i32 %x, %y
+  br i1 %cmp1, label %end, label %b
+
+b:
+  %add = add i32 %x, 1
+  br label %end
+
+end:
+  %ret.0 = phi i32 [ 0, %if.then ], [1, %then], [ %sub, %then1 ], [ %add, %b ]
+  ret i32 %ret.0
+}
+
+declare i32 @dummy()
+
+define i32 @three_entry_test_multiple_dests_fail(i32 %x, i32 %y, i1 %cond, i1 %cond1){
+; CHECK-LABEL: define i32 @three_entry_test_multiple_dests_fail(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]], i1 [[COND:%.*]], i1 [[COND1:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br i1 [[COND]], label [[COMMON_RET:%.*]], label [[THEN:%.*]]
+; CHECK:       then:
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[X]], [[Y]]
+; CHECK-NEXT:    br i1 [[CMP]], label [[B1:%.*]], label [[B2:%.*]]
+; CHECK:       b1:
+; CHECK-NEXT:    [[SUB:%.*]] = add i32 [[X]], -1
+; CHECK-NEXT:    br label [[COMMON_RET]]
+; CHECK:       b2:
+; CHECK-NEXT:    [[ADD:%.*]] = add i32 [[X]], 1
+; CHECK-NEXT:    br i1 [[COND1]], label [[END:%.*]], label [[COMMON_RET]]
+; CHECK:       common.ret:
+; CHECK-NEXT:    [[COMMON_RET_OP:%.*]] = phi i32 [ [[CALL:%.*]], [[END]] ], [ [[SUB]], [[B1]] ], [ [[ADD]], [[B2]] ], [ 0, [[ENTRY:%.*]] ]
+; CHECK-NEXT:    ret i32 [[COMMON_RET_OP]]
+; CHECK:       end:
+; CHECK-NEXT:    [[CALL]] = call i32 @dummy()
+; CHECK-NEXT:    br label [[COMMON_RET]]
+;
+entry:
+  br i1 %cond, label %if.then, label %then
+
+if.then:
+  br label %end1
+
+then:
+  %cmp = icmp sgt i32 %x, %y
+  br i1 %cmp, label %b1, label %b2
+
+b1:
+  %sub = add i32 %x, -1
+  br label %end1
+
+b2:
+  %add = add i32 %x, 1
+  br i1 %cond1, label %end, label %end1
+
+end:
+  %call = call i32 @dummy()
+  ret i32 %call
+
+end1:
+  %ret.0 = phi i32 [ 0, %if.then ], [ %sub, %b1 ], [%add, %b2]
+  ret i32 %ret.0
+}
+
+declare i32 @dummy1()
+define i32 @three_entry_test_different_dest(i32 %x, i32 %y, i1 %cond, i1 %cond1){
+; CHECK-LABEL: define i32 @three_entry_test_different_dest(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]], i1 [[COND:%.*]], i1 [[COND1:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br i1 [[COND]], label [[END1:%.*]], label [[THEN:%.*]]
+; CHECK:       then:
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[X]], [[Y]]
+; CHECK-NEXT:    br i1 [[CMP]], label [[B1:%.*]], label [[B2:%.*]]
+; CHECK:       b1:
+; CHECK-NEXT:    [[SUB:%.*]] = add i32 [[X]], -1
+; CHECK-NEXT:    br label [[END1]]
+; CHECK:       b2:
+; CHECK-NEXT:    [[ADD:%.*]] = add i32 [[X]], 1
+; CHECK-NEXT:    [[CALL:%.*]] = call i32 @dummy()
+; CHECK-NEXT:    br label [[COMMON_RET:%.*]]
+; CHECK:       common.ret:
+; CHECK-NEXT:    [[COMMON_RET_OP:%.*]] = phi i32 [ [[CALL]], [[B2]] ], [ [[RET_0:%.*]], [[END1]] ]
+; CHECK-NEXT:    ret i32 [[COMMON_RET_OP]]
+; CHECK:       end1:
+; CHECK-NEXT:    [[RET_0]] = phi i32 [ [[SUB]], [[B1]] ], [ 0, [[ENTRY:%.*]] ]
+; CHECK-NEXT:    [[CALL1:%.*]] = call i32 @dummy1()
+; CHECK-NEXT:    br label [[COMMON_RET]]
+;
+entry:
+  br i1 %cond, label %if.then, label %then
+
+if.then:
+  br label %end1
+
+then:
+  %cmp = icmp sgt i32 %x, %y
+  br i1 %cmp, label %b1, label %b2
+
+b1:
+  %sub = add i32 %x, -1
+  br label %end1
+
+b2:
+  %add = add i32 %x, 1
+  br label %end
+
+end:
+  %call = call i32 @dummy()
+  ret i32 %call
+
+end1:
+  %ret.0 = phi i32 [ 0, %if.then ], [ %sub, %b1 ]
+  %call1 = call i32 @dummy1()
+  ret i32 %ret.0
+}

>From be735d288e8a52620a4321e99585f7ef0dee72bf Mon Sep 17 00:00:00 2001
From: XChy <xxs_chy at outlook.com>
Date: Tue, 28 Nov 2023 22:37:54 +0800
Subject: [PATCH 2/3] [SimplifyCFG] Refactor logic of FoldTwoEntryPHINode

---
 .../llvm/Transforms/Utils/BasicBlockUtils.h   |  14 ++-
 llvm/lib/Transforms/Utils/BasicBlockUtils.cpp |  43 ++++++-
 llvm/lib/Transforms/Utils/FlattenCFG.cpp      |   4 +-
 llvm/lib/Transforms/Utils/SimplifyCFG.cpp     | 105 ++++++++++++------
 .../Transforms/SimplifyCFG/PhiEliminate2.ll   |  33 +++---
 5 files changed, 143 insertions(+), 56 deletions(-)

diff --git a/llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h b/llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h
index e6dde450b7df9c8..998acbe9ab75da7 100644
--- a/llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h
+++ b/llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h
@@ -595,9 +595,21 @@ void SplitBlockAndInsertForEachLane(
 ///
 /// This does no checking to see if the true/false blocks have large or unsavory
 /// instructions in them.
-BranchInst *GetIfCondition(BasicBlock *BB, BasicBlock *&IfTrue,
+BranchInst *GetIfConditionFromMergePoint(BasicBlock *BB, BasicBlock *&IfTrue,
                            BasicBlock *&IfFalse);
 
+/// Check whether BB is the dominant point of a if-region.
+/// If so, return the merge point of the if-region. Also, return by references
+/// the block that will be entered from if the condition is true, and the block
+/// that will be entered if the condition is false.
+///
+/// This does no checking to see if the true/false blocks have large or unsavory
+/// instructions in them.
+///
+/// NOTE: we assume that the terminator of DomBB is a conditional branch instruction. 
+BasicBlock *GetIfConditionFromDom(BasicBlock *DomBB, BasicBlock *&IfTrue,
+                                  BasicBlock *&IfFalse);
+
 // Split critical edges where the source of the edge is an indirectbr
 // instruction. This isn't always possible, but we can handle some easy cases.
 // This is useful because MI is unable to split such critical edges,
diff --git a/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp b/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp
index 168998fbee114ab..d43a5f72846f72c 100644
--- a/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp
+++ b/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp
@@ -1727,7 +1727,7 @@ void llvm::SplitBlockAndInsertForEachLane(
   }
 }
 
-BranchInst *llvm::GetIfCondition(BasicBlock *BB, BasicBlock *&IfTrue,
+BranchInst *llvm::GetIfConditionFromMergePoint(BasicBlock *BB, BasicBlock *&IfTrue,
                                  BasicBlock *&IfFalse) {
   PHINode *SomePHI = dyn_cast<PHINode>(BB->begin());
   BasicBlock *Pred1 = nullptr;
@@ -1819,6 +1819,47 @@ BranchInst *llvm::GetIfCondition(BasicBlock *BB, BasicBlock *&IfTrue,
   return BI;
 }
 
+BasicBlock *llvm::GetIfConditionFromDom(BasicBlock *DomBB, BasicBlock *&IfTrue,
+                                        BasicBlock *&IfFalse) {
+  BranchInst* BI = cast<BranchInst>(DomBB->getTerminator());
+  BasicBlock *Succ1 = BI->getSuccessor(0);
+  BasicBlock *Succ2 = BI->getSuccessor(1);
+
+  if (!Succ1->getSinglePredecessor() || !Succ2->getSinglePredecessor() ||
+      Succ1 == Succ2 || Succ1 == DomBB || Succ2 == DomBB)
+    return nullptr;
+
+  // We can only handle branches.  Other control flow will be lowered to
+  // branches if possible anyway.
+  BranchInst *Succ1Br = dyn_cast<BranchInst>(Succ1->getTerminator());
+  BranchInst *Succ2Br = dyn_cast<BranchInst>(Succ2->getTerminator());
+  if (!Succ1Br || !Succ2Br)
+    return nullptr;
+
+  if (Succ1->getSingleSuccessor() == Succ2) {
+    IfTrue = Succ1;
+    IfFalse = DomBB;
+    return Succ2;
+  }
+
+  if (Succ2->getSingleSuccessor() == Succ1) {
+    IfTrue = DomBB;
+    IfFalse = Succ2;
+    return Succ1;
+  }
+
+  auto *CommonDest = Succ1->getSingleSuccessor();
+  if (CommonDest && CommonDest != DomBB &&
+      CommonDest == Succ2->getSingleSuccessor()) {
+    IfTrue = Succ1;
+    IfFalse = Succ2;
+    return CommonDest;
+  }
+
+  // There may be other cases, but we just handle the trivial ones now.
+  return nullptr;
+}
+
 // After creating a control flow hub, the operands of PHINodes in an outgoing
 // block Out no longer match the predecessors of that block. Predecessors of Out
 // that are incoming blocks to the hub are now replaced by just one edge from
diff --git a/llvm/lib/Transforms/Utils/FlattenCFG.cpp b/llvm/lib/Transforms/Utils/FlattenCFG.cpp
index 1925b91c4da7ec1..4480202bae8e7db 100644
--- a/llvm/lib/Transforms/Utils/FlattenCFG.cpp
+++ b/llvm/lib/Transforms/Utils/FlattenCFG.cpp
@@ -408,7 +408,7 @@ bool FlattenCFGOpt::CompareIfRegionBlock(BasicBlock *Block1, BasicBlock *Block2,
 /// approach goes for the opposite case.
 bool FlattenCFGOpt::MergeIfRegion(BasicBlock *BB, IRBuilder<> &Builder) {
   BasicBlock *IfTrue2, *IfFalse2;
-  BranchInst *DomBI2 = GetIfCondition(BB, IfTrue2, IfFalse2);
+  BranchInst *DomBI2 = GetIfConditionFromMergePoint(BB, IfTrue2, IfFalse2);
   if (!DomBI2)
     return false;
   Instruction *CInst2 = dyn_cast<Instruction>(DomBI2->getCondition());
@@ -420,7 +420,7 @@ bool FlattenCFGOpt::MergeIfRegion(BasicBlock *BB, IRBuilder<> &Builder) {
     return false;
 
   BasicBlock *IfTrue1, *IfFalse1;
-  BranchInst *DomBI1 = GetIfCondition(SecondEntryBlock, IfTrue1, IfFalse1);
+  BranchInst *DomBI1 = GetIfConditionFromMergePoint(SecondEntryBlock, IfTrue1, IfFalse1);
   if (!DomBI1)
     return false;
   Instruction *CInst1 = dyn_cast<Instruction>(DomBI1->getCondition());
diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index c09cf9c2325c405..a161d32aec761a1 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -3403,35 +3403,37 @@ static bool FoldCondBranchOnValueKnownInPredecessor(BranchInst *BI,
   return EverChanged;
 }
 
-/// Given a BB that starts with the specified two-entry PHI node,
-/// see if we can eliminate it.
-static bool FoldTwoEntryPHINode(PHINode *PN, const TargetTransformInfo &TTI,
-                                DomTreeUpdater *DTU, const DataLayout &DL) {
-  // Ok, this is a two entry PHI node.  Check to see if this is a simple "if
-  // statement", which has a very simple dominance structure.  Basically, we
-  // are trying to find the condition that is being branched on, which
-  // subsequently causes this merge to happen.  We really want control
-  // dependence information for this check, but simplifycfg can't keep it up
-  // to date, and this catches most of the cases we care about anyway.
-  BasicBlock *BB = PN->getParent();
-
-  BasicBlock *IfTrue, *IfFalse;
-  BranchInst *DomBI = GetIfCondition(BB, IfTrue, IfFalse);
-  if (!DomBI)
+// Fold phis in BB based on if-else information.
+static bool FoldPHIOfIfRegion(BasicBlock *BB, BasicBlock *DomBlock,
+                              BasicBlock *IfTrue, BasicBlock *IfFalse,
+                              const TargetTransformInfo &TTI,
+                              DomTreeUpdater *DTU, const DataLayout &DL) {
+  assert(isa<BranchInst>(DomBlock->getTerminator()));
+
+  if (BB->phis().empty())
     return false;
+
+  PHINode *PN = &*BB->phis().begin();
+
+  BranchInst *DomBI = cast<BranchInst>(DomBlock->getTerminator());
   Value *IfCond = DomBI->getCondition();
   // Don't bother if the branch will be constant folded trivially.
   if (isa<ConstantInt>(IfCond))
     return false;
 
-  BasicBlock *DomBlock = DomBI->getParent();
-  SmallVector<BasicBlock *, 2> IfBlocks;
+  // Track BBs that jumps into phi unconditionally, to handle the cases where
+  // one of {IfTrue, IfFalse} is DomBlock. 
+  SmallVector<BasicBlock *, 2> UncondEnterBlocks;
   llvm::copy_if(
-      PN->blocks(), std::back_inserter(IfBlocks), [](BasicBlock *IfBlock) {
+      SmallVector<BasicBlock *, 2>{IfTrue, IfFalse},
+      std::back_inserter(UncondEnterBlocks), [](BasicBlock *IfBlock) {
         return cast<BranchInst>(IfBlock->getTerminator())->isUnconditional();
       });
-  assert((IfBlocks.size() == 1 || IfBlocks.size() == 2) &&
-         "Will have either one or two blocks to speculate.");
+
+  // NOTE: Keep the order of BBs the same as the order in phi.
+  llvm::sort(UncondEnterBlocks, [PN](BasicBlock *B1, BasicBlock *B2) {
+    return PN->getBasicBlockIndex(B1) < PN->getBasicBlockIndex(B2);
+  });
 
   // If the branch is non-unpredictable, see if we either predictably jump to
   // the merge bb (if we have only a single 'then' block), or if we predictably
@@ -3446,7 +3448,7 @@ static bool FoldTwoEntryPHINode(PHINode *PN, const TargetTransformInfo &TTI,
           BranchProbability::getBranchProbability(TWeight, TWeight + FWeight);
       BranchProbability Likely = TTI.getPredictableBranchThreshold();
       BranchProbability BIFalseProb = BITrueProb.getCompl();
-      if (IfBlocks.size() == 1) {
+      if (UncondEnterBlocks.size() == 1) {
         BranchProbability BIBBProb =
             DomBI->getSuccessor(0) == BB ? BITrueProb : BIFalseProb;
         if (BIBBProb >= Likely)
@@ -3492,10 +3494,10 @@ static bool FoldTwoEntryPHINode(PHINode *PN, const TargetTransformInfo &TTI,
       continue;
     }
 
-    if (!dominatesMergePoint(PN->getIncomingValue(0), BB, AggressiveInsts,
-                             Cost, Budget, TTI) ||
-        !dominatesMergePoint(PN->getIncomingValue(1), BB, AggressiveInsts,
-                             Cost, Budget, TTI))
+    if (!dominatesMergePoint(PN->getIncomingValueForBlock(IfTrue), BB,
+                             AggressiveInsts, Cost, Budget, TTI) ||
+        !dominatesMergePoint(PN->getIncomingValueForBlock(IfFalse), BB,
+                             AggressiveInsts, Cost, Budget, TTI))
       return Changed;
   }
 
@@ -3525,18 +3527,21 @@ static bool FoldTwoEntryPHINode(PHINode *PN, const TargetTransformInfo &TTI,
                m_CombineOr(m_Select(m_Value(), m_ImmConstant(), m_Value()),
                            m_Select(m_Value(), m_Value(), m_ImmConstant()))));
   };
+
+  Value *TrueVal = PN->getIncomingValueForBlock(IfTrue);
+  Value *FalseVal = PN->getIncomingValueForBlock(IfFalse);
+
   if (PN->getType()->isIntegerTy(1) &&
-      (IsBinOpOrAnd(PN->getIncomingValue(0)) ||
-       IsBinOpOrAnd(PN->getIncomingValue(1)) || IsBinOpOrAnd(IfCond)) &&
-      !CanHoistNotFromBothValues(PN->getIncomingValue(0),
-                                 PN->getIncomingValue(1)))
+      (IsBinOpOrAnd(TrueVal) || IsBinOpOrAnd(FalseVal) ||
+       IsBinOpOrAnd(IfCond)) &&
+      !CanHoistNotFromBothValues(TrueVal, FalseVal))
     return Changed;
 
   // If all PHI nodes are promotable, check to make sure that all instructions
   // in the predecessor blocks can be promoted as well. If not, we won't be able
   // to get rid of the control flow, so it's not worth promoting to select
   // instructions.
-  for (BasicBlock *IfBlock : IfBlocks)
+  for (BasicBlock *IfBlock : UncondEnterBlocks)
     for (BasicBlock::iterator I = IfBlock->begin(); !I->isTerminator(); ++I)
       if (!AggressiveInsts.count(&*I) && !I->isDebugOrPseudoInst()) {
         // This is not an aggressive instruction that we can promote.
@@ -3546,7 +3551,7 @@ static bool FoldTwoEntryPHINode(PHINode *PN, const TargetTransformInfo &TTI,
       }
 
   // If either of the blocks has it's address taken, we can't do this fold.
-  if (any_of(IfBlocks,
+  if (any_of(UncondEnterBlocks,
              [](BasicBlock *IfBlock) { return IfBlock->hasAddressTaken(); }))
     return Changed;
 
@@ -3559,8 +3564,8 @@ static bool FoldTwoEntryPHINode(PHINode *PN, const TargetTransformInfo &TTI,
 
   // Move all 'aggressive' instructions, which are defined in the
   // conditional parts of the if's up to the dominating block.
-  for (BasicBlock *IfBlock : IfBlocks)
-      hoistAllInstructionsInto(DomBlock, DomBI, IfBlock);
+  for (BasicBlock *IfBlock : UncondEnterBlocks)
+    hoistAllInstructionsInto(DomBlock, DomBI, IfBlock);
 
   IRBuilder<NoFolder> Builder(DomBI);
   // Propagate fast-math-flags from phi nodes to replacement selects.
@@ -3574,12 +3579,18 @@ static bool FoldTwoEntryPHINode(PHINode *PN, const TargetTransformInfo &TTI,
     Value *FalseVal = PN->getIncomingValueForBlock(IfFalse);
 
     Value *Sel = Builder.CreateSelect(IfCond, TrueVal, FalseVal, "", DomBI);
-    PN->replaceAllUsesWith(Sel);
-    Sel->takeName(PN);
-    PN->eraseFromParent();
+    if (PN->getNumIncomingValues() == 2) {
+      PN->replaceAllUsesWith(Sel);
+      Sel->takeName(PN);
+      PN->eraseFromParent();
+    } else {
+      PN->removeIncomingValue(IfTrue);
+      PN->removeIncomingValue(IfFalse);
+      PN->addIncoming(Sel, DomBlock);
+    }
   }
 
-  // At this point, all IfBlocks are empty, so our if statement
+  // At this point, all UncondEnterBlocks are empty, so our if statement
   // has been flattened.  Change DomBlock to jump directly to our new block to
   // avoid other simplifycfg's kicking in on the diamond.
   Builder.CreateBr(BB);
@@ -3598,6 +3609,25 @@ static bool FoldTwoEntryPHINode(PHINode *PN, const TargetTransformInfo &TTI,
   return true;
 }
 
+/// Given a BB that starts with the specified two-entry PHI node,
+/// see if we can eliminate it.
+static bool FoldTwoEntryPHINode(PHINode *PN, const TargetTransformInfo &TTI,
+                                DomTreeUpdater *DTU, const DataLayout &DL) {
+  // Ok, this is a two entry PHI node.  Check to see if this is a simple "if
+  // statement", which has a very simple dominance structure.  Basically, we
+  // are trying to find the condition that is being branched on, which
+  // subsequently causes this merge to happen.  We really want control
+  // dependence information for this check, but simplifycfg can't keep it up
+  // to date, and this catches most of the cases we care about anyway.
+  BasicBlock *BB = PN->getParent();
+  BasicBlock *IfTrue, *IfFalse;
+  BranchInst *DomBI = GetIfConditionFromMergePoint(BB, IfTrue, IfFalse);
+  if (!DomBI)
+    return false;
+  BasicBlock *DomBlock = DomBI->getParent();
+  return FoldPHIOfIfRegion(BB, DomBlock, IfTrue, IfFalse, TTI, DTU, DL);
+}
+
 static Value *createLogicalOp(IRBuilderBase &Builder,
                               Instruction::BinaryOps Opc, Value *LHS,
                               Value *RHS, const Twine &Name = "") {
@@ -7315,6 +7345,7 @@ bool SimplifyCFGOpt::simplifyCondBranch(BranchInst *BI, IRBuilder<> &Builder) {
       if (HoistCommon && hoistCommonCodeFromSuccessors(
                              BI->getParent(), !Options.HoistCommonInsts))
         return requestResimplify();
+
     } else {
       // If Successor #1 has multiple preds, we may be able to conditionally
       // execute Successor #0 if it branches to Successor #1.
diff --git a/llvm/test/Transforms/SimplifyCFG/PhiEliminate2.ll b/llvm/test/Transforms/SimplifyCFG/PhiEliminate2.ll
index 3b7cbcf1534ae42..ea2f2f1491c5289 100644
--- a/llvm/test/Transforms/SimplifyCFG/PhiEliminate2.ll
+++ b/llvm/test/Transforms/SimplifyCFG/PhiEliminate2.ll
@@ -1,29 +1,32 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 3
 ; RUN: opt < %s -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S | FileCheck %s
 
 ; Use a select to make this a single BB.
 ; Also, make sure the profile metadata is propagated to the select (PR26636).
 
 define i32 @FoldTwoEntryPHINode(i1 %C, i32 %V1, i32 %V2, i16 %V3) {
+; CHECK-LABEL: define i32 @FoldTwoEntryPHINode(
+; CHECK-SAME: i1 [[C:%.*]], i32 [[V1:%.*]], i32 [[V2:%.*]], i16 [[V3:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[V5:%.*]] = sext i16 [[V3]] to i32
+; CHECK-NEXT:    [[V4:%.*]] = or i32 [[V2]], [[V1]]
+; CHECK-NEXT:    [[V6:%.*]] = select i1 [[C]], i32 [[V4]], i32 [[V5]], !prof [[PROF0:![0-9]+]], !unpredictable !1
+; CHECK-NEXT:    [[TMP0:%.*]] = call i32 @FoldTwoEntryPHINode(i1 false, i32 0, i32 0, i16 0)
+; CHECK-NEXT:    ret i32 [[V1]]
+;
 entry:
-        br i1 %C, label %then, label %else, !prof !0, !unpredictable !1
+  br i1 %C, label %then, label %else, !prof !0, !unpredictable !1
 then:
-        %V4 = or i32 %V2, %V1
-        br label %Cont
+  %V4 = or i32 %V2, %V1
+  br label %Cont
 else:
-        %V5 = sext i16 %V3 to i32
-        br label %Cont
+  %V5 = sext i16 %V3 to i32
+  br label %Cont
 Cont:
-        %V6 = phi i32 [ %V5, %else ], [ %V4, %then ]
-        call i32 @FoldTwoEntryPHINode( i1 false, i32 0, i32 0, i16 0 )
-        ret i32 %V1
+  %V6 = phi i32 [ %V5, %else ], [ %V4, %then ]
+  call i32 @FoldTwoEntryPHINode( i1 false, i32 0, i32 0, i16 0 )
+  ret i32 %V1
 
-; CHECK-LABEL: @FoldTwoEntryPHINode(
-; CHECK-NEXT:  entry:
-; CHECK-NEXT:  %V5 = sext i16 %V3 to i32
-; CHECK-NEXT:  %V4 = or i32 %V2, %V1
-; CHECK-NEXT:  %V6 = select i1 %C, i32 %V4, i32 %V5, !prof !0, !unpredictable !1
-; CHECK-NEXT:  %0 = call i32 @FoldTwoEntryPHINode(i1 false, i32 0, i32 0, i16 0)
-; CHECK-NEXT:  ret i32 %V1
 }
 
 !0 = !{!"branch_weights", i32 3, i32 5}

>From e8f00600aa476ca9f498a875964bfd20c35396d5 Mon Sep 17 00:00:00 2001
From: XChy <xxs_chy at outlook.com>
Date: Wed, 29 Nov 2023 01:31:30 +0800
Subject: [PATCH 3/3] [SimplifyCFG] Fold pairs of entries in multiple-entry phi

---
 llvm/lib/Transforms/Utils/SimplifyCFG.cpp     |  31 ++--
 .../SimplifyCFG/UnreachableEliminate.ll       |  10 +-
 .../SimplifyCFG/X86/sink-common-code.ll       |  25 ++--
 .../SimplifyCFG/X86/switch_to_lookup_table.ll | 139 ++++++++----------
 .../SimplifyCFG/fold-multiple-entry-phi.ll    |  32 ++--
 .../test/Transforms/SimplifyCFG/no-md-sink.ll |   7 +-
 .../test/Transforms/SimplifyCFG/opaque-ptr.ll |   6 +-
 7 files changed, 118 insertions(+), 132 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index a161d32aec761a1..cc6badab9d19712 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -3422,7 +3422,7 @@ static bool FoldPHIOfIfRegion(BasicBlock *BB, BasicBlock *DomBlock,
     return false;
 
   // Track BBs that jumps into phi unconditionally, to handle the cases where
-  // one of {IfTrue, IfFalse} is DomBlock. 
+  // one of {IfTrue, IfFalse} is DomBlock.
   SmallVector<BasicBlock *, 2> UncondEnterBlocks;
   llvm::copy_if(
       SmallVector<BasicBlock *, 2>{IfTrue, IfFalse},
@@ -3570,23 +3570,21 @@ static bool FoldPHIOfIfRegion(BasicBlock *BB, BasicBlock *DomBlock,
   IRBuilder<NoFolder> Builder(DomBI);
   // Propagate fast-math-flags from phi nodes to replacement selects.
   IRBuilder<>::FastMathFlagGuard FMFGuard(Builder);
-  while (PHINode *PN = dyn_cast<PHINode>(BB->begin())) {
+  for (PHINode &PN : make_early_inc_range(BB->phis())) {
     if (isa<FPMathOperator>(PN))
-      Builder.setFastMathFlags(PN->getFastMathFlags());
+      Builder.setFastMathFlags(PN.getFastMathFlags());
 
     // Change the PHI node into a select instruction.
-    Value *TrueVal = PN->getIncomingValueForBlock(IfTrue);
-    Value *FalseVal = PN->getIncomingValueForBlock(IfFalse);
+    Value *TrueVal = PN.getIncomingValueForBlock(IfTrue);
+    Value *FalseVal = PN.getIncomingValueForBlock(IfFalse);
 
     Value *Sel = Builder.CreateSelect(IfCond, TrueVal, FalseVal, "", DomBI);
-    if (PN->getNumIncomingValues() == 2) {
-      PN->replaceAllUsesWith(Sel);
-      Sel->takeName(PN);
-      PN->eraseFromParent();
+    if (PN.getNumIncomingValues() == 2) {
+      PN.replaceAllUsesWith(Sel);
+      Sel->takeName(&PN);
+      PN.eraseFromParent();
     } else {
-      PN->removeIncomingValue(IfTrue);
-      PN->removeIncomingValue(IfFalse);
-      PN->addIncoming(Sel, DomBlock);
+      PN.addIncoming(Sel, DomBlock);
     }
   }
 
@@ -7386,6 +7384,15 @@ bool SimplifyCFGOpt::simplifyCondBranch(BranchInst *BI, IRBuilder<> &Builder) {
           if (mergeConditionalStores(PBI, BI, DTU, DL, TTI))
             return requestResimplify();
 
+  // Fold the merge-point phi of if-region.
+  BasicBlock *IfTrue;
+  BasicBlock *IfFalse;
+  if (Options.SpeculateBlocks &&
+      !BB->getParent()->hasFnAttribute(Attribute::OptForFuzzing))
+    if (BasicBlock *CommonDest = GetIfConditionFromDom(BB, IfTrue, IfFalse))
+      if (FoldPHIOfIfRegion(CommonDest, BB, IfTrue, IfFalse, TTI, DTU, DL))
+        return requestResimplify();
+
   return false;
 }
 
diff --git a/llvm/test/Transforms/SimplifyCFG/UnreachableEliminate.ll b/llvm/test/Transforms/SimplifyCFG/UnreachableEliminate.ll
index 5ba43c055f9be12..2710f8426eeab96 100644
--- a/llvm/test/Transforms/SimplifyCFG/UnreachableEliminate.ll
+++ b/llvm/test/Transforms/SimplifyCFG/UnreachableEliminate.ll
@@ -64,9 +64,8 @@ T:
 define void @test5(i1 %cond, ptr %ptr) {
 ; CHECK-LABEL: @test5(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[TMP0:%.*]] = xor i1 [[COND:%.*]], true
-; CHECK-NEXT:    call void @llvm.assume(i1 [[TMP0]])
-; CHECK-NEXT:    store i8 2, ptr [[PTR:%.*]], align 8
+; CHECK-NEXT:    [[PTR_2:%.*]] = select i1 [[COND:%.*]], ptr null, ptr [[PTR:%.*]]
+; CHECK-NEXT:    store i8 2, ptr [[PTR_2]], align 8
 ; CHECK-NEXT:    ret void
 ;
 entry:
@@ -93,11 +92,10 @@ declare i1 @llvm.type.test(ptr, metadata) nounwind readnone
 define void @test5_type_test_assume(i1 %cond, ptr %ptr, ptr %vtable) {
 ; CHECK-LABEL: @test5_type_test_assume(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[TMP0:%.*]] = xor i1 [[COND:%.*]], true
-; CHECK-NEXT:    call void @llvm.assume(i1 [[TMP0]])
+; CHECK-NEXT:    [[PTR_2:%.*]] = select i1 [[COND:%.*]], ptr null, ptr [[PTR:%.*]]
 ; CHECK-NEXT:    [[P:%.*]] = call i1 @llvm.type.test(ptr [[VTABLE:%.*]], metadata !"foo")
 ; CHECK-NEXT:    tail call void @llvm.assume(i1 [[P]])
-; CHECK-NEXT:    store i8 2, ptr [[PTR:%.*]], align 8
+; CHECK-NEXT:    store i8 2, ptr [[PTR_2]], align 8
 ; CHECK-NEXT:    ret void
 ;
 entry:
diff --git a/llvm/test/Transforms/SimplifyCFG/X86/sink-common-code.ll b/llvm/test/Transforms/SimplifyCFG/X86/sink-common-code.ll
index 26107965a1a8b6d..b54b55725fd8425 100644
--- a/llvm/test/Transforms/SimplifyCFG/X86/sink-common-code.ll
+++ b/llvm/test/Transforms/SimplifyCFG/X86/sink-common-code.ll
@@ -693,8 +693,8 @@ define zeroext i1 @test17(i32 %flag, i32 %blksA, i32 %blksB, i32 %nblks) {
 ; CHECK-LABEL: @test17(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    switch i32 [[FLAG:%.*]], label [[IF_END:%.*]] [
-; CHECK-NEXT:    i32 0, label [[IF_THEN:%.*]]
-; CHECK-NEXT:    i32 1, label [[IF_THEN2:%.*]]
+; CHECK-NEXT:      i32 0, label [[IF_THEN:%.*]]
+; CHECK-NEXT:      i32 1, label [[IF_THEN2:%.*]]
 ; CHECK-NEXT:    ]
 ; CHECK:       if.then:
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp uge i32 [[BLKSA:%.*]], [[NBLKS:%.*]]
@@ -744,8 +744,8 @@ define zeroext i1 @test18(i32 %flag, i32 %blksA, i32 %blksB, i32 %nblks) {
 ; CHECK-LABEL: @test18(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    switch i32 [[FLAG:%.*]], label [[IF_THEN3:%.*]] [
-; CHECK-NEXT:    i32 0, label [[IF_THEN:%.*]]
-; CHECK-NEXT:    i32 1, label [[IF_THEN2:%.*]]
+; CHECK-NEXT:      i32 0, label [[IF_THEN:%.*]]
+; CHECK-NEXT:      i32 1, label [[IF_THEN2:%.*]]
 ; CHECK-NEXT:    ]
 ; CHECK:       if.then:
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp uge i32 [[BLKSA:%.*]], [[NBLKS:%.*]]
@@ -1257,8 +1257,9 @@ merge:
 define i32 @test_insertvalue(i1 zeroext %flag, %TP %P) {
 ; CHECK-LABEL: @test_insertvalue(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[DOT:%.*]] = select i1 [[FLAG:%.*]], i32 0, i32 1
-; CHECK-NEXT:    [[I2:%.*]] = insertvalue [[TP:%.*]] [[P:%.*]], i32 [[DOT]], 0
+; CHECK-NEXT:    [[I1:%.*]] = insertvalue [[TP:%.*]] [[P:%.*]], i32 0, 0
+; CHECK-NEXT:    [[I2:%.*]] = insertvalue [[TP]] [[P]], i32 1, 0
+; CHECK-NEXT:    [[I:%.*]] = select i1 [[FLAG:%.*]], [[TP]] [[I1]], [[TP]] [[I2]]
 ; CHECK-NEXT:    ret i32 1
 ;
 entry:
@@ -1285,11 +1286,11 @@ define void @test_sink_void_calls(i32 %x) {
 ; CHECK-LABEL: @test_sink_void_calls(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    switch i32 [[X:%.*]], label [[DEFAULT:%.*]] [
-; CHECK-NEXT:    i32 0, label [[RETURN:%.*]]
-; CHECK-NEXT:    i32 1, label [[BB1:%.*]]
-; CHECK-NEXT:    i32 2, label [[BB2:%.*]]
-; CHECK-NEXT:    i32 3, label [[BB3:%.*]]
-; CHECK-NEXT:    i32 4, label [[BB4:%.*]]
+; CHECK-NEXT:      i32 0, label [[RETURN:%.*]]
+; CHECK-NEXT:      i32 1, label [[BB1:%.*]]
+; CHECK-NEXT:      i32 2, label [[BB2:%.*]]
+; CHECK-NEXT:      i32 3, label [[BB3:%.*]]
+; CHECK-NEXT:      i32 4, label [[BB4:%.*]]
 ; CHECK-NEXT:    ]
 ; CHECK:       bb1:
 ; CHECK-NEXT:    br label [[RETURN]]
@@ -1563,7 +1564,7 @@ end:
 define void @nontemporal(ptr %ptr, i1 %cond) {
 ; CHECK-LABEL: @nontemporal(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    store i64 0, ptr [[PTR:%.*]], align 8, !nontemporal !7
+; CHECK-NEXT:    store i64 0, ptr [[PTR:%.*]], align 8, !nontemporal [[META7:![0-9]+]]
 ; CHECK-NEXT:    ret void
 ;
 entry:
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 3873f0c0ae0bbd5..40a00eae79687a5 100644
--- a/llvm/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll
+++ b/llvm/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll
@@ -5,28 +5,20 @@ target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f3
 target triple = "x86_64-unknown-linux-gnu"
 
 ; The table for @f
-; CHECK: @switch.table.f = private unnamed_addr constant [7 x i32] [i32 55, i32 123, i32 0, i32 -1, i32 27, i32 62, i32 1], align 4
 
 ; The char table for char
-; CHECK: @switch.table.char = private unnamed_addr constant [9 x i8] c"7{\00\FF\1B>\01!T", align 1
 
 ; The float table for @h
-; CHECK: @switch.table.h = private unnamed_addr constant [4 x float] [float 0x40091EB860000000, float 0x3FF3BE76C0000000, float 0x4012449BA0000000, float 0x4001AE1480000000], align 4
 
 ; The table for @foostring
-; CHECK: @switch.table.foostring = private unnamed_addr constant [4 x ptr] [ptr @.str, ptr @.str1, ptr @.str2, ptr @.str3], align 8
 
 ; The table for @earlyreturncrash
-; CHECK: @switch.table.earlyreturncrash = private unnamed_addr constant [4 x i32] [i32 42, i32 9, i32 88, i32 5], align 4
 
 ; The table for @large
-; CHECK: @switch.table.large = private unnamed_addr constant [199 x i32] [i32 1, i32 4, i32 9,
 
 ; The table for @cprop
-; CHECK: @switch.table.cprop = private unnamed_addr constant [7 x i32] [i32 5, i32 42, i32 126, i32 -452, i32 128, i32 6, i32 7], align 4
 
 ; The table for @unreachable_case
-; CHECK: @switch.table.unreachable_case = private unnamed_addr constant [9 x i32] [i32 0, i32 0, i32 0, i32 2, i32 -1, i32 1, i32 1, i32 1, i32 1], align 4
 
 ; A simple int-to-int selection switch.
 ; It is dense enough to be replaced by table lookup.
@@ -254,16 +246,15 @@ define i32 @crud(i8 zeroext %c)  {
 ; CHECK:       switch.early.test:
 ; CHECK-NEXT:    [[SWITCH_TABLEIDX:%.*]] = sub i8 [[C]], 34
 ; CHECK-NEXT:    [[TMP0:%.*]] = icmp ult i8 [[SWITCH_TABLEIDX]], 59
-; CHECK-NEXT:    br i1 [[TMP0]], label [[SWITCH_LOOKUP:%.*]], label [[LOR_END]]
-; CHECK:       switch.lookup:
 ; CHECK-NEXT:    [[SWITCH_CAST:%.*]] = zext i8 [[SWITCH_TABLEIDX]] to i59
 ; CHECK-NEXT:    [[SWITCH_SHIFTAMT:%.*]] = mul nuw nsw i59 [[SWITCH_CAST]], 1
 ; CHECK-NEXT:    [[SWITCH_DOWNSHIFT:%.*]] = lshr i59 -288230375765830623, [[SWITCH_SHIFTAMT]]
 ; CHECK-NEXT:    [[SWITCH_MASKED:%.*]] = trunc i59 [[SWITCH_DOWNSHIFT]] to i1
+; CHECK-NEXT:    [[TMP1:%.*]] = select i1 [[TMP0]], i1 [[SWITCH_MASKED]], i1 false
 ; CHECK-NEXT:    br label [[LOR_END]]
 ; CHECK:       lor.end:
-; CHECK-NEXT:    [[TMP1:%.*]] = phi i1 [ true, [[ENTRY:%.*]] ], [ [[SWITCH_MASKED]], [[SWITCH_LOOKUP]] ], [ false, [[SWITCH_EARLY_TEST]] ]
-; CHECK-NEXT:    [[LOR_EXT:%.*]] = zext i1 [[TMP1]] to i32
+; CHECK-NEXT:    [[TMP2:%.*]] = phi i1 [ true, [[ENTRY:%.*]] ], [ [[TMP1]], [[SWITCH_EARLY_TEST]] ]
+; CHECK-NEXT:    [[LOR_EXT:%.*]] = zext i1 [[TMP2]] to i32
 ; CHECK-NEXT:    ret i32 [[LOR_EXT]]
 ;
 entry:
@@ -308,10 +299,10 @@ define i32 @overflow(i32 %type) {
 ; CHECK-LABEL: @overflow(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    switch i32 [[TYPE:%.*]], label [[IF_END:%.*]] [
-; CHECK-NEXT:    i32 3, label [[SW_BB3:%.*]]
-; CHECK-NEXT:    i32 -2147483645, label [[SW_BB3]]
-; CHECK-NEXT:    i32 1, label [[SW_BB1:%.*]]
-; CHECK-NEXT:    i32 2, label [[SW_BB2:%.*]]
+; CHECK-NEXT:      i32 3, label [[SW_BB3:%.*]]
+; CHECK-NEXT:      i32 -2147483645, label [[SW_BB3]]
+; CHECK-NEXT:      i32 1, label [[SW_BB1:%.*]]
+; CHECK-NEXT:      i32 2, label [[SW_BB2:%.*]]
 ; CHECK-NEXT:    ]
 ; CHECK:       sw.bb1:
 ; CHECK-NEXT:    br label [[IF_END]]
@@ -931,11 +922,11 @@ define i96 @illegaltype(i32 %c) {
 ; CHECK-LABEL: @illegaltype(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    switch i32 [[C:%.*]], label [[SW_DEFAULT:%.*]] [
-; CHECK-NEXT:    i32 42, label [[RETURN:%.*]]
-; CHECK-NEXT:    i32 43, label [[SW_BB1:%.*]]
-; CHECK-NEXT:    i32 44, label [[SW_BB2:%.*]]
-; CHECK-NEXT:    i32 45, label [[SW_BB3:%.*]]
-; CHECK-NEXT:    i32 46, label [[SW_BB4:%.*]]
+; CHECK-NEXT:      i32 42, label [[RETURN:%.*]]
+; CHECK-NEXT:      i32 43, label [[SW_BB1:%.*]]
+; CHECK-NEXT:      i32 44, label [[SW_BB2:%.*]]
+; CHECK-NEXT:      i32 45, label [[SW_BB3:%.*]]
+; CHECK-NEXT:      i32 46, label [[SW_BB4:%.*]]
 ; CHECK-NEXT:    ]
 ; CHECK:       sw.bb1:
 ; CHECK-NEXT:    br label [[RETURN]]
@@ -1050,9 +1041,9 @@ define i32 @threecasesholes(i32 %c) {
 ; CHECK-LABEL: @threecasesholes(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    switch i32 [[C:%.*]], label [[SW_DEFAULT:%.*]] [
-; CHECK-NEXT:    i32 0, label [[RETURN:%.*]]
-; CHECK-NEXT:    i32 1, label [[SW_BB1:%.*]]
-; CHECK-NEXT:    i32 3, label [[SW_BB2:%.*]]
+; CHECK-NEXT:      i32 0, label [[RETURN:%.*]]
+; CHECK-NEXT:      i32 1, label [[SW_BB1:%.*]]
+; CHECK-NEXT:      i32 3, label [[SW_BB2:%.*]]
 ; CHECK-NEXT:    ]
 ; CHECK:       sw.bb1:
 ; CHECK-NEXT:    br label [[RETURN]]
@@ -1142,9 +1133,9 @@ define ptr @tls(i32 %x) {
 ; CHECK-LABEL: @tls(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    switch i32 [[X:%.*]], label [[SW_DEFAULT:%.*]] [
-; CHECK-NEXT:    i32 0, label [[RETURN:%.*]]
-; CHECK-NEXT:    i32 1, label [[SW_BB1:%.*]]
-; CHECK-NEXT:    i32 2, label [[SW_BB2:%.*]]
+; CHECK-NEXT:      i32 0, label [[RETURN:%.*]]
+; CHECK-NEXT:      i32 1, label [[SW_BB1:%.*]]
+; CHECK-NEXT:      i32 2, label [[SW_BB2:%.*]]
 ; CHECK-NEXT:    ]
 ; CHECK:       sw.bb1:
 ; CHECK-NEXT:    br label [[RETURN]]
@@ -1182,9 +1173,9 @@ define ptr @dllimport(i32 %x) {
 ; CHECK-LABEL: @dllimport(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    switch i32 [[X:%.*]], label [[SW_DEFAULT:%.*]] [
-; CHECK-NEXT:    i32 0, label [[RETURN:%.*]]
-; CHECK-NEXT:    i32 1, label [[SW_BB1:%.*]]
-; CHECK-NEXT:    i32 2, label [[SW_BB2:%.*]]
+; CHECK-NEXT:      i32 0, label [[RETURN:%.*]]
+; CHECK-NEXT:      i32 1, label [[SW_BB1:%.*]]
+; CHECK-NEXT:      i32 2, label [[SW_BB2:%.*]]
 ; CHECK-NEXT:    ]
 ; CHECK:       sw.bb1:
 ; CHECK-NEXT:    br label [[RETURN]]
@@ -1225,8 +1216,8 @@ define i8 @linearmap1(i32 %c) {
 ; CHECK-NEXT:    [[SWITCH_IDX_CAST:%.*]] = trunc i32 [[SWITCH_TABLEIDX]] to i8
 ; CHECK-NEXT:    [[SWITCH_IDX_MULT:%.*]] = mul nsw i8 [[SWITCH_IDX_CAST]], -5
 ; CHECK-NEXT:    [[SWITCH_OFFSET:%.*]] = add nsw i8 [[SWITCH_IDX_MULT]], 18
-; CHECK-NEXT:    [[X:%.*]] = select i1 [[TMP0]], i8 [[SWITCH_OFFSET]], i8 3
-; CHECK-NEXT:    ret i8 [[X]]
+; CHECK-NEXT:    [[TMP1:%.*]] = select i1 [[TMP0]], i8 [[SWITCH_OFFSET]], i8 3
+; CHECK-NEXT:    ret i8 [[TMP1]]
 ;
 entry:
   switch i32 %c, label %sw.default [
@@ -1252,8 +1243,8 @@ define i32 @linearmap2(i8 %c) {
 ; CHECK-NEXT:    [[TMP0:%.*]] = icmp ult i8 [[SWITCH_TABLEIDX]], 4
 ; CHECK-NEXT:    [[SWITCH_IDX_CAST:%.*]] = zext i8 [[SWITCH_TABLEIDX]] to i32
 ; CHECK-NEXT:    [[SWITCH_OFFSET:%.*]] = add nsw i32 [[SWITCH_IDX_CAST]], 18
-; CHECK-NEXT:    [[X:%.*]] = select i1 [[TMP0]], i32 [[SWITCH_OFFSET]], i32 3
-; CHECK-NEXT:    ret i32 [[X]]
+; CHECK-NEXT:    [[TMP1:%.*]] = select i1 [[TMP0]], i32 [[SWITCH_OFFSET]], i32 3
+; CHECK-NEXT:    ret i32 [[TMP1]]
 ;
 entry:
   switch i8 %c, label %sw.default [
@@ -1279,8 +1270,8 @@ define i8 @linearmap3(i32 %c) {
 ; CHECK-NEXT:    [[TMP0:%.*]] = icmp ult i32 [[SWITCH_TABLEIDX]], 4
 ; CHECK-NEXT:    [[SWITCH_IDX_CAST:%.*]] = trunc i32 [[SWITCH_TABLEIDX]] to i8
 ; CHECK-NEXT:    [[SWITCH_IDX_MULT:%.*]] = mul i8 [[SWITCH_IDX_CAST]], 100
-; CHECK-NEXT:    [[X:%.*]] = select i1 [[TMP0]], i8 [[SWITCH_IDX_MULT]], i8 3
-; CHECK-NEXT:    ret i8 [[X]]
+; CHECK-NEXT:    [[TMP1:%.*]] = select i1 [[TMP0]], i8 [[SWITCH_IDX_MULT]], i8 3
+; CHECK-NEXT:    ret i8 [[TMP1]]
 ;
 entry:
   switch i32 %c, label %sw.default [
@@ -1305,8 +1296,8 @@ define i8 @linearmap4(i32 %c) {
 ; CHECK-NEXT:    [[SWITCH_TABLEIDX:%.*]] = sub i32 [[C:%.*]], -2
 ; CHECK-NEXT:    [[TMP0:%.*]] = icmp ult i32 [[SWITCH_TABLEIDX]], 4
 ; CHECK-NEXT:    [[SWITCH_IDX_CAST:%.*]] = trunc i32 [[SWITCH_TABLEIDX]] to i8
-; CHECK-NEXT:    [[X:%.*]] = select i1 [[TMP0]], i8 [[SWITCH_IDX_CAST]], i8 3
-; CHECK-NEXT:    ret i8 [[X]]
+; CHECK-NEXT:    [[TMP1:%.*]] = select i1 [[TMP0]], i8 [[SWITCH_IDX_CAST]], i8 3
+; CHECK-NEXT:    ret i8 [[TMP1]]
 ;
 entry:
   switch i32 %c, label %sw.default [
@@ -1331,9 +1322,9 @@ define i32 @reuse_cmp1(i32 %x) {
 ; CHECK-NEXT:    [[TMP0:%.*]] = icmp ult i32 [[X:%.*]], 4
 ; CHECK-NEXT:    [[INVERTED_CMP:%.*]] = xor i1 [[TMP0]], true
 ; CHECK-NEXT:    [[SWITCH_OFFSET:%.*]] = add nsw i32 [[X]], 10
-; CHECK-NEXT:    [[R_0:%.*]] = select i1 [[TMP0]], i32 [[SWITCH_OFFSET]], i32 0
-; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[R_0]], 0
-; CHECK-NEXT:    [[RETVAL_0:%.*]] = select i1 [[INVERTED_CMP]], i32 100, i32 [[R_0]]
+; CHECK-NEXT:    [[TMP1:%.*]] = select i1 [[TMP0]], i32 [[SWITCH_OFFSET]], i32 0
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP1]], 0
+; CHECK-NEXT:    [[RETVAL_0:%.*]] = select i1 [[INVERTED_CMP]], i32 100, i32 [[TMP1]]
 ; CHECK-NEXT:    ret i32 [[RETVAL_0]]
 ;
 entry:
@@ -1399,9 +1390,9 @@ define i32 @no_reuse_cmp(i32 %x) {
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[TMP0:%.*]] = icmp ult i32 [[X:%.*]], 4
 ; CHECK-NEXT:    [[SWITCH_OFFSET:%.*]] = add nsw i32 [[X]], 10
-; CHECK-NEXT:    [[R_0:%.*]] = select i1 [[TMP0]], i32 [[SWITCH_OFFSET]], i32 12
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i32 [[R_0]], 0
-; CHECK-NEXT:    [[RETVAL_0:%.*]] = select i1 [[CMP]], i32 [[R_0]], i32 100
+; CHECK-NEXT:    [[TMP1:%.*]] = select i1 [[TMP0]], i32 [[SWITCH_OFFSET]], i32 12
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i32 [[TMP1]], 0
+; CHECK-NEXT:    [[RETVAL_0:%.*]] = select i1 [[CMP]], i32 [[TMP1]], i32 100
 ; CHECK-NEXT:    ret i32 [[RETVAL_0]]
 ;
 entry:
@@ -1435,11 +1426,11 @@ define i32 @no_reuse_cmp2(i32 %x, i32 %y) {
 ; CHECK-NEXT:    [[EC:%.*]] = icmp ne i32 [[Y:%.*]], 0
 ; CHECK-NEXT:    [[TMP0:%.*]] = icmp ult i32 [[X:%.*]], 4
 ; CHECK-NEXT:    [[SWITCH_OFFSET:%.*]] = add nsw i32 [[X]], 10
-; CHECK-NEXT:    [[SPEC_SELECT:%.*]] = select i1 [[TMP0]], i32 [[SWITCH_OFFSET]], i32 0
-; CHECK-NEXT:    [[R_0:%.*]] = select i1 [[EC]], i32 [[SPEC_SELECT]], i32 100
+; CHECK-NEXT:    [[TMP1:%.*]] = select i1 [[TMP0]], i32 [[SWITCH_OFFSET]], i32 0
+; CHECK-NEXT:    [[R_0:%.*]] = select i1 [[EC]], i32 [[TMP1]], i32 100
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[R_0]], 0
-; CHECK-NEXT:    [[DOTR_0:%.*]] = select i1 [[CMP]], i32 100, i32 [[R_0]]
-; CHECK-NEXT:    ret i32 [[DOTR_0]]
+; CHECK-NEXT:    [[RETVAL_0:%.*]] = select i1 [[CMP]], i32 100, i32 [[R_0]]
+; CHECK-NEXT:    ret i32 [[RETVAL_0]]
 ;
 entry:
   %ec = icmp ne i32 %y, 0
@@ -1476,11 +1467,11 @@ define void @pr20210(i8 %x, i1 %y) {
 ; CHECK-NEXT:    br i1 [[Y:%.*]], label [[SW:%.*]], label [[INTERMEDIATE:%.*]]
 ; CHECK:       sw:
 ; CHECK-NEXT:    switch i8 [[X:%.*]], label [[END:%.*]] [
-; CHECK-NEXT:    i8 7, label [[INTERMEDIATE]]
-; CHECK-NEXT:    i8 3, label [[INTERMEDIATE]]
-; CHECK-NEXT:    i8 2, label [[INTERMEDIATE]]
-; CHECK-NEXT:    i8 1, label [[INTERMEDIATE]]
-; CHECK-NEXT:    i8 0, label [[INTERMEDIATE]]
+; CHECK-NEXT:      i8 7, label [[INTERMEDIATE]]
+; CHECK-NEXT:      i8 3, label [[INTERMEDIATE]]
+; CHECK-NEXT:      i8 2, label [[INTERMEDIATE]]
+; CHECK-NEXT:      i8 1, label [[INTERMEDIATE]]
+; CHECK-NEXT:      i8 0, label [[INTERMEDIATE]]
 ; CHECK-NEXT:    ]
 ; CHECK:       intermediate:
 ; CHECK-NEXT:    [[Z:%.*]] = zext i8 [[X]] to i32
@@ -1612,15 +1603,15 @@ define void @wineh_test(i64 %val) personality ptr @__CxxFrameHandler3 {
 ; CHECK-LABEL: @wineh_test(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    invoke void @throw(i1 false)
-; CHECK-NEXT:    to label [[UNREACHABLE:%.*]] unwind label [[CLEANUP1:%.*]]
+; CHECK-NEXT:            to label [[UNREACHABLE:%.*]] unwind label [[CLEANUP1:%.*]]
 ; CHECK:       unreachable:
 ; CHECK-NEXT:    unreachable
 ; CHECK:       cleanup1:
 ; CHECK-NEXT:    [[CLEANUPPAD1:%.*]] = cleanuppad within none []
 ; CHECK-NEXT:    switch i64 [[VAL:%.*]], label [[CLEANUPDONE2:%.*]] [
-; CHECK-NEXT:    i64 0, label [[CLEANUPDONE1:%.*]]
-; CHECK-NEXT:    i64 1, label [[CLEANUPDONE1]]
-; CHECK-NEXT:    i64 6, label [[CLEANUPDONE1]]
+; CHECK-NEXT:      i64 0, label [[CLEANUPDONE1:%.*]]
+; CHECK-NEXT:      i64 1, label [[CLEANUPDONE1]]
+; CHECK-NEXT:      i64 6, label [[CLEANUPDONE1]]
 ; CHECK-NEXT:    ]
 ; CHECK:       cleanupdone1:
 ; CHECK-NEXT:    cleanupret from [[CLEANUPPAD1]] unwind label [[CLEANUP2:%.*]]
@@ -1670,8 +1661,8 @@ define i1 @use_x_as_index(i32 %x) {
 ; CHECK-NEXT:    [[SWITCH_SHIFTAMT:%.*]] = mul nuw nsw i9 [[SWITCH_CAST]], 1
 ; CHECK-NEXT:    [[SWITCH_DOWNSHIFT:%.*]] = lshr i9 -234, [[SWITCH_SHIFTAMT]]
 ; CHECK-NEXT:    [[SWITCH_MASKED:%.*]] = trunc i9 [[SWITCH_DOWNSHIFT]] to i1
-; CHECK-NEXT:    [[STOREMERGE:%.*]] = select i1 [[TMP0]], i1 [[SWITCH_MASKED]], i1 false
-; CHECK-NEXT:    ret i1 [[STOREMERGE]]
+; CHECK-NEXT:    [[TMP1:%.*]] = select i1 [[TMP0]], i1 [[SWITCH_MASKED]], i1 false
+; CHECK-NEXT:    ret i1 [[TMP1]]
 ;
 entry:
   switch i32 %x, label %sw.default [
@@ -1733,9 +1724,9 @@ define i32 @signed_overflow2(i8 %n) {
 ; CHECK-NEXT:  start:
 ; CHECK-NEXT:    [[TRUNC:%.*]] = trunc i8 [[N:%.*]] to i2
 ; CHECK-NEXT:    switch i2 [[TRUNC]], label [[BB1:%.*]] [
-; CHECK-NEXT:    i2 1, label [[BB6:%.*]]
-; CHECK-NEXT:    i2 -2, label [[BB4:%.*]]
-; CHECK-NEXT:    i2 -1, label [[BB5:%.*]]
+; CHECK-NEXT:      i2 1, label [[BB6:%.*]]
+; CHECK-NEXT:      i2 -2, label [[BB4:%.*]]
+; CHECK-NEXT:      i2 -1, label [[BB5:%.*]]
 ; CHECK-NEXT:    ]
 ; CHECK:       bb1:
 ; CHECK-NEXT:    unreachable
@@ -1858,8 +1849,8 @@ define i32 @wrapped_on_index_sub(i8 %n) {
 ; CHECK-NEXT:    [[SWITCH_IDX_CAST:%.*]] = zext i3 [[SWITCH_TABLEIDX]] to i32
 ; CHECK-NEXT:    [[SWITCH_IDX_MULT:%.*]] = mul nsw i32 [[SWITCH_IDX_CAST]], 1111
 ; CHECK-NEXT:    [[SWITCH_OFFSET:%.*]] = add nsw i32 [[SWITCH_IDX_MULT]], 1111
-; CHECK-NEXT:    [[DOTSROA_0_0:%.*]] = select i1 [[TMP0]], i32 [[SWITCH_OFFSET]], i32 0
-; CHECK-NEXT:    ret i32 [[DOTSROA_0_0]]
+; CHECK-NEXT:    [[TMP1:%.*]] = select i1 [[TMP0]], i32 [[SWITCH_OFFSET]], i32 0
+; CHECK-NEXT:    ret i32 [[TMP1]]
 ;
 start:
   %trunc = trunc i8 %n to i3
@@ -1903,8 +1894,8 @@ define i32 @wrapped_on_index_sub_default(i8 %n) {
 ; CHECK-NEXT:    [[SWITCH_IDX_CAST:%.*]] = zext i3 [[SWITCH_TABLEIDX]] to i32
 ; CHECK-NEXT:    [[SWITCH_IDX_MULT:%.*]] = mul nsw i32 [[SWITCH_IDX_CAST]], 1111
 ; CHECK-NEXT:    [[SWITCH_OFFSET:%.*]] = add nsw i32 [[SWITCH_IDX_MULT]], 1111
-; CHECK-NEXT:    [[DOTSROA_0_0:%.*]] = select i1 [[TMP0]], i32 [[SWITCH_OFFSET]], i32 0
-; CHECK-NEXT:    ret i32 [[DOTSROA_0_0]]
+; CHECK-NEXT:    [[TMP1:%.*]] = select i1 [[TMP0]], i32 [[SWITCH_OFFSET]], i32 0
+; CHECK-NEXT:    ret i32 [[TMP1]]
 ;
 start:
   %trunc = trunc i8 %n to i3
@@ -1940,8 +1931,8 @@ define i8 @linearmap_inc_nsw(i32 %c) {
 ; CHECK-NEXT:    [[SWITCH_IDX_CAST:%.*]] = trunc i32 [[SWITCH_TABLEIDX]] to i8
 ; CHECK-NEXT:    [[SWITCH_IDX_MULT:%.*]] = mul nsw i8 [[SWITCH_IDX_CAST]], 31
 ; CHECK-NEXT:    [[SWITCH_OFFSET:%.*]] = add nsw i8 [[SWITCH_IDX_MULT]], 31
-; CHECK-NEXT:    [[X:%.*]] = select i1 [[TMP0]], i8 [[SWITCH_OFFSET]], i8 3
-; CHECK-NEXT:    ret i8 [[X]]
+; CHECK-NEXT:    [[TMP1:%.*]] = select i1 [[TMP0]], i8 [[SWITCH_OFFSET]], i8 3
+; CHECK-NEXT:    ret i8 [[TMP1]]
 ;
 entry:
   switch i32 %c, label %sw.default [
@@ -1967,8 +1958,8 @@ define i8 @linearmap_inc_wrapped(i32 %c) {
 ; CHECK-NEXT:    [[SWITCH_IDX_CAST:%.*]] = trunc i32 [[SWITCH_TABLEIDX]] to i8
 ; CHECK-NEXT:    [[SWITCH_IDX_MULT:%.*]] = mul i8 [[SWITCH_IDX_CAST]], 32
 ; CHECK-NEXT:    [[SWITCH_OFFSET:%.*]] = add i8 [[SWITCH_IDX_MULT]], 32
-; CHECK-NEXT:    [[X:%.*]] = select i1 [[TMP0]], i8 [[SWITCH_OFFSET]], i8 3
-; CHECK-NEXT:    ret i8 [[X]]
+; CHECK-NEXT:    [[TMP1:%.*]] = select i1 [[TMP0]], i8 [[SWITCH_OFFSET]], i8 3
+; CHECK-NEXT:    ret i8 [[TMP1]]
 ;
 entry:
   switch i32 %c, label %sw.default [
@@ -1994,8 +1985,8 @@ define i8 @linearmap_dec_nsw(i32 %c) {
 ; CHECK-NEXT:    [[SWITCH_IDX_CAST:%.*]] = trunc i32 [[SWITCH_TABLEIDX]] to i8
 ; CHECK-NEXT:    [[SWITCH_IDX_MULT:%.*]] = mul nsw i8 [[SWITCH_IDX_CAST]], -32
 ; CHECK-NEXT:    [[SWITCH_OFFSET:%.*]] = add nsw i8 [[SWITCH_IDX_MULT]], -32
-; CHECK-NEXT:    [[X:%.*]] = select i1 [[TMP0]], i8 [[SWITCH_OFFSET]], i8 3
-; CHECK-NEXT:    ret i8 [[X]]
+; CHECK-NEXT:    [[TMP1:%.*]] = select i1 [[TMP0]], i8 [[SWITCH_OFFSET]], i8 3
+; CHECK-NEXT:    ret i8 [[TMP1]]
 ;
 entry:
   switch i32 %c, label %sw.default [
@@ -2021,8 +2012,8 @@ define i8 @linearmap_dec_wrapped(i32 %c) {
 ; CHECK-NEXT:    [[SWITCH_IDX_CAST:%.*]] = trunc i32 [[SWITCH_TABLEIDX]] to i8
 ; CHECK-NEXT:    [[SWITCH_IDX_MULT:%.*]] = mul i8 [[SWITCH_IDX_CAST]], -33
 ; CHECK-NEXT:    [[SWITCH_OFFSET:%.*]] = add i8 [[SWITCH_IDX_MULT]], -33
-; CHECK-NEXT:    [[X:%.*]] = select i1 [[TMP0]], i8 [[SWITCH_OFFSET]], i8 3
-; CHECK-NEXT:    ret i8 [[X]]
+; CHECK-NEXT:    [[TMP1:%.*]] = select i1 [[TMP0]], i8 [[SWITCH_OFFSET]], i8 3
+; CHECK-NEXT:    ret i8 [[TMP1]]
 ;
 entry:
   switch i32 %c, label %sw.default [
diff --git a/llvm/test/Transforms/SimplifyCFG/fold-multiple-entry-phi.ll b/llvm/test/Transforms/SimplifyCFG/fold-multiple-entry-phi.ll
index c86f20164ebc525..da333addf5af481 100644
--- a/llvm/test/Transforms/SimplifyCFG/fold-multiple-entry-phi.ll
+++ b/llvm/test/Transforms/SimplifyCFG/fold-multiple-entry-phi.ll
@@ -1,20 +1,15 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 3
-; RUN: opt -S -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1 -two-entry-phi-node-folding-threshold=4 -phi-node-folding-threshold=0 < %s | FileCheck %s
+; RUN: opt -S -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1< %s | FileCheck %s
 
 define i32 @three_entry_test(i32 %x, i32 %y, i1 %cond){
 ; CHECK-LABEL: define i32 @three_entry_test(
 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]], i1 [[COND:%.*]]) {
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    br i1 [[COND]], label [[END:%.*]], label [[THEN:%.*]]
-; CHECK:       then:
 ; CHECK-NEXT:    [[SUB:%.*]] = add i32 [[X]], -1
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[X]], [[Y]]
-; CHECK-NEXT:    br i1 [[CMP]], label [[END]], label [[B:%.*]]
-; CHECK:       b:
 ; CHECK-NEXT:    [[ADD:%.*]] = add i32 [[X]], 1
-; CHECK-NEXT:    br label [[END]]
-; CHECK:       end:
-; CHECK-NEXT:    [[RET_0:%.*]] = phi i32 [ [[SUB]], [[THEN]] ], [ [[ADD]], [[B]] ], [ 0, [[ENTRY:%.*]] ]
+; CHECK-NEXT:    [[SPEC_SELECT:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 [[ADD]]
+; CHECK-NEXT:    [[RET_0:%.*]] = select i1 [[COND]], i32 0, i32 [[SPEC_SELECT]]
 ; CHECK-NEXT:    ret i32 [[RET_0]]
 ;
 entry:
@@ -41,18 +36,11 @@ define i32 @three_entry_test_diamond(i32 %x, i32 %y, i1 %cond){
 ; CHECK-LABEL: define i32 @three_entry_test_diamond(
 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]], i1 [[COND:%.*]]) {
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    br i1 [[COND]], label [[END:%.*]], label [[THEN:%.*]]
-; CHECK:       then:
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[X]], [[Y]]
-; CHECK-NEXT:    br i1 [[CMP]], label [[B1:%.*]], label [[B2:%.*]]
-; CHECK:       b1:
 ; CHECK-NEXT:    [[SUB:%.*]] = add i32 [[X]], -1
-; CHECK-NEXT:    br label [[END]]
-; CHECK:       b2:
 ; CHECK-NEXT:    [[ADD:%.*]] = add i32 [[X]], 1
-; CHECK-NEXT:    br label [[END]]
-; CHECK:       end:
-; CHECK-NEXT:    [[RET_0:%.*]] = phi i32 [ [[SUB]], [[B1]] ], [ [[ADD]], [[B2]] ], [ 0, [[ENTRY:%.*]] ]
+; CHECK-NEXT:    [[TMP0:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 [[ADD]]
+; CHECK-NEXT:    [[RET_0:%.*]] = select i1 [[COND]], i32 0, i32 [[TMP0]]
 ; CHECK-NEXT:    ret i32 [[RET_0]]
 ;
 entry:
@@ -86,18 +74,16 @@ define i32 @four_entry_test(i32 %x, i32 %y, i1 %cond, i1 %cond1){
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    br i1 [[COND]], label [[IF_THEN:%.*]], label [[THEN1:%.*]]
 ; CHECK:       if.then:
-; CHECK-NEXT:    br i1 [[COND1]], label [[THEN:%.*]], label [[END:%.*]]
-; CHECK:       then:
-; CHECK-NEXT:    br label [[END]]
+; CHECK-NEXT:    [[SPEC_SELECT:%.*]] = select i1 [[COND1]], i32 1, i32 0
+; CHECK-NEXT:    br label [[END:%.*]]
 ; CHECK:       then1:
 ; CHECK-NEXT:    [[SUB:%.*]] = add i32 [[X]], -1
 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp sgt i32 [[X]], [[Y]]
-; CHECK-NEXT:    br i1 [[CMP1]], label [[END]], label [[B:%.*]]
-; CHECK:       b:
 ; CHECK-NEXT:    [[ADD:%.*]] = add i32 [[X]], 1
+; CHECK-NEXT:    [[SPEC_SELECT1:%.*]] = select i1 [[CMP1]], i32 [[SUB]], i32 [[ADD]]
 ; CHECK-NEXT:    br label [[END]]
 ; CHECK:       end:
-; CHECK-NEXT:    [[RET_0:%.*]] = phi i32 [ 0, [[IF_THEN]] ], [ 1, [[THEN]] ], [ [[SUB]], [[THEN1]] ], [ [[ADD]], [[B]] ]
+; CHECK-NEXT:    [[RET_0:%.*]] = phi i32 [ [[SPEC_SELECT]], [[IF_THEN]] ], [ [[SPEC_SELECT1]], [[THEN1]] ]
 ; CHECK-NEXT:    ret i32 [[RET_0]]
 ;
 entry:
diff --git a/llvm/test/Transforms/SimplifyCFG/no-md-sink.ll b/llvm/test/Transforms/SimplifyCFG/no-md-sink.ll
index 29d8caa01e1433f..4d23fa561fc3d4b 100644
--- a/llvm/test/Transforms/SimplifyCFG/no-md-sink.ll
+++ b/llvm/test/Transforms/SimplifyCFG/no-md-sink.ll
@@ -34,9 +34,10 @@ declare i1 @llvm.type.test(ptr %ptr, metadata %bitset) nounwind readnone
 define i1 @test2(i1 zeroext %flag, ptr %y, ptr %z) #0 {
 ; CHECK-LABEL: @test2(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[Y_Z:%.*]] = select i1 [[FLAG:%.*]], ptr [[Y:%.*]], ptr [[Z:%.*]]
-; CHECK-NEXT:    [[S:%.*]] = call i1 @llvm.type.test(ptr [[Y_Z]], metadata [[META1]])
-; CHECK-NEXT:    ret i1 [[S]]
+; CHECK-NEXT:    [[S:%.*]] = call i1 @llvm.type.test(ptr [[Z:%.*]], metadata [[META1]])
+; CHECK-NEXT:    [[R:%.*]] = call i1 @llvm.type.test(ptr [[Y:%.*]], metadata [[META1]])
+; CHECK-NEXT:    [[T:%.*]] = select i1 [[FLAG:%.*]], i1 [[R]], i1 [[S]]
+; CHECK-NEXT:    ret i1 [[T]]
 ;
 entry:
   br i1 %flag, label %if.then, label %if.else
diff --git a/llvm/test/Transforms/SimplifyCFG/opaque-ptr.ll b/llvm/test/Transforms/SimplifyCFG/opaque-ptr.ll
index ee5b55222adfc33..a7e8796a57584d5 100644
--- a/llvm/test/Transforms/SimplifyCFG/opaque-ptr.ll
+++ b/llvm/test/Transforms/SimplifyCFG/opaque-ptr.ll
@@ -4,8 +4,10 @@
 define ptr @test_sink_gep(i1 %c, ptr %p) {
 ; CHECK-LABEL: @test_sink_gep(
 ; CHECK-NEXT:  join:
-; CHECK-NEXT:    [[GEP2:%.*]] = getelementptr i32, ptr [[P:%.*]], i64 1
-; CHECK-NEXT:    ret ptr [[GEP2]]
+; CHECK-NEXT:    [[GEP1:%.*]] = getelementptr i32, ptr [[P:%.*]], i64 1
+; CHECK-NEXT:    [[GEP2:%.*]] = getelementptr i32, ptr [[P]], i64 1
+; CHECK-NEXT:    [[PHI:%.*]] = select i1 [[C:%.*]], ptr [[GEP1]], ptr [[GEP2]]
+; CHECK-NEXT:    ret ptr [[PHI]]
 ;
   br i1 %c, label %if, label %else
 



More information about the llvm-commits mailing list