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

via llvm-commits llvm-commits at lists.llvm.org
Wed Nov 29 04:49:02 PST 2023


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

>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 92911d3920b64a49f90bdae0b9d10f3c78e3abf1 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/Transforms/Utils/BasicBlockUtils.h   |   5 +-
 llvm/lib/Transforms/Utils/BasicBlockUtils.cpp |  21 +--
 llvm/lib/Transforms/Utils/FlattenCFG.cpp      |   3 +-
 llvm/lib/Transforms/Utils/SimplifyCFG.cpp     |  43 ++++--
 .../CodeGen/ARM/2013-05-05-IfConvertBug.ll    |  51 +++----
 .../SimplifyCFG/X86/sink-common-code.ll       |  20 +--
 .../SimplifyCFG/X86/switch_to_lookup_table.ll | 139 ++++++++----------
 .../SimplifyCFG/fold-multiple-entry-phi.ll    |  32 ++--
 8 files changed, 155 insertions(+), 159 deletions(-)

diff --git a/llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h b/llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h
index 998acbe9ab75da7..588028cdff929db 100644
--- a/llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h
+++ b/llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h
@@ -596,7 +596,7 @@ void SplitBlockAndInsertForEachLane(
 /// This does no checking to see if the true/false blocks have large or unsavory
 /// instructions in them.
 BranchInst *GetIfConditionFromMergePoint(BasicBlock *BB, BasicBlock *&IfTrue,
-                           BasicBlock *&IfFalse);
+                                         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
@@ -606,7 +606,8 @@ BranchInst *GetIfConditionFromMergePoint(BasicBlock *BB, BasicBlock *&IfTrue,
 /// 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. 
+/// NOTE: we assume that the terminator of DomBB is a conditional branch
+/// instruction.
 BasicBlock *GetIfConditionFromDom(BasicBlock *DomBB, BasicBlock *&IfTrue,
                                   BasicBlock *&IfFalse);
 
diff --git a/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp b/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp
index d43a5f72846f72c..9145c2dacc2f622 100644
--- a/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp
+++ b/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp
@@ -1727,8 +1727,9 @@ void llvm::SplitBlockAndInsertForEachLane(
   }
 }
 
-BranchInst *llvm::GetIfConditionFromMergePoint(BasicBlock *BB, BasicBlock *&IfTrue,
-                                 BasicBlock *&IfFalse) {
+BranchInst *llvm::GetIfConditionFromMergePoint(BasicBlock *BB,
+                                               BasicBlock *&IfTrue,
+                                               BasicBlock *&IfFalse) {
   PHINode *SomePHI = dyn_cast<PHINode>(BB->begin());
   BasicBlock *Pred1 = nullptr;
   BasicBlock *Pred2 = nullptr;
@@ -1821,7 +1822,7 @@ BranchInst *llvm::GetIfConditionFromMergePoint(BasicBlock *BB, BasicBlock *&IfTr
 
 BasicBlock *llvm::GetIfConditionFromDom(BasicBlock *DomBB, BasicBlock *&IfTrue,
                                         BasicBlock *&IfFalse) {
-  BranchInst* BI = cast<BranchInst>(DomBB->getTerminator());
+  BranchInst *BI = cast<BranchInst>(DomBB->getTerminator());
   BasicBlock *Succ1 = BI->getSuccessor(0);
   BasicBlock *Succ2 = BI->getSuccessor(1);
 
@@ -1829,13 +1830,6 @@ BasicBlock *llvm::GetIfConditionFromDom(BasicBlock *DomBB, BasicBlock *&IfTrue,
       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;
@@ -1848,6 +1842,13 @@ BasicBlock *llvm::GetIfConditionFromDom(BasicBlock *DomBB, BasicBlock *&IfTrue,
     return Succ1;
   }
 
+  // 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;
+
   auto *CommonDest = Succ1->getSingleSuccessor();
   if (CommonDest && CommonDest != DomBB &&
       CommonDest == Succ2->getSingleSuccessor()) {
diff --git a/llvm/lib/Transforms/Utils/FlattenCFG.cpp b/llvm/lib/Transforms/Utils/FlattenCFG.cpp
index 4480202bae8e7db..08fbcef5cd91f64 100644
--- a/llvm/lib/Transforms/Utils/FlattenCFG.cpp
+++ b/llvm/lib/Transforms/Utils/FlattenCFG.cpp
@@ -420,7 +420,8 @@ bool FlattenCFGOpt::MergeIfRegion(BasicBlock *BB, IRBuilder<> &Builder) {
     return false;
 
   BasicBlock *IfTrue1, *IfFalse1;
-  BranchInst *DomBI1 = GetIfConditionFromMergePoint(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 a161d32aec761a1..a1d51d911f6a2be 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -237,11 +237,19 @@ struct ValueEqualityComparisonCase {
   bool operator==(BasicBlock *RHSDest) const { return Dest == RHSDest; }
 };
 
+struct IfRegion {
+  BasicBlock *DomBB;
+  BasicBlock *IfTrue;
+  BasicBlock *IfFalse;
+  BasicBlock *MergePoint;
+};
+
 class SimplifyCFGOpt {
   const TargetTransformInfo &TTI;
   DomTreeUpdater *DTU;
   const DataLayout &DL;
   ArrayRef<WeakVH> LoopHeaders;
+  DenseMap<BasicBlock *, IfRegion> IfRegions; // Merge point -> If region
   const SimplifyCFGOptions &Options;
   bool Resimplify;
 
@@ -3422,7 +3430,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 +3578,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 +7392,19 @@ 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)
+    if (BasicBlock *MergePoint = GetIfConditionFromDom(BB, IfTrue, IfFalse)) {
+      // Guarantee that the merge point is simplified before dominant point.
+      // FIXME: Prevent recursive calls.
+      if (simplifyOnce(MergePoint))
+        return requestResimplify();
+      if (FoldPHIOfIfRegion(MergePoint, BB, IfTrue, IfFalse, TTI, DTU, DL))
+        return requestResimplify();
+    }
+
   return false;
 }
 
diff --git a/llvm/test/CodeGen/ARM/2013-05-05-IfConvertBug.ll b/llvm/test/CodeGen/ARM/2013-05-05-IfConvertBug.ll
index 344bb15d2a8b8fa..d39807116371d87 100644
--- a/llvm/test/CodeGen/ARM/2013-05-05-IfConvertBug.ll
+++ b/llvm/test/CodeGen/ARM/2013-05-05-IfConvertBug.ll
@@ -309,16 +309,15 @@ define i32 @wrapDistance(i32 %tx, i32 %sx, i32 %w) {
 ; CHECK-NEXT:    suble r0, r2, #1
 ; CHECK-NEXT:    bxle lr
 ; CHECK-NEXT:  LBB4_1: @ %if.else
-; CHECK-NEXT:    subs r2, #120
+; CHECK-NEXT:    subs r3, r1, r0
+; CHECK-NEXT:    cmp r0, #120
+; CHECK-NEXT:    sub.w r2, r2, #120
+; CHECK-NEXT:    mov r0, r3
+; CHECK-NEXT:    it lt
+; CHECK-NEXT:    addlt r0, r1, #1
 ; CHECK-NEXT:    cmp r2, r1
-; CHECK-NEXT:    bge LBB4_3
-; CHECK-NEXT:  @ %bb.2: @ %if.else
-; CHECK-NEXT:    cmp r0, #119
-; CHECK-NEXT:    itt le
-; CHECK-NEXT:    addle r0, r1, #1
-; CHECK-NEXT:    bxle lr
-; CHECK-NEXT:  LBB4_3: @ %if.end5
-; CHECK-NEXT:    subs r0, r1, r0
+; CHECK-NEXT:    it ge
+; CHECK-NEXT:    movge r0, r3
 ; CHECK-NEXT:    bx lr
 ;
 ; CHECK-V8-LABEL: wrapDistance:
@@ -328,16 +327,15 @@ define i32 @wrapDistance(i32 %tx, i32 %sx, i32 %w) {
 ; CHECK-V8-NEXT:    suble r0, r2, #1
 ; CHECK-V8-NEXT:    bxle lr
 ; CHECK-V8-NEXT:  .LBB4_1: @ %if.else
-; CHECK-V8-NEXT:    subs r2, #120
+; CHECK-V8-NEXT:    subs r3, r1, r0
+; CHECK-V8-NEXT:    cmp r0, #120
+; CHECK-V8-NEXT:    sub.w r2, r2, #120
+; CHECK-V8-NEXT:    mov r0, r3
+; CHECK-V8-NEXT:    it lt
+; CHECK-V8-NEXT:    addlt r0, r1, #1
 ; CHECK-V8-NEXT:    cmp r2, r1
-; CHECK-V8-NEXT:    bge .LBB4_3
-; CHECK-V8-NEXT:  @ %bb.2: @ %if.else
-; CHECK-V8-NEXT:    cmp r0, #119
-; CHECK-V8-NEXT:    itt le
-; CHECK-V8-NEXT:    addle r0, r1, #1
-; CHECK-V8-NEXT:    bxle lr
-; CHECK-V8-NEXT:  .LBB4_3: @ %if.end5
-; CHECK-V8-NEXT:    subs r0, r1, r0
+; CHECK-V8-NEXT:    it ge
+; CHECK-V8-NEXT:    movge r0, r3
 ; CHECK-V8-NEXT:    bx lr
 ;
 ; CHECK-RESTRICT-IT-LABEL: wrapDistance:
@@ -348,17 +346,16 @@ define i32 @wrapDistance(i32 %tx, i32 %sx, i32 %w) {
 ; CHECK-RESTRICT-IT-NEXT:    subs r0, r2, #1
 ; CHECK-RESTRICT-IT-NEXT:    bx lr
 ; CHECK-RESTRICT-IT-NEXT:  .LBB4_2: @ %if.else
+; CHECK-RESTRICT-IT-NEXT:    subs r3, r1, r0
+; CHECK-RESTRICT-IT-NEXT:    mov r12, r0
+; CHECK-RESTRICT-IT-NEXT:    adds r0, r1, #1
+; CHECK-RESTRICT-IT-NEXT:    cmp.w r12, #120
+; CHECK-RESTRICT-IT-NEXT:    it ge
+; CHECK-RESTRICT-IT-NEXT:    movge r0, r3
 ; CHECK-RESTRICT-IT-NEXT:    subs r2, #120
 ; CHECK-RESTRICT-IT-NEXT:    cmp r2, r1
-; CHECK-RESTRICT-IT-NEXT:    bge .LBB4_5
-; CHECK-RESTRICT-IT-NEXT:  @ %bb.3: @ %if.else
-; CHECK-RESTRICT-IT-NEXT:    cmp r0, #119
-; CHECK-RESTRICT-IT-NEXT:    bgt .LBB4_5
-; CHECK-RESTRICT-IT-NEXT:  @ %bb.4: @ %if.then4
-; CHECK-RESTRICT-IT-NEXT:    adds r0, r1, #1
-; CHECK-RESTRICT-IT-NEXT:    bx lr
-; CHECK-RESTRICT-IT-NEXT:  .LBB4_5: @ %if.end5
-; CHECK-RESTRICT-IT-NEXT:    subs r0, r1, r0
+; CHECK-RESTRICT-IT-NEXT:    it ge
+; CHECK-RESTRICT-IT-NEXT:    movge r0, r3
 ; CHECK-RESTRICT-IT-NEXT:    bx lr
 entry:
   %cmp = icmp slt i32 %sx, 60
diff --git a/llvm/test/Transforms/SimplifyCFG/X86/sink-common-code.ll b/llvm/test/Transforms/SimplifyCFG/X86/sink-common-code.ll
index 26107965a1a8b6d..c3eab615afb2ae1 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:%.*]]
@@ -1285,11 +1285,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 +1563,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:



More information about the llvm-commits mailing list