[llvm] 9f4c9b9 - Revert D155711 "[SimplifyCFG] Hoist common instructions on Switch."

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 20 11:49:25 PDT 2023


Author: Fangrui Song
Date: 2023-09-20T11:49:20-07:00
New Revision: 9f4c9b90c935ea071d931917bb2bbfcca252c430

URL: https://github.com/llvm/llvm-project/commit/9f4c9b90c935ea071d931917bb2bbfcca252c430
DIFF: https://github.com/llvm/llvm-project/commit/9f4c9b90c935ea071d931917bb2bbfcca252c430.diff

LOG: Revert D155711 "[SimplifyCFG] Hoist common instructions on Switch."

This reverts commit 96ea48ff5dcba46af350f5300eafd7f7394ba606.

The change may cause Verifier.cpp error
"musttail call must precede a ret with an optional bitcast"

Added: 
    

Modified: 
    llvm/lib/Transforms/Utils/SimplifyCFG.cpp
    llvm/test/CodeGen/AArch64/patchable-function-entry-bti.ll
    llvm/test/Transforms/SimplifyCFG/HoistCode.ll
    llvm/test/Transforms/SimplifyCFG/hoist-common-code-with-unreachable.ll
    llvm/test/Transforms/SimplifyCFG/hoist-common-code.ll
    llvm/test/Transforms/SimplifyCFG/hoist-common-skip.ll
    llvm/test/Transforms/SimplifyCFG/hoist-with-metadata.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index 897058ed5351836..14cabd275d5b111 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -271,10 +271,7 @@ class SimplifyCFGOpt {
   bool tryToSimplifyUncondBranchWithICmpInIt(ICmpInst *ICI,
                                              IRBuilder<> &Builder);
 
-  bool hoistCommonCodeFromSuccessors(BasicBlock *BB, bool EqTermsOnly);
-  bool hoistSuccIdenticalTerminatorToSwitchOrIf(
-      Instruction *TI, Instruction *I1,
-      SmallVectorImpl<Instruction *> &OtherSuccTIs);
+  bool HoistThenElseCodeToIf(BranchInst *BI, bool EqTermsOnly);
   bool SpeculativelyExecuteBB(BranchInst *BI, BasicBlock *ThenBB);
   bool SimplifyTerminatorOnSelect(Instruction *OldTerm, Value *Cond,
                                   BasicBlock *TrueBB, BasicBlock *FalseBB,
@@ -1411,9 +1408,8 @@ bool SimplifyCFGOpt::FoldValueComparisonIntoPredecessors(Instruction *TI,
 }
 
 // If we would need to insert a select that uses the value of this invoke
-// (comments in hoistSuccIdenticalTerminatorToSwitchOrIf explain why we would
-// need to do this), we can't hoist the invoke, as there is nowhere to put the
-// select in this case.
+// (comments in HoistThenElseCodeToIf explain why we would need to do this), we
+// can't hoist the invoke, as there is nowhere to put the select in this case.
 static bool isSafeToHoistInvoke(BasicBlock *BB1, BasicBlock *BB2,
                                 Instruction *I1, Instruction *I2) {
   for (BasicBlock *Succ : successors(BB1)) {
@@ -1428,9 +1424,9 @@ static bool isSafeToHoistInvoke(BasicBlock *BB1, BasicBlock *BB2,
   return true;
 }
 
-// Get interesting characteristics of instructions that
-// `hoistCommonCodeFromSuccessors` didn't hoist. They restrict what kind of
-// instructions can be reordered across.
+// Get interesting characteristics of instructions that `HoistThenElseCodeToIf`
+// didn't hoist. They restrict what kind of instructions can be reordered
+// across.
 enum SkipFlags {
   SkipReadMem = 1,
   SkipSideEffect = 2,
@@ -1488,7 +1484,7 @@ static bool isSafeToHoistInstr(Instruction *I, unsigned Flags) {
 
 static bool passingValueIsAlwaysUndefined(Value *V, Instruction *I, bool PtrValueMayBeModified = false);
 
-/// Helper function for hoistCommonCodeFromSuccessors. Return true if identical
+/// Helper function for HoistThenElseCodeToIf. Return true if identical
 /// instructions \p I1 and \p I2 can and should be hoisted.
 static bool shouldHoistCommonInstructions(Instruction *I1, Instruction *I2,
                                           const TargetTransformInfo &TTI) {
@@ -1519,51 +1515,62 @@ static bool shouldHoistCommonInstructions(Instruction *I1, Instruction *I2,
   return true;
 }
 
-/// Hoist any common code in the successor blocks up into the block. This
-/// function guarantees that BB dominates all successors. If EqTermsOnly is
-/// given, only perform hoisting in case both blocks only contain a terminator.
-/// In that case, only the original BI will be replaced and selects for PHIs are
-/// added.
-bool SimplifyCFGOpt::hoistCommonCodeFromSuccessors(BasicBlock *BB,
-                                                   bool EqTermsOnly) {
+/// Given a conditional branch that goes to BB1 and BB2, hoist any common code
+/// in the two blocks up into the branch block. The caller of this function
+/// guarantees that BI's block dominates BB1 and BB2. If EqTermsOnly is given,
+/// only perform hoisting in case both blocks only contain a terminator. In that
+/// case, only the original BI will be replaced and selects for PHIs are added.
+bool SimplifyCFGOpt::HoistThenElseCodeToIf(BranchInst *BI, bool EqTermsOnly) {
   // This does very trivial matching, with limited scanning, to find identical
-  // instructions in the two blocks. In particular, we don't want to get into
-  // O(N1*N2*...) situations here where Ni are the sizes of these successors. As
+  // instructions in the two blocks.  In particular, we don't want to get into
+  // O(M*N) situations here where M and N are the sizes of BB1 and BB2.  As
   // such, we currently just scan for obviously identical instructions in an
   // identical order, possibly separated by the same number of non-identical
   // instructions.
-  unsigned int SuccSize = succ_size(BB);
-  if (SuccSize < 2)
-    return false;
+  BasicBlock *BB1 = BI->getSuccessor(0); // The true destination.
+  BasicBlock *BB2 = BI->getSuccessor(1); // The false destination
 
   // If either of the blocks has it's address taken, then we can't do this fold,
   // because the code we'd hoist would no longer run when we jump into the block
   // by it's address.
-  for (auto *Succ : successors(BB))
-    if (Succ->hasAddressTaken() || !Succ->getSinglePredecessor())
-      return false;
+  if (BB1->hasAddressTaken() || BB2->hasAddressTaken())
+    return false;
 
-  auto *TI = BB->getTerminator();
+  BasicBlock::iterator BB1_Itr = BB1->begin();
+  BasicBlock::iterator BB2_Itr = BB2->begin();
 
-  // The second of pair is a SkipFlags bitmask.
-  using SuccIterPair = std::pair<BasicBlock::iterator, unsigned>;
-  SmallVector<SuccIterPair, 8> SuccIterPairs;
-  for (auto *Succ : successors(BB)) {
-    BasicBlock::iterator SuccItr = Succ->begin();
-    if (isa<PHINode>(*SuccItr))
-      return false;
-    SuccIterPairs.push_back(SuccIterPair(SuccItr, 0));
+  Instruction *I1 = &*BB1_Itr++, *I2 = &*BB2_Itr++;
+  // Skip debug info if it is not identical.
+  DbgInfoIntrinsic *DBI1 = dyn_cast<DbgInfoIntrinsic>(I1);
+  DbgInfoIntrinsic *DBI2 = dyn_cast<DbgInfoIntrinsic>(I2);
+  if (!DBI1 || !DBI2 || !DBI1->isIdenticalToWhenDefined(DBI2)) {
+    while (isa<DbgInfoIntrinsic>(I1))
+      I1 = &*BB1_Itr++;
+    while (isa<DbgInfoIntrinsic>(I2))
+      I2 = &*BB2_Itr++;
   }
+  if (isa<PHINode>(I1))
+    return false;
+
+  BasicBlock *BIParent = BI->getParent();
+
+  bool Changed = false;
+
+  auto _ = make_scope_exit([&]() {
+    if (Changed)
+      ++NumHoistCommonCode;
+  });
 
   // Check if only hoisting terminators is allowed. This does not add new
   // instructions to the hoist location.
   if (EqTermsOnly) {
     // Skip any debug intrinsics, as they are free to hoist.
-    for (auto &SuccIter : make_first_range(SuccIterPairs)) {
-      auto *INonDbg = &*skipDebugIntrinsics(SuccIter);
-      if (!INonDbg->isTerminator())
-        return false;
-    }
+    auto *I1NonDbg = &*skipDebugIntrinsics(I1->getIterator());
+    auto *I2NonDbg = &*skipDebugIntrinsics(I2->getIterator());
+    if (!I1NonDbg->isIdenticalToWhenDefined(I2NonDbg))
+      return false;
+    if (!I1NonDbg->isTerminator())
+      return false;
     // Now we know that we only need to hoist debug intrinsics and the
     // terminator. Let the loop below handle those 2 cases.
   }
@@ -1572,234 +1579,154 @@ bool SimplifyCFGOpt::hoistCommonCodeFromSuccessors(BasicBlock *BB,
   // many instructions we skip, serving as a compilation time control as well as
   // preventing excessive increase of life ranges.
   unsigned NumSkipped = 0;
-  // If we find an unreachable instruction at the beginning of a basic block, we
-  // can still hoist instructions from the rest of the basic blocks.
-  if (SuccIterPairs.size() > 2) {
-    erase_if(SuccIterPairs,
-             [](const auto &Pair) { return isa<UnreachableInst>(Pair.first); });
-    if (SuccIterPairs.size() < 2)
-      return false;
-  }
 
-  bool Changed = false;
+  // Record any skipped instuctions that may read memory, write memory or have
+  // side effects, or have implicit control flow.
+  unsigned SkipFlagsBB1 = 0;
+  unsigned SkipFlagsBB2 = 0;
 
   for (;;) {
-    auto *SuccIterPairBegin = SuccIterPairs.begin();
-    auto &BB1ItrPair = *SuccIterPairBegin++;
-    auto OtherSuccIterPairRange =
-        iterator_range(SuccIterPairBegin, SuccIterPairs.end());
-    auto OtherSuccIterRange = make_first_range(OtherSuccIterPairRange);
-
-    Instruction *I1 = &*BB1ItrPair.first;
-    auto *BB1 = I1->getParent();
-
-    // Skip debug info if it is not identical.
-    bool AllDbgInstsAreIdentical = all_of(OtherSuccIterRange, [I1](auto &Iter) {
-      Instruction *I2 = &*Iter;
-      return I1->isIdenticalToWhenDefined(I2);
-    });
-    if (!AllDbgInstsAreIdentical) {
-      while (isa<DbgInfoIntrinsic>(I1))
-        I1 = &*++BB1ItrPair.first;
-      for (auto &SuccIter : OtherSuccIterRange) {
-        Instruction *I2 = &*SuccIter;
-        while (isa<DbgInfoIntrinsic>(I2))
-          I2 = &*++SuccIter;
-      }
-    }
-
-    bool AllInstsAreIdentical = true;
-    bool HasTerminator = I1->isTerminator();
-    for (auto &SuccIter : OtherSuccIterRange) {
-      Instruction *I2 = &*SuccIter;
-      HasTerminator |= I2->isTerminator();
-      if (AllInstsAreIdentical && !I1->isIdenticalToWhenDefined(I2))
-        AllInstsAreIdentical = false;
-    }
-
     // If we are hoisting the terminator instruction, don't move one (making a
     // broken BB), instead clone it, and remove BI.
-    if (HasTerminator) {
+    if (I1->isTerminator() || I2->isTerminator()) {
       // If any instructions remain in the block, we cannot hoist terminators.
-      if (NumSkipped || SuccSize != SuccIterPairs.size() ||
-          !AllInstsAreIdentical)
+      if (NumSkipped || !I1->isIdenticalToWhenDefined(I2))
         return Changed;
-      SmallVector<Instruction *, 8> Insts;
-      for (auto &SuccIter : OtherSuccIterRange)
-        Insts.push_back(&*SuccIter);
-      return hoistSuccIdenticalTerminatorToSwitchOrIf(TI, I1, Insts) || Changed;
+      goto HoistTerminator;
     }
 
-    if (AllInstsAreIdentical) {
-      unsigned SkipFlagsBB1 = BB1ItrPair.second;
-      AllInstsAreIdentical =
-          isSafeToHoistInstr(I1, SkipFlagsBB1) &&
-          all_of(OtherSuccIterPairRange, [=](const auto &Pair) {
-            Instruction *I2 = &*Pair.first;
-            unsigned SkipFlagsBB2 = Pair.second;
-            // Even if the instructions are identical, it may not
-            // be safe to hoist them if we have skipped over
-            // instructions with side effects or their operands
-            // weren't hoisted.
-            return isSafeToHoistInstr(I2, SkipFlagsBB2) &&
-                   shouldHoistCommonInstructions(I1, I2, TTI);
-          });
-    }
-
-    if (AllInstsAreIdentical) {
-      BB1ItrPair.first++;
-      if (isa<DbgInfoIntrinsic>(I1)) {
+    if (I1->isIdenticalToWhenDefined(I2) &&
+        // Even if the instructions are identical, it may not be safe to hoist
+        // them if we have skipped over instructions with side effects or their
+        // operands weren't hoisted.
+        isSafeToHoistInstr(I1, SkipFlagsBB1) &&
+        isSafeToHoistInstr(I2, SkipFlagsBB2) &&
+        shouldHoistCommonInstructions(I1, I2, TTI)) {
+      if (isa<DbgInfoIntrinsic>(I1) || isa<DbgInfoIntrinsic>(I2)) {
+        assert(isa<DbgInfoIntrinsic>(I1) && isa<DbgInfoIntrinsic>(I2));
         // The debug location is an integral part of a debug info intrinsic
         // and can't be separated from it or replaced.  Instead of attempting
         // to merge locations, simply hoist both copies of the intrinsic.
-        I1->moveBeforePreserving(TI);
-        for (auto &SuccIter : OtherSuccIterRange) {
-          auto *I2 = &*SuccIter++;
-          assert(isa<DbgInfoIntrinsic>(I2));
-          I2->moveBeforePreserving(TI);
-        }
+        I1->moveBeforePreserving(BI);
+        I2->moveBeforePreserving(BI);
+        Changed = true;
       } else {
         // For a normal instruction, we just move one to right before the
         // branch, then replace all uses of the other with the first.  Finally,
         // we remove the now redundant second instruction.
-        I1->moveBeforePreserving(TI);
-        BB->splice(TI->getIterator(), BB1, I1->getIterator());
-        for (auto &SuccIter : OtherSuccIterRange) {
-          Instruction *I2 = &*SuccIter++;
-          assert(I2 != I1);
-          if (!I2->use_empty())
-            I2->replaceAllUsesWith(I1);
-          I1->andIRFlags(I2);
-          combineMetadataForCSE(I1, I2, true);
-          // I1 and I2 are being combined into a single instruction.  Its debug
-          // location is the merged locations of the original instructions.
-          I1->applyMergedLocation(I1->getDebugLoc(), I2->getDebugLoc());
-          I2->eraseFromParent();
-        }
+        I1->moveBeforePreserving(BI);
+        if (!I2->use_empty())
+          I2->replaceAllUsesWith(I1);
+        I1->andIRFlags(I2);
+        combineMetadataForCSE(I1, I2, true);
+
+        // I1 and I2 are being combined into a single instruction.  Its debug
+        // location is the merged locations of the original instructions.
+        I1->applyMergedLocation(I1->getDebugLoc(), I2->getDebugLoc());
+
+        I2->eraseFromParent();
       }
-      if (!Changed)
-        NumHoistCommonCode += SuccIterPairs.size();
       Changed = true;
-      NumHoistCommonInstrs += SuccIterPairs.size();
+      ++NumHoistCommonInstrs;
     } else {
       if (NumSkipped >= HoistCommonSkipLimit)
         return Changed;
       // We are about to skip over a pair of non-identical instructions. Record
       // if any have characteristics that would prevent reordering instructions
       // across them.
-      for (auto &SuccIterPair : SuccIterPairs) {
-        Instruction *I = &*SuccIterPair.first++;
-        SuccIterPair.second |= skippedInstrFlags(I);
-      }
+      SkipFlagsBB1 |= skippedInstrFlags(I1);
+      SkipFlagsBB2 |= skippedInstrFlags(I2);
       ++NumSkipped;
     }
-  }
-}
-
-bool SimplifyCFGOpt::hoistSuccIdenticalTerminatorToSwitchOrIf(
-    Instruction *TI, Instruction *I1,
-    SmallVectorImpl<Instruction *> &OtherSuccTIs) {
 
-  auto *BI = dyn_cast<BranchInst>(TI);
-
-  bool Changed = false;
-  BasicBlock *TIParent = TI->getParent();
-  BasicBlock *BB1 = I1->getParent();
-
-  // Use only for an if statement.
-  auto *I2 = *OtherSuccTIs.begin();
-  auto *BB2 = I2->getParent();
-  if (BI) {
-    assert(OtherSuccTIs.size() == 1);
-    assert(BI->getSuccessor(0) == I1->getParent());
-    assert(BI->getSuccessor(1) == I2->getParent());
+    I1 = &*BB1_Itr++;
+    I2 = &*BB2_Itr++;
+    // Skip debug info if it is not identical.
+    DbgInfoIntrinsic *DBI1 = dyn_cast<DbgInfoIntrinsic>(I1);
+    DbgInfoIntrinsic *DBI2 = dyn_cast<DbgInfoIntrinsic>(I2);
+    if (!DBI1 || !DBI2 || !DBI1->isIdenticalToWhenDefined(DBI2)) {
+      while (isa<DbgInfoIntrinsic>(I1))
+        I1 = &*BB1_Itr++;
+      while (isa<DbgInfoIntrinsic>(I2))
+        I2 = &*BB2_Itr++;
+    }
   }
 
-  // In the case of an if statement, we try to hoist an invoke.
+  return Changed;
+
+HoistTerminator:
+  // It may not be possible to hoist an invoke.
   // FIXME: Can we define a safety predicate for CallBr?
-  // FIXME: Test case llvm/test/Transforms/SimplifyCFG/2009-06-15-InvokeCrash.ll
-  // removed in 4c923b3b3fd0ac1edebf0603265ca3ba51724937 commit?
-  if (isa<InvokeInst>(I1) && (!BI || !isSafeToHoistInvoke(BB1, BB2, I1, I2)))
-    return false;
+  if (isa<InvokeInst>(I1) && !isSafeToHoistInvoke(BB1, BB2, I1, I2))
+    return Changed;
 
   // TODO: callbr hoisting currently disabled pending further study.
   if (isa<CallBrInst>(I1))
-    return false;
+    return Changed;
 
   for (BasicBlock *Succ : successors(BB1)) {
     for (PHINode &PN : Succ->phis()) {
       Value *BB1V = PN.getIncomingValueForBlock(BB1);
-      for (Instruction *OtherSuccTI : OtherSuccTIs) {
-        Value *BB2V = PN.getIncomingValueForBlock(OtherSuccTI->getParent());
-        if (BB1V == BB2V)
-          continue;
+      Value *BB2V = PN.getIncomingValueForBlock(BB2);
+      if (BB1V == BB2V)
+        continue;
 
-        // In the case of an if statement, check for
-        // passingValueIsAlwaysUndefined here because we would rather eliminate
-        // undefined control flow then converting it to a select.
-        if (!BI || passingValueIsAlwaysUndefined(BB1V, &PN) ||
-            passingValueIsAlwaysUndefined(BB2V, &PN))
-          return false;
-      }
+      // Check for passingValueIsAlwaysUndefined here because we would rather
+      // eliminate undefined control flow then converting it to a select.
+      if (passingValueIsAlwaysUndefined(BB1V, &PN) ||
+          passingValueIsAlwaysUndefined(BB2V, &PN))
+        return Changed;
     }
   }
 
   // Okay, it is safe to hoist the terminator.
   Instruction *NT = I1->clone();
-  NT->insertInto(TIParent, TI->getIterator());
+  NT->insertInto(BIParent, BI->getIterator());
   if (!NT->getType()->isVoidTy()) {
     I1->replaceAllUsesWith(NT);
-    for (Instruction *OtherSuccTI : OtherSuccTIs)
-      OtherSuccTI->replaceAllUsesWith(NT);
+    I2->replaceAllUsesWith(NT);
     NT->takeName(I1);
   }
   Changed = true;
-  NumHoistCommonInstrs += OtherSuccTIs.size() + 1;
+  ++NumHoistCommonInstrs;
 
   // Ensure terminator gets a debug location, even an unknown one, in case
   // it involves inlinable calls.
-  SmallVector<DILocation *, 4> Locs;
-  Locs.push_back(I1->getDebugLoc());
-  for (auto *OtherSuccTI : OtherSuccTIs)
-    Locs.push_back(OtherSuccTI->getDebugLoc());
-  NT->setDebugLoc(DILocation::getMergedLocations(Locs));
+  NT->applyMergedLocation(I1->getDebugLoc(), I2->getDebugLoc());
 
   // PHIs created below will adopt NT's merged DebugLoc.
   IRBuilder<NoFolder> Builder(NT);
 
-  // In the case of an if statement, hoisting one of the terminators from our
-  // successor is a great thing. Unfortunately, the successors of the if/else
-  // blocks may have PHI nodes in them.  If they do, all PHI entries for BB1/BB2
-  // must agree for all PHI nodes, so we insert select instruction to compute
-  // the final result.
-  if (BI) {
-    std::map<std::pair<Value *, Value *>, SelectInst *> InsertedSelects;
-    for (BasicBlock *Succ : successors(BB1)) {
-      for (PHINode &PN : Succ->phis()) {
-        Value *BB1V = PN.getIncomingValueForBlock(BB1);
-        Value *BB2V = PN.getIncomingValueForBlock(BB2);
-        if (BB1V == BB2V)
-          continue;
-
-        // These values do not agree.  Insert a select instruction before NT
-        // that determines the right value.
-        SelectInst *&SI = InsertedSelects[std::make_pair(BB1V, BB2V)];
-        if (!SI) {
-          // Propagate fast-math-flags from phi node to its replacement select.
-          IRBuilder<>::FastMathFlagGuard FMFGuard(Builder);
-          if (isa<FPMathOperator>(PN))
-            Builder.setFastMathFlags(PN.getFastMathFlags());
-
-          SI = cast<SelectInst>(Builder.CreateSelect(
-              BI->getCondition(), BB1V, BB2V,
-              BB1V->getName() + "." + BB2V->getName(), BI));
-        }
+  // Hoisting one of the terminators from our successor is a great thing.
+  // Unfortunately, the successors of the if/else blocks may have PHI nodes in
+  // them.  If they do, all PHI entries for BB1/BB2 must agree for all PHI
+  // nodes, so we insert select instruction to compute the final result.
+  std::map<std::pair<Value *, Value *>, SelectInst *> InsertedSelects;
+  for (BasicBlock *Succ : successors(BB1)) {
+    for (PHINode &PN : Succ->phis()) {
+      Value *BB1V = PN.getIncomingValueForBlock(BB1);
+      Value *BB2V = PN.getIncomingValueForBlock(BB2);
+      if (BB1V == BB2V)
+        continue;
 
-        // Make the PHI node use the select for all incoming values for BB1/BB2
-        for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i)
-          if (PN.getIncomingBlock(i) == BB1 || PN.getIncomingBlock(i) == BB2)
-            PN.setIncomingValue(i, SI);
+      // These values do not agree.  Insert a select instruction before NT
+      // that determines the right value.
+      SelectInst *&SI = InsertedSelects[std::make_pair(BB1V, BB2V)];
+      if (!SI) {
+        // Propagate fast-math-flags from phi node to its replacement select.
+        IRBuilder<>::FastMathFlagGuard FMFGuard(Builder);
+        if (isa<FPMathOperator>(PN))
+          Builder.setFastMathFlags(PN.getFastMathFlags());
+
+        SI = cast<SelectInst>(
+            Builder.CreateSelect(BI->getCondition(), BB1V, BB2V,
+                                 BB1V->getName() + "." + BB2V->getName(), BI));
       }
+
+      // Make the PHI node use the select for all incoming values for BB1/BB2
+      for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i)
+        if (PN.getIncomingBlock(i) == BB1 || PN.getIncomingBlock(i) == BB2)
+          PN.setIncomingValue(i, SI);
     }
   }
 
@@ -1807,16 +1734,16 @@ bool SimplifyCFGOpt::hoistSuccIdenticalTerminatorToSwitchOrIf(
 
   // Update any PHI nodes in our new successors.
   for (BasicBlock *Succ : successors(BB1)) {
-    AddPredecessorToBlock(Succ, TIParent, BB1);
+    AddPredecessorToBlock(Succ, BIParent, BB1);
     if (DTU)
-      Updates.push_back({DominatorTree::Insert, TIParent, Succ});
+      Updates.push_back({DominatorTree::Insert, BIParent, Succ});
   }
 
   if (DTU)
-    for (BasicBlock *Succ : successors(TI))
-      Updates.push_back({DominatorTree::Delete, TIParent, Succ});
+    for (BasicBlock *Succ : successors(BI))
+      Updates.push_back({DominatorTree::Delete, BIParent, Succ});
 
-  EraseTerminatorAndDCECond(TI);
+  EraseTerminatorAndDCECond(BI);
   if (DTU)
     DTU->applyUpdates(Updates);
   return Changed;
@@ -2850,8 +2777,8 @@ static bool validateAndCostRequiredSelects(BasicBlock *BB, BasicBlock *ThenBB,
     Value *OrigV = PN.getIncomingValueForBlock(BB);
     Value *ThenV = PN.getIncomingValueForBlock(ThenBB);
 
-    // FIXME: Try to remove some of the duplication with
-    // hoistCommonCodeFromSuccessors. Skip PHIs which are trivial.
+    // FIXME: Try to remove some of the duplication with HoistThenElseCodeToIf.
+    // Skip PHIs which are trivial.
     if (ThenV == OrigV)
       continue;
 
@@ -6888,10 +6815,6 @@ bool SimplifyCFGOpt::simplifySwitch(SwitchInst *SI, IRBuilder<> &Builder) {
   if (ReduceSwitchRange(SI, Builder, DL, TTI))
     return requestResimplify();
 
-  if (HoistCommon &&
-      hoistCommonCodeFromSuccessors(SI->getParent(), !Options.HoistCommonInsts))
-    return requestResimplify();
-
   return false;
 }
 
@@ -7158,8 +7081,7 @@ bool SimplifyCFGOpt::simplifyCondBranch(BranchInst *BI, IRBuilder<> &Builder) {
   // can hoist it up to the branching block.
   if (BI->getSuccessor(0)->getSinglePredecessor()) {
     if (BI->getSuccessor(1)->getSinglePredecessor()) {
-      if (HoistCommon && hoistCommonCodeFromSuccessors(
-                             BI->getParent(), !Options.HoistCommonInsts))
+      if (HoistCommon && HoistThenElseCodeToIf(BI, !Options.HoistCommonInsts))
         return requestResimplify();
     } else {
       // If Successor #1 has multiple preds, we may be able to conditionally

diff  --git a/llvm/test/CodeGen/AArch64/patchable-function-entry-bti.ll b/llvm/test/CodeGen/AArch64/patchable-function-entry-bti.ll
index 15657730c2cdcb6..0dfb5764f55b8cc 100644
--- a/llvm/test/CodeGen/AArch64/patchable-function-entry-bti.ll
+++ b/llvm/test/CodeGen/AArch64/patchable-function-entry-bti.ll
@@ -70,7 +70,7 @@ entry:
     i64 4, label %sw.bb4
   ]
 sw.bb0:
-  call void asm sideeffect "nop", ""()
+  call void asm sideeffect "", ""()
   ret void
 sw.bb1:
   call void asm sideeffect "", ""()

diff  --git a/llvm/test/Transforms/SimplifyCFG/HoistCode.ll b/llvm/test/Transforms/SimplifyCFG/HoistCode.ll
index 4088ecfc818982f..0b634fac8c640ae 100644
--- a/llvm/test/Transforms/SimplifyCFG/HoistCode.ll
+++ b/llvm/test/Transforms/SimplifyCFG/HoistCode.ll
@@ -19,9 +19,21 @@ F:              ; preds = %0
 
 define void @foo_switch(i64 %C, ptr %P) {
 ; CHECK-LABEL: @foo_switch(
-; CHECK-NEXT:  common.ret:
-; CHECK-NEXT:    store i32 7, ptr [[P:%.*]], align 4
+; CHECK-NEXT:    switch i64 [[C:%.*]], label [[BB0:%.*]] [
+; CHECK-NEXT:    i64 1, label [[BB1:%.*]]
+; CHECK-NEXT:    i64 2, label [[BB2:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       common.ret:
 ; CHECK-NEXT:    ret void
+; CHECK:       bb0:
+; CHECK-NEXT:    store i32 7, ptr [[P:%.*]], align 4
+; CHECK-NEXT:    br label [[COMMON_RET:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    store i32 7, ptr [[P]], align 4
+; CHECK-NEXT:    br label [[COMMON_RET]]
+; CHECK:       bb2:
+; CHECK-NEXT:    store i32 7, ptr [[P]], align 4
+; CHECK-NEXT:    br label [[COMMON_RET]]
 ;
   switch i64 %C, label %bb0 [
   i64 1, label %bb1

diff  --git a/llvm/test/Transforms/SimplifyCFG/hoist-common-code-with-unreachable.ll b/llvm/test/Transforms/SimplifyCFG/hoist-common-code-with-unreachable.ll
index d948737c16c9266..8cb6339713d6f6a 100644
--- a/llvm/test/Transforms/SimplifyCFG/hoist-common-code-with-unreachable.ll
+++ b/llvm/test/Transforms/SimplifyCFG/hoist-common-code-with-unreachable.ll
@@ -4,8 +4,25 @@
 define i1 @common_instr_with_unreachable(i64 %a, i64 %b, i64 %c) {
 ; CHECK-LABEL: @common_instr_with_unreachable(
 ; CHECK-NEXT:  start:
+; CHECK-NEXT:    switch i64 [[A:%.*]], label [[UNREACHABLE:%.*]] [
+; CHECK-NEXT:    i64 0, label [[BB0:%.*]]
+; CHECK-NEXT:    i64 1, label [[BB1:%.*]]
+; CHECK-NEXT:    i64 2, label [[BB2:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       unreachable:
+; CHECK-NEXT:    unreachable
+; CHECK:       bb0:
 ; CHECK-NEXT:    [[TMP0:%.*]] = icmp eq i64 [[B:%.*]], [[C:%.*]]
-; CHECK-NEXT:    ret i1 [[TMP0]]
+; CHECK-NEXT:    br label [[EXIT:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i64 [[B]], [[C]]
+; CHECK-NEXT:    br label [[EXIT]]
+; CHECK:       bb2:
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i64 [[B]], [[C]]
+; CHECK-NEXT:    br label [[EXIT]]
+; CHECK:       exit:
+; CHECK-NEXT:    [[RESULT:%.*]] = phi i1 [ [[TMP0]], [[BB0]] ], [ [[TMP1]], [[BB1]] ], [ [[TMP2]], [[BB2]] ]
+; CHECK-NEXT:    ret i1 [[RESULT]]
 ;
 start:
   switch i64 %a, label %unreachable [
@@ -37,90 +54,43 @@ exit:                                             ; preds = %bb2, %bb1, %bb0
 define i1 @common_instr_with_unreachable_2(i64 %a, i64 %b, i64 %c) {
 ; CHECK-LABEL: @common_instr_with_unreachable_2(
 ; CHECK-NEXT:  start:
-; CHECK-NEXT:    [[TMP0:%.*]] = icmp eq i64 [[B:%.*]], [[C:%.*]]
-; CHECK-NEXT:    ret i1 [[TMP0]]
-;
-start:
-  switch i64 %a, label %bb1 [
-  i64 0, label %bb0
-  i64 1, label %unreachable
-  i64 2, label %bb2
-  ]
-
-unreachable:
-  unreachable
-
-bb0:                                              ; preds = %start
-  %0 = icmp eq i64 %b, %c
-  br label %exit
-
-bb1:                                              ; preds = %start
-  %1 = icmp eq i64 %b, %c
-  br label %exit
-
-bb2:                                              ; preds = %start
-  %2 = icmp eq i64 %b, %c
-  br label %exit
-
-exit:                                             ; preds = %bb2, %bb1, %bb0
-  %result = phi i1 [ %0, %bb0 ], [ %1, %bb1 ], [ %2, %bb2 ]
-  ret i1 %result
-}
-
-declare void @no_return()
-declare void @foo()
-
-define i1 @not_only_unreachable(i64 %a, i64 %b, i64 %c) {
-; CHECK-LABEL: @not_only_unreachable(
-; CHECK-NEXT:  start:
-; CHECK-NEXT:    switch i64 [[A:%.*]], label [[UNREACHABLE:%.*]] [
+; CHECK-NEXT:    switch i64 [[A:%.*]], label [[BB1:%.*]] [
 ; CHECK-NEXT:    i64 0, label [[BB0:%.*]]
-; CHECK-NEXT:    i64 1, label [[BB1:%.*]]
 ; CHECK-NEXT:    i64 2, label [[BB2:%.*]]
 ; CHECK-NEXT:    ]
-; CHECK:       unreachable:
-; CHECK-NEXT:    call void @no_return()
-; CHECK-NEXT:    unreachable
 ; CHECK:       bb0:
 ; CHECK-NEXT:    [[TMP0:%.*]] = icmp eq i64 [[B:%.*]], [[C:%.*]]
-; CHECK-NEXT:    call void @foo()
 ; CHECK-NEXT:    br label [[EXIT:%.*]]
 ; CHECK:       bb1:
 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i64 [[B]], [[C]]
-; CHECK-NEXT:    call void @foo()
 ; CHECK-NEXT:    br label [[EXIT]]
 ; CHECK:       bb2:
 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i64 [[B]], [[C]]
-; CHECK-NEXT:    call void @foo()
 ; CHECK-NEXT:    br label [[EXIT]]
 ; CHECK:       exit:
 ; CHECK-NEXT:    [[RESULT:%.*]] = phi i1 [ [[TMP0]], [[BB0]] ], [ [[TMP1]], [[BB1]] ], [ [[TMP2]], [[BB2]] ]
 ; CHECK-NEXT:    ret i1 [[RESULT]]
 ;
 start:
-  switch i64 %a, label %unreachable [
+  switch i64 %a, label %bb1 [
   i64 0, label %bb0
-  i64 1, label %bb1
+  i64 1, label %unreachable
   i64 2, label %bb2
   ]
 
 unreachable:
-  call void @no_return()
   unreachable
 
 bb0:                                              ; preds = %start
   %0 = icmp eq i64 %b, %c
-  call void @foo()
   br label %exit
 
 bb1:                                              ; preds = %start
   %1 = icmp eq i64 %b, %c
-  call void @foo()
   br label %exit
 
 bb2:                                              ; preds = %start
   %2 = icmp eq i64 %b, %c
-  call void @foo()
   br label %exit
 
 exit:                                             ; preds = %bb2, %bb1, %bb0

diff  --git a/llvm/test/Transforms/SimplifyCFG/hoist-common-code.ll b/llvm/test/Transforms/SimplifyCFG/hoist-common-code.ll
index bfe31d8345d506c..43fb8faad7cfd94 100644
--- a/llvm/test/Transforms/SimplifyCFG/hoist-common-code.ll
+++ b/llvm/test/Transforms/SimplifyCFG/hoist-common-code.ll
@@ -26,11 +26,27 @@ F:              ; preds = %0
 
 define void @test_switch(i64 %i, ptr %Q) {
 ; CHECK-LABEL: @test_switch(
-; CHECK-NEXT:  common.ret:
+; CHECK-NEXT:    switch i64 [[I:%.*]], label [[BB0:%.*]] [
+; CHECK-NEXT:    i64 1, label [[BB1:%.*]]
+; CHECK-NEXT:    i64 2, label [[BB2:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       common.ret:
+; CHECK-NEXT:    ret void
+; CHECK:       bb0:
 ; CHECK-NEXT:    store i32 1, ptr [[Q:%.*]], align 4
 ; CHECK-NEXT:    [[A:%.*]] = load i32, ptr [[Q]], align 4
 ; CHECK-NEXT:    call void @bar(i32 [[A]])
-; CHECK-NEXT:    ret void
+; CHECK-NEXT:    br label [[COMMON_RET:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    store i32 1, ptr [[Q]], align 4
+; CHECK-NEXT:    [[B:%.*]] = load i32, ptr [[Q]], align 4
+; CHECK-NEXT:    call void @bar(i32 [[B]])
+; CHECK-NEXT:    br label [[COMMON_RET]]
+; CHECK:       bb2:
+; CHECK-NEXT:    store i32 1, ptr [[Q]], align 4
+; CHECK-NEXT:    [[C:%.*]] = load i32, ptr [[Q]], align 4
+; CHECK-NEXT:    call void @bar(i32 [[C]])
+; CHECK-NEXT:    br label [[COMMON_RET]]
 ;
   switch i64 %i, label %bb0 [
   i64 1, label %bb1
@@ -53,41 +69,25 @@ bb2:              ; preds = %0
   ret void
 }
 
-; We ensure that we examine all instructions during each iteration to confirm the presence of a terminating one.
-define void @test_switch_reach_terminator(i64 %i, ptr %p) {
-; CHECK-LABEL: @test_switch_reach_terminator(
-; CHECK-NEXT:    switch i64 [[I:%.*]], label [[BB0:%.*]] [
-; CHECK-NEXT:    i64 1, label [[BB1:%.*]]
-; CHECK-NEXT:    i64 2, label [[COMMON_RET:%.*]]
-; CHECK-NEXT:    ]
-; CHECK:       common.ret:
-; CHECK-NEXT:    ret void
-; CHECK:       bb0:
-; CHECK-NEXT:    store i32 1, ptr [[P:%.*]], align 4
-; CHECK-NEXT:    br label [[COMMON_RET]]
-; CHECK:       bb1:
-; CHECK-NEXT:    store i32 2, ptr [[P]], align 4
-; CHECK-NEXT:    br label [[COMMON_RET]]
-;
-  switch i64 %i, label %bb0 [
-  i64 1, label %bb1
-  i64 2, label %bb2
-  ]
-bb0:              ; preds = %0
-  store i32 1, ptr %p
-  ret void
-bb1:              ; preds = %0
-  store i32 2, ptr %p
-  ret void
-bb2:              ; preds = %0
-  ret void
-}
-
 define i1 @common_instr_on_switch(i64 %a, i64 %b, i64 %c) unnamed_addr {
 ; CHECK-LABEL: @common_instr_on_switch(
 ; CHECK-NEXT:  start:
+; CHECK-NEXT:    switch i64 [[A:%.*]], label [[BB0:%.*]] [
+; CHECK-NEXT:    i64 1, label [[BB1:%.*]]
+; CHECK-NEXT:    i64 2, label [[BB2:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       bb0:
 ; CHECK-NEXT:    [[TMP0:%.*]] = icmp eq i64 [[B:%.*]], [[C:%.*]]
-; CHECK-NEXT:    ret i1 [[TMP0]]
+; CHECK-NEXT:    br label [[EXIT:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i64 [[B]], [[C]]
+; CHECK-NEXT:    br label [[EXIT]]
+; CHECK:       bb2:
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i64 [[B]], [[C]]
+; CHECK-NEXT:    br label [[EXIT]]
+; CHECK:       exit:
+; CHECK-NEXT:    [[RESULT:%.*]] = phi i1 [ [[TMP0]], [[BB0]] ], [ [[TMP1]], [[BB1]] ], [ [[TMP2]], [[BB2]] ]
+; CHECK-NEXT:    ret i1 [[RESULT]]
 ;
 start:
   switch i64 %a, label %bb0 [

diff  --git a/llvm/test/Transforms/SimplifyCFG/hoist-common-skip.ll b/llvm/test/Transforms/SimplifyCFG/hoist-common-skip.ll
index 1e06abf62c9fe3e..93e822b589b1424 100644
--- a/llvm/test/Transforms/SimplifyCFG/hoist-common-skip.ll
+++ b/llvm/test/Transforms/SimplifyCFG/hoist-common-skip.ll
@@ -48,68 +48,6 @@ if.end:
   ret void
 }
 
-define void @f0_switch(i64 %i, ptr nocapture noundef %d, ptr nocapture noundef readonly %m,  ptr nocapture noundef readonly %b) {
-; CHECK-LABEL: @f0_switch(
-; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[TMP0:%.*]] = load i16, ptr [[B:%.*]], align 2
-; CHECK-NEXT:    [[TMP1:%.*]] = load i16, ptr [[M:%.*]], align 2
-; CHECK-NEXT:    switch i64 [[I:%.*]], label [[BB0:%.*]] [
-; CHECK-NEXT:    i64 1, label [[BB1:%.*]]
-; CHECK-NEXT:    i64 2, label [[BB2:%.*]]
-; CHECK-NEXT:    ]
-; CHECK:       bb0:
-; CHECK-NEXT:    [[ADD:%.*]] = add nsw i16 [[TMP0]], 1
-; CHECK-NEXT:    [[U:%.*]] = add i16 [[ADD]], [[TMP1]]
-; CHECK-NEXT:    br label [[END:%.*]]
-; CHECK:       bb1:
-; CHECK-NEXT:    [[SUB:%.*]] = sub nsw i16 [[TMP0]], 1
-; CHECK-NEXT:    [[TMP2:%.*]] = add i16 [[SUB]], 3
-; CHECK-NEXT:    [[V:%.*]] = add i16 [[SUB]], [[TMP2]]
-; CHECK-NEXT:    br label [[END]]
-; CHECK:       bb2:
-; CHECK-NEXT:    [[SUB2:%.*]] = sub nsw i16 [[TMP0]], 1
-; CHECK-NEXT:    [[TMP3:%.*]] = add i16 [[SUB2]], 3
-; CHECK-NEXT:    [[W:%.*]] = add i16 [[SUB2]], [[TMP3]]
-; CHECK-NEXT:    br label [[END]]
-; CHECK:       end:
-; CHECK-NEXT:    [[UV:%.*]] = phi i16 [ [[U]], [[BB0]] ], [ [[V]], [[BB1]] ], [ [[W]], [[BB2]] ]
-; CHECK-NEXT:    store i16 [[UV]], ptr [[D:%.*]], align 2
-; CHECK-NEXT:    ret void
-;
-entry:
-  switch i64 %i, label %bb0 [
-  i64 1, label %bb1
-  i64 2, label %bb2
-  ]
-
-bb0:
-  %0 = load i16, ptr %b, align 2
-  %add = add nsw i16 %0, 1
-  %1 = load i16, ptr %m, align 2
-  %u = add i16 %add, %1
-  br label %end
-
-bb1:
-  %2 = load i16, ptr %b, align 2
-  %sub = sub nsw i16 %2, 1
-  %3 = load i16, ptr %m, align 2
-  %4 = add i16 %sub, 3
-  %v = add i16 %sub, %4
-  br label %end
-
-bb2:
-  %5 = load i16, ptr %b, align 2
-  %sub2 = sub nsw i16 %5, 1
-  %6 = load i16, ptr %m, align 2
-  %7 = add i16 %sub2, 3
-  %w = add i16 %sub2, %7
-  br label %end
-
-end:
-  %uv = phi i16 [ %u, %bb0 ], [ %v, %bb1 ], [ %w, %bb2 ]
-  store i16 %uv, ptr %d, align 2
-  ret void
-}
 
 ;; Check some instructions (e.g. add) can be reordered across instructions with side
 ;; effects, while others (e.g. load) can't.
@@ -159,70 +97,6 @@ if.end:
   ret void
 }
 
-define void @f2_switch(i64 %i, ptr nocapture noundef %d, ptr nocapture noundef readonly %m, ptr nocapture noundef readonly %b) {
-; CHECK-LABEL: @f2_switch(
-; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[TMP0:%.*]] = load i16, ptr [[B:%.*]], align 2
-; CHECK-NEXT:    [[ADD_0:%.*]] = add nsw i16 [[TMP0]], 1
-; CHECK-NEXT:    switch i64 [[I:%.*]], label [[BB0:%.*]] [
-; CHECK-NEXT:    i64 1, label [[BB1:%.*]]
-; CHECK-NEXT:    i64 2, label [[BB2:%.*]]
-; CHECK-NEXT:    ]
-; CHECK:       bb0:
-; CHECK-NEXT:    call void @side_effects0()
-; CHECK-NEXT:    [[TMP1:%.*]] = load i16, ptr [[M:%.*]], align 2
-; CHECK-NEXT:    [[U:%.*]] = add i16 [[ADD_0]], [[TMP1]]
-; CHECK-NEXT:    br label [[END:%.*]]
-; CHECK:       bb1:
-; CHECK-NEXT:    call void @no_side_effects0()
-; CHECK-NEXT:    [[TMP2:%.*]] = load i16, ptr [[M]], align 2
-; CHECK-NEXT:    [[V:%.*]] = add i16 [[ADD_0]], [[TMP2]]
-; CHECK-NEXT:    br label [[END]]
-; CHECK:       bb2:
-; CHECK-NEXT:    call void @no_side_effects0()
-; CHECK-NEXT:    [[TMP3:%.*]] = load i16, ptr [[M]], align 2
-; CHECK-NEXT:    [[W:%.*]] = add i16 [[ADD_0]], [[TMP3]]
-; CHECK-NEXT:    br label [[END]]
-; CHECK:       end:
-; CHECK-NEXT:    [[UV:%.*]] = phi i16 [ [[U]], [[BB0]] ], [ [[V]], [[BB1]] ], [ [[W]], [[BB2]] ]
-; CHECK-NEXT:    store i16 [[UV]], ptr [[D:%.*]], align 2
-; CHECK-NEXT:    ret void
-;
-entry:
-  switch i64 %i, label %bb0 [
-  i64 1, label %bb1
-  i64 2, label %bb2
-  ]
-
-bb0:
-  %0 = load i16, ptr %b, align 2
-  call void @side_effects0()
-  %add.0 = add nsw i16 %0, 1
-  %1 = load i16, ptr %m, align 2
-  %u = add i16 %add.0, %1
-  br label %end
-
-bb1:
-  %2 = load i16, ptr %b, align 2
-  call void @no_side_effects0()
-  %add.1 = add nsw i16 %2, 1
-  %3 = load i16, ptr %m, align 2
-  %v = add i16 %add.1, %3
-  br label %end
-
-bb2:
-  %4 = load i16, ptr %b, align 2
-  call void @no_side_effects0()
-  %add.2 = add nsw i16 %4, 1
-  %5 = load i16, ptr %m, align 2
-  %w = add i16 %add.2, %5
-  br label %end
-
-end:
-  %uv = phi i16 [ %u, %bb0 ], [ %v, %bb1 ], [ %w, %bb2 ]
-  store i16 %uv, ptr %d, align 2
-  ret void
-}
 
 ;; Check indeed it was the side effects that prevented hoisting the load
 ;; in the previous test.
@@ -269,67 +143,6 @@ if.end:
   ret void
 }
 
-define void @f3_switch(i64 %i, ptr nocapture noundef %d, ptr nocapture noundef readonly %m, ptr nocapture noundef readonly %b) {
-; CHECK-LABEL: @f3_switch(
-; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[TMP0:%.*]] = load i16, ptr [[B:%.*]], align 2
-; CHECK-NEXT:    [[ADD_0:%.*]] = add nsw i16 [[TMP0]], 1
-; CHECK-NEXT:    [[TMP1:%.*]] = load i16, ptr [[M:%.*]], align 2
-; CHECK-NEXT:    [[U:%.*]] = add i16 [[ADD_0]], [[TMP1]]
-; CHECK-NEXT:    switch i64 [[I:%.*]], label [[BB0:%.*]] [
-; CHECK-NEXT:    i64 1, label [[BB1:%.*]]
-; CHECK-NEXT:    i64 2, label [[BB2:%.*]]
-; CHECK-NEXT:    ]
-; CHECK:       bb0:
-; CHECK-NEXT:    call void @no_side_effects0()
-; CHECK-NEXT:    br label [[END:%.*]]
-; CHECK:       bb1:
-; CHECK-NEXT:    call void @no_side_effects1()
-; CHECK-NEXT:    br label [[END]]
-; CHECK:       bb2:
-; CHECK-NEXT:    call void @no_side_effects1()
-; CHECK-NEXT:    br label [[END]]
-; CHECK:       end:
-; CHECK-NEXT:    [[UV:%.*]] = phi i16 [ [[U]], [[BB0]] ], [ [[U]], [[BB1]] ], [ [[U]], [[BB2]] ]
-; CHECK-NEXT:    store i16 [[UV]], ptr [[D:%.*]], align 2
-; CHECK-NEXT:    ret void
-;
-entry:
-  switch i64 %i, label %bb0 [
-  i64 1, label %bb1
-  i64 2, label %bb2
-  ]
-
-bb0:
-  %0 = load i16, ptr %b, align 2
-  call void @no_side_effects0()
-  %add.0 = add nsw i16 %0, 1
-  %1 = load i16, ptr %m, align 2
-  %u = add i16 %add.0, %1
-  br label %end
-
-bb1:
-  %2 = load i16, ptr %b, align 2
-  call void @no_side_effects1()
-  %add.1 = add nsw i16 %2, 1
-  %3 = load i16, ptr %m, align 2
-  %v = add i16 %add.1, %3
-  br label %end
-
-bb2:
-  %4 = load i16, ptr %b, align 2
-  call void @no_side_effects1()
-  %add.2 = add nsw i16 %4, 1
-  %5 = load i16, ptr %m, align 2
-  %w = add i16 %add.2, %5
-  br label %end
-
-end:
-  %uv = phi i16 [ %u, %bb0 ], [ %v, %bb1 ], [ %w, %bb2 ]
-  store i16 %uv, ptr %d, align 2
-  ret void
-}
-
 ;; Check some instructions (e.g. sdiv) are not speculatively executed.
 
 ;; Division by non-zero constant OK to speculate ...
@@ -373,63 +186,6 @@ if.end:
   ret void
 }
 
-define void @f4_switch(i64 %i, ptr nocapture noundef %d, ptr nocapture noundef readonly %m, ptr nocapture noundef readonly %b) {
-; CHECK-LABEL: @f4_switch(
-; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[TMP0:%.*]] = load i16, ptr [[B:%.*]], align 2
-; CHECK-NEXT:    [[DIV_0:%.*]] = sdiv i16 [[TMP0]], 2
-; CHECK-NEXT:    [[U:%.*]] = add i16 [[DIV_0]], [[TMP0]]
-; CHECK-NEXT:    switch i64 [[I:%.*]], label [[BB0:%.*]] [
-; CHECK-NEXT:    i64 1, label [[BB1:%.*]]
-; CHECK-NEXT:    i64 2, label [[BB2:%.*]]
-; CHECK-NEXT:    ]
-; CHECK:       bb0:
-; CHECK-NEXT:    call void @side_effects0()
-; CHECK-NEXT:    br label [[IF_END:%.*]]
-; CHECK:       bb1:
-; CHECK-NEXT:    call void @side_effects1()
-; CHECK-NEXT:    br label [[IF_END]]
-; CHECK:       bb2:
-; CHECK-NEXT:    call void @side_effects1()
-; CHECK-NEXT:    br label [[IF_END]]
-; CHECK:       if.end:
-; CHECK-NEXT:    [[UV:%.*]] = phi i16 [ [[U]], [[BB0]] ], [ [[U]], [[BB1]] ], [ [[U]], [[BB2]] ]
-; CHECK-NEXT:    store i16 [[UV]], ptr [[D:%.*]], align 2
-; CHECK-NEXT:    ret void
-;
-entry:
-  switch i64 %i, label %bb0 [
-  i64 1, label %bb1
-  i64 2, label %bb2
-  ]
-
-bb0:
-  %0 = load i16, ptr %b, align 2
-  call void @side_effects0()
-  %div.0 = sdiv i16 %0, 2
-  %u = add i16 %div.0, %0
-  br label %if.end
-
-bb1:
-  %1 = load i16, ptr %b, align 2
-  call void @side_effects1()
-  %div.1 = sdiv i16 %1, 2
-  %v = add i16 %div.1, %1
-  br label %if.end
-
-bb2:
-  %2 = load i16, ptr %b, align 2
-  call void @side_effects1()
-  %div.2 = sdiv i16 %2, 2
-  %w = add i16 %div.2, %2
-  br label %if.end
-
-if.end:
-  %uv = phi i16 [ %u, %bb0 ], [ %v, %bb1 ], [ %w, %bb2 ]
-  store i16 %uv, ptr %d, align 2
-  ret void
-}
-
 ;; ... but not a general division ...
 define void @f5(i1 %c, ptr nocapture noundef %d, ptr nocapture noundef readonly %m, ptr nocapture noundef readonly %b) {
 ; CHECK-LABEL: @f5(
@@ -474,67 +230,6 @@ if.end:
   ret void
 }
 
-define void @f5_switch(i64 %i, ptr nocapture noundef %d, ptr nocapture noundef readonly %m, ptr nocapture noundef readonly %b) {
-; CHECK-LABEL: @f5_switch(
-; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[TMP0:%.*]] = load i16, ptr [[B:%.*]], align 2
-; CHECK-NEXT:    switch i64 [[I:%.*]], label [[BB0:%.*]] [
-; CHECK-NEXT:    i64 1, label [[BB1:%.*]]
-; CHECK-NEXT:    i64 2, label [[BB2:%.*]]
-; CHECK-NEXT:    ]
-; CHECK:       bb0:
-; CHECK-NEXT:    call void @side_effects0()
-; CHECK-NEXT:    [[DIV_0:%.*]] = sdiv i16 211, [[TMP0]]
-; CHECK-NEXT:    [[U:%.*]] = add i16 [[DIV_0]], [[TMP0]]
-; CHECK-NEXT:    br label [[END:%.*]]
-; CHECK:       bb1:
-; CHECK-NEXT:    call void @side_effects1()
-; CHECK-NEXT:    [[DIV_1:%.*]] = sdiv i16 211, [[TMP0]]
-; CHECK-NEXT:    [[V:%.*]] = add i16 [[DIV_1]], [[TMP0]]
-; CHECK-NEXT:    br label [[END]]
-; CHECK:       bb2:
-; CHECK-NEXT:    call void @side_effects1()
-; CHECK-NEXT:    [[DIV_2:%.*]] = sdiv i16 211, [[TMP0]]
-; CHECK-NEXT:    [[W:%.*]] = add i16 [[DIV_2]], [[TMP0]]
-; CHECK-NEXT:    br label [[END]]
-; CHECK:       end:
-; CHECK-NEXT:    [[UV:%.*]] = phi i16 [ [[U]], [[BB0]] ], [ [[V]], [[BB1]] ], [ [[W]], [[BB2]] ]
-; CHECK-NEXT:    store i16 [[UV]], ptr [[D:%.*]], align 2
-; CHECK-NEXT:    ret void
-;
-entry:
-  switch i64 %i, label %bb0 [
-  i64 1, label %bb1
-  i64 2, label %bb2
-  ]
-
-bb0:
-  %0 = load i16, ptr %b, align 2
-  call void @side_effects0()
-  %div.0 = sdiv i16 211, %0
-  %u = add i16 %div.0, %0
-  br label %end
-
-bb1:
-  %1 = load i16, ptr %b, align 2
-  call void @side_effects1()
-  %div.1 = sdiv i16 211, %1
-  %v = add i16 %div.1, %1
-  br label %end
-
-bb2:
-  %2 = load i16, ptr %b, align 2
-  call void @side_effects1()
-  %div.2 = sdiv i16 211, %2
-  %w = add i16 %div.2, %2
-  br label %end
-
-end:
-  %uv = phi i16 [ %u, %bb0 ], [ %v, %bb1 ], [ %w, %bb2 ]
-  store i16 %uv, ptr %d, align 2
-  ret void
-}
-
 ;; ... and it's also OK to hoist the division when there's no speculation happening.
 define void @f6(i1 %c, ptr nocapture noundef %d, ptr nocapture noundef readonly %m, ptr nocapture noundef readonly %b) {
 ; CHECK-LABEL: @f6(
@@ -576,63 +271,6 @@ if.end:
   ret void
 }
 
-define void @f6_switch(i64 %i, ptr nocapture noundef %d, ptr nocapture noundef readonly %m, ptr nocapture noundef readonly %b) {
-; CHECK-LABEL: @f6_switch(
-; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[TMP0:%.*]] = load i16, ptr [[B:%.*]], align 2
-; CHECK-NEXT:    [[DIV_0:%.*]] = sdiv i16 211, [[TMP0]]
-; CHECK-NEXT:    [[U:%.*]] = add i16 [[DIV_0]], [[TMP0]]
-; CHECK-NEXT:    switch i64 [[I:%.*]], label [[BB0:%.*]] [
-; CHECK-NEXT:    i64 1, label [[BB1:%.*]]
-; CHECK-NEXT:    i64 2, label [[BB2:%.*]]
-; CHECK-NEXT:    ]
-; CHECK:       bb0:
-; CHECK-NEXT:    call void @no_side_effects0()
-; CHECK-NEXT:    br label [[END:%.*]]
-; CHECK:       bb1:
-; CHECK-NEXT:    call void @no_side_effects1()
-; CHECK-NEXT:    br label [[END]]
-; CHECK:       bb2:
-; CHECK-NEXT:    call void @no_side_effects1()
-; CHECK-NEXT:    br label [[END]]
-; CHECK:       end:
-; CHECK-NEXT:    [[UV:%.*]] = phi i16 [ [[U]], [[BB0]] ], [ [[U]], [[BB1]] ], [ [[U]], [[BB2]] ]
-; CHECK-NEXT:    store i16 [[UV]], ptr [[D:%.*]], align 2
-; CHECK-NEXT:    ret void
-;
-entry:
-  switch i64 %i, label %bb0 [
-  i64 1, label %bb1
-  i64 2, label %bb2
-  ]
-
-bb0:
-  %0 = load i16, ptr %b, align 2
-  call void @no_side_effects0()
-  %div.0 = sdiv i16 211, %0
-  %u = add i16 %div.0, %0
-  br label %end
-
-bb1:
-  %1 = load i16, ptr %b, align 2
-  call void @no_side_effects1()
-  %div.1 = sdiv i16 211, %1
-  %v = add i16 %div.1, %1
-  br label %end
-
-bb2:
-  %2 = load i16, ptr %b, align 2
-  call void @no_side_effects1()
-  %div.2 = sdiv i16 211, %2
-  %w = add i16 %div.2, %2
-  br label %end
-
-end:
-  %uv = phi i16 [ %u, %bb0 ], [ %v, %bb1 ], [ %w, %bb2 ]
-  store i16 %uv, ptr %d, align 2
-  ret void
-}
-
 ;; No reorder of store over a load.
 define i16 @f7(i1 %c, ptr %a, ptr %b) {
 ; CHECK-LABEL: @f7(
@@ -668,55 +306,6 @@ if.end:
   ret i16 %v
 }
 
-define i16 @f7_switch(i64 %i, ptr %a, ptr %b) {
-; CHECK-LABEL: @f7_switch(
-; CHECK-NEXT:  entry:
-; CHECK-NEXT:    switch i64 [[I:%.*]], label [[BB0:%.*]] [
-; CHECK-NEXT:    i64 1, label [[BB1:%.*]]
-; CHECK-NEXT:    i64 2, label [[BB2:%.*]]
-; CHECK-NEXT:    ]
-; CHECK:       bb0:
-; CHECK-NEXT:    [[VA:%.*]] = load i16, ptr [[A:%.*]], align 2
-; CHECK-NEXT:    store i16 0, ptr [[B:%.*]], align 2
-; CHECK-NEXT:    br label [[END:%.*]]
-; CHECK:       bb1:
-; CHECK-NEXT:    [[VB:%.*]] = load i16, ptr [[B]], align 2
-; CHECK-NEXT:    store i16 0, ptr [[B]], align 2
-; CHECK-NEXT:    br label [[END]]
-; CHECK:       bb2:
-; CHECK-NEXT:    [[VC:%.*]] = load i16, ptr [[B]], align 2
-; CHECK-NEXT:    store i16 0, ptr [[B]], align 2
-; CHECK-NEXT:    br label [[END]]
-; CHECK:       end:
-; CHECK-NEXT:    [[V:%.*]] = phi i16 [ [[VA]], [[BB0]] ], [ [[VB]], [[BB1]] ], [ [[VC]], [[BB2]] ]
-; CHECK-NEXT:    ret i16 [[V]]
-;
-entry:
-  switch i64 %i, label %bb0 [
-  i64 1, label %bb1
-  i64 2, label %bb2
-  ]
-
-bb0:
-  %va = load i16, ptr %a, align 2
-  store i16 0, ptr %b, align 2
-  br label %end
-
-bb1:
-  %vb = load i16, ptr %b, align 2
-  store i16 0, ptr %b, align 2
-  br label %end
-
-bb2:
-  %vc = load i16, ptr %b, align 2
-  store i16 0, ptr %b, align 2
-  br label %end
-
-end:
-  %v = phi i16 [ %va, %bb0 ], [ %vb, %bb1 ], [ %vc, %bb2 ]
-  ret i16 %v
-}
-
 ;; Can reorder load over another load
 define i16 @f8(i1 %cond, ptr %a, ptr %b, ptr %c) {
 ; CHECK-LABEL: @f8(
@@ -757,59 +346,6 @@ if.end:
   ret i16 %w
 }
 
-define i16 @f8_switch(i64 %i, ptr %a, ptr %b, ptr %c) {
-; CHECK-LABEL: @f8_switch(
-; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[C_0:%.*]] = load i16, ptr [[C:%.*]], align 2
-; CHECK-NEXT:    switch i64 [[I:%.*]], label [[BB0:%.*]] [
-; CHECK-NEXT:    i64 1, label [[BB1:%.*]]
-; CHECK-NEXT:    i64 2, label [[BB2:%.*]]
-; CHECK-NEXT:    ]
-; CHECK:       bb0:
-; CHECK-NEXT:    [[VA:%.*]] = load i16, ptr [[A:%.*]], align 2
-; CHECK-NEXT:    br label [[END:%.*]]
-; CHECK:       bb1:
-; CHECK-NEXT:    [[VB:%.*]] = load i16, ptr [[B:%.*]], align 2
-; CHECK-NEXT:    br label [[END]]
-; CHECK:       bb2:
-; CHECK-NEXT:    [[VC:%.*]] = load i16, ptr [[B]], align 2
-; CHECK-NEXT:    br label [[END]]
-; CHECK:       end:
-; CHECK-NEXT:    [[V:%.*]] = phi i16 [ [[VA]], [[BB0]] ], [ [[VB]], [[BB1]] ], [ [[VC]], [[BB2]] ]
-; CHECK-NEXT:    [[U:%.*]] = phi i16 [ [[C_0]], [[BB0]] ], [ [[C_0]], [[BB1]] ], [ [[C_0]], [[BB2]] ]
-; CHECK-NEXT:    [[W:%.*]] = add i16 [[V]], [[U]]
-; CHECK-NEXT:    ret i16 [[W]]
-;
-entry:
-  switch i64 %i, label %bb0 [
-  i64 1, label %bb1
-  i64 2, label %bb2
-  ]
-
-bb0:
-  %va = load i16, ptr %a, align 2
-  %c.0 = load i16, ptr %c
-  br label %end
-
-bb1:
-  %vb = load i16, ptr %b, align 2
-  %c.1 = load i16, ptr %c
-  br label %end
-
-bb2:
-  %vc = load i16, ptr %b, align 2
-  %c.2 = load i16, ptr %c
-  br label %end
-
-end:
-  %v = phi i16 [ %va, %bb0 ], [ %vb, %bb1 ], [ %vc, %bb2 ]
-  %u = phi i16 [ %c.0, %bb0 ], [ %c.1, %bb1 ], [ %c.2, %bb2 ]
-
-  %w = add i16 %v, %u
-
-  ret i16 %w
-}
-
 ;; Currently won't reorder volatile and non-volatile loads.
 define i16 @f9(i1 %cond, ptr %a, ptr %b, ptr %c) {
 ; CHECK-LABEL: @f9(
@@ -851,61 +387,6 @@ if.end:
   ret i16 %w
 }
 
-define i16 @f9_switch(i64 %i, ptr %a, ptr %b, ptr %c) {
-; CHECK-LABEL: @f9_switch(
-; CHECK-NEXT:  entry:
-; CHECK-NEXT:    switch i64 [[I:%.*]], label [[BB0:%.*]] [
-; CHECK-NEXT:    i64 1, label [[BB1:%.*]]
-; CHECK-NEXT:    i64 2, label [[BB2:%.*]]
-; CHECK-NEXT:    ]
-; CHECK:       bb0:
-; CHECK-NEXT:    [[VA:%.*]] = load volatile i16, ptr [[A:%.*]], align 2
-; CHECK-NEXT:    [[C_0:%.*]] = load i16, ptr [[C:%.*]], align 2
-; CHECK-NEXT:    br label [[END:%.*]]
-; CHECK:       bb1:
-; CHECK-NEXT:    [[VB:%.*]] = load i16, ptr [[B:%.*]], align 2
-; CHECK-NEXT:    [[C_1:%.*]] = load i16, ptr [[C]], align 2
-; CHECK-NEXT:    br label [[END]]
-; CHECK:       bb2:
-; CHECK-NEXT:    [[VC:%.*]] = load i16, ptr [[B]], align 2
-; CHECK-NEXT:    [[C_2:%.*]] = load i16, ptr [[C]], align 2
-; CHECK-NEXT:    br label [[END]]
-; CHECK:       end:
-; CHECK-NEXT:    [[V:%.*]] = phi i16 [ [[VA]], [[BB0]] ], [ [[VB]], [[BB1]] ], [ [[VC]], [[BB2]] ]
-; CHECK-NEXT:    [[U:%.*]] = phi i16 [ [[C_0]], [[BB0]] ], [ [[C_1]], [[BB1]] ], [ [[C_2]], [[BB2]] ]
-; CHECK-NEXT:    [[W:%.*]] = add i16 [[V]], [[U]]
-; CHECK-NEXT:    ret i16 [[W]]
-;
-entry:
-  switch i64 %i, label %bb0 [
-  i64 1, label %bb1
-  i64 2, label %bb2
-  ]
-
-bb0:
-  %va = load volatile i16, ptr %a, align 2
-  %c.0 = load i16, ptr %c
-  br label %end
-
-bb1:
-  %vb = load i16, ptr %b, align 2
-  %c.1 = load i16, ptr %c
-  br label %end
-
-bb2:
-  %vc = load i16, ptr %b, align 2
-  %c.2 = load i16, ptr %c
-  br label %end
-
-end:
-  %v = phi i16 [ %va, %bb0 ], [ %vb, %bb1 ], [ %vc, %bb2 ]
-  %u = phi i16 [ %c.0, %bb0 ], [ %c.1, %bb1 ], [ %c.2, %bb2 ]
-
-  %w = add i16 %v, %u
-
-  ret i16 %w
-}
-
 ;; Don't hoist stacksaves across inalloca allocas
 define void @f10(i1 %cond) {
 ; CHECK-LABEL: @f10(
@@ -957,79 +438,6 @@ end:
   ret void
 }
 
-define void @f10_switch(i64 %i) {
-; CHECK-LABEL: @f10_switch(
-; CHECK-NEXT:    [[SS:%.*]] = call ptr @llvm.stacksave.p0()
-; CHECK-NEXT:    switch i64 [[I:%.*]], label [[BB0:%.*]] [
-; CHECK-NEXT:    i64 1, label [[BB1:%.*]]
-; CHECK-NEXT:    i64 2, label [[BB2:%.*]]
-; CHECK-NEXT:    ]
-; CHECK:       bb0:
-; CHECK-NEXT:    [[I1:%.*]] = alloca inalloca i32, align 4
-; CHECK-NEXT:    [[SS2:%.*]] = call ptr @llvm.stacksave.p0()
-; CHECK-NEXT:    [[I2:%.*]] = alloca inalloca i64, align 8
-; CHECK-NEXT:    call void @inalloca_i64(ptr inalloca(i64) [[I2]])
-; CHECK-NEXT:    call void @llvm.stackrestore.p0(ptr [[SS2]])
-; CHECK-NEXT:    call void @inalloca_i32(ptr inalloca(i32) [[I1]])
-; CHECK-NEXT:    br label [[END:%.*]]
-; CHECK:       bb1:
-; CHECK-NEXT:    [[I3:%.*]] = alloca inalloca i64, align 8
-; CHECK-NEXT:    [[SS3:%.*]] = call ptr @llvm.stacksave.p0()
-; CHECK-NEXT:    [[I4:%.*]] = alloca inalloca i64, align 8
-; CHECK-NEXT:    [[TMP1:%.*]] = call ptr @inalloca_i64(ptr inalloca(i64) [[I4]])
-; CHECK-NEXT:    call void @llvm.stackrestore.p0(ptr [[SS3]])
-; CHECK-NEXT:    [[TMP2:%.*]] = call ptr @inalloca_i64(ptr inalloca(i64) [[I3]])
-; CHECK-NEXT:    br label [[END]]
-; CHECK:       bb2:
-; CHECK-NEXT:    [[I5:%.*]] = alloca inalloca i64, align 8
-; CHECK-NEXT:    [[SS4:%.*]] = call ptr @llvm.stacksave.p0()
-; CHECK-NEXT:    [[I6:%.*]] = alloca inalloca i64, align 8
-; CHECK-NEXT:    [[TMP3:%.*]] = call ptr @inalloca_i64(ptr inalloca(i64) [[I6]])
-; CHECK-NEXT:    call void @llvm.stackrestore.p0(ptr [[SS4]])
-; CHECK-NEXT:    [[TMP4:%.*]] = call ptr @inalloca_i64(ptr inalloca(i64) [[I5]])
-; CHECK-NEXT:    br label [[END]]
-; CHECK:       end:
-; CHECK-NEXT:    call void @llvm.stackrestore.p0(ptr [[SS]])
-; CHECK-NEXT:    ret void
-;
-  %ss = call ptr @llvm.stacksave()
-  switch i64 %i, label %bb0 [
-  i64 1, label %bb1
-  i64 2, label %bb2
-  ]
-
-bb0:
-  %i1 = alloca inalloca i32
-  %ss2 = call ptr @llvm.stacksave()
-  %i2 = alloca inalloca i64
-  call void @inalloca_i64(ptr inalloca(i64) %i2)
-  call void @llvm.stackrestore(ptr %ss2)
-  call void @inalloca_i32(ptr inalloca(i32) %i1)
-  br label %end
-
-bb1:
-  %i3 = alloca inalloca i64
-  %ss3 = call ptr @llvm.stacksave()
-  %i4 = alloca inalloca i64
-  call ptr @inalloca_i64(ptr inalloca(i64) %i4)
-  call void @llvm.stackrestore(ptr %ss3)
-  call ptr @inalloca_i64(ptr inalloca(i64) %i3)
-  br label %end
-
-bb2:
-  %i5 = alloca inalloca i64
-  %ss4 = call ptr @llvm.stacksave()
-  %i6 = alloca inalloca i64
-  call ptr @inalloca_i64(ptr inalloca(i64) %i6)
-  call void @llvm.stackrestore(ptr %ss4)
-  call ptr @inalloca_i64(ptr inalloca(i64) %i5)
-  br label %end
-
-end:
-  call void @llvm.stackrestore(ptr %ss)
-  ret void
-}
-
 declare void @side_effects0()
 declare void @side_effects1()
 declare void @no_side_effects0() readonly nounwind willreturn

diff  --git a/llvm/test/Transforms/SimplifyCFG/hoist-with-metadata.ll b/llvm/test/Transforms/SimplifyCFG/hoist-with-metadata.ll
index 90daf38e39d529e..b53224c944f1101 100644
--- a/llvm/test/Transforms/SimplifyCFG/hoist-with-metadata.ll
+++ b/llvm/test/Transforms/SimplifyCFG/hoist-with-metadata.ll
@@ -21,8 +21,20 @@ out:
 
 define void @hoist_range_switch(i64 %i, ptr %p) {
 ; CHECK-LABEL: @hoist_range_switch(
-; CHECK-NEXT:  out:
+; CHECK-NEXT:    switch i64 [[I:%.*]], label [[BB0:%.*]] [
+; CHECK-NEXT:    i64 1, label [[BB1:%.*]]
+; CHECK-NEXT:    i64 2, label [[BB2:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       bb0:
 ; CHECK-NEXT:    [[T:%.*]] = load i8, ptr [[P:%.*]], align 1, !range [[RNG1:![0-9]+]]
+; CHECK-NEXT:    br label [[OUT:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    [[E:%.*]] = load i8, ptr [[P]], align 1, !range [[RNG2:![0-9]+]]
+; CHECK-NEXT:    br label [[OUT]]
+; CHECK:       bb2:
+; CHECK-NEXT:    [[F:%.*]] = load i8, ptr [[P]], align 1, !range [[RNG3:![0-9]+]]
+; CHECK-NEXT:    br label [[OUT]]
+; CHECK:       out:
 ; CHECK-NEXT:    ret void
 ;
   switch i64 %i, label %bb0 [
@@ -45,7 +57,7 @@ out:
 define void @hoist_both_noundef(i1 %c, ptr %p) {
 ; CHECK-LABEL: @hoist_both_noundef(
 ; CHECK-NEXT:  if:
-; CHECK-NEXT:    [[T:%.*]] = load i8, ptr [[P:%.*]], align 1, !noundef !2
+; CHECK-NEXT:    [[T:%.*]] = load i8, ptr [[P:%.*]], align 1, !noundef !4
 ; CHECK-NEXT:    ret void
 ;
 if:
@@ -66,8 +78,20 @@ out:
 
 define void @hoist_both_noundef_switch(i64 %i, ptr %p) {
 ; CHECK-LABEL: @hoist_both_noundef_switch(
-; CHECK-NEXT:  out:
-; CHECK-NEXT:    [[T:%.*]] = load i8, ptr [[P:%.*]], align 1, !noundef !2
+; CHECK-NEXT:    switch i64 [[I:%.*]], label [[BB0:%.*]] [
+; CHECK-NEXT:    i64 1, label [[BB1:%.*]]
+; CHECK-NEXT:    i64 2, label [[BB2:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       bb0:
+; CHECK-NEXT:    [[T:%.*]] = load i8, ptr [[P:%.*]], align 1, !noundef !4
+; CHECK-NEXT:    br label [[OUT:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    [[E:%.*]] = load i8, ptr [[P]], align 1, !noundef !4
+; CHECK-NEXT:    br label [[OUT]]
+; CHECK:       bb2:
+; CHECK-NEXT:    [[F:%.*]] = load i8, ptr [[P]], align 1, !noundef !4
+; CHECK-NEXT:    br label [[OUT]]
+; CHECK:       out:
 ; CHECK-NEXT:    ret void
 ;
   switch i64 %i, label %bb0 [
@@ -110,8 +134,20 @@ out:
 
 define void @hoist_one_noundef_switch(i64 %i, ptr %p) {
 ; CHECK-LABEL: @hoist_one_noundef_switch(
-; CHECK-NEXT:  out:
-; CHECK-NEXT:    [[T:%.*]] = load i8, ptr [[P:%.*]], align 1
+; CHECK-NEXT:    switch i64 [[I:%.*]], label [[BB0:%.*]] [
+; CHECK-NEXT:    i64 1, label [[BB1:%.*]]
+; CHECK-NEXT:    i64 2, label [[BB2:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       bb0:
+; CHECK-NEXT:    [[T:%.*]] = load i8, ptr [[P:%.*]], align 1, !noundef !4
+; CHECK-NEXT:    br label [[OUT:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    [[E:%.*]] = load i8, ptr [[P]], align 1
+; CHECK-NEXT:    br label [[OUT]]
+; CHECK:       bb2:
+; CHECK-NEXT:    [[F:%.*]] = load i8, ptr [[P]], align 1, !noundef !4
+; CHECK-NEXT:    br label [[OUT]]
+; CHECK:       out:
 ; CHECK-NEXT:    ret void
 ;
   switch i64 %i, label %bb0 [
@@ -134,7 +170,7 @@ out:
 define void @hoist_dereferenceable(i1 %c, ptr %p) {
 ; CHECK-LABEL: @hoist_dereferenceable(
 ; CHECK-NEXT:  if:
-; CHECK-NEXT:    [[T:%.*]] = load ptr, ptr [[P:%.*]], align 8, !dereferenceable !3
+; CHECK-NEXT:    [[T:%.*]] = load ptr, ptr [[P:%.*]], align 8, !dereferenceable !5
 ; CHECK-NEXT:    ret void
 ;
 if:
@@ -151,8 +187,20 @@ out:
 
 define void @hoist_dereferenceable_switch(i64 %i, ptr %p) {
 ; CHECK-LABEL: @hoist_dereferenceable_switch(
-; CHECK-NEXT:  out:
-; CHECK-NEXT:    [[T:%.*]] = load ptr, ptr [[P:%.*]], align 8, !dereferenceable !3
+; CHECK-NEXT:    switch i64 [[I:%.*]], label [[BB0:%.*]] [
+; CHECK-NEXT:    i64 1, label [[BB1:%.*]]
+; CHECK-NEXT:    i64 2, label [[BB2:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       bb0:
+; CHECK-NEXT:    [[T:%.*]] = load ptr, ptr [[P:%.*]], align 8, !dereferenceable !5
+; CHECK-NEXT:    br label [[OUT:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    [[E:%.*]] = load ptr, ptr [[P]], align 8, !dereferenceable !6
+; CHECK-NEXT:    br label [[OUT]]
+; CHECK:       bb2:
+; CHECK-NEXT:    [[F:%.*]] = load ptr, ptr [[P]], align 8, !dereferenceable !7
+; CHECK-NEXT:    br label [[OUT]]
+; CHECK:       out:
 ; CHECK-NEXT:    ret void
 ;
   switch i64 %i, label %bb0 [
@@ -175,7 +223,7 @@ out:
 define void @hoist_dereferenceable_or_null(i1 %c, ptr %p) {
 ; CHECK-LABEL: @hoist_dereferenceable_or_null(
 ; CHECK-NEXT:  if:
-; CHECK-NEXT:    [[T:%.*]] = load ptr, ptr [[P:%.*]], align 8, !dereferenceable_or_null !3
+; CHECK-NEXT:    [[T:%.*]] = load ptr, ptr [[P:%.*]], align 8, !dereferenceable_or_null !5
 ; CHECK-NEXT:    ret void
 ;
 if:
@@ -192,8 +240,20 @@ out:
 
 define void @hoist_dereferenceable_or_null_switch(i64 %i, ptr %p) {
 ; CHECK-LABEL: @hoist_dereferenceable_or_null_switch(
-; CHECK-NEXT:  out:
-; CHECK-NEXT:    [[T:%.*]] = load ptr, ptr [[P:%.*]], align 8, !dereferenceable_or_null !3
+; CHECK-NEXT:    switch i64 [[I:%.*]], label [[BB0:%.*]] [
+; CHECK-NEXT:    i64 1, label [[BB1:%.*]]
+; CHECK-NEXT:    i64 2, label [[BB2:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       bb0:
+; CHECK-NEXT:    [[T:%.*]] = load ptr, ptr [[P:%.*]], align 8, !dereferenceable_or_null !6
+; CHECK-NEXT:    br label [[OUT:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    [[E:%.*]] = load ptr, ptr [[P]], align 8, !dereferenceable_or_null !5
+; CHECK-NEXT:    br label [[OUT]]
+; CHECK:       bb2:
+; CHECK-NEXT:    [[F:%.*]] = load ptr, ptr [[P]], align 8, !dereferenceable_or_null !7
+; CHECK-NEXT:    br label [[OUT]]
+; CHECK:       out:
 ; CHECK-NEXT:    ret void
 ;
   switch i64 %i, label %bb0 [
@@ -217,7 +277,7 @@ out:
 define i32 @speculate_range(i1 %c, ptr dereferenceable(8) align 8 %p) {
 ; CHECK-LABEL: @speculate_range(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[V:%.*]] = load i32, ptr [[P:%.*]], align 4, !range [[RNG4:![0-9]+]]
+; CHECK-NEXT:    [[V:%.*]] = load i32, ptr [[P:%.*]], align 4, !range [[RNG8:![0-9]+]]
 ; CHECK-NEXT:    [[SPEC_SELECT:%.*]] = select i1 [[C:%.*]], i32 [[V]], i32 0
 ; CHECK-NEXT:    ret i32 [[SPEC_SELECT]]
 ;
@@ -238,7 +298,7 @@ join:
 define ptr @speculate_nonnull(i1 %c, ptr dereferenceable(8) align 8 %p) {
 ; CHECK-LABEL: @speculate_nonnull(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[V:%.*]] = load ptr, ptr [[P:%.*]], align 8, !nonnull !2
+; CHECK-NEXT:    [[V:%.*]] = load ptr, ptr [[P:%.*]], align 8, !nonnull !4
 ; CHECK-NEXT:    [[SPEC_SELECT:%.*]] = select i1 [[C:%.*]], ptr [[V]], ptr null
 ; CHECK-NEXT:    ret ptr [[SPEC_SELECT]]
 ;
@@ -259,7 +319,7 @@ join:
 define ptr @speculate_align(i1 %c, ptr dereferenceable(8) align 8 %p) {
 ; CHECK-LABEL: @speculate_align(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[V:%.*]] = load ptr, ptr [[P:%.*]], align 8, !align !5
+; CHECK-NEXT:    [[V:%.*]] = load ptr, ptr [[P:%.*]], align 8, !align !9
 ; CHECK-NEXT:    [[SPEC_SELECT:%.*]] = select i1 [[C:%.*]], ptr [[V]], ptr null
 ; CHECK-NEXT:    ret ptr [[SPEC_SELECT]]
 ;
@@ -278,7 +338,7 @@ join:
 define void @hoist_fpmath(i1 %c, double %x) {
 ; CHECK-LABEL: @hoist_fpmath(
 ; CHECK-NEXT:  if:
-; CHECK-NEXT:    [[T:%.*]] = fadd double [[X:%.*]], 1.000000e+00, !fpmath !6
+; CHECK-NEXT:    [[T:%.*]] = fadd double [[X:%.*]], 1.000000e+00, !fpmath !10
 ; CHECK-NEXT:    ret void
 ;
 if:
@@ -295,8 +355,20 @@ out:
 
 define void @hoist_fpmath_switch(i64 %i, double %x) {
 ; CHECK-LABEL: @hoist_fpmath_switch(
-; CHECK-NEXT:  out:
-; CHECK-NEXT:    [[T:%.*]] = fadd double [[X:%.*]], 1.000000e+00, !fpmath !6
+; CHECK-NEXT:    switch i64 [[I:%.*]], label [[BB0:%.*]] [
+; CHECK-NEXT:    i64 1, label [[BB1:%.*]]
+; CHECK-NEXT:    i64 2, label [[BB2:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       bb0:
+; CHECK-NEXT:    [[T:%.*]] = fadd double [[X:%.*]], 1.000000e+00, !fpmath !10
+; CHECK-NEXT:    br label [[OUT:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    [[E:%.*]] = fadd double [[X]], 1.000000e+00, !fpmath !11
+; CHECK-NEXT:    br label [[OUT]]
+; CHECK:       bb2:
+; CHECK-NEXT:    [[F:%.*]] = fadd double [[X]], 1.000000e+00, !fpmath !12
+; CHECK-NEXT:    br label [[OUT]]
+; CHECK:       out:
 ; CHECK-NEXT:    ret void
 ;
   switch i64 %i, label %bb0 [
@@ -322,10 +394,16 @@ out:
 !3 = !{ i8 7, i8 9 }
 ;.
 ; CHECK: [[RNG0]] = !{i8 0, i8 1, i8 3, i8 5}
-; CHECK: [[RNG1]] = !{i8 0, i8 1, i8 3, i8 5, i8 7, i8 9}
-; CHECK: [[META2:![0-9]+]] = !{}
-; CHECK: [[META3:![0-9]+]] = !{i64 10}
-; CHECK: [[RNG4]] = !{i32 0, i32 10}
-; CHECK: [[META5:![0-9]+]] = !{i64 4}
-; CHECK: [[META6:![0-9]+]] = !{float 2.500000e+00}
+; CHECK: [[RNG1]] = !{i8 0, i8 1}
+; CHECK: [[RNG2]] = !{i8 3, i8 5}
+; CHECK: [[RNG3]] = !{i8 7, i8 9}
+; CHECK: [[META4:![0-9]+]] = !{}
+; CHECK: [[META5:![0-9]+]] = !{i64 10}
+; CHECK: [[META6:![0-9]+]] = !{i64 20}
+; CHECK: [[META7:![0-9]+]] = !{i64 30}
+; CHECK: [[RNG8]] = !{i32 0, i32 10}
+; CHECK: [[META9:![0-9]+]] = !{i64 4}
+; CHECK: [[META10:![0-9]+]] = !{float 2.500000e+00}
+; CHECK: [[META11:![0-9]+]] = !{float 5.000000e+00}
+; CHECK: [[META12:![0-9]+]] = !{float 7.500000e+00}
 ;.


        


More information about the llvm-commits mailing list