///===- SimpleLoopUnswitch.cpp - Hoist loop-invariant control flow ---------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/Scalar/SimpleLoopUnswitch.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Sequence.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Analysis/AssumptionCache.h"
#include "llvm/Analysis/BlockFrequencyInfo.h"
#include "llvm/Analysis/CFG.h"
#include "llvm/Analysis/CodeMetrics.h"
#include "llvm/Analysis/DomTreeUpdater.h"
#include "llvm/Analysis/GuardUtils.h"
#include "llvm/Analysis/LoopAnalysisManager.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/LoopIterator.h"
#include "llvm/Analysis/MemorySSA.h"
#include "llvm/Analysis/MemorySSAUpdater.h"
#include "llvm/Analysis/MustExecute.h"
#include "llvm/Analysis/ProfileSummaryInfo.h"
#include "llvm/Analysis/ScalarEvolution.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Constant.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/PatternMatch.h"
#include "llvm/IR/ProfDataUtils.h"
#include "llvm/IR/Use.h"
#include "llvm/IR/Value.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/GenericDomTree.h"
#include "llvm/Support/InstructionCost.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/Scalar/LoopPassManager.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/Transforms/Utils/LoopUtils.h"
#include "llvm/Transforms/Utils/ValueMapper.h"
#include <algorithm>
#include <cassert>
#include <iterator>
#include <numeric>
#include <optional>
#include <utility>

#define DEBUG_TYPE "simple-loop-unswitch"

using namespace llvm;
using namespace llvm::PatternMatch;

STATISTIC(NumBranches, "Number of branches unswitched");
STATISTIC(NumSwitches, "Number of switches unswitched");
STATISTIC(NumSelects, "Number of selects turned into branches for unswitching");
STATISTIC(NumGuards, "Number of guards turned into branches for unswitching");
STATISTIC(NumTrivial, "Number of unswitches that are trivial");
STATISTIC(
    NumCostMultiplierSkipped,
    "Number of unswitch candidates that had their cost multiplier skipped");
STATISTIC(NumInvariantConditionsInjected,
          "Number of invariant conditions injected and unswitched");

static cl::opt<bool> EnableNonTrivialUnswitch(
    "enable-nontrivial-unswitch", cl::init(false), cl::Hidden,
    cl::desc("Forcibly enables non-trivial loop unswitching rather than "
             "following the configuration passed into the pass."));

static cl::opt<int>
    UnswitchThreshold("unswitch-threshold", cl::init(50), cl::Hidden,
                      cl::desc("The cost threshold for unswitching a loop."));

static cl::opt<bool> EnableUnswitchCostMultiplier(
    "enable-unswitch-cost-multiplier", cl::init(true), cl::Hidden,
    cl::desc("Enable unswitch cost multiplier that prohibits exponential "
             "explosion in nontrivial unswitch."));
static cl::opt<int> UnswitchSiblingsToplevelDiv(
    "unswitch-siblings-toplevel-div", cl::init(2), cl::Hidden,
    cl::desc("Toplevel siblings divisor for cost multiplier."));
static cl::opt<int> UnswitchNumInitialUnscaledCandidates(
    "unswitch-num-initial-unscaled-candidates", cl::init(8), cl::Hidden,
    cl::desc("Number of unswitch candidates that are ignored when calculating "
             "cost multiplier."));
static cl::opt<bool> UnswitchGuards(
    "simple-loop-unswitch-guards", cl::init(true), cl::Hidden,
    cl::desc("If enabled, simple loop unswitching will also consider "
             "llvm.experimental.guard intrinsics as unswitch candidates."));
static cl::opt<bool> DropNonTrivialImplicitNullChecks(
    "simple-loop-unswitch-drop-non-trivial-implicit-null-checks",
    cl::init(false), cl::Hidden,
    cl::desc("If enabled, drop make.implicit metadata in unswitched implicit "
             "null checks to save time analyzing if we can keep it."));
static cl::opt<unsigned>
    MSSAThreshold("simple-loop-unswitch-memoryssa-threshold",
                  cl::desc("Max number of memory uses to explore during "
                           "partial unswitching analysis"),
                  cl::init(100), cl::Hidden);
static cl::opt<bool> FreezeLoopUnswitchCond(
    "freeze-loop-unswitch-cond", cl::init(true), cl::Hidden,
    cl::desc("If enabled, the freeze instruction will be added to condition "
             "of loop unswitch to prevent miscompilation."));

static cl::opt<bool> InjectInvariantConditions(
    "simple-loop-unswitch-inject-invariant-conditions", cl::Hidden,
    cl::desc("Whether we should inject new invariants and unswitch them to "
             "eliminate some existing (non-invariant) conditions."),
    cl::init(true));

static cl::opt<unsigned> InjectInvariantConditionHotnesThreshold(
    "simple-loop-unswitch-inject-invariant-condition-hotness-threshold",
    cl::Hidden, cl::desc("Only try to inject loop invariant conditions and "
                         "unswitch on them to eliminate branches that are "
                         "not-taken 1/<this option> times or less."),
    cl::init(16));

AnalysisKey ShouldRunExtraSimpleLoopUnswitch::Key;
namespace {
struct CompareDesc {
  BranchInst *Term;
  Value *Invariant;
  BasicBlock *InLoopSucc;

  CompareDesc(BranchInst *Term, Value *Invariant, BasicBlock *InLoopSucc)
      : Term(Term), Invariant(Invariant), InLoopSucc(InLoopSucc) {}
};

struct InjectedInvariant {
  ICmpInst::Predicate Pred;
  Value *LHS;
  Value *RHS;
  BasicBlock *InLoopSucc;

  InjectedInvariant(ICmpInst::Predicate Pred, Value *LHS, Value *RHS,
                    BasicBlock *InLoopSucc)
      : Pred(Pred), LHS(LHS), RHS(RHS), InLoopSucc(InLoopSucc) {}
};

struct NonTrivialUnswitchCandidate {
  Instruction *TI = nullptr;
  TinyPtrVector<Value *> Invariants;
  std::optional<InstructionCost> Cost;
  std::optional<InjectedInvariant> PendingInjection;
  NonTrivialUnswitchCandidate(
      Instruction *TI, ArrayRef<Value *> Invariants,
      std::optional<InstructionCost> Cost = std::nullopt,
      std::optional<InjectedInvariant> PendingInjection = std::nullopt)
      : TI(TI), Invariants(Invariants), Cost(Cost),
        PendingInjection(PendingInjection) {};

  bool hasPendingInjection() const { return PendingInjection.has_value(); }
};
} // end anonymous namespace.

// Helper to skip (select x, true, false), which matches both a logical AND and
// OR and can confuse code that tries to determine if \p Cond is either a
// logical AND or OR but not both.
static Value *skipTrivialSelect(Value *Cond) {
  Value *CondNext;
  while (match(Cond, m_Select(m_Value(CondNext), m_One(), m_Zero())))
    Cond = CondNext;
  return Cond;
}

/// Collect all of the loop invariant input values transitively used by the
/// homogeneous instruction graph from a given root.
///
/// This essentially walks from a root recursively through loop variant operands
/// which have perform the same logical operation (AND or OR) and finds all
/// inputs which are loop invariant. For some operations these can be
/// re-associated and unswitched out of the loop entirely.
static TinyPtrVector<Value *>
collectHomogenousInstGraphLoopInvariants(const Loop &L, Instruction &Root,
                                         const LoopInfo &LI) {
  assert(!L.isLoopInvariant(&Root) &&
         "Only need to walk the graph if root itself is not invariant.");
  TinyPtrVector<Value *> Invariants;

  bool IsRootAnd = match(&Root, m_LogicalAnd());
  bool IsRootOr  = match(&Root, m_LogicalOr());

  // Build a worklist and recurse through operators collecting invariants.
  SmallVector<Instruction *, 4> Worklist;
  SmallPtrSet<Instruction *, 8> Visited;
  Worklist.push_back(&Root);
  Visited.insert(&Root);
  do {
    Instruction &I = *Worklist.pop_back_val();
    for (Value *OpV : I.operand_values()) {
      // Skip constants as unswitching isn't interesting for them.
      if (isa<Constant>(OpV))
        continue;

      // Add it to our result if loop invariant.
      if (L.isLoopInvariant(OpV)) {
        Invariants.push_back(OpV);
        continue;
      }

      // If not an instruction with the same opcode, nothing we can do.
      Instruction *OpI = dyn_cast<Instruction>(skipTrivialSelect(OpV));

      if (OpI && ((IsRootAnd && match(OpI, m_LogicalAnd())) ||
                  (IsRootOr  && match(OpI, m_LogicalOr())))) {
        // Visit this operand.
        if (Visited.insert(OpI).second)
          Worklist.push_back(OpI);
      }
    }
  } while (!Worklist.empty());

  return Invariants;
}

static void replaceLoopInvariantUses(const Loop &L, Value *Invariant,
                                     Constant &Replacement) {
  assert(!isa<Constant>(Invariant) && "Why are we unswitching on a constant?");

  // Replace uses of LIC in the loop with the given constant.
  // We use make_early_inc_range as set invalidates the iterator.
  for (Use &U : llvm::make_early_inc_range(Invariant->uses())) {
    Instruction *UserI = dyn_cast<Instruction>(U.getUser());

    // Replace this use within the loop body.
    if (UserI && L.contains(UserI))
      U.set(&Replacement);
  }
}

/// Check that all the LCSSA PHI nodes in the loop exit block have trivial
/// incoming values along this edge.
static bool areLoopExitPHIsLoopInvariant(const Loop &L,
                                         const BasicBlock &ExitingBB,
                                         const BasicBlock &ExitBB) {
  for (const Instruction &I : ExitBB) {
    auto *PN = dyn_cast<PHINode>(&I);
    if (!PN)
      // No more PHIs to check.
      return true;

    // If the incoming value for this edge isn't loop invariant the unswitch
    // won't be trivial.
    if (!L.isLoopInvariant(PN->getIncomingValueForBlock(&ExitingBB)))
      return false;
  }
  llvm_unreachable("Basic blocks should never be empty!");
}

/// Copy a set of loop invariant values \p ToDuplicate and insert them at the
/// end of \p BB and conditionally branch on the copied condition. We only
/// branch on a single value.
static void buildPartialUnswitchConditionalBranch(
    BasicBlock &BB, ArrayRef<Value *> Invariants, bool Direction,
    BasicBlock &UnswitchedSucc, BasicBlock &NormalSucc, bool InsertFreeze,
    const Instruction *I, AssumptionCache *AC, const DominatorTree &DT) {
  IRBuilder<> IRB(&BB);

  SmallVector<Value *> FrozenInvariants;
  for (Value *Inv : Invariants) {
    if (InsertFreeze && !isGuaranteedNotToBeUndefOrPoison(Inv, AC, I, &DT))
      Inv = IRB.CreateFreeze(Inv, Inv->getName() + ".fr");
    FrozenInvariants.push_back(Inv);
  }

  Value *Cond = Direction ? IRB.CreateOr(FrozenInvariants)
                          : IRB.CreateAnd(FrozenInvariants);
  IRB.CreateCondBr(Cond, Direction ? &UnswitchedSucc : &NormalSucc,
                   Direction ? &NormalSucc : &UnswitchedSucc);
}

/// Copy a set of loop invariant values, and conditionally branch on them.
static void buildPartialInvariantUnswitchConditionalBranch(
    BasicBlock &BB, ArrayRef<Value *> ToDuplicate, bool Direction,
    BasicBlock &UnswitchedSucc, BasicBlock &NormalSucc, Loop &L,
    MemorySSAUpdater *MSSAU) {
  ValueToValueMapTy VMap;
  for (auto *Val : reverse(ToDuplicate)) {
    Instruction *Inst = cast<Instruction>(Val);
    Instruction *NewInst = Inst->clone();
    NewInst->insertInto(&BB, BB.end());
    RemapInstruction(NewInst, VMap,
                     RF_NoModuleLevelChanges | RF_IgnoreMissingLocals);
    VMap[Val] = NewInst;

    if (!MSSAU)
      continue;

    MemorySSA *MSSA = MSSAU->getMemorySSA();
    if (auto *MemUse =
            dyn_cast_or_null<MemoryUse>(MSSA->getMemoryAccess(Inst))) {
      auto *DefiningAccess = MemUse->getDefiningAccess();
      // Get the first defining access before the loop.
      while (L.contains(DefiningAccess->getBlock())) {
        // If the defining access is a MemoryPhi, get the incoming
        // value for the pre-header as defining access.
        if (auto *MemPhi = dyn_cast<MemoryPhi>(DefiningAccess))
          DefiningAccess =
              MemPhi->getIncomingValueForBlock(L.getLoopPreheader());
        else
          DefiningAccess = cast<MemoryDef>(DefiningAccess)->getDefiningAccess();
      }
      MSSAU->createMemoryAccessInBB(NewInst, DefiningAccess,
                                    NewInst->getParent(),
                                    MemorySSA::BeforeTerminator);
    }
  }

  IRBuilder<> IRB(&BB);
  Value *Cond = VMap[ToDuplicate[0]];
  IRB.CreateCondBr(Cond, Direction ? &UnswitchedSucc : &NormalSucc,
                   Direction ? &NormalSucc : &UnswitchedSucc);
}

/// Rewrite the PHI nodes in an unswitched loop exit basic block.
///
/// Requires that the loop exit and unswitched basic block are the same, and
/// that the exiting block was a unique predecessor of that block. Rewrites the
/// PHI nodes in that block such that what were LCSSA PHI nodes become trivial
/// PHI nodes from the old preheader that now contains the unswitched
/// terminator.
static void rewritePHINodesForUnswitchedExitBlock(BasicBlock &UnswitchedBB,
                                                  BasicBlock &OldExitingBB,
                                                  BasicBlock &OldPH) {
  for (PHINode &PN : UnswitchedBB.phis()) {
    // When the loop exit is directly unswitched we just need to update the
    // incoming basic block. We loop to handle weird cases with repeated
    // incoming blocks, but expect to typically only have one operand here.
    for (auto i : seq<int>(0, PN.getNumOperands())) {
      assert(PN.getIncomingBlock(i) == &OldExitingBB &&
             "Found incoming block different from unique predecessor!");
      PN.setIncomingBlock(i, &OldPH);
    }
  }
}

/// Rewrite the PHI nodes in the loop exit basic block and the split off
/// unswitched block.
///
/// Because the exit block remains an exit from the loop, this rewrites the
/// LCSSA PHI nodes in it to remove the unswitched edge and introduces PHI
/// nodes into the unswitched basic block to select between the value in the
/// old preheader and the loop exit.
static void rewritePHINodesForExitAndUnswitchedBlocks(BasicBlock &ExitBB,
                                                      BasicBlock &UnswitchedBB,
                                                      BasicBlock &OldExitingBB,
                                                      BasicBlock &OldPH,
                                                      bool FullUnswitch) {
  assert(&ExitBB != &UnswitchedBB &&
         "Must have different loop exit and unswitched blocks!");
  BasicBlock::iterator InsertPt = UnswitchedBB.begin();
  for (PHINode &PN : ExitBB.phis()) {
    auto *NewPN = PHINode::Create(PN.getType(), /*NumReservedValues*/ 2,
                                  PN.getName() + ".split");
    NewPN->insertBefore(InsertPt);

    // Walk backwards over the old PHI node's inputs to minimize the cost of
    // removing each one. We have to do this weird loop manually so that we
    // create the same number of new incoming edges in the new PHI as we expect
    // each case-based edge to be included in the unswitched switch in some
    // cases.
    // FIXME: This is really, really gross. It would be much cleaner if LLVM
    // allowed us to create a single entry for a predecessor block without
    // having separate entries for each "edge" even though these edges are
    // required to produce identical results.
    for (int i = PN.getNumIncomingValues() - 1; i >= 0; --i) {
      if (PN.getIncomingBlock(i) != &OldExitingBB)
        continue;

      Value *Incoming = PN.getIncomingValue(i);
      if (FullUnswitch)
        // No more edge from the old exiting block to the exit block.
        PN.removeIncomingValue(i);

      NewPN->addIncoming(Incoming, &OldPH);
    }

    // Now replace the old PHI with the new one and wire the old one in as an
    // input to the new one.
    PN.replaceAllUsesWith(NewPN);
    NewPN->addIncoming(&PN, &ExitBB);
  }
}

/// Hoist the current loop up to the innermost loop containing a remaining exit.
///
/// Because we've removed an exit from the loop, we may have changed the set of
/// loops reachable and need to move the current loop up the loop nest or even
/// to an entirely separate nest.
static void hoistLoopToNewParent(Loop &L, BasicBlock &Preheader,
                                 DominatorTree &DT, LoopInfo &LI,
                                 MemorySSAUpdater *MSSAU, ScalarEvolution *SE) {
  // If the loop is already at the top level, we can't hoist it anywhere.
  Loop *OldParentL = L.getParentLoop();
  if (!OldParentL)
    return;

  SmallVector<BasicBlock *, 4> Exits;
  L.getExitBlocks(Exits);
  Loop *NewParentL = nullptr;
  for (auto *ExitBB : Exits)
    if (Loop *ExitL = LI.getLoopFor(ExitBB))
      if (!NewParentL || NewParentL->contains(ExitL))
        NewParentL = ExitL;

  if (NewParentL == OldParentL)
    return;

  // The new parent loop (if different) should always contain the old one.
  if (NewParentL)
    assert(NewParentL->contains(OldParentL) &&
           "Can only hoist this loop up the nest!");

  // The preheader will need to move with the body of this loop. However,
  // because it isn't in this loop we also need to update the primary loop map.
  assert(OldParentL == LI.getLoopFor(&Preheader) &&
         "Parent loop of this loop should contain this loop's preheader!");
  LI.changeLoopFor(&Preheader, NewParentL);

  // Remove this loop from its old parent.
  OldParentL->removeChildLoop(&L);

  // Add the loop either to the new parent or as a top-level loop.
  if (NewParentL)
    NewParentL->addChildLoop(&L);
  else
    LI.addTopLevelLoop(&L);

  // Remove this loops blocks from the old parent and every other loop up the
  // nest until reaching the new parent. Also update all of these
  // no-longer-containing loops to reflect the nesting change.
  for (Loop *OldContainingL = OldParentL; OldContainingL != NewParentL;
       OldContainingL = OldContainingL->getParentLoop()) {
    llvm::erase_if(OldContainingL->getBlocksVector(),
                   [&](const BasicBlock *BB) {
                     return BB == &Preheader || L.contains(BB);
                   });

    OldContainingL->getBlocksSet().erase(&Preheader);
    for (BasicBlock *BB : L.blocks())
      OldContainingL->getBlocksSet().erase(BB);

    // Because we just hoisted a loop out of this one, we have essentially
    // created new exit paths from it. That means we need to form LCSSA PHI
    // nodes for values used in the no-longer-nested loop.
    formLCSSA(*OldContainingL, DT, &LI, SE);

    // We shouldn't need to form dedicated exits because the exit introduced
    // here is the (just split by unswitching) preheader. However, after trivial
    // unswitching it is possible to get new non-dedicated exits out of parent
    // loop so let's conservatively form dedicated exit blocks and figure out
    // if we can optimize later.
    formDedicatedExitBlocks(OldContainingL, &DT, &LI, MSSAU,
                            /*PreserveLCSSA*/ true);
  }
}

// Return the top-most loop containing ExitBB and having ExitBB as exiting block
// or the loop containing ExitBB, if there is no parent loop containing ExitBB
// as exiting block.
static Loop *getTopMostExitingLoop(const BasicBlock *ExitBB,
                                   const LoopInfo &LI) {
  Loop *TopMost = LI.getLoopFor(ExitBB);
  Loop *Current = TopMost;
  while (Current) {
    if (Current->isLoopExiting(ExitBB))
      TopMost = Current;
    Current = Current->getParentLoop();
  }
  return TopMost;
}

/// Unswitch a trivial branch if the condition is loop invariant.
///
/// This routine should only be called when loop code leading to the branch has
/// been validated as trivial (no side effects). This routine checks if the
/// condition is invariant and one of the successors is a loop exit. This
/// allows us to unswitch without duplicating the loop, making it trivial.
///
/// If this routine fails to unswitch the branch it returns false.
///
/// If the branch can be unswitched, this routine splits the preheader and
/// hoists the branch above that split. Preserves loop simplified form
/// (splitting the exit block as necessary). It simplifies the branch within
/// the loop to an unconditional branch but doesn't remove it entirely. Further
/// cleanup can be done with some simplifycfg like pass.
///
/// If `SE` is not null, it will be updated based on the potential loop SCEVs
/// invalidated by this.
static bool unswitchTrivialBranch(Loop &L, BranchInst &BI, DominatorTree &DT,
                                  LoopInfo &LI, ScalarEvolution *SE,
                                  MemorySSAUpdater *MSSAU) {
  assert(BI.isConditional() && "Can only unswitch a conditional branch!");
  LLVM_DEBUG(dbgs() << "  Trying to unswitch branch: " << BI << "\n");

  // The loop invariant values that we want to unswitch.
  TinyPtrVector<Value *> Invariants;

  // When true, we're fully unswitching the branch rather than just unswitching
  // some input conditions to the branch.
  bool FullUnswitch = false;

  Value *Cond = skipTrivialSelect(BI.getCondition());
  if (L.isLoopInvariant(Cond)) {
    Invariants.push_back(Cond);
    FullUnswitch = true;
  } else {
    if (auto *CondInst = dyn_cast<Instruction>(Cond))
      Invariants = collectHomogenousInstGraphLoopInvariants(L, *CondInst, LI);
    if (Invariants.empty()) {
      LLVM_DEBUG(dbgs() << "   Couldn't find invariant inputs!\n");
      return false;
    }
  }

  // Check that one of the branch's successors exits, and which one.
  bool ExitDirection = true;
  int LoopExitSuccIdx = 0;
  auto *LoopExitBB = BI.getSuccessor(0);
  if (L.contains(LoopExitBB)) {
    ExitDirection = false;
    LoopExitSuccIdx = 1;
    LoopExitBB = BI.getSuccessor(1);
    if (L.contains(LoopExitBB)) {
      LLVM_DEBUG(dbgs() << "   Branch doesn't exit the loop!\n");
      return false;
    }
  }
  auto *ContinueBB = BI.getSuccessor(1 - LoopExitSuccIdx);
  auto *ParentBB = BI.getParent();
  if (!areLoopExitPHIsLoopInvariant(L, *ParentBB, *LoopExitBB)) {
    LLVM_DEBUG(dbgs() << "   Loop exit PHI's aren't loop-invariant!\n");
    return false;
  }

  // When unswitching only part of the branch's condition, we need the exit
  // block to be reached directly from the partially unswitched input. This can
  // be done when the exit block is along the true edge and the branch condition
  // is a graph of `or` operations, or the exit block is along the false edge
  // and the condition is a graph of `and` operations.
  if (!FullUnswitch) {
    if (ExitDirection ? !match(Cond, m_LogicalOr())
                      : !match(Cond, m_LogicalAnd())) {
      LLVM_DEBUG(dbgs() << "   Branch condition is in improper form for "
                           "non-full unswitch!\n");
      return false;
    }
  }

  LLVM_DEBUG({
    dbgs() << "    unswitching trivial invariant conditions for: " << BI
           << "\n";
    for (Value *Invariant : Invariants) {
      dbgs() << "      " << *Invariant << " == true";
      if (Invariant != Invariants.back())
        dbgs() << " ||";
      dbgs() << "\n";
    }
  });

  // If we have scalar evolutions, we need to invalidate them including this
  // loop, the loop containing the exit block and the topmost parent loop
  // exiting via LoopExitBB.
  if (SE) {
    if (const Loop *ExitL = getTopMostExitingLoop(LoopExitBB, LI))
      SE->forgetLoop(ExitL);
    else
      // Forget the entire nest as this exits the entire nest.
      SE->forgetTopmostLoop(&L);
    SE->forgetBlockAndLoopDispositions();
  }

  if (MSSAU && VerifyMemorySSA)
    MSSAU->getMemorySSA()->verifyMemorySSA();

  // Split the preheader, so that we know that there is a safe place to insert
  // the conditional branch. We will change the preheader to have a conditional
  // branch on LoopCond.
  BasicBlock *OldPH = L.getLoopPreheader();
  BasicBlock *NewPH = SplitEdge(OldPH, L.getHeader(), &DT, &LI, MSSAU);

  // Now that we have a place to insert the conditional branch, create a place
  // to branch to: this is the exit block out of the loop that we are
  // unswitching. We need to split this if there are other loop predecessors.
  // Because the loop is in simplified form, *any* other predecessor is enough.
  BasicBlock *UnswitchedBB;
  if (FullUnswitch && LoopExitBB->getUniquePredecessor()) {
    assert(LoopExitBB->getUniquePredecessor() == BI.getParent() &&
           "A branch's parent isn't a predecessor!");
    UnswitchedBB = LoopExitBB;
  } else {
    UnswitchedBB =
        SplitBlock(LoopExitBB, LoopExitBB->begin(), &DT, &LI, MSSAU, "", false);
  }

  if (MSSAU && VerifyMemorySSA)
    MSSAU->getMemorySSA()->verifyMemorySSA();

  // Actually move the invariant uses into the unswitched position. If possible,
  // we do this by moving the instructions, but when doing partial unswitching
  // we do it by building a new merge of the values in the unswitched position.
  OldPH->getTerminator()->eraseFromParent();
  if (FullUnswitch) {
    // If fully unswitching, we can use the existing branch instruction.
    // Splice it into the old PH to gate reaching the new preheader and re-point
    // its successors.
    BI.moveBefore(*OldPH, OldPH->end());
    BI.setCondition(Cond);
    if (MSSAU) {
      // Temporarily clone the terminator, to make MSSA update cheaper by
      // separating "insert edge" updates from "remove edge" ones.
      BI.clone()->insertInto(ParentBB, ParentBB->end());
    } else {
      // Create a new unconditional branch that will continue the loop as a new
      // terminator.
      BranchInst::Create(ContinueBB, ParentBB);
    }
    BI.setSuccessor(LoopExitSuccIdx, UnswitchedBB);
    BI.setSuccessor(1 - LoopExitSuccIdx, NewPH);
  } else {
    // Only unswitching a subset of inputs to the condition, so we will need to
    // build a new branch that merges the invariant inputs.
    if (ExitDirection)
      assert(match(skipTrivialSelect(BI.getCondition()), m_LogicalOr()) &&
             "Must have an `or` of `i1`s or `select i1 X, true, Y`s for the "
             "condition!");
    else
      assert(match(skipTrivialSelect(BI.getCondition()), m_LogicalAnd()) &&
             "Must have an `and` of `i1`s or `select i1 X, Y, false`s for the"
             " condition!");
    buildPartialUnswitchConditionalBranch(
        *OldPH, Invariants, ExitDirection, *UnswitchedBB, *NewPH,
        FreezeLoopUnswitchCond, OldPH->getTerminator(), nullptr, DT);
  }

  // Update the dominator tree with the added edge.
  DT.insertEdge(OldPH, UnswitchedBB);

  // After the dominator tree was updated with the added edge, update MemorySSA
  // if available.
  if (MSSAU) {
    SmallVector<CFGUpdate, 1> Updates;
    Updates.push_back({cfg::UpdateKind::Insert, OldPH, UnswitchedBB});
    MSSAU->applyInsertUpdates(Updates, DT);
  }

  // Finish updating dominator tree and memory ssa for full unswitch.
  if (FullUnswitch) {
    if (MSSAU) {
      // Remove the cloned branch instruction.
      ParentBB->getTerminator()->eraseFromParent();
      // Create unconditional branch now.
      BranchInst::Create(ContinueBB, ParentBB);
      MSSAU->removeEdge(ParentBB, LoopExitBB);
    }
    DT.deleteEdge(ParentBB, LoopExitBB);
  }

  if (MSSAU && VerifyMemorySSA)
    MSSAU->getMemorySSA()->verifyMemorySSA();

  // Rewrite the relevant PHI nodes.
  if (UnswitchedBB == LoopExitBB)
    rewritePHINodesForUnswitchedExitBlock(*UnswitchedBB, *ParentBB, *OldPH);
  else
    rewritePHINodesForExitAndUnswitchedBlocks(*LoopExitBB, *UnswitchedBB,
                                              *ParentBB, *OldPH, FullUnswitch);

  // The constant we can replace all of our invariants with inside the loop
  // body. If any of the invariants have a value other than this the loop won't
  // be entered.
  ConstantInt *Replacement = ExitDirection
                                 ? ConstantInt::getFalse(BI.getContext())
                                 : ConstantInt::getTrue(BI.getContext());

  // Since this is an i1 condition we can also trivially replace uses of it
  // within the loop with a constant.
  for (Value *Invariant : Invariants)
    replaceLoopInvariantUses(L, Invariant, *Replacement);

  // If this was full unswitching, we may have changed the nesting relationship
  // for this loop so hoist it to its correct parent if needed.
  if (FullUnswitch)
    hoistLoopToNewParent(L, *NewPH, DT, LI, MSSAU, SE);

  if (MSSAU && VerifyMemorySSA)
    MSSAU->getMemorySSA()->verifyMemorySSA();

  LLVM_DEBUG(dbgs() << "    done: unswitching trivial branch...\n");
  ++NumTrivial;
  ++NumBranches;
  return true;
}

/// Unswitch a trivial switch if the condition is loop invariant.
///
/// This routine should only be called when loop code leading to the switch has
/// been validated as trivial (no side effects). This routine checks if the
/// condition is invariant and that at least one of the successors is a loop
/// exit. This allows us to unswitch without duplicating the loop, making it
/// trivial.
///
/// If this routine fails to unswitch the switch it returns false.
///
/// If the switch can be unswitched, this routine splits the preheader and
/// copies the switch above that split. If the default case is one of the
/// exiting cases, it copies the non-exiting cases and points them at the new
/// preheader. If the default case is not exiting, it copies the exiting cases
/// and points the default at the preheader. It preserves loop simplified form
/// (splitting the exit blocks as necessary). It simplifies the switch within
/// the loop by removing now-dead cases. If the default case is one of those
/// unswitched, it replaces its destination with a new basic block containing
/// only unreachable. Such basic blocks, while technically loop exits, are not
/// considered for unswitching so this is a stable transform and the same
/// switch will not be revisited. If after unswitching there is only a single
/// in-loop successor, the switch is further simplified to an unconditional
/// branch. Still more cleanup can be done with some simplifycfg like pass.
///
/// If `SE` is not null, it will be updated based on the potential loop SCEVs
/// invalidated by this.
static bool unswitchTrivialSwitch(Loop &L, SwitchInst &SI, DominatorTree &DT,
                                  LoopInfo &LI, ScalarEvolution *SE,
                                  MemorySSAUpdater *MSSAU) {
  LLVM_DEBUG(dbgs() << "  Trying to unswitch switch: " << SI << "\n");
  Value *LoopCond = SI.getCondition();

  // If this isn't switching on an invariant condition, we can't unswitch it.
  if (!L.isLoopInvariant(LoopCond))
    return false;

  auto *ParentBB = SI.getParent();

  // The same check must be used both for the default and the exit cases. We
  // should never leave edges from the switch instruction to a basic block that
  // we are unswitching, hence the condition used to determine the default case
  // needs to also be used to populate ExitCaseIndices, which is then used to
  // remove cases from the switch.
  auto IsTriviallyUnswitchableExitBlock = [&](BasicBlock &BBToCheck) {
    // BBToCheck is not an exit block if it is inside loop L.
    if (L.contains(&BBToCheck))
      return false;
    // BBToCheck is not trivial to unswitch if its phis aren't loop invariant.
    if (!areLoopExitPHIsLoopInvariant(L, *ParentBB, BBToCheck))
      return false;
    // We do not unswitch a block that only has an unreachable statement, as
    // it's possible this is a previously unswitched block. Only unswitch if
    // either the terminator is not unreachable, or, if it is, it's not the only
    // instruction in the block.
    auto *TI = BBToCheck.getTerminator();
    bool isUnreachable = isa<UnreachableInst>(TI);
    return !isUnreachable ||
           (isUnreachable && (BBToCheck.getFirstNonPHIOrDbg() != TI));
  };

  SmallVector<int, 4> ExitCaseIndices;
  for (auto Case : SI.cases())
    if (IsTriviallyUnswitchableExitBlock(*Case.getCaseSuccessor()))
      ExitCaseIndices.push_back(Case.getCaseIndex());
  BasicBlock *DefaultExitBB = nullptr;
  SwitchInstProfUpdateWrapper::CaseWeightOpt DefaultCaseWeight =
      SwitchInstProfUpdateWrapper::getSuccessorWeight(SI, 0);
  if (IsTriviallyUnswitchableExitBlock(*SI.getDefaultDest())) {
    DefaultExitBB = SI.getDefaultDest();
  } else if (ExitCaseIndices.empty())
    return false;

  LLVM_DEBUG(dbgs() << "    unswitching trivial switch...\n");

  if (MSSAU && VerifyMemorySSA)
    MSSAU->getMemorySSA()->verifyMemorySSA();

  // We may need to invalidate SCEVs for the outermost loop reached by any of
  // the exits.
  Loop *OuterL = &L;

  if (DefaultExitBB) {
    // Check the loop containing this exit.
    Loop *ExitL = getTopMostExitingLoop(DefaultExitBB, LI);
    if (!ExitL || ExitL->contains(OuterL))
      OuterL = ExitL;
  }
  for (unsigned Index : ExitCaseIndices) {
    auto CaseI = SI.case_begin() + Index;
    // Compute the outer loop from this exit.
    Loop *ExitL = getTopMostExitingLoop(CaseI->getCaseSuccessor(), LI);
    if (!ExitL || ExitL->contains(OuterL))
      OuterL = ExitL;
  }

  if (SE) {
    if (OuterL)
      SE->forgetLoop(OuterL);
    else
      SE->forgetTopmostLoop(&L);
  }

  if (DefaultExitBB) {
    // Clear out the default destination temporarily to allow accurate
    // predecessor lists to be examined below.
    SI.setDefaultDest(nullptr);
  }

  // Store the exit cases into a separate data structure and remove them from
  // the switch.
  SmallVector<std::tuple<ConstantInt *, BasicBlock *,
                         SwitchInstProfUpdateWrapper::CaseWeightOpt>,
              4> ExitCases;
  ExitCases.reserve(ExitCaseIndices.size());
  SwitchInstProfUpdateWrapper SIW(SI);
  // We walk the case indices backwards so that we remove the last case first
  // and don't disrupt the earlier indices.
  for (unsigned Index : reverse(ExitCaseIndices)) {
    auto CaseI = SI.case_begin() + Index;
    // Save the value of this case.
    auto W = SIW.getSuccessorWeight(CaseI->getSuccessorIndex());
    ExitCases.emplace_back(CaseI->getCaseValue(), CaseI->getCaseSuccessor(), W);
    // Delete the unswitched cases.
    SIW.removeCase(CaseI);
  }

  // Check if after this all of the remaining cases point at the same
  // successor.
  BasicBlock *CommonSuccBB = nullptr;
  if (SI.getNumCases() > 0 &&
      all_of(drop_begin(SI.cases()), [&SI](const SwitchInst::CaseHandle &Case) {
        return Case.getCaseSuccessor() == SI.case_begin()->getCaseSuccessor();
      }))
    CommonSuccBB = SI.case_begin()->getCaseSuccessor();
  if (!DefaultExitBB) {
    // If we're not unswitching the default, we need it to match any cases to
    // have a common successor or if we have no cases it is the common
    // successor.
    if (SI.getNumCases() == 0)
      CommonSuccBB = SI.getDefaultDest();
    else if (SI.getDefaultDest() != CommonSuccBB)
      CommonSuccBB = nullptr;
  }

  // Split the preheader, so that we know that there is a safe place to insert
  // the switch.
  BasicBlock *OldPH = L.getLoopPreheader();
  BasicBlock *NewPH = SplitEdge(OldPH, L.getHeader(), &DT, &LI, MSSAU);
  OldPH->getTerminator()->eraseFromParent();

  // Now add the unswitched switch.
  auto *NewSI = SwitchInst::Create(LoopCond, NewPH, ExitCases.size(), OldPH);
  SwitchInstProfUpdateWrapper NewSIW(*NewSI);

  // Rewrite the IR for the unswitched basic blocks. This requires two steps.
  // First, we split any exit blocks with remaining in-loop predecessors. Then
  // we update the PHIs in one of two ways depending on if there was a split.
  // We walk in reverse so that we split in the same order as the cases
  // appeared. This is purely for convenience of reading the resulting IR, but
  // it doesn't cost anything really.
  SmallPtrSet<BasicBlock *, 2> UnswitchedExitBBs;
  SmallDenseMap<BasicBlock *, BasicBlock *, 2> SplitExitBBMap;
  // Handle the default exit if necessary.
  // FIXME: It'd be great if we could merge this with the loop below but LLVM's
  // ranges aren't quite powerful enough yet.
  if (DefaultExitBB) {
    if (pred_empty(DefaultExitBB)) {
      UnswitchedExitBBs.insert(DefaultExitBB);
      rewritePHINodesForUnswitchedExitBlock(*DefaultExitBB, *ParentBB, *OldPH);
    } else {
      auto *SplitBB =
          SplitBlock(DefaultExitBB, DefaultExitBB->begin(), &DT, &LI, MSSAU);
      rewritePHINodesForExitAndUnswitchedBlocks(*DefaultExitBB, *SplitBB,
                                                *ParentBB, *OldPH,
                                                /*FullUnswitch*/ true);
      DefaultExitBB = SplitExitBBMap[DefaultExitBB] = SplitBB;
    }
  }
  // Note that we must use a reference in the for loop so that we update the
  // container.
  for (auto &ExitCase : reverse(ExitCases)) {
    // Grab a reference to the exit block in the pair so that we can update it.
    BasicBlock *ExitBB = std::get<1>(ExitCase);

    // If this case is the last edge into the exit block, we can simply reuse it
    // as it will no longer be a loop exit. No mapping necessary.
    if (pred_empty(ExitBB)) {
      // Only rewrite once.
      if (UnswitchedExitBBs.insert(ExitBB).second)
        rewritePHINodesForUnswitchedExitBlock(*ExitBB, *ParentBB, *OldPH);
      continue;
    }

    // Otherwise we need to split the exit block so that we retain an exit
    // block from the loop and a target for the unswitched condition.
    BasicBlock *&SplitExitBB = SplitExitBBMap[ExitBB];
    if (!SplitExitBB) {
      // If this is the first time we see this, do the split and remember it.
      SplitExitBB = SplitBlock(ExitBB, ExitBB->begin(), &DT, &LI, MSSAU);
      rewritePHINodesForExitAndUnswitchedBlocks(*ExitBB, *SplitExitBB,
                                                *ParentBB, *OldPH,
                                                /*FullUnswitch*/ true);
    }
    // Update the case pair to point to the split block.
    std::get<1>(ExitCase) = SplitExitBB;
  }

  // Now add the unswitched cases. We do this in reverse order as we built them
  // in reverse order.
  for (auto &ExitCase : reverse(ExitCases)) {
    ConstantInt *CaseVal = std::get<0>(ExitCase);
    BasicBlock *UnswitchedBB = std::get<1>(ExitCase);

    NewSIW.addCase(CaseVal, UnswitchedBB, std::get<2>(ExitCase));
  }

  // If the default was unswitched, re-point it and add explicit cases for
  // entering the loop.
  if (DefaultExitBB) {
    NewSIW->setDefaultDest(DefaultExitBB);
    NewSIW.setSuccessorWeight(0, DefaultCaseWeight);

    // We removed all the exit cases, so we just copy the cases to the
    // unswitched switch.
    for (const auto &Case : SI.cases())
      NewSIW.addCase(Case.getCaseValue(), NewPH,
                     SIW.getSuccessorWeight(Case.getSuccessorIndex()));
  } else if (DefaultCaseWeight) {
    // We have to set branch weight of the default case.
    uint64_t SW = *DefaultCaseWeight;
    for (const auto &Case : SI.cases()) {
      auto W = SIW.getSuccessorWeight(Case.getSuccessorIndex());
      assert(W &&
             "case weight must be defined as default case weight is defined");
      SW += *W;
    }
    NewSIW.setSuccessorWeight(0, SW);
  }

  // If we ended up with a common successor for every path through the switch
  // after unswitching, rewrite it to an unconditional branch to make it easy
  // to recognize. Otherwise we potentially have to recognize the default case
  // pointing at unreachable and other complexity.
  if (CommonSuccBB) {
    BasicBlock *BB = SI.getParent();
    // We may have had multiple edges to this common successor block, so remove
    // them as predecessors. We skip the first one, either the default or the
    // actual first case.
    bool SkippedFirst = DefaultExitBB == nullptr;
    for (auto Case : SI.cases()) {
      assert(Case.getCaseSuccessor() == CommonSuccBB &&
             "Non-common successor!");
      (void)Case;
      if (!SkippedFirst) {
        SkippedFirst = true;
        continue;
      }
      CommonSuccBB->removePredecessor(BB,
                                      /*KeepOneInputPHIs*/ true);
    }
    // Now nuke the switch and replace it with a direct branch.
    SIW.eraseFromParent();
    BranchInst::Create(CommonSuccBB, BB);
  } else if (DefaultExitBB) {
    assert(SI.getNumCases() > 0 &&
           "If we had no cases we'd have a common successor!");
    // Move the last case to the default successor. This is valid as if the
    // default got unswitched it cannot be reached. This has the advantage of
    // being simple and keeping the number of edges from this switch to
    // successors the same, and avoiding any PHI update complexity.
    auto LastCaseI = std::prev(SI.case_end());

    SI.setDefaultDest(LastCaseI->getCaseSuccessor());
    SIW.setSuccessorWeight(
        0, SIW.getSuccessorWeight(LastCaseI->getSuccessorIndex()));
    SIW.removeCase(LastCaseI);
  }

  // Walk the unswitched exit blocks and the unswitched split blocks and update
  // the dominator tree based on the CFG edits. While we are walking unordered
  // containers here, the API for applyUpdates takes an unordered list of
  // updates and requires them to not contain duplicates.
  SmallVector<DominatorTree::UpdateType, 4> DTUpdates;
  for (auto *UnswitchedExitBB : UnswitchedExitBBs) {
    DTUpdates.push_back({DT.Delete, ParentBB, UnswitchedExitBB});
    DTUpdates.push_back({DT.Insert, OldPH, UnswitchedExitBB});
  }
  for (auto SplitUnswitchedPair : SplitExitBBMap) {
    DTUpdates.push_back({DT.Delete, ParentBB, SplitUnswitchedPair.first});
    DTUpdates.push_back({DT.Insert, OldPH, SplitUnswitchedPair.second});
  }

  if (MSSAU) {
    MSSAU->applyUpdates(DTUpdates, DT, /*UpdateDT=*/true);
    if (VerifyMemorySSA)
      MSSAU->getMemorySSA()->verifyMemorySSA();
  } else {
    DT.applyUpdates(DTUpdates);
  }

  assert(DT.verify(DominatorTree::VerificationLevel::Fast));

  // We may have changed the nesting relationship for this loop so hoist it to
  // its correct parent if needed.
  hoistLoopToNewParent(L, *NewPH, DT, LI, MSSAU, SE);

  if (MSSAU && VerifyMemorySSA)
    MSSAU->getMemorySSA()->verifyMemorySSA();

  ++NumTrivial;
  ++NumSwitches;
  LLVM_DEBUG(dbgs() << "    done: unswitching trivial switch...\n");
  return true;
}

/// This routine scans the loop to find a branch or switch which occurs before
/// any side effects occur. These can potentially be unswitched without
/// duplicating the loop. If a branch or switch is successfully unswitched the
/// scanning continues to see if subsequent branches or switches have become
/// trivial. Once all trivial candidates have been unswitched, this routine
/// returns.
///
/// The return value indicates whether anything was unswitched (and therefore
/// changed).
///
/// If `SE` is not null, it will be updated based on the potential loop SCEVs
/// invalidated by this.
static bool unswitchAllTrivialConditions(Loop &L, DominatorTree &DT,
                                         LoopInfo &LI, ScalarEvolution *SE,
                                         MemorySSAUpdater *MSSAU) {
  bool Changed = false;

  // If loop header has only one reachable successor we should keep looking for
  // trivial condition candidates in the successor as well. An alternative is
  // to constant fold conditions and merge successors into loop header (then we
  // only need to check header's terminator). The reason for not doing this in
  // LoopUnswitch pass is that it could potentially break LoopPassManager's
  // invariants. Folding dead branches could either eliminate the current loop
  // or make other loops unreachable. LCSSA form might also not be preserved
  // after deleting branches. The following code keeps traversing loop header's
  // successors until it finds the trivial condition candidate (condition that
  // is not a constant). Since unswitching generates branches with constant
  // conditions, this scenario could be very common in practice.
  BasicBlock *CurrentBB = L.getHeader();
  SmallPtrSet<BasicBlock *, 8> Visited;
  Visited.insert(CurrentBB);
  do {
    // Check if there are any side-effecting instructions (e.g. stores, calls,
    // volatile loads) in the part of the loop that the code *would* execute
    // without unswitching.
    if (MSSAU) // Possible early exit with MSSA
      if (auto *Defs = MSSAU->getMemorySSA()->getBlockDefs(CurrentBB))
        if (!isa<MemoryPhi>(*Defs->begin()) || (++Defs->begin() != Defs->end()))
          return Changed;
    if (llvm::any_of(*CurrentBB,
                     [](Instruction &I) { return I.mayHaveSideEffects(); }))
      return Changed;

    Instruction *CurrentTerm = CurrentBB->getTerminator();

    if (auto *SI = dyn_cast<SwitchInst>(CurrentTerm)) {
      // Don't bother trying to unswitch past a switch with a constant
      // condition. This should be removed prior to running this pass by
      // simplifycfg.
      if (isa<Constant>(SI->getCondition()))
        return Changed;

      if (!unswitchTrivialSwitch(L, *SI, DT, LI, SE, MSSAU))
        // Couldn't unswitch this one so we're done.
        return Changed;

      // Mark that we managed to unswitch something.
      Changed = true;

      // If unswitching turned the terminator into an unconditional branch then
      // we can continue. The unswitching logic specifically works to fold any
      // cases it can into an unconditional branch to make it easier to
      // recognize here.
      auto *BI = dyn_cast<BranchInst>(CurrentBB->getTerminator());
      if (!BI || BI->isConditional())
        return Changed;

      CurrentBB = BI->getSuccessor(0);
      continue;
    }

    auto *BI = dyn_cast<BranchInst>(CurrentTerm);
    if (!BI)
      // We do not understand other terminator instructions.
      return Changed;

    // Don't bother trying to unswitch past an unconditional branch or a branch
    // with a constant value. These should be removed by simplifycfg prior to
    // running this pass.
    if (!BI->isConditional() ||
        isa<Constant>(skipTrivialSelect(BI->getCondition())))
      return Changed;

    // Found a trivial condition candidate: non-foldable conditional branch. If
    // we fail to unswitch this, we can't do anything else that is trivial.
    if (!unswitchTrivialBranch(L, *BI, DT, LI, SE, MSSAU))
      return Changed;

    // Mark that we managed to unswitch something.
    Changed = true;

    // If we only unswitched some of the conditions feeding the branch, we won't
    // have collapsed it to a single successor.
    BI = cast<BranchInst>(CurrentBB->getTerminator());
    if (BI->isConditional())
      return Changed;

    // Follow the newly unconditional branch into its successor.
    CurrentBB = BI->getSuccessor(0);

    // When continuing, if we exit the loop or reach a previous visited block,
    // then we can not reach any trivial condition candidates (unfoldable
    // branch instructions or switch instructions) and no unswitch can happen.
  } while (L.contains(CurrentBB) && Visited.insert(CurrentBB).second);

  return Changed;
}

/// Build the cloned blocks for an unswitched copy of the given loop.
///
/// The cloned blocks are inserted before the loop preheader (`LoopPH`) and
/// after the split block (`SplitBB`) that will be used to select between the
/// cloned and original loop.
///
/// This routine handles cloning all of the necessary loop blocks and exit
/// blocks including rewriting their instructions and the relevant PHI nodes.
/// Any loop blocks or exit blocks which are dominated by a different successor
/// than the one for this clone of the loop blocks can be trivially skipped. We
/// use the `DominatingSucc` map to determine whether a block satisfies that
/// property with a simple map lookup.
///
/// It also correctly creates the unconditional branch in the cloned
/// unswitched parent block to only point at the unswitched successor.
///
/// This does not handle most of the necessary updates to `LoopInfo`. Only exit
/// block splitting is correctly reflected in `LoopInfo`, essentially all of
/// the cloned blocks (and their loops) are left without full `LoopInfo`
/// updates. This also doesn't fully update `DominatorTree`. It adds the cloned
/// blocks to them but doesn't create the cloned `DominatorTree` structure and
/// instead the caller must recompute an accurate DT. It *does* correctly
/// update the `AssumptionCache` provided in `AC`.
static BasicBlock *buildClonedLoopBlocks(
    Loop &L, BasicBlock *LoopPH, BasicBlock *SplitBB,
    ArrayRef<BasicBlock *> ExitBlocks, BasicBlock *ParentBB,
    BasicBlock *UnswitchedSuccBB, BasicBlock *ContinueSuccBB,
    const SmallDenseMap<BasicBlock *, BasicBlock *, 16> &DominatingSucc,
    ValueToValueMapTy &VMap,
    SmallVectorImpl<DominatorTree::UpdateType> &DTUpdates, AssumptionCache &AC,
    DominatorTree &DT, LoopInfo &LI, MemorySSAUpdater *MSSAU,
    ScalarEvolution *SE) {
  SmallVector<BasicBlock *, 4> NewBlocks;
  NewBlocks.reserve(L.getNumBlocks() + ExitBlocks.size());

  // We will need to clone a bunch of blocks, wrap up the clone operation in
  // a helper.
  auto CloneBlock = [&](BasicBlock *OldBB) {
    // Clone the basic block and insert it before the new preheader.
    BasicBlock *NewBB = CloneBasicBlock(OldBB, VMap, ".us", OldBB->getParent());
    NewBB->moveBefore(LoopPH);

    // Record this block and the mapping.
    NewBlocks.push_back(NewBB);
    VMap[OldBB] = NewBB;

    return NewBB;
  };

  // We skip cloning blocks when they have a dominating succ that is not the
  // succ we are cloning for.
  auto SkipBlock = [&](BasicBlock *BB) {
    auto It = DominatingSucc.find(BB);
    return It != DominatingSucc.end() && It->second != UnswitchedSuccBB;
  };

  // First, clone the preheader.
  auto *ClonedPH = CloneBlock(LoopPH);

  // Then clone all the loop blocks, skipping the ones that aren't necessary.
  for (auto *LoopBB : L.blocks())
    if (!SkipBlock(LoopBB))
      CloneBlock(LoopBB);

  // Split all the loop exit edges so that when we clone the exit blocks, if
  // any of the exit blocks are *also* a preheader for some other loop, we
  // don't create multiple predecessors entering the loop header.
  for (auto *ExitBB : ExitBlocks) {
    if (SkipBlock(ExitBB))
      continue;

    // When we are going to clone an exit, we don't need to clone all the
    // instructions in the exit block and we want to ensure we have an easy
    // place to merge the CFG, so split the exit first. This is always safe to
    // do because there cannot be any non-loop predecessors of a loop exit in
    // loop simplified form.
    auto *MergeBB = SplitBlock(ExitBB, ExitBB->begin(), &DT, &LI, MSSAU);

    // Rearrange the names to make it easier to write test cases by having the
    // exit block carry the suffix rather than the merge block carrying the
    // suffix.
    MergeBB->takeName(ExitBB);
    ExitBB->setName(Twine(MergeBB->getName()) + ".split");

    // Now clone the original exit block.
    auto *ClonedExitBB = CloneBlock(ExitBB);
    assert(ClonedExitBB->getTerminator()->getNumSuccessors() == 1 &&
           "Exit block should have been split to have one successor!");
    assert(ClonedExitBB->getTerminator()->getSuccessor(0) == MergeBB &&
           "Cloned exit block has the wrong successor!");

    // Remap any cloned instructions and create a merge phi node for them.
    for (auto ZippedInsts : llvm::zip_first(
             llvm::make_range(ExitBB->begin(), std::prev(ExitBB->end())),
             llvm::make_range(ClonedExitBB->begin(),
                              std::prev(ClonedExitBB->end())))) {
      Instruction &I = std::get<0>(ZippedInsts);
      Instruction &ClonedI = std::get<1>(ZippedInsts);

      // The only instructions in the exit block should be PHI nodes and
      // potentially a landing pad.
      assert(
          (isa<PHINode>(I) || isa<LandingPadInst>(I) || isa<CatchPadInst>(I)) &&
          "Bad instruction in exit block!");
      // We should have a value map between the instruction and its clone.
      assert(VMap.lookup(&I) == &ClonedI && "Mismatch in the value map!");

      // Forget SCEVs based on exit phis in case SCEV looked through the phi.
      if (SE && isa<PHINode>(I))
        SE->forgetValue(&I);

      auto *MergePN =
          PHINode::Create(I.getType(), /*NumReservedValues*/ 2, ".us-phi");
      MergePN->insertBefore(MergeBB->getFirstInsertionPt());
      I.replaceAllUsesWith(MergePN);
      MergePN->addIncoming(&I, ExitBB);
      MergePN->addIncoming(&ClonedI, ClonedExitBB);
    }
  }

  // Rewrite the instructions in the cloned blocks to refer to the instructions
  // in the cloned blocks. We have to do this as a second pass so that we have
  // everything available. Also, we have inserted new instructions which may
  // include assume intrinsics, so we update the assumption cache while
  // processing this.
  Module *M = ClonedPH->getParent()->getParent();
  for (auto *ClonedBB : NewBlocks)
    for (Instruction &I : *ClonedBB) {
      RemapDbgVariableRecordRange(M, I.getDbgRecordRange(), VMap,
                                  RF_NoModuleLevelChanges |
                                      RF_IgnoreMissingLocals);
      RemapInstruction(&I, VMap,
                       RF_NoModuleLevelChanges | RF_IgnoreMissingLocals);
      if (auto *II = dyn_cast<AssumeInst>(&I))
        AC.registerAssumption(II);
    }

  // Update any PHI nodes in the cloned successors of the skipped blocks to not
  // have spurious incoming values.
  for (auto *LoopBB : L.blocks())
    if (SkipBlock(LoopBB))
      for (auto *SuccBB : successors(LoopBB))
        if (auto *ClonedSuccBB = cast_or_null<BasicBlock>(VMap.lookup(SuccBB)))
          for (PHINode &PN : ClonedSuccBB->phis())
            PN.removeIncomingValue(LoopBB, /*DeletePHIIfEmpty*/ false);

  // Remove the cloned parent as a predecessor of any successor we ended up
  // cloning other than the unswitched one.
  auto *ClonedParentBB = cast<BasicBlock>(VMap.lookup(ParentBB));
  for (auto *SuccBB : successors(ParentBB)) {
    if (SuccBB == UnswitchedSuccBB)
      continue;

    auto *ClonedSuccBB = cast_or_null<BasicBlock>(VMap.lookup(SuccBB));
    if (!ClonedSuccBB)
      continue;

    ClonedSuccBB->removePredecessor(ClonedParentBB,
                                    /*KeepOneInputPHIs*/ true);
  }

  // Replace the cloned branch with an unconditional branch to the cloned
  // unswitched successor.
  auto *ClonedSuccBB = cast<BasicBlock>(VMap.lookup(UnswitchedSuccBB));
  Instruction *ClonedTerminator = ClonedParentBB->getTerminator();
  // Trivial Simplification. If Terminator is a conditional branch and
  // condition becomes dead - erase it.
  Value *ClonedConditionToErase = nullptr;
  if (auto *BI = dyn_cast<BranchInst>(ClonedTerminator))
    ClonedConditionToErase = BI->getCondition();
  else if (auto *SI = dyn_cast<SwitchInst>(ClonedTerminator))
    ClonedConditionToErase = SI->getCondition();

  ClonedTerminator->eraseFromParent();
  BranchInst::Create(ClonedSuccBB, ClonedParentBB);

  if (ClonedConditionToErase)
    RecursivelyDeleteTriviallyDeadInstructions(ClonedConditionToErase, nullptr,
                                               MSSAU);

  // If there are duplicate entries in the PHI nodes because of multiple edges
  // to the unswitched successor, we need to nuke all but one as we replaced it
  // with a direct branch.
  for (PHINode &PN : ClonedSuccBB->phis()) {
    bool Found = false;
    // Loop over the incoming operands backwards so we can easily delete as we
    // go without invalidating the index.
    for (int i = PN.getNumOperands() - 1; i >= 0; --i) {
      if (PN.getIncomingBlock(i) != ClonedParentBB)
        continue;
      if (!Found) {
        Found = true;
        continue;
      }
      PN.removeIncomingValue(i, /*DeletePHIIfEmpty*/ false);
    }
  }

  // Record the domtree updates for the new blocks.
  SmallPtrSet<BasicBlock *, 4> SuccSet;
  for (auto *ClonedBB : NewBlocks) {
    for (auto *SuccBB : successors(ClonedBB))
      if (SuccSet.insert(SuccBB).second)
        DTUpdates.push_back({DominatorTree::Insert, ClonedBB, SuccBB});
    SuccSet.clear();
  }

  return ClonedPH;
}

/// Recursively clone the specified loop and all of its children.
///
/// The target parent loop for the clone should be provided, or can be null if
/// the clone is a top-level loop. While cloning, all the blocks are mapped
/// with the provided value map. The entire original loop must be present in
/// the value map. The cloned loop is returned.
static Loop *cloneLoopNest(Loop &OrigRootL, Loop *RootParentL,
                           const ValueToValueMapTy &VMap, LoopInfo &LI) {
  auto AddClonedBlocksToLoop = [&](Loop &OrigL, Loop &ClonedL) {
    assert(ClonedL.getBlocks().empty() && "Must start with an empty loop!");
    ClonedL.reserveBlocks(OrigL.getNumBlocks());
    for (auto *BB : OrigL.blocks()) {
      auto *ClonedBB = cast<BasicBlock>(VMap.lookup(BB));
      ClonedL.addBlockEntry(ClonedBB);
      if (LI.getLoopFor(BB) == &OrigL)
        LI.changeLoopFor(ClonedBB, &ClonedL);
    }
  };

  // We specially handle the first loop because it may get cloned into
  // a different parent and because we most commonly are cloning leaf loops.
  Loop *ClonedRootL = LI.AllocateLoop();
  if (RootParentL)
    RootParentL->addChildLoop(ClonedRootL);
  else
    LI.addTopLevelLoop(ClonedRootL);
  AddClonedBlocksToLoop(OrigRootL, *ClonedRootL);

  if (OrigRootL.isInnermost())
    return ClonedRootL;

  // If we have a nest, we can quickly clone the entire loop nest using an
  // iterative approach because it is a tree. We keep the cloned parent in the
  // data structure to avoid repeatedly querying through a map to find it.
  SmallVector<std::pair<Loop *, Loop *>, 16> LoopsToClone;
  // Build up the loops to clone in reverse order as we'll clone them from the
  // back.
  for (Loop *ChildL : llvm::reverse(OrigRootL))
    LoopsToClone.push_back({ClonedRootL, ChildL});
  do {
    Loop *ClonedParentL, *L;
    std::tie(ClonedParentL, L) = LoopsToClone.pop_back_val();
    Loop *ClonedL = LI.AllocateLoop();
    ClonedParentL->addChildLoop(ClonedL);
    AddClonedBlocksToLoop(*L, *ClonedL);
    for (Loop *ChildL : llvm::reverse(*L))
      LoopsToClone.push_back({ClonedL, ChildL});
  } while (!LoopsToClone.empty());

  return ClonedRootL;
}

/// Build the cloned loops of an original loop from unswitching.
///
/// Because unswitching simplifies the CFG of the loop, this isn't a trivial
/// operation. We need to re-verify that there even is a loop (as the backedge
/// may not have been cloned), and even if there are remaining backedges the
/// backedge set may be different. However, we know that each child loop is
/// undisturbed, we only need to find where to place each child loop within
/// either any parent loop or within a cloned version of the original loop.
///
/// Because child loops may end up cloned outside of any cloned version of the
/// original loop, multiple cloned sibling loops may be created. All of them
/// are returned so that the newly introduced loop nest roots can be
/// identified.
static void buildClonedLoops(Loop &OrigL, ArrayRef<BasicBlock *> ExitBlocks,
                             const ValueToValueMapTy &VMap, LoopInfo &LI,
                             SmallVectorImpl<Loop *> &NonChildClonedLoops) {
  Loop *ClonedL = nullptr;

  auto *OrigPH = OrigL.getLoopPreheader();
  auto *OrigHeader = OrigL.getHeader();

  auto *ClonedPH = cast<BasicBlock>(VMap.lookup(OrigPH));
  auto *ClonedHeader = cast<BasicBlock>(VMap.lookup(OrigHeader));

  // We need to know the loops of the cloned exit blocks to even compute the
  // accurate parent loop. If we only clone exits to some parent of the
  // original parent, we want to clone into that outer loop. We also keep track
  // of the loops that our cloned exit blocks participate in.
  Loop *ParentL = nullptr;
  SmallVector<BasicBlock *, 4> ClonedExitsInLoops;
  SmallDenseMap<BasicBlock *, Loop *, 16> ExitLoopMap;
  ClonedExitsInLoops.reserve(ExitBlocks.size());
  for (auto *ExitBB : ExitBlocks)
    if (auto *ClonedExitBB = cast_or_null<BasicBlock>(VMap.lookup(ExitBB)))
      if (Loop *ExitL = LI.getLoopFor(ExitBB)) {
        ExitLoopMap[ClonedExitBB] = ExitL;
        ClonedExitsInLoops.push_back(ClonedExitBB);
        if (!ParentL || (ParentL != ExitL && ParentL->contains(ExitL)))
          ParentL = ExitL;
      }
  assert((!ParentL || ParentL == OrigL.getParentLoop() ||
          ParentL->contains(OrigL.getParentLoop())) &&
         "The computed parent loop should always contain (or be) the parent of "
         "the original loop.");

  // We build the set of blocks dominated by the cloned header from the set of
  // cloned blocks out of the original loop. While not all of these will
  // necessarily be in the cloned loop, it is enough to establish that they
  // aren't in unreachable cycles, etc.
  SmallSetVector<BasicBlock *, 16> ClonedLoopBlocks;
  for (auto *BB : OrigL.blocks())
    if (auto *ClonedBB = cast_or_null<BasicBlock>(VMap.lookup(BB)))
      ClonedLoopBlocks.insert(ClonedBB);

  // Rebuild the set of blocks that will end up in the cloned loop. We may have
  // skipped cloning some region of this loop which can in turn skip some of
  // the backedges so we have to rebuild the blocks in the loop based on the
  // backedges that remain after cloning.
  SmallVector<BasicBlock *, 16> Worklist;
  SmallPtrSet<BasicBlock *, 16> BlocksInClonedLoop;
  for (auto *Pred : predecessors(ClonedHeader)) {
    // The only possible non-loop header predecessor is the preheader because
    // we know we cloned the loop in simplified form.
    if (Pred == ClonedPH)
      continue;

    // Because the loop was in simplified form, the only non-loop predecessor
    // should be the preheader.
    assert(ClonedLoopBlocks.count(Pred) && "Found a predecessor of the loop "
                                           "header other than the preheader "
                                           "that is not part of the loop!");

    // Insert this block into the loop set and on the first visit (and if it
    // isn't the header we're currently walking) put it into the worklist to
    // recurse through.
    if (BlocksInClonedLoop.insert(Pred).second && Pred != ClonedHeader)
      Worklist.push_back(Pred);
  }

  // If we had any backedges then there *is* a cloned loop. Put the header into
  // the loop set and then walk the worklist backwards to find all the blocks
  // that remain within the loop after cloning.
  if (!BlocksInClonedLoop.empty()) {
    BlocksInClonedLoop.insert(ClonedHeader);

    while (!Worklist.empty()) {
      BasicBlock *BB = Worklist.pop_back_val();
      assert(BlocksInClonedLoop.count(BB) &&
             "Didn't put block into the loop set!");

      // Insert any predecessors that are in the possible set into the cloned
      // set, and if the insert is successful, add them to the worklist. Note
      // that we filter on the blocks that are definitely reachable via the
      // backedge to the loop header so we may prune out dead code within the
      // cloned loop.
      for (auto *Pred : predecessors(BB))
        if (ClonedLoopBlocks.count(Pred) &&
            BlocksInClonedLoop.insert(Pred).second)
          Worklist.push_back(Pred);
    }

    ClonedL = LI.AllocateLoop();
    if (ParentL) {
      ParentL->addBasicBlockToLoop(ClonedPH, LI);
      ParentL->addChildLoop(ClonedL);
    } else {
      LI.addTopLevelLoop(ClonedL);
    }
    NonChildClonedLoops.push_back(ClonedL);

    ClonedL->reserveBlocks(BlocksInClonedLoop.size());
    // We don't want to just add the cloned loop blocks based on how we
    // discovered them. The original order of blocks was carefully built in
    // a way that doesn't rely on predecessor ordering. Rather than re-invent
    // that logic, we just re-walk the original blocks (and those of the child
    // loops) and filter them as we add them into the cloned loop.
    for (auto *BB : OrigL.blocks()) {
      auto *ClonedBB = cast_or_null<BasicBlock>(VMap.lookup(BB));
      if (!ClonedBB || !BlocksInClonedLoop.count(ClonedBB))
        continue;

      // Directly add the blocks that are only in this loop.
      if (LI.getLoopFor(BB) == &OrigL) {
        ClonedL->addBasicBlockToLoop(ClonedBB, LI);
        continue;
      }

      // We want to manually add it to this loop and parents.
      // Registering it with LoopInfo will happen when we clone the top
      // loop for this block.
      for (Loop *PL = ClonedL; PL; PL = PL->getParentLoop())
        PL->addBlockEntry(ClonedBB);
    }

    // Now add each child loop whose header remains within the cloned loop. All
    // of the blocks within the loop must satisfy the same constraints as the
    // header so once we pass the header checks we can just clone the entire
    // child loop nest.
    for (Loop *ChildL : OrigL) {
      auto *ClonedChildHeader =
          cast_or_null<BasicBlock>(VMap.lookup(ChildL->getHeader()));
      if (!ClonedChildHeader || !BlocksInClonedLoop.count(ClonedChildHeader))
        continue;

#ifndef NDEBUG
      // We should never have a cloned child loop header but fail to have
      // all of the blocks for that child loop.
      for (auto *ChildLoopBB : ChildL->blocks())
        assert(BlocksInClonedLoop.count(
                   cast<BasicBlock>(VMap.lookup(ChildLoopBB))) &&
               "Child cloned loop has a header within the cloned outer "
               "loop but not all of its blocks!");
#endif

      cloneLoopNest(*ChildL, ClonedL, VMap, LI);
    }
  }

  // Now that we've handled all the components of the original loop that were
  // cloned into a new loop, we still need to handle anything from the original
  // loop that wasn't in a cloned loop.

  // Figure out what blocks are left to place within any loop nest containing
  // the unswitched loop. If we never formed a loop, the cloned PH is one of
  // them.
  SmallPtrSet<BasicBlock *, 16> UnloopedBlockSet;
  if (BlocksInClonedLoop.empty())
    UnloopedBlockSet.insert(ClonedPH);
  for (auto *ClonedBB : ClonedLoopBlocks)
    if (!BlocksInClonedLoop.count(ClonedBB))
      UnloopedBlockSet.insert(ClonedBB);

  // Copy the cloned exits and sort them in ascending loop depth, we'll work
  // backwards across these to process them inside out. The order shouldn't
  // matter as we're just trying to build up the map from inside-out; we use
  // the map in a more stably ordered way below.
  auto OrderedClonedExitsInLoops = ClonedExitsInLoops;
  llvm::sort(OrderedClonedExitsInLoops, [&](BasicBlock *LHS, BasicBlock *RHS) {
    return ExitLoopMap.lookup(LHS)->getLoopDepth() <
           ExitLoopMap.lookup(RHS)->getLoopDepth();
  });

  // Populate the existing ExitLoopMap with everything reachable from each
  // exit, starting from the inner most exit.
  while (!UnloopedBlockSet.empty() && !OrderedClonedExitsInLoops.empty()) {
    assert(Worklist.empty() && "Didn't clear worklist!");

    BasicBlock *ExitBB = OrderedClonedExitsInLoops.pop_back_val();
    Loop *ExitL = ExitLoopMap.lookup(ExitBB);

    // Walk the CFG back until we hit the cloned PH adding everything reachable
    // and in the unlooped set to this exit block's loop.
    Worklist.push_back(ExitBB);
    do {
      BasicBlock *BB = Worklist.pop_back_val();
      // We can stop recursing at the cloned preheader (if we get there).
      if (BB == ClonedPH)
        continue;

      for (BasicBlock *PredBB : predecessors(BB)) {
        // If this pred has already been moved to our set or is part of some
        // (inner) loop, no update needed.
        if (!UnloopedBlockSet.erase(PredBB)) {
          assert(
              (BlocksInClonedLoop.count(PredBB) || ExitLoopMap.count(PredBB)) &&
              "Predecessor not mapped to a loop!");
          continue;
        }

        // We just insert into the loop set here. We'll add these blocks to the
        // exit loop after we build up the set in an order that doesn't rely on
        // predecessor order (which in turn relies on use list order).
        bool Inserted = ExitLoopMap.insert({PredBB, ExitL}).second;
        (void)Inserted;
        assert(Inserted && "Should only visit an unlooped block once!");

        // And recurse through to its predecessors.
        Worklist.push_back(PredBB);
      }
    } while (!Worklist.empty());
  }

  // Now that the ExitLoopMap gives as  mapping for all the non-looping cloned
  // blocks to their outer loops, walk the cloned blocks and the cloned exits
  // in their original order adding them to the correct loop.

  // We need a stable insertion order. We use the order of the original loop
  // order and map into the correct parent loop.
  for (auto *BB : llvm::concat<BasicBlock *const>(
           ArrayRef(ClonedPH), ClonedLoopBlocks, ClonedExitsInLoops))
    if (Loop *OuterL = ExitLoopMap.lookup(BB))
      OuterL->addBasicBlockToLoop(BB, LI);

#ifndef NDEBUG
  for (auto &BBAndL : ExitLoopMap) {
    auto *BB = BBAndL.first;
    auto *OuterL = BBAndL.second;
    assert(LI.getLoopFor(BB) == OuterL &&
           "Failed to put all blocks into outer loops!");
  }
#endif

  // Now that all the blocks are placed into the correct containing loop in the
  // absence of child loops, find all the potentially cloned child loops and
  // clone them into whatever outer loop we placed their header into.
  for (Loop *ChildL : OrigL) {
    auto *ClonedChildHeader =
        cast_or_null<BasicBlock>(VMap.lookup(ChildL->getHeader()));
    if (!ClonedChildHeader || BlocksInClonedLoop.count(ClonedChildHeader))
      continue;

#ifndef NDEBUG
    for (auto *ChildLoopBB : ChildL->blocks())
      assert(VMap.count(ChildLoopBB) &&
             "Cloned a child loop header but not all of that loops blocks!");
#endif

    NonChildClonedLoops.push_back(cloneLoopNest(
        *ChildL, ExitLoopMap.lookup(ClonedChildHeader), VMap, LI));
  }
}

static void
deleteDeadClonedBlocks(Loop &L, ArrayRef<BasicBlock *> ExitBlocks,
                       ArrayRef<std::unique_ptr<ValueToValueMapTy>> VMaps,
                       DominatorTree &DT, MemorySSAUpdater *MSSAU) {
  // Find all the dead clones, and remove them from their successors.
  SmallVector<BasicBlock *, 16> DeadBlocks;
  for (BasicBlock *BB : llvm::concat<BasicBlock *const>(L.blocks(), ExitBlocks))
    for (const auto &VMap : VMaps)
      if (BasicBlock *ClonedBB = cast_or_null<BasicBlock>(VMap->lookup(BB)))
        if (!DT.isReachableFromEntry(ClonedBB)) {
          for (BasicBlock *SuccBB : successors(ClonedBB))
            SuccBB->removePredecessor(ClonedBB);
          DeadBlocks.push_back(ClonedBB);
        }

  // Remove all MemorySSA in the dead blocks
  if (MSSAU) {
    SmallSetVector<BasicBlock *, 8> DeadBlockSet(DeadBlocks.begin(),
                                                 DeadBlocks.end());
    MSSAU->removeBlocks(DeadBlockSet);
  }

  // Drop any remaining references to break cycles.
  for (BasicBlock *BB : DeadBlocks)
    BB->dropAllReferences();
  // Erase them from the IR.
  for (BasicBlock *BB : DeadBlocks)
    BB->eraseFromParent();
}

static void deleteDeadBlocksFromLoop(Loop &L,
                                     SmallVectorImpl<BasicBlock *> &ExitBlocks,
                                     DominatorTree &DT, LoopInfo &LI,
                                     MemorySSAUpdater *MSSAU,
                                     ScalarEvolution *SE,
                                     LPMUpdater &LoopUpdater) {
  // Find all the dead blocks tied to this loop, and remove them from their
  // successors.
  SmallSetVector<BasicBlock *, 8> DeadBlockSet;

  // Start with loop/exit blocks and get a transitive closure of reachable dead
  // blocks.
  SmallVector<BasicBlock *, 16> DeathCandidates(ExitBlocks.begin(),
                                                ExitBlocks.end());
  DeathCandidates.append(L.blocks().begin(), L.blocks().end());
  while (!DeathCandidates.empty()) {
    auto *BB = DeathCandidates.pop_back_val();
    if (!DeadBlockSet.count(BB) && !DT.isReachableFromEntry(BB)) {
      for (BasicBlock *SuccBB : successors(BB)) {
        SuccBB->removePredecessor(BB);
        DeathCandidates.push_back(SuccBB);
      }
      DeadBlockSet.insert(BB);
    }
  }

  // Remove all MemorySSA in the dead blocks
  if (MSSAU)
    MSSAU->removeBlocks(DeadBlockSet);

  // Filter out the dead blocks from the exit blocks list so that it can be
  // used in the caller.
  llvm::erase_if(ExitBlocks,
                 [&](BasicBlock *BB) { return DeadBlockSet.count(BB); });

  // Walk from this loop up through its parents removing all of the dead blocks.
  for (Loop *ParentL = &L; ParentL; ParentL = ParentL->getParentLoop()) {
    for (auto *BB : DeadBlockSet)
      ParentL->getBlocksSet().erase(BB);
    llvm::erase_if(ParentL->getBlocksVector(),
                   [&](BasicBlock *BB) { return DeadBlockSet.count(BB); });
  }

  // Now delete the dead child loops. This raw delete will clear them
  // recursively.
  llvm::erase_if(L.getSubLoopsVector(), [&](Loop *ChildL) {
    if (!DeadBlockSet.count(ChildL->getHeader()))
      return false;

    assert(llvm::all_of(ChildL->blocks(),
                        [&](BasicBlock *ChildBB) {
                          return DeadBlockSet.count(ChildBB);
                        }) &&
           "If the child loop header is dead all blocks in the child loop must "
           "be dead as well!");
    LoopUpdater.markLoopAsDeleted(*ChildL, ChildL->getName());
    if (SE)
      SE->forgetBlockAndLoopDispositions();
    LI.destroy(ChildL);
    return true;
  });

  // Remove the loop mappings for the dead blocks and drop all the references
  // from these blocks to others to handle cyclic references as we start
  // deleting the blocks themselves.
  for (auto *BB : DeadBlockSet) {
    // Check that the dominator tree has already been updated.
    assert(!DT.getNode(BB) && "Should already have cleared domtree!");
    LI.changeLoopFor(BB, nullptr);
    // Drop all uses of the instructions to make sure we won't have dangling
    // uses in other blocks.
    for (auto &I : *BB)
      if (!I.use_empty())
        I.replaceAllUsesWith(PoisonValue::get(I.getType()));
    BB->dropAllReferences();
  }

  // Actually delete the blocks now that they've been fully unhooked from the
  // IR.
  for (auto *BB : DeadBlockSet)
    BB->eraseFromParent();
}

/// Recompute the set of blocks in a loop after unswitching.
///
/// This walks from the original headers predecessors to rebuild the loop. We
/// take advantage of the fact that new blocks can't have been added, and so we
/// filter by the original loop's blocks. This also handles potentially
/// unreachable code that we don't want to explore but might be found examining
/// the predecessors of the header.
///
/// If the original loop is no longer a loop, this will return an empty set. If
/// it remains a loop, all the blocks within it will be added to the set
/// (including those blocks in inner loops).
static SmallPtrSet<const BasicBlock *, 16> recomputeLoopBlockSet(Loop &L,
                                                                 LoopInfo &LI) {
  SmallPtrSet<const BasicBlock *, 16> LoopBlockSet;

  auto *PH = L.getLoopPreheader();
  auto *Header = L.getHeader();

  // A worklist to use while walking backwards from the header.
  SmallVector<BasicBlock *, 16> Worklist;

  // First walk the predecessors of the header to find the backedges. This will
  // form the basis of our walk.
  for (auto *Pred : predecessors(Header)) {
    // Skip the preheader.
    if (Pred == PH)
      continue;

    // Because the loop was in simplified form, the only non-loop predecessor
    // is the preheader.
    assert(L.contains(Pred) && "Found a predecessor of the loop header other "
                               "than the preheader that is not part of the "
                               "loop!");

    // Insert this block into the loop set and on the first visit and, if it
    // isn't the header we're currently walking, put it into the worklist to
    // recurse through.
    if (LoopBlockSet.insert(Pred).second && Pred != Header)
      Worklist.push_back(Pred);
  }

  // If no backedges were found, we're done.
  if (LoopBlockSet.empty())
    return LoopBlockSet;

  // We found backedges, recurse through them to identify the loop blocks.
  while (!Worklist.empty()) {
    BasicBlock *BB = Worklist.pop_back_val();
    assert(LoopBlockSet.count(BB) && "Didn't put block into the loop set!");

    // No need to walk past the header.
    if (BB == Header)
      continue;

    // Because we know the inner loop structure remains valid we can use the
    // loop structure to jump immediately across the entire nested loop.
    // Further, because it is in loop simplified form, we can directly jump
    // to its preheader afterward.
    if (Loop *InnerL = LI.getLoopFor(BB))
      if (InnerL != &L) {
        assert(L.contains(InnerL) &&
               "Should not reach a loop *outside* this loop!");
        // The preheader is the only possible predecessor of the loop so
        // insert it into the set and check whether it was already handled.
        auto *InnerPH = InnerL->getLoopPreheader();
        assert(L.contains(InnerPH) && "Cannot contain an inner loop block "
                                      "but not contain the inner loop "
                                      "preheader!");
        if (!LoopBlockSet.insert(InnerPH).second)
          // The only way to reach the preheader is through the loop body
          // itself so if it has been visited the loop is already handled.
          continue;

        // Insert all of the blocks (other than those already present) into
        // the loop set. We expect at least the block that led us to find the
        // inner loop to be in the block set, but we may also have other loop
        // blocks if they were already enqueued as predecessors of some other
        // outer loop block.
        for (auto *InnerBB : InnerL->blocks()) {
          if (InnerBB == BB) {
            assert(LoopBlockSet.count(InnerBB) &&
                   "Block should already be in the set!");
            continue;
          }

          LoopBlockSet.insert(InnerBB);
        }

        // Add the preheader to the worklist so we will continue past the
        // loop body.
        Worklist.push_back(InnerPH);
        continue;
      }

    // Insert any predecessors that were in the original loop into the new
    // set, and if the insert is successful, add them to the worklist.
    for (auto *Pred : predecessors(BB))
      if (L.contains(Pred) && LoopBlockSet.insert(Pred).second)
        Worklist.push_back(Pred);
  }

  assert(LoopBlockSet.count(Header) && "Cannot fail to add the header!");

  // We've found all the blocks participating in the loop, return our completed
  // set.
  return LoopBlockSet;
}

/// Rebuild a loop after unswitching removes some subset of blocks and edges.
///
/// The removal may have removed some child loops entirely but cannot have
/// disturbed any remaining child loops. However, they may need to be hoisted
/// to the parent loop (or to be top-level loops). The original loop may be
/// completely removed.
///
/// The sibling loops resulting from this update are returned. If the original
/// loop remains a valid loop, it will be the first entry in this list with all
/// of the newly sibling loops following it.
///
/// Returns true if the loop remains a loop after unswitching, and false if it
/// is no longer a loop after unswitching (and should not continue to be
/// referenced).
static bool rebuildLoopAfterUnswitch(Loop &L, ArrayRef<BasicBlock *> ExitBlocks,
                                     LoopInfo &LI,
                                     SmallVectorImpl<Loop *> &HoistedLoops,
                                     ScalarEvolution *SE) {
  auto *PH = L.getLoopPreheader();

  // Compute the actual parent loop from the exit blocks. Because we may have
  // pruned some exits the loop may be different from the original parent.
  Loop *ParentL = nullptr;
  SmallVector<Loop *, 4> ExitLoops;
  SmallVector<BasicBlock *, 4> ExitsInLoops;
  ExitsInLoops.reserve(ExitBlocks.size());
  for (auto *ExitBB : ExitBlocks)
    if (Loop *ExitL = LI.getLoopFor(ExitBB)) {
      ExitLoops.push_back(ExitL);
      ExitsInLoops.push_back(ExitBB);
      if (!ParentL || (ParentL != ExitL && ParentL->contains(ExitL)))
        ParentL = ExitL;
    }

  // Recompute the blocks participating in this loop. This may be empty if it
  // is no longer a loop.
  auto LoopBlockSet = recomputeLoopBlockSet(L, LI);

  // If we still have a loop, we need to re-set the loop's parent as the exit
  // block set changing may have moved it within the loop nest. Note that this
  // can only happen when this loop has a parent as it can only hoist the loop
  // *up* the nest.
  if (!LoopBlockSet.empty() && L.getParentLoop() != ParentL) {
    // Remove this loop's (original) blocks from all of the intervening loops.
    for (Loop *IL = L.getParentLoop(); IL != ParentL;
         IL = IL->getParentLoop()) {
      IL->getBlocksSet().erase(PH);
      for (auto *BB : L.blocks())
        IL->getBlocksSet().erase(BB);
      llvm::erase_if(IL->getBlocksVector(), [&](BasicBlock *BB) {
        return BB == PH || L.contains(BB);
      });
    }

    LI.changeLoopFor(PH, ParentL);
    L.getParentLoop()->removeChildLoop(&L);
    if (ParentL)
      ParentL->addChildLoop(&L);
    else
      LI.addTopLevelLoop(&L);
  }

  // Now we update all the blocks which are no longer within the loop.
  auto &Blocks = L.getBlocksVector();
  auto BlocksSplitI =
      LoopBlockSet.empty()
          ? Blocks.begin()
          : std::stable_partition(
                Blocks.begin(), Blocks.end(),
                [&](BasicBlock *BB) { return LoopBlockSet.count(BB); });

  // Before we erase the list of unlooped blocks, build a set of them.
  SmallPtrSet<BasicBlock *, 16> UnloopedBlocks(BlocksSplitI, Blocks.end());
  if (LoopBlockSet.empty())
    UnloopedBlocks.insert(PH);

  // Now erase these blocks from the loop.
  for (auto *BB : make_range(BlocksSplitI, Blocks.end()))
    L.getBlocksSet().erase(BB);
  Blocks.erase(BlocksSplitI, Blocks.end());

  // Sort the exits in ascending loop depth, we'll work backwards across these
  // to process them inside out.
  llvm::stable_sort(ExitsInLoops, [&](BasicBlock *LHS, BasicBlock *RHS) {
    return LI.getLoopDepth(LHS) < LI.getLoopDepth(RHS);
  });

  // We'll build up a set for each exit loop.
  SmallPtrSet<BasicBlock *, 16> NewExitLoopBlocks;
  Loop *PrevExitL = L.getParentLoop(); // The deepest possible exit loop.

  auto RemoveUnloopedBlocksFromLoop =
      [](Loop &L, SmallPtrSetImpl<BasicBlock *> &UnloopedBlocks) {
        for (auto *BB : UnloopedBlocks)
          L.getBlocksSet().erase(BB);
        llvm::erase_if(L.getBlocksVector(), [&](BasicBlock *BB) {
          return UnloopedBlocks.count(BB);
        });
      };

  SmallVector<BasicBlock *, 16> Worklist;
  while (!UnloopedBlocks.empty() && !ExitsInLoops.empty()) {
    assert(Worklist.empty() && "Didn't clear worklist!");
    assert(NewExitLoopBlocks.empty() && "Didn't clear loop set!");

    // Grab the next exit block, in decreasing loop depth order.
    BasicBlock *ExitBB = ExitsInLoops.pop_back_val();
    Loop &ExitL = *LI.getLoopFor(ExitBB);
    assert(ExitL.contains(&L) && "Exit loop must contain the inner loop!");

    // Erase all of the unlooped blocks from the loops between the previous
    // exit loop and this exit loop. This works because the ExitInLoops list is
    // sorted in increasing order of loop depth and thus we visit loops in
    // decreasing order of loop depth.
    for (; PrevExitL != &ExitL; PrevExitL = PrevExitL->getParentLoop())
      RemoveUnloopedBlocksFromLoop(*PrevExitL, UnloopedBlocks);

    // Walk the CFG back until we hit the cloned PH adding everything reachable
    // and in the unlooped set to this exit block's loop.
    Worklist.push_back(ExitBB);
    do {
      BasicBlock *BB = Worklist.pop_back_val();
      // We can stop recursing at the cloned preheader (if we get there).
      if (BB == PH)
        continue;

      for (BasicBlock *PredBB : predecessors(BB)) {
        // If this pred has already been moved to our set or is part of some
        // (inner) loop, no update needed.
        if (!UnloopedBlocks.erase(PredBB)) {
          assert((NewExitLoopBlocks.count(PredBB) ||
                  ExitL.contains(LI.getLoopFor(PredBB))) &&
                 "Predecessor not in a nested loop (or already visited)!");
          continue;
        }

        // We just insert into the loop set here. We'll add these blocks to the
        // exit loop after we build up the set in a deterministic order rather
        // than the predecessor-influenced visit order.
        bool Inserted = NewExitLoopBlocks.insert(PredBB).second;
        (void)Inserted;
        assert(Inserted && "Should only visit an unlooped block once!");

        // And recurse through to its predecessors.
        Worklist.push_back(PredBB);
      }
    } while (!Worklist.empty());

    // If blocks in this exit loop were directly part of the original loop (as
    // opposed to a child loop) update the map to point to this exit loop. This
    // just updates a map and so the fact that the order is unstable is fine.
    for (auto *BB : NewExitLoopBlocks)
      if (Loop *BBL = LI.getLoopFor(BB))
        if (BBL == &L || !L.contains(BBL))
          LI.changeLoopFor(BB, &ExitL);

    // We will remove the remaining unlooped blocks from this loop in the next
    // iteration or below.
    NewExitLoopBlocks.clear();
  }

  // Any remaining unlooped blocks are no longer part of any loop unless they
  // are part of some child loop.
  for (; PrevExitL; PrevExitL = PrevExitL->getParentLoop())
    RemoveUnloopedBlocksFromLoop(*PrevExitL, UnloopedBlocks);
  for (auto *BB : UnloopedBlocks)
    if (Loop *BBL = LI.getLoopFor(BB))
      if (BBL == &L || !L.contains(BBL))
        LI.changeLoopFor(BB, nullptr);

  // Sink all the child loops whose headers are no longer in the loop set to
  // the parent (or to be top level loops). We reach into the loop and directly
  // update its subloop vector to make this batch update efficient.
  auto &SubLoops = L.getSubLoopsVector();
  auto SubLoopsSplitI =
      LoopBlockSet.empty()
          ? SubLoops.begin()
          : std::stable_partition(
                SubLoops.begin(), SubLoops.end(), [&](Loop *SubL) {
                  return LoopBlockSet.count(SubL->getHeader());
                });
  for (auto *HoistedL : make_range(SubLoopsSplitI, SubLoops.end())) {
    HoistedLoops.push_back(HoistedL);
    HoistedL->setParentLoop(nullptr);

    // To compute the new parent of this hoisted loop we look at where we
    // placed the preheader above. We can't lookup the header itself because we
    // retained the mapping from the header to the hoisted loop. But the
    // preheader and header should have the exact same new parent computed
    // based on the set of exit blocks from the original loop as the preheader
    // is a predecessor of the header and so reached in the reverse walk. And
    // because the loops were all in simplified form the preheader of the
    // hoisted loop can't be part of some *other* loop.
    if (auto *NewParentL = LI.getLoopFor(HoistedL->getLoopPreheader()))
      NewParentL->addChildLoop(HoistedL);
    else
      LI.addTopLevelLoop(HoistedL);
  }
  SubLoops.erase(SubLoopsSplitI, SubLoops.end());

  // Actually delete the loop if nothing remained within it.
  if (Blocks.empty()) {
    assert(SubLoops.empty() &&
           "Failed to remove all subloops from the original loop!");
    if (Loop *ParentL = L.getParentLoop())
      ParentL->removeChildLoop(llvm::find(*ParentL, &L));
    else
      LI.removeLoop(llvm::find(LI, &L));
    // markLoopAsDeleted for L should be triggered by the caller (it is
    // typically done within postUnswitch).
    if (SE)
      SE->forgetBlockAndLoopDispositions();
    LI.destroy(&L);
    return false;
  }

  return true;
}

/// Helper to visit a dominator subtree, invoking a callable on each node.
///
/// Returning false at any point will stop walking past that node of the tree.
template <typename CallableT>
void visitDomSubTree(DominatorTree &DT, BasicBlock *BB, CallableT Callable) {
  SmallVector<DomTreeNode *, 4> DomWorklist;
  DomWorklist.push_back(DT[BB]);
#ifndef NDEBUG
  SmallPtrSet<DomTreeNode *, 4> Visited;
  Visited.insert(DT[BB]);
#endif
  do {
    DomTreeNode *N = DomWorklist.pop_back_val();

    // Visit this node.
    if (!Callable(N->getBlock()))
      continue;

    // Accumulate the child nodes.
    for (DomTreeNode *ChildN : *N) {
      assert(Visited.insert(ChildN).second &&
             "Cannot visit a node twice when walking a tree!");
      DomWorklist.push_back(ChildN);
    }
  } while (!DomWorklist.empty());
}

void postUnswitch(Loop &L, LPMUpdater &U, StringRef LoopName,
                  bool CurrentLoopValid, bool PartiallyInvariant,
                  bool InjectedCondition, ArrayRef<Loop *> NewLoops) {
  // If we did a non-trivial unswitch, we have added new (cloned) loops.
  if (!NewLoops.empty())
    U.addSiblingLoops(NewLoops);

  // If the current loop remains valid, we should revisit it to catch any
  // other unswitch opportunities. Otherwise, we need to mark it as deleted.
  if (CurrentLoopValid) {
    if (PartiallyInvariant) {
      // Mark the new loop as partially unswitched, to avoid unswitching on
      // the same condition again.
      auto &Context = L.getHeader()->getContext();
      MDNode *DisableUnswitchMD = MDNode::get(
          Context,
          MDString::get(Context, "llvm.loop.unswitch.partial.disable"));
      MDNode *NewLoopID = makePostTransformationMetadata(
          Context, L.getLoopID(), {"llvm.loop.unswitch.partial"},
          {DisableUnswitchMD});
      L.setLoopID(NewLoopID);
    } else if (InjectedCondition) {
      // Do the same for injection of invariant conditions.
      auto &Context = L.getHeader()->getContext();
      MDNode *DisableUnswitchMD = MDNode::get(
          Context,
          MDString::get(Context, "llvm.loop.unswitch.injection.disable"));
      MDNode *NewLoopID = makePostTransformationMetadata(
          Context, L.getLoopID(), {"llvm.loop.unswitch.injection"},
          {DisableUnswitchMD});
      L.setLoopID(NewLoopID);
    } else
      U.revisitCurrentLoop();
  } else
    U.markLoopAsDeleted(L, LoopName);
}

static void unswitchNontrivialInvariants(
    Loop &L, Instruction &TI, ArrayRef<Value *> Invariants,
    IVConditionInfo &PartialIVInfo, DominatorTree &DT, LoopInfo &LI,
    AssumptionCache &AC, ScalarEvolution *SE, MemorySSAUpdater *MSSAU,
    LPMUpdater &LoopUpdater, bool InsertFreeze, bool InjectedCondition) {
  auto *ParentBB = TI.getParent();
  BranchInst *BI = dyn_cast<BranchInst>(&TI);
  SwitchInst *SI = BI ? nullptr : cast<SwitchInst>(&TI);

  // Save the current loop name in a variable so that we can report it even
  // after it has been deleted.
  std::string LoopName(L.getName());

  // We can only unswitch switches, conditional branches with an invariant
  // condition, or combining invariant conditions with an instruction or
  // partially invariant instructions.
  assert((SI || (BI && BI->isConditional())) &&
         "Can only unswitch switches and conditional branch!");
  bool PartiallyInvariant = !PartialIVInfo.InstToDuplicate.empty();
  bool FullUnswitch =
      SI || (skipTrivialSelect(BI->getCondition()) == Invariants[0] &&
             !PartiallyInvariant);
  if (FullUnswitch)
    assert(Invariants.size() == 1 &&
           "Cannot have other invariants with full unswitching!");
  else
    assert(isa<Instruction>(skipTrivialSelect(BI->getCondition())) &&
           "Partial unswitching requires an instruction as the condition!");

  if (MSSAU && VerifyMemorySSA)
    MSSAU->getMemorySSA()->verifyMemorySSA();

  // Constant and BBs tracking the cloned and continuing successor. When we are
  // unswitching the entire condition, this can just be trivially chosen to
  // unswitch towards `true`. However, when we are unswitching a set of
  // invariants combined with `and` or `or` or partially invariant instructions,
  // the combining operation determines the best direction to unswitch: we want
  // to unswitch the direction that will collapse the branch.
  bool Direction = true;
  int ClonedSucc = 0;
  if (!FullUnswitch) {
    Value *Cond = skipTrivialSelect(BI->getCondition());
    (void)Cond;
    assert(((match(Cond, m_LogicalAnd()) ^ match(Cond, m_LogicalOr())) ||
            PartiallyInvariant) &&
           "Only `or`, `and`, an `select`, partially invariant instructions "
           "can combine invariants being unswitched.");
    if (!match(Cond, m_LogicalOr())) {
      if (match(Cond, m_LogicalAnd()) ||
          (PartiallyInvariant && !PartialIVInfo.KnownValue->isOneValue())) {
        Direction = false;
        ClonedSucc = 1;
      }
    }
  }

  BasicBlock *RetainedSuccBB =
      BI ? BI->getSuccessor(1 - ClonedSucc) : SI->getDefaultDest();
  SmallSetVector<BasicBlock *, 4> UnswitchedSuccBBs;
  if (BI)
    UnswitchedSuccBBs.insert(BI->getSuccessor(ClonedSucc));
  else
    for (auto Case : SI->cases())
      if (Case.getCaseSuccessor() != RetainedSuccBB)
        UnswitchedSuccBBs.insert(Case.getCaseSuccessor());

  assert(!UnswitchedSuccBBs.count(RetainedSuccBB) &&
         "Should not unswitch the same successor we are retaining!");

  // The branch should be in this exact loop. Any inner loop's invariant branch
  // should be handled by unswitching that inner loop. The caller of this
  // routine should filter out any candidates that remain (but were skipped for
  // whatever reason).
  assert(LI.getLoopFor(ParentBB) == &L && "Branch in an inner loop!");

  // Compute the parent loop now before we start hacking on things.
  Loop *ParentL = L.getParentLoop();
  // Get blocks in RPO order for MSSA update, before changing the CFG.
  LoopBlocksRPO LBRPO(&L);
  if (MSSAU)
    LBRPO.perform(&LI);

  // Compute the outer-most loop containing one of our exit blocks. This is the
  // furthest up our loopnest which can be mutated, which we will use below to
  // update things.
  Loop *OuterExitL = &L;
  SmallVector<BasicBlock *, 4> ExitBlocks;
  L.getUniqueExitBlocks(ExitBlocks);
  for (auto *ExitBB : ExitBlocks) {
    // ExitBB can be an exit block for several levels in the loop nest. Make
    // sure we find the top most.
    Loop *NewOuterExitL = getTopMostExitingLoop(ExitBB, LI);
    if (!NewOuterExitL) {
      // We exited the entire nest with this block, so we're done.
      OuterExitL = nullptr;
      break;
    }
    if (NewOuterExitL != OuterExitL && NewOuterExitL->contains(OuterExitL))
      OuterExitL = NewOuterExitL;
  }

  // At this point, we're definitely going to unswitch something so invalidate
  // any cached information in ScalarEvolution for the outer most loop
  // containing an exit block and all nested loops.
  if (SE) {
    if (OuterExitL)
      SE->forgetLoop(OuterExitL);
    else
      SE->forgetTopmostLoop(&L);
    SE->forgetBlockAndLoopDispositions();
  }

  // If the edge from this terminator to a successor dominates that successor,
  // store a map from each block in its dominator subtree to it. This lets us
  // tell when cloning for a particular successor if a block is dominated by
  // some *other* successor with a single data structure. We use this to
  // significantly reduce cloning.
  SmallDenseMap<BasicBlock *, BasicBlock *, 16> DominatingSucc;
  for (auto *SuccBB : llvm::concat<BasicBlock *const>(ArrayRef(RetainedSuccBB),
                                                      UnswitchedSuccBBs))
    if (SuccBB->getUniquePredecessor() ||
        llvm::all_of(predecessors(SuccBB), [&](BasicBlock *PredBB) {
          return PredBB == ParentBB || DT.dominates(SuccBB, PredBB);
        }))
      visitDomSubTree(DT, SuccBB, [&](BasicBlock *BB) {
        DominatingSucc[BB] = SuccBB;
        return true;
      });

  // Split the preheader, so that we know that there is a safe place to insert
  // the conditional branch. We will change the preheader to have a conditional
  // branch on LoopCond. The original preheader will become the split point
  // between the unswitched versions, and we will have a new preheader for the
  // original loop.
  BasicBlock *SplitBB = L.getLoopPreheader();
  BasicBlock *LoopPH = SplitEdge(SplitBB, L.getHeader(), &DT, &LI, MSSAU);

  // Keep track of the dominator tree updates needed.
  SmallVector<DominatorTree::UpdateType, 4> DTUpdates;

  // Clone the loop for each unswitched successor.
  SmallVector<std::unique_ptr<ValueToValueMapTy>, 4> VMaps;
  VMaps.reserve(UnswitchedSuccBBs.size());
  SmallDenseMap<BasicBlock *, BasicBlock *, 4> ClonedPHs;
  for (auto *SuccBB : UnswitchedSuccBBs) {
    VMaps.emplace_back(new ValueToValueMapTy());
    ClonedPHs[SuccBB] = buildClonedLoopBlocks(
        L, LoopPH, SplitBB, ExitBlocks, ParentBB, SuccBB, RetainedSuccBB,
        DominatingSucc, *VMaps.back(), DTUpdates, AC, DT, LI, MSSAU, SE);
  }

  // Drop metadata if we may break its semantics by moving this instr into the
  // split block.
  if (TI.getMetadata(LLVMContext::MD_make_implicit)) {
    if (DropNonTrivialImplicitNullChecks)
      // Do not spend time trying to understand if we can keep it, just drop it
      // to save compile time.
      TI.setMetadata(LLVMContext::MD_make_implicit, nullptr);
    else {
      // It is only legal to preserve make.implicit metadata if we are
      // guaranteed no reach implicit null check after following this branch.
      ICFLoopSafetyInfo SafetyInfo;
      SafetyInfo.computeLoopSafetyInfo(&L);
      if (!SafetyInfo.isGuaranteedToExecute(TI, &DT, &L))
        TI.setMetadata(LLVMContext::MD_make_implicit, nullptr);
    }
  }

  // The stitching of the branched code back together depends on whether we're
  // doing full unswitching or not with the exception that we always want to
  // nuke the initial terminator placed in the split block.
  SplitBB->getTerminator()->eraseFromParent();
  if (FullUnswitch) {
    // Splice the terminator from the original loop and rewrite its
    // successors.
    TI.moveBefore(*SplitBB, SplitBB->end());

    // Keep a clone of the terminator for MSSA updates.
    Instruction *NewTI = TI.clone();
    NewTI->insertInto(ParentBB, ParentBB->end());

    // First wire up the moved terminator to the preheaders.
    if (BI) {
      BasicBlock *ClonedPH = ClonedPHs.begin()->second;
      BI->setSuccessor(ClonedSucc, ClonedPH);
      BI->setSuccessor(1 - ClonedSucc, LoopPH);
      Value *Cond = skipTrivialSelect(BI->getCondition());
      if (InsertFreeze)
        Cond = new FreezeInst(Cond, Cond->getName() + ".fr", BI->getIterator());
      BI->setCondition(Cond);
      DTUpdates.push_back({DominatorTree::Insert, SplitBB, ClonedPH});
    } else {
      assert(SI && "Must either be a branch or switch!");

      // Walk the cases and directly update their successors.
      assert(SI->getDefaultDest() == RetainedSuccBB &&
             "Not retaining default successor!");
      SI->setDefaultDest(LoopPH);
      for (const auto &Case : SI->cases())
        if (Case.getCaseSuccessor() == RetainedSuccBB)
          Case.setSuccessor(LoopPH);
        else
          Case.setSuccessor(ClonedPHs.find(Case.getCaseSuccessor())->second);

      if (InsertFreeze)
        SI->setCondition(new FreezeInst(SI->getCondition(),
                                        SI->getCondition()->getName() + ".fr",
                                        SI->getIterator()));

      // We need to use the set to populate domtree updates as even when there
      // are multiple cases pointing at the same successor we only want to
      // remove and insert one edge in the domtree.
      for (BasicBlock *SuccBB : UnswitchedSuccBBs)
        DTUpdates.push_back(
            {DominatorTree::Insert, SplitBB, ClonedPHs.find(SuccBB)->second});
    }

    if (MSSAU) {
      DT.applyUpdates(DTUpdates);
      DTUpdates.clear();

      // Remove all but one edge to the retained block and all unswitched
      // blocks. This is to avoid having duplicate entries in the cloned Phis,
      // when we know we only keep a single edge for each case.
      MSSAU->removeDuplicatePhiEdgesBetween(ParentBB, RetainedSuccBB);
      for (BasicBlock *SuccBB : UnswitchedSuccBBs)
        MSSAU->removeDuplicatePhiEdgesBetween(ParentBB, SuccBB);

      for (auto &VMap : VMaps)
        MSSAU->updateForClonedLoop(LBRPO, ExitBlocks, *VMap,
                                   /*IgnoreIncomingWithNoClones=*/true);
      MSSAU->updateExitBlocksForClonedLoop(ExitBlocks, VMaps, DT);

      // Remove all edges to unswitched blocks.
      for (BasicBlock *SuccBB : UnswitchedSuccBBs)
        MSSAU->removeEdge(ParentBB, SuccBB);
    }

    // Now unhook the successor relationship as we'll be replacing
    // the terminator with a direct branch. This is much simpler for branches
    // than switches so we handle those first.
    if (BI) {
      // Remove the parent as a predecessor of the unswitched successor.
      assert(UnswitchedSuccBBs.size() == 1 &&
             "Only one possible unswitched block for a branch!");
      BasicBlock *UnswitchedSuccBB = *UnswitchedSuccBBs.begin();
      UnswitchedSuccBB->removePredecessor(ParentBB,
                                          /*KeepOneInputPHIs*/ true);
      DTUpdates.push_back({DominatorTree::Delete, ParentBB, UnswitchedSuccBB});
    } else {
      // Note that we actually want to remove the parent block as a predecessor
      // of *every* case successor. The case successor is either unswitched,
      // completely eliminating an edge from the parent to that successor, or it
      // is a duplicate edge to the retained successor as the retained successor
      // is always the default successor and as we'll replace this with a direct
      // branch we no longer need the duplicate entries in the PHI nodes.
      SwitchInst *NewSI = cast<SwitchInst>(NewTI);
      assert(NewSI->getDefaultDest() == RetainedSuccBB &&
             "Not retaining default successor!");
      for (const auto &Case : NewSI->cases())
        Case.getCaseSuccessor()->removePredecessor(
            ParentBB,
            /*KeepOneInputPHIs*/ true);

      // We need to use the set to populate domtree updates as even when there
      // are multiple cases pointing at the same successor we only want to
      // remove and insert one edge in the domtree.
      for (BasicBlock *SuccBB : UnswitchedSuccBBs)
        DTUpdates.push_back({DominatorTree::Delete, ParentBB, SuccBB});
    }

    // After MSSAU update, remove the cloned terminator instruction NewTI.
    ParentBB->getTerminator()->eraseFromParent();

    // Create a new unconditional branch to the continuing block (as opposed to
    // the one cloned).
    BranchInst::Create(RetainedSuccBB, ParentBB);
  } else {
    assert(BI && "Only branches have partial unswitching.");
    assert(UnswitchedSuccBBs.size() == 1 &&
           "Only one possible unswitched block for a branch!");
    BasicBlock *ClonedPH = ClonedPHs.begin()->second;
    // When doing a partial unswitch, we have to do a bit more work to build up
    // the branch in the split block.
    if (PartiallyInvariant)
      buildPartialInvariantUnswitchConditionalBranch(
          *SplitBB, Invariants, Direction, *ClonedPH, *LoopPH, L, MSSAU);
    else {
      buildPartialUnswitchConditionalBranch(
          *SplitBB, Invariants, Direction, *ClonedPH, *LoopPH,
          FreezeLoopUnswitchCond, BI, &AC, DT);
    }
    DTUpdates.push_back({DominatorTree::Insert, SplitBB, ClonedPH});

    if (MSSAU) {
      DT.applyUpdates(DTUpdates);
      DTUpdates.clear();

      // Perform MSSA cloning updates.
      for (auto &VMap : VMaps)
        MSSAU->updateForClonedLoop(LBRPO, ExitBlocks, *VMap,
                                   /*IgnoreIncomingWithNoClones=*/true);
      MSSAU->updateExitBlocksForClonedLoop(ExitBlocks, VMaps, DT);
    }
  }

  // Apply the updates accumulated above to get an up-to-date dominator tree.
  DT.applyUpdates(DTUpdates);

  // Now that we have an accurate dominator tree, first delete the dead cloned
  // blocks so that we can accurately build any cloned loops. It is important to
  // not delete the blocks from the original loop yet because we still want to
  // reference the original loop to understand the cloned loop's structure.
  deleteDeadClonedBlocks(L, ExitBlocks, VMaps, DT, MSSAU);

  // Build the cloned loop structure itself. This may be substantially
  // different from the original structure due to the simplified CFG. This also
  // handles inserting all the cloned blocks into the correct loops.
  SmallVector<Loop *, 4> NonChildClonedLoops;
  for (std::unique_ptr<ValueToValueMapTy> &VMap : VMaps)
    buildClonedLoops(L, ExitBlocks, *VMap, LI, NonChildClonedLoops);

  // Now that our cloned loops have been built, we can update the original loop.
  // First we delete the dead blocks from it and then we rebuild the loop
  // structure taking these deletions into account.
  deleteDeadBlocksFromLoop(L, ExitBlocks, DT, LI, MSSAU, SE, LoopUpdater);

  if (MSSAU && VerifyMemorySSA)
    MSSAU->getMemorySSA()->verifyMemorySSA();

  SmallVector<Loop *, 4> HoistedLoops;
  bool IsStillLoop =
      rebuildLoopAfterUnswitch(L, ExitBlocks, LI, HoistedLoops, SE);

  if (MSSAU && VerifyMemorySSA)
    MSSAU->getMemorySSA()->verifyMemorySSA();

  // This transformation has a high risk of corrupting the dominator tree, and
  // the below steps to rebuild loop structures will result in hard to debug
  // errors in that case so verify that the dominator tree is sane first.
  // FIXME: Remove this when the bugs stop showing up and rely on existing
  // verification steps.
  assert(DT.verify(DominatorTree::VerificationLevel::Fast));

  if (BI && !PartiallyInvariant) {
    // If we unswitched a branch which collapses the condition to a known
    // constant we want to replace all the uses of the invariants within both
    // the original and cloned blocks. We do this here so that we can use the
    // now updated dominator tree to identify which side the users are on.
    assert(UnswitchedSuccBBs.size() == 1 &&
           "Only one possible unswitched block for a branch!");
    BasicBlock *ClonedPH = ClonedPHs.begin()->second;

    // When considering multiple partially-unswitched invariants
    // we cant just go replace them with constants in both branches.
    //
    // For 'AND' we infer that true branch ("continue") means true
    // for each invariant operand.
    // For 'OR' we can infer that false branch ("continue") means false
    // for each invariant operand.
    // So it happens that for multiple-partial case we dont replace
    // in the unswitched branch.
    bool ReplaceUnswitched =
        FullUnswitch || (Invariants.size() == 1) || PartiallyInvariant;

    ConstantInt *UnswitchedReplacement =
        Direction ? ConstantInt::getTrue(BI->getContext())
                  : ConstantInt::getFalse(BI->getContext());
    ConstantInt *ContinueReplacement =
        Direction ? ConstantInt::getFalse(BI->getContext())
                  : ConstantInt::getTrue(BI->getContext());
    for (Value *Invariant : Invariants) {
      assert(!isa<Constant>(Invariant) &&
             "Should not be replacing constant values!");
      // Use make_early_inc_range here as set invalidates the iterator.
      for (Use &U : llvm::make_early_inc_range(Invariant->uses())) {
        Instruction *UserI = dyn_cast<Instruction>(U.getUser());
        if (!UserI)
          continue;

        // Replace it with the 'continue' side if in the main loop body, and the
        // unswitched if in the cloned blocks.
        if (DT.dominates(LoopPH, UserI->getParent()))
          U.set(ContinueReplacement);
        else if (ReplaceUnswitched &&
                 DT.dominates(ClonedPH, UserI->getParent()))
          U.set(UnswitchedReplacement);
      }
    }
  }

  // We can change which blocks are exit blocks of all the cloned sibling
  // loops, the current loop, and any parent loops which shared exit blocks
  // with the current loop. As a consequence, we need to re-form LCSSA for
  // them. But we shouldn't need to re-form LCSSA for any child loops.
  // FIXME: This could be made more efficient by tracking which exit blocks are
  // new, and focusing on them, but that isn't likely to be necessary.
  //
  // In order to reasonably rebuild LCSSA we need to walk inside-out across the
  // loop nest and update every loop that could have had its exits changed. We
  // also need to cover any intervening loops. We add all of these loops to
  // a list and sort them by loop depth to achieve this without updating
  // unnecessary loops.
  auto UpdateLoop = [&](Loop &UpdateL) {
#ifndef NDEBUG
    UpdateL.verifyLoop();
    for (Loop *ChildL : UpdateL) {
      ChildL->verifyLoop();
      assert(ChildL->isRecursivelyLCSSAForm(DT, LI) &&
             "Perturbed a child loop's LCSSA form!");
    }
#endif
    // First build LCSSA for this loop so that we can preserve it when
    // forming dedicated exits. We don't want to perturb some other loop's
    // LCSSA while doing that CFG edit.
    formLCSSA(UpdateL, DT, &LI, SE);

    // For loops reached by this loop's original exit blocks we may
    // introduced new, non-dedicated exits. At least try to re-form dedicated
    // exits for these loops. This may fail if they couldn't have dedicated
    // exits to start with.
    formDedicatedExitBlocks(&UpdateL, &DT, &LI, MSSAU, /*PreserveLCSSA*/ true);
  };

  // For non-child cloned loops and hoisted loops, we just need to update LCSSA
  // and we can do it in any order as they don't nest relative to each other.
  //
  // Also check if any of the loops we have updated have become top-level loops
  // as that will necessitate widening the outer loop scope.
  for (Loop *UpdatedL :
       llvm::concat<Loop *>(NonChildClonedLoops, HoistedLoops)) {
    UpdateLoop(*UpdatedL);
    if (UpdatedL->isOutermost())
      OuterExitL = nullptr;
  }
  if (IsStillLoop) {
    UpdateLoop(L);
    if (L.isOutermost())
      OuterExitL = nullptr;
  }

  // If the original loop had exit blocks, walk up through the outer most loop
  // of those exit blocks to update LCSSA and form updated dedicated exits.
  if (OuterExitL != &L)
    for (Loop *OuterL = ParentL; OuterL != OuterExitL;
         OuterL = OuterL->getParentLoop())
      UpdateLoop(*OuterL);

#ifndef NDEBUG
  // Verify the entire loop structure to catch any incorrect updates before we
  // progress in the pass pipeline.
  LI.verify(DT);
#endif

  // Now that we've unswitched something, make callbacks to report the changes.
  // For that we need to merge together the updated loops and the cloned loops
  // and check whether the original loop survived.
  SmallVector<Loop *, 4> SibLoops;
  for (Loop *UpdatedL : llvm::concat<Loop *>(NonChildClonedLoops, HoistedLoops))
    if (UpdatedL->getParentLoop() == ParentL)
      SibLoops.push_back(UpdatedL);
  postUnswitch(L, LoopUpdater, LoopName, IsStillLoop, PartiallyInvariant,
               InjectedCondition, SibLoops);

  if (MSSAU && VerifyMemorySSA)
    MSSAU->getMemorySSA()->verifyMemorySSA();

  if (BI)
    ++NumBranches;
  else
    ++NumSwitches;
}

/// Recursively compute the cost of a dominator subtree based on the per-block
/// cost map provided.
///
/// The recursive computation is memozied into the provided DT-indexed cost map
/// to allow querying it for most nodes in the domtree without it becoming
/// quadratic.
static InstructionCost computeDomSubtreeCost(
    DomTreeNode &N,
    const SmallDenseMap<BasicBlock *, InstructionCost, 4> &BBCostMap,
    SmallDenseMap<DomTreeNode *, InstructionCost, 4> &DTCostMap) {
  // Don't accumulate cost (or recurse through) blocks not in our block cost
  // map and thus not part of the duplication cost being considered.
  auto BBCostIt = BBCostMap.find(N.getBlock());
  if (BBCostIt == BBCostMap.end())
    return 0;

  // Lookup this node to see if we already computed its cost.
  auto DTCostIt = DTCostMap.find(&N);
  if (DTCostIt != DTCostMap.end())
    return DTCostIt->second;

  // If not, we have to compute it. We can't use insert above and update
  // because computing the cost may insert more things into the map.
  InstructionCost Cost = std::accumulate(
      N.begin(), N.end(), BBCostIt->second,
      [&](InstructionCost Sum, DomTreeNode *ChildN) -> InstructionCost {
        return Sum + computeDomSubtreeCost(*ChildN, BBCostMap, DTCostMap);
      });
  bool Inserted = DTCostMap.insert({&N, Cost}).second;
  (void)Inserted;
  assert(Inserted && "Should not insert a node while visiting children!");
  return Cost;
}

/// Turns a select instruction into implicit control flow branch,
/// making the following replacement:
///
/// head:
///   --code before select--
///   select %cond, %trueval, %falseval
///   --code after select--
///
/// into
///
/// head:
///   --code before select--
///   br i1 %cond, label %then, label %tail
///
/// then:
///   br %tail
///
/// tail:
///   phi [ %trueval, %then ], [ %falseval, %head]
///   unreachable
///
/// It also makes all relevant DT and LI updates, so that all structures are in
/// valid state after this transform.
static BranchInst *turnSelectIntoBranch(SelectInst *SI, DominatorTree &DT,
                                        LoopInfo &LI, MemorySSAUpdater *MSSAU,
                                        AssumptionCache *AC) {
  LLVM_DEBUG(dbgs() << "Turning " << *SI << " into a branch.\n");
  BasicBlock *HeadBB = SI->getParent();

  DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Eager);
  SplitBlockAndInsertIfThen(SI->getCondition(), SI, false,
                            SI->getMetadata(LLVMContext::MD_prof), &DTU, &LI);
  auto *CondBr = cast<BranchInst>(HeadBB->getTerminator());
  BasicBlock *ThenBB = CondBr->getSuccessor(0),
             *TailBB = CondBr->getSuccessor(1);
  if (MSSAU)
    MSSAU->moveAllAfterSpliceBlocks(HeadBB, TailBB, SI);

  PHINode *Phi =
      PHINode::Create(SI->getType(), 2, "unswitched.select", SI->getIterator());
  Phi->addIncoming(SI->getTrueValue(), ThenBB);
  Phi->addIncoming(SI->getFalseValue(), HeadBB);
  SI->replaceAllUsesWith(Phi);
  SI->eraseFromParent();

  if (MSSAU && VerifyMemorySSA)
    MSSAU->getMemorySSA()->verifyMemorySSA();

  ++NumSelects;
  return CondBr;
}

/// Turns a llvm.experimental.guard intrinsic into implicit control flow branch,
/// making the following replacement:
///
///   --code before guard--
///   call void (i1, ...) @llvm.experimental.guard(i1 %cond) [ "deopt"() ]
///   --code after guard--
///
/// into
///
///   --code before guard--
///   br i1 %cond, label %guarded, label %deopt
///
/// guarded:
///   --code after guard--
///
/// deopt:
///   call void (i1, ...) @llvm.experimental.guard(i1 false) [ "deopt"() ]
///   unreachable
///
/// It also makes all relevant DT and LI updates, so that all structures are in
/// valid state after this transform.
static BranchInst *turnGuardIntoBranch(IntrinsicInst *GI, Loop &L,
                                       DominatorTree &DT, LoopInfo &LI,
                                       MemorySSAUpdater *MSSAU) {
  SmallVector<DominatorTree::UpdateType, 4> DTUpdates;
  LLVM_DEBUG(dbgs() << "Turning " << *GI << " into a branch.\n");
  BasicBlock *CheckBB = GI->getParent();

  if (MSSAU && VerifyMemorySSA)
     MSSAU->getMemorySSA()->verifyMemorySSA();

  DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Eager);
  Instruction *DeoptBlockTerm =
      SplitBlockAndInsertIfThen(GI->getArgOperand(0), GI, true,
                                GI->getMetadata(LLVMContext::MD_prof), &DTU, &LI);
  BranchInst *CheckBI = cast<BranchInst>(CheckBB->getTerminator());
  // SplitBlockAndInsertIfThen inserts control flow that branches to
  // DeoptBlockTerm if the condition is true.  We want the opposite.
  CheckBI->swapSuccessors();

  BasicBlock *GuardedBlock = CheckBI->getSuccessor(0);
  GuardedBlock->setName("guarded");
  CheckBI->getSuccessor(1)->setName("deopt");
  BasicBlock *DeoptBlock = CheckBI->getSuccessor(1);

  if (MSSAU)
    MSSAU->moveAllAfterSpliceBlocks(CheckBB, GuardedBlock, GI);

  GI->moveBefore(DeoptBlockTerm);
  GI->setArgOperand(0, ConstantInt::getFalse(GI->getContext()));

  if (MSSAU) {
    MemoryDef *MD = cast<MemoryDef>(MSSAU->getMemorySSA()->getMemoryAccess(GI));
    MSSAU->moveToPlace(MD, DeoptBlock, MemorySSA::BeforeTerminator);
    if (VerifyMemorySSA)
      MSSAU->getMemorySSA()->verifyMemorySSA();
  }

  if (VerifyLoopInfo)
    LI.verify(DT);
  ++NumGuards;
  return CheckBI;
}

/// Cost multiplier is a way to limit potentially exponential behavior
/// of loop-unswitch. Cost is multipied in proportion of 2^number of unswitch
/// candidates available. Also accounting for the number of "sibling" loops with
/// the idea to account for previous unswitches that already happened on this
/// cluster of loops. There was an attempt to keep this formula simple,
/// just enough to limit the worst case behavior. Even if it is not that simple
/// now it is still not an attempt to provide a detailed heuristic size
/// prediction.
///
/// TODO: Make a proper accounting of "explosion" effect for all kinds of
/// unswitch candidates, making adequate predictions instead of wild guesses.
/// That requires knowing not just the number of "remaining" candidates but
/// also costs of unswitching for each of these candidates.
static int CalculateUnswitchCostMultiplier(
    const Instruction &TI, const Loop &L, const LoopInfo &LI,
    const DominatorTree &DT,
    ArrayRef<NonTrivialUnswitchCandidate> UnswitchCandidates) {

  // Guards and other exiting conditions do not contribute to exponential
  // explosion as soon as they dominate the latch (otherwise there might be
  // another path to the latch remaining that does not allow to eliminate the
  // loop copy on unswitch).
  const BasicBlock *Latch = L.getLoopLatch();
  const BasicBlock *CondBlock = TI.getParent();
  if (DT.dominates(CondBlock, Latch) &&
      (isGuard(&TI) ||
       (TI.isTerminator() &&
        llvm::count_if(successors(&TI), [&L](const BasicBlock *SuccBB) {
          return L.contains(SuccBB);
        }) <= 1))) {
    NumCostMultiplierSkipped++;
    return 1;
  }

  auto *ParentL = L.getParentLoop();
  int SiblingsCount = (ParentL ? ParentL->getSubLoopsVector().size()
                               : std::distance(LI.begin(), LI.end()));
  // Count amount of clones that all the candidates might cause during
  // unswitching. Branch/guard/select counts as 1, switch counts as log2 of its
  // cases.
  int UnswitchedClones = 0;
  for (const auto &Candidate : UnswitchCandidates) {
    const Instruction *CI = Candidate.TI;
    const BasicBlock *CondBlock = CI->getParent();
    bool SkipExitingSuccessors = DT.dominates(CondBlock, Latch);
    if (isa<SelectInst>(CI)) {
      UnswitchedClones++;
      continue;
    }
    if (isGuard(CI)) {
      if (!SkipExitingSuccessors)
        UnswitchedClones++;
      continue;
    }
    int NonExitingSuccessors =
        llvm::count_if(successors(CondBlock),
                       [SkipExitingSuccessors, &L](const BasicBlock *SuccBB) {
          return !SkipExitingSuccessors || L.contains(SuccBB);
        });
    UnswitchedClones += Log2_32(NonExitingSuccessors);
  }

  // Ignore up to the "unscaled candidates" number of unswitch candidates
  // when calculating the power-of-two scaling of the cost. The main idea
  // with this control is to allow a small number of unswitches to happen
  // and rely more on siblings multiplier (see below) when the number
  // of candidates is small.
  unsigned ClonesPower =
      std::max(UnswitchedClones - (int)UnswitchNumInitialUnscaledCandidates, 0);

  // Allowing top-level loops to spread a bit more than nested ones.
  int SiblingsMultiplier =
      std::max((ParentL ? SiblingsCount
                        : SiblingsCount / (int)UnswitchSiblingsToplevelDiv),
               1);
  // Compute the cost multiplier in a way that won't overflow by saturating
  // at an upper bound.
  int CostMultiplier;
  if (ClonesPower > Log2_32(UnswitchThreshold) ||
      SiblingsMultiplier > UnswitchThreshold)
    CostMultiplier = UnswitchThreshold;
  else
    CostMultiplier = std::min(SiblingsMultiplier * (1 << ClonesPower),
                              (int)UnswitchThreshold);

  LLVM_DEBUG(dbgs() << "  Computed multiplier  " << CostMultiplier
                    << " (siblings " << SiblingsMultiplier << " * clones "
                    << (1 << ClonesPower) << ")"
                    << " for unswitch candidate: " << TI << "\n");
  return CostMultiplier;
}

static bool collectUnswitchCandidates(
    SmallVectorImpl<NonTrivialUnswitchCandidate> &UnswitchCandidates,
    IVConditionInfo &PartialIVInfo, Instruction *&PartialIVCondBranch,
    const Loop &L, const LoopInfo &LI, AAResults &AA,
    const MemorySSAUpdater *MSSAU) {
  assert(UnswitchCandidates.empty() && "Should be!");

  auto AddUnswitchCandidatesForInst = [&](Instruction *I, Value *Cond) {
    Cond = skipTrivialSelect(Cond);
    if (isa<Constant>(Cond))
      return;
    if (L.isLoopInvariant(Cond)) {
      UnswitchCandidates.push_back({I, {Cond}});
      return;
    }
    if (match(Cond, m_CombineOr(m_LogicalAnd(), m_LogicalOr()))) {
      TinyPtrVector<Value *> Invariants =
          collectHomogenousInstGraphLoopInvariants(
              L, *static_cast<Instruction *>(Cond), LI);
      if (!Invariants.empty())
        UnswitchCandidates.push_back({I, std::move(Invariants)});
    }
  };

  // Whether or not we should also collect guards in the loop.
  bool CollectGuards = false;
  if (UnswitchGuards) {
    auto *GuardDecl = L.getHeader()->getParent()->getParent()->getFunction(
        Intrinsic::getName(Intrinsic::experimental_guard));
    if (GuardDecl && !GuardDecl->use_empty())
      CollectGuards = true;
  }

  for (auto *BB : L.blocks()) {
    if (LI.getLoopFor(BB) != &L)
      continue;

    for (auto &I : *BB) {
      if (auto *SI = dyn_cast<SelectInst>(&I)) {
        auto *Cond = SI->getCondition();
        // Do not unswitch vector selects and logical and/or selects
        if (Cond->getType()->isIntegerTy(1) && !SI->getType()->isIntegerTy(1))
          AddUnswitchCandidatesForInst(SI, Cond);
      } else if (CollectGuards && isGuard(&I)) {
        auto *Cond =
            skipTrivialSelect(cast<IntrinsicInst>(&I)->getArgOperand(0));
        // TODO: Support AND, OR conditions and partial unswitching.
        if (!isa<Constant>(Cond) && L.isLoopInvariant(Cond))
          UnswitchCandidates.push_back({&I, {Cond}});
      }
    }

    if (auto *SI = dyn_cast<SwitchInst>(BB->getTerminator())) {
      // We can only consider fully loop-invariant switch conditions as we need
      // to completely eliminate the switch after unswitching.
      if (!isa<Constant>(SI->getCondition()) &&
          L.isLoopInvariant(SI->getCondition()) && !BB->getUniqueSuccessor())
        UnswitchCandidates.push_back({SI, {SI->getCondition()}});
      continue;
    }

    auto *BI = dyn_cast<BranchInst>(BB->getTerminator());
    if (!BI || !BI->isConditional() ||
        BI->getSuccessor(0) == BI->getSuccessor(1))
      continue;

    AddUnswitchCandidatesForInst(BI, BI->getCondition());
  }

  if (MSSAU && !findOptionMDForLoop(&L, "llvm.loop.unswitch.partial.disable") &&
      !any_of(UnswitchCandidates, [&L](auto &TerminatorAndInvariants) {
         return TerminatorAndInvariants.TI == L.getHeader()->getTerminator();
       })) {
    MemorySSA *MSSA = MSSAU->getMemorySSA();
    if (auto Info = hasPartialIVCondition(L, MSSAThreshold, *MSSA, AA)) {
      LLVM_DEBUG(
          dbgs() << "simple-loop-unswitch: Found partially invariant condition "
                 << *Info->InstToDuplicate[0] << "\n");
      PartialIVInfo = *Info;
      PartialIVCondBranch = L.getHeader()->getTerminator();
      TinyPtrVector<Value *> ValsToDuplicate;
      llvm::append_range(ValsToDuplicate, Info->InstToDuplicate);
      UnswitchCandidates.push_back(
          {L.getHeader()->getTerminator(), std::move(ValsToDuplicate)});
    }
  }
  return !UnswitchCandidates.empty();
}

/// Tries to canonicalize condition described by:
///
///   br (LHS pred RHS), label IfTrue, label IfFalse
///
/// into its equivalent where `Pred` is something that we support for injected
/// invariants (so far it is limited to ult), LHS in canonicalized form is
/// non-invariant and RHS is an invariant.
static void canonicalizeForInvariantConditionInjection(
    ICmpInst::Predicate &Pred, Value *&LHS, Value *&RHS, BasicBlock *&IfTrue,
    BasicBlock *&IfFalse, const Loop &L) {
  if (!L.contains(IfTrue)) {
    Pred = ICmpInst::getInversePredicate(Pred);
    std::swap(IfTrue, IfFalse);
  }

  // Move loop-invariant argument to RHS position.
  if (L.isLoopInvariant(LHS)) {
    Pred = ICmpInst::getSwappedPredicate(Pred);
    std::swap(LHS, RHS);
  }

  if (Pred == ICmpInst::ICMP_SGE && match(RHS, m_Zero())) {
    // Turn "x >=s 0" into "x <u UMIN_INT"
    Pred = ICmpInst::ICMP_ULT;
    RHS = ConstantInt::get(
        RHS->getContext(),
        APInt::getSignedMinValue(RHS->getType()->getIntegerBitWidth()));
  }
}

/// Returns true, if predicate described by ( \p Pred, \p LHS, \p RHS )
/// succeeding into blocks ( \p IfTrue, \p IfFalse) can be optimized by
/// injecting a loop-invariant condition.
static bool shouldTryInjectInvariantCondition(
    const ICmpInst::Predicate Pred, const Value *LHS, const Value *RHS,
    const BasicBlock *IfTrue, const BasicBlock *IfFalse, const Loop &L) {
  if (L.isLoopInvariant(LHS) || !L.isLoopInvariant(RHS))
    return false;
  // TODO: Support other predicates.
  if (Pred != ICmpInst::ICMP_ULT)
    return false;
  // TODO: Support non-loop-exiting branches?
  if (!L.contains(IfTrue) || L.contains(IfFalse))
    return false;
  // FIXME: For some reason this causes problems with MSSA updates, need to
  // investigate why. So far, just don't unswitch latch.
  if (L.getHeader() == IfTrue)
    return false;
  return true;
}

/// Returns true, if metadata on \p BI allows us to optimize branching into \p
/// TakenSucc via injection of invariant conditions. The branch should be not
/// enough and not previously unswitched, the information about this comes from
/// the metadata.
bool shouldTryInjectBasingOnMetadata(const BranchInst *BI,
                                     const BasicBlock *TakenSucc) {
  SmallVector<uint32_t> Weights;
  if (!extractBranchWeights(*BI, Weights))
    return false;
  unsigned T = InjectInvariantConditionHotnesThreshold;
  BranchProbability LikelyTaken(T - 1, T);

  assert(Weights.size() == 2 && "Unexpected profile data!");
  size_t Idx = BI->getSuccessor(0) == TakenSucc ? 0 : 1;
  auto Num = Weights[Idx];
  auto Denom = Weights[0] + Weights[1];
  // Degenerate or overflowed metadata.
  if (Denom == 0 || Num > Denom)
    return false;
  BranchProbability ActualTaken(Num, Denom);
  if (LikelyTaken > ActualTaken)
    return false;
  return true;
}

/// Materialize pending invariant condition of the given candidate into IR. The
/// injected loop-invariant condition implies the original loop-variant branch
/// condition, so the materialization turns
///
/// loop_block:
///   ...
///   br i1 %variant_cond, label InLoopSucc, label OutOfLoopSucc
///
/// into
///
/// preheader:
///   %invariant_cond = LHS pred RHS
/// ...
/// loop_block:
///   br i1 %invariant_cond, label InLoopSucc, label OriginalCheck
/// OriginalCheck:
///   br i1 %variant_cond, label InLoopSucc, label OutOfLoopSucc
/// ...
static NonTrivialUnswitchCandidate
injectPendingInvariantConditions(NonTrivialUnswitchCandidate Candidate, Loop &L,
                                 DominatorTree &DT, LoopInfo &LI,
                                 AssumptionCache &AC, MemorySSAUpdater *MSSAU) {
  assert(Candidate.hasPendingInjection() && "Nothing to inject!");
  BasicBlock *Preheader = L.getLoopPreheader();
  assert(Preheader && "Loop is not in simplified form?");
  assert(LI.getLoopFor(Candidate.TI->getParent()) == &L &&
         "Unswitching branch of inner loop!");

  auto Pred = Candidate.PendingInjection->Pred;
  auto *LHS = Candidate.PendingInjection->LHS;
  auto *RHS = Candidate.PendingInjection->RHS;
  auto *InLoopSucc = Candidate.PendingInjection->InLoopSucc;
  auto *TI = cast<BranchInst>(Candidate.TI);
  auto *BB = Candidate.TI->getParent();
  auto *OutOfLoopSucc = InLoopSucc == TI->getSuccessor(0) ? TI->getSuccessor(1)
                                                          : TI->getSuccessor(0);
  // FIXME: Remove this once limitation on successors is lifted.
  assert(L.contains(InLoopSucc) && "Not supported yet!");
  assert(!L.contains(OutOfLoopSucc) && "Not supported yet!");
  auto &Ctx = BB->getContext();

  IRBuilder<> Builder(Preheader->getTerminator());
  assert(ICmpInst::isUnsigned(Pred) && "Not supported yet!");
  if (LHS->getType() != RHS->getType()) {
    if (LHS->getType()->getIntegerBitWidth() <
        RHS->getType()->getIntegerBitWidth())
      LHS = Builder.CreateZExt(LHS, RHS->getType(), LHS->getName() + ".wide");
    else
      RHS = Builder.CreateZExt(RHS, LHS->getType(), RHS->getName() + ".wide");
  }
  // Do not use builder here: CreateICmp may simplify this into a constant and
  // unswitching will break. Better optimize it away later.
  auto *InjectedCond =
      ICmpInst::Create(Instruction::ICmp, Pred, LHS, RHS, "injected.cond",
                       Preheader->getTerminator()->getIterator());

  BasicBlock *CheckBlock = BasicBlock::Create(Ctx, BB->getName() + ".check",
                                              BB->getParent(), InLoopSucc);
  Builder.SetInsertPoint(TI);
  auto *InvariantBr =
      Builder.CreateCondBr(InjectedCond, InLoopSucc, CheckBlock);

  Builder.SetInsertPoint(CheckBlock);
  Builder.CreateCondBr(TI->getCondition(), TI->getSuccessor(0),
                       TI->getSuccessor(1));
  TI->eraseFromParent();

  // Fixup phis.
  for (auto &I : *InLoopSucc) {
    auto *PN = dyn_cast<PHINode>(&I);
    if (!PN)
      break;
    auto *Inc = PN->getIncomingValueForBlock(BB);
    PN->addIncoming(Inc, CheckBlock);
  }
  OutOfLoopSucc->replacePhiUsesWith(BB, CheckBlock);

  SmallVector<DominatorTree::UpdateType, 4> DTUpdates = {
    { DominatorTree::Insert, BB, CheckBlock },
    { DominatorTree::Insert, CheckBlock, InLoopSucc },
    { DominatorTree::Insert, CheckBlock, OutOfLoopSucc },
    { DominatorTree::Delete, BB, OutOfLoopSucc }
  };

  DT.applyUpdates(DTUpdates);
  if (MSSAU)
    MSSAU->applyUpdates(DTUpdates, DT);
  L.addBasicBlockToLoop(CheckBlock, LI);

#ifndef NDEBUG
  DT.verify();
  LI.verify(DT);
  if (MSSAU && VerifyMemorySSA)
    MSSAU->getMemorySSA()->verifyMemorySSA();
#endif

  // TODO: In fact, cost of unswitching a new invariant candidate is *slightly*
  // higher because we have just inserted a new block. Need to think how to
  // adjust the cost of injected candidates when it was first computed.
  LLVM_DEBUG(dbgs() << "Injected a new loop-invariant branch " << *InvariantBr
                    << " and considering it for unswitching.");
  ++NumInvariantConditionsInjected;
  return NonTrivialUnswitchCandidate(InvariantBr, { InjectedCond },
                                     Candidate.Cost);
}

/// Given chain of loop branch conditions looking like:
///   br (Variant < Invariant1)
///   br (Variant < Invariant2)
///   br (Variant < Invariant3)
///   ...
/// collect set of invariant conditions on which we want to unswitch, which
/// look like:
///   Invariant1 <= Invariant2
///   Invariant2 <= Invariant3
///   ...
/// Though they might not immediately exist in the IR, we can still inject them.
static bool insertCandidatesWithPendingInjections(
    SmallVectorImpl<NonTrivialUnswitchCandidate> &UnswitchCandidates, Loop &L,
    ICmpInst::Predicate Pred, ArrayRef<CompareDesc> Compares,
    const DominatorTree &DT) {

  assert(ICmpInst::isRelational(Pred));
  assert(ICmpInst::isStrictPredicate(Pred));
  if (Compares.size() < 2)
    return false;
  ICmpInst::Predicate NonStrictPred = ICmpInst::getNonStrictPredicate(Pred);
  for (auto Prev = Compares.begin(), Next = Compares.begin() + 1;
       Next != Compares.end(); ++Prev, ++Next) {
    Value *LHS = Next->Invariant;
    Value *RHS = Prev->Invariant;
    BasicBlock *InLoopSucc = Prev->InLoopSucc;
    InjectedInvariant ToInject(NonStrictPred, LHS, RHS, InLoopSucc);
    NonTrivialUnswitchCandidate Candidate(Prev->Term, { LHS, RHS },
                                          std::nullopt, std::move(ToInject));
    UnswitchCandidates.push_back(std::move(Candidate));
  }
  return true;
}

/// Collect unswitch candidates by invariant conditions that are not immediately
/// present in the loop. However, they can be injected into the code if we
/// decide it's profitable.
/// An example of such conditions is following:
///
///   for (...) {
///     x = load ...
///     if (! x <u C1) break;
///     if (! x <u C2) break;
///     <do something>
///   }
///
/// We can unswitch by condition "C1 <=u C2". If that is true, then "x <u C1 <=
/// C2" automatically implies "x <u C2", so we can get rid of one of
/// loop-variant checks in unswitched loop version.
static bool collectUnswitchCandidatesWithInjections(
    SmallVectorImpl<NonTrivialUnswitchCandidate> &UnswitchCandidates,
    IVConditionInfo &PartialIVInfo, Instruction *&PartialIVCondBranch, Loop &L,
    const DominatorTree &DT, const LoopInfo &LI, AAResults &AA,
    const MemorySSAUpdater *MSSAU) {
  if (!InjectInvariantConditions)
    return false;

  if (!DT.isReachableFromEntry(L.getHeader()))
    return false;
  auto *Latch = L.getLoopLatch();
  // Need to have a single latch and a preheader.
  if (!Latch)
    return false;
  assert(L.getLoopPreheader() && "Must have a preheader!");

  DenseMap<Value *, SmallVector<CompareDesc, 4> > CandidatesULT;
  // Traverse the conditions that dominate latch (and therefore dominate each
  // other).
  for (auto *DTN = DT.getNode(Latch); L.contains(DTN->getBlock());
       DTN = DTN->getIDom()) {
    ICmpInst::Predicate Pred;
    Value *LHS = nullptr, *RHS = nullptr;
    BasicBlock *IfTrue = nullptr, *IfFalse = nullptr;
    auto *BB = DTN->getBlock();
    // Ignore inner loops.
    if (LI.getLoopFor(BB) != &L)
      continue;
    auto *Term = BB->getTerminator();
    if (!match(Term, m_Br(m_ICmp(Pred, m_Value(LHS), m_Value(RHS)),
                          m_BasicBlock(IfTrue), m_BasicBlock(IfFalse))))
      continue;
    if (!LHS->getType()->isIntegerTy())
      continue;
    canonicalizeForInvariantConditionInjection(Pred, LHS, RHS, IfTrue, IfFalse,
                                               L);
    if (!shouldTryInjectInvariantCondition(Pred, LHS, RHS, IfTrue, IfFalse, L))
      continue;
    if (!shouldTryInjectBasingOnMetadata(cast<BranchInst>(Term), IfTrue))
      continue;
    // Strip ZEXT for unsigned predicate.
    // TODO: once signed predicates are supported, also strip SEXT.
    CompareDesc Desc(cast<BranchInst>(Term), RHS, IfTrue);
    while (auto *Zext = dyn_cast<ZExtInst>(LHS))
      LHS = Zext->getOperand(0);
    CandidatesULT[LHS].push_back(Desc);
  }

  bool Found = false;
  for (auto &It : CandidatesULT)
    Found |= insertCandidatesWithPendingInjections(
        UnswitchCandidates, L, ICmpInst::ICMP_ULT, It.second, DT);
  return Found;
}

static bool isSafeForNoNTrivialUnswitching(Loop &L, LoopInfo &LI) {
  if (!L.isSafeToClone())
    return false;
  for (auto *BB : L.blocks())
    for (auto &I : *BB) {
      if (I.getType()->isTokenTy() && I.isUsedOutsideOfBlock(BB))
        return false;
      if (auto *CB = dyn_cast<CallBase>(&I)) {
        assert(!CB->cannotDuplicate() && "Checked by L.isSafeToClone().");
        if (CB->isConvergent())
          return false;
      }
    }

  // Check if there are irreducible CFG cycles in this loop. If so, we cannot
  // easily unswitch non-trivial edges out of the loop. Doing so might turn the
  // irreducible control flow into reducible control flow and introduce new
  // loops "out of thin air". If we ever discover important use cases for doing
  // this, we can add support to loop unswitch, but it is a lot of complexity
  // for what seems little or no real world benefit.
  LoopBlocksRPO RPOT(&L);
  RPOT.perform(&LI);
  if (containsIrreducibleCFG<const BasicBlock *>(RPOT, LI))
    return false;

  SmallVector<BasicBlock *, 4> ExitBlocks;
  L.getUniqueExitBlocks(ExitBlocks);
  // We cannot unswitch if exit blocks contain a cleanuppad/catchswitch
  // instruction as we don't know how to split those exit blocks.
  // FIXME: We should teach SplitBlock to handle this and remove this
  // restriction.
  for (auto *ExitBB : ExitBlocks) {
    auto *I = ExitBB->getFirstNonPHI();
    if (isa<CleanupPadInst>(I) || isa<CatchSwitchInst>(I)) {
      LLVM_DEBUG(dbgs() << "Cannot unswitch because of cleanuppad/catchswitch "
                           "in exit block\n");
      return false;
    }
  }

  return true;
}

static NonTrivialUnswitchCandidate findBestNonTrivialUnswitchCandidate(
    ArrayRef<NonTrivialUnswitchCandidate> UnswitchCandidates, const Loop &L,
    const DominatorTree &DT, const LoopInfo &LI, AssumptionCache &AC,
    const TargetTransformInfo &TTI, const IVConditionInfo &PartialIVInfo) {
  // Given that unswitching these terminators will require duplicating parts of
  // the loop, so we need to be able to model that cost. Compute the ephemeral
  // values and set up a data structure to hold per-BB costs. We cache each
  // block's cost so that we don't recompute this when considering different
  // subsets of the loop for duplication during unswitching.
  SmallPtrSet<const Value *, 4> EphValues;
  CodeMetrics::collectEphemeralValues(&L, &AC, EphValues);
  SmallDenseMap<BasicBlock *, InstructionCost, 4> BBCostMap;

  // Compute the cost of each block, as well as the total loop cost. Also, bail
  // out if we see instructions which are incompatible with loop unswitching
  // (convergent, noduplicate, or cross-basic-block tokens).
  // FIXME: We might be able to safely handle some of these in non-duplicated
  // regions.
  TargetTransformInfo::TargetCostKind CostKind =
      L.getHeader()->getParent()->hasMinSize()
      ? TargetTransformInfo::TCK_CodeSize
      : TargetTransformInfo::TCK_SizeAndLatency;
  InstructionCost LoopCost = 0;
  for (auto *BB : L.blocks()) {
    InstructionCost Cost = 0;
    for (auto &I : *BB) {
      if (EphValues.count(&I))
        continue;
      Cost += TTI.getInstructionCost(&I, CostKind);
    }
    assert(Cost >= 0 && "Must not have negative costs!");
    LoopCost += Cost;
    assert(LoopCost >= 0 && "Must not have negative loop costs!");
    BBCostMap[BB] = Cost;
  }
  LLVM_DEBUG(dbgs() << "  Total loop cost: " << LoopCost << "\n");

  // Now we find the best candidate by searching for the one with the following
  // properties in order:
  //
  // 1) An unswitching cost below the threshold
  // 2) The smallest number of duplicated unswitch candidates (to avoid
  //    creating redundant subsequent unswitching)
  // 3) The smallest cost after unswitching.
  //
  // We prioritize reducing fanout of unswitch candidates provided the cost
  // remains below the threshold because this has a multiplicative effect.
  //
  // This requires memoizing each dominator subtree to avoid redundant work.
  //
  // FIXME: Need to actually do the number of candidates part above.
  SmallDenseMap<DomTreeNode *, InstructionCost, 4> DTCostMap;
  // Given a terminator which might be unswitched, computes the non-duplicated
  // cost for that terminator.
  auto ComputeUnswitchedCost = [&](Instruction &TI,
                                   bool FullUnswitch) -> InstructionCost {
    // Unswitching selects unswitches the entire loop.
    if (isa<SelectInst>(TI))
      return LoopCost;

    BasicBlock &BB = *TI.getParent();
    SmallPtrSet<BasicBlock *, 4> Visited;

    InstructionCost Cost = 0;
    for (BasicBlock *SuccBB : successors(&BB)) {
      // Don't count successors more than once.
      if (!Visited.insert(SuccBB).second)
        continue;

      // If this is a partial unswitch candidate, then it must be a conditional
      // branch with a condition of either `or`, `and`, their corresponding
      // select forms or partially invariant instructions. In that case, one of
      // the successors is necessarily duplicated, so don't even try to remove
      // its cost.
      if (!FullUnswitch) {
        auto &BI = cast<BranchInst>(TI);
        Value *Cond = skipTrivialSelect(BI.getCondition());
        if (match(Cond, m_LogicalAnd())) {
          if (SuccBB == BI.getSuccessor(1))
            continue;
        } else if (match(Cond, m_LogicalOr())) {
          if (SuccBB == BI.getSuccessor(0))
            continue;
        } else if ((PartialIVInfo.KnownValue->isOneValue() &&
                    SuccBB == BI.getSuccessor(0)) ||
                   (!PartialIVInfo.KnownValue->isOneValue() &&
                    SuccBB == BI.getSuccessor(1)))
          continue;
      }

      // This successor's domtree will not need to be duplicated after
      // unswitching if the edge to the successor dominates it (and thus the
      // entire tree). This essentially means there is no other path into this
      // subtree and so it will end up live in only one clone of the loop.
      if (SuccBB->getUniquePredecessor() ||
          llvm::all_of(predecessors(SuccBB), [&](BasicBlock *PredBB) {
            return PredBB == &BB || DT.dominates(SuccBB, PredBB);
          })) {
        Cost += computeDomSubtreeCost(*DT[SuccBB], BBCostMap, DTCostMap);
        assert(Cost <= LoopCost &&
               "Non-duplicated cost should never exceed total loop cost!");
      }
    }

    // Now scale the cost by the number of unique successors minus one. We
    // subtract one because there is already at least one copy of the entire
    // loop. This is computing the new cost of unswitching a condition.
    // Note that guards always have 2 unique successors that are implicit and
    // will be materialized if we decide to unswitch it.
    int SuccessorsCount = isGuard(&TI) ? 2 : Visited.size();
    assert(SuccessorsCount > 1 &&
           "Cannot unswitch a condition without multiple distinct successors!");
    return (LoopCost - Cost) * (SuccessorsCount - 1);
  };

  std::optional<NonTrivialUnswitchCandidate> Best;
  for (auto &Candidate : UnswitchCandidates) {
    Instruction &TI = *Candidate.TI;
    ArrayRef<Value *> Invariants = Candidate.Invariants;
    BranchInst *BI = dyn_cast<BranchInst>(&TI);
    bool FullUnswitch =
        !BI || Candidate.hasPendingInjection() ||
        (Invariants.size() == 1 &&
         Invariants[0] == skipTrivialSelect(BI->getCondition()));
    InstructionCost CandidateCost = ComputeUnswitchedCost(TI, FullUnswitch);
    // Calculate cost multiplier which is a tool to limit potentially
    // exponential behavior of loop-unswitch.
    if (EnableUnswitchCostMultiplier) {
      int CostMultiplier =
          CalculateUnswitchCostMultiplier(TI, L, LI, DT, UnswitchCandidates);
      assert(
          (CostMultiplier > 0 && CostMultiplier <= UnswitchThreshold) &&
          "cost multiplier needs to be in the range of 1..UnswitchThreshold");
      CandidateCost *= CostMultiplier;
      LLVM_DEBUG(dbgs() << "  Computed cost of " << CandidateCost
                        << " (multiplier: " << CostMultiplier << ")"
                        << " for unswitch candidate: " << TI << "\n");
    } else {
      LLVM_DEBUG(dbgs() << "  Computed cost of " << CandidateCost
                        << " for unswitch candidate: " << TI << "\n");
    }

    if (!Best || CandidateCost < Best->Cost) {
      Best = Candidate;
      Best->Cost = CandidateCost;
    }
  }
  assert(Best && "Must be!");
  return *Best;
}

// Insert a freeze on an unswitched branch if all is true:
// 1. freeze-loop-unswitch-cond option is true
// 2. The branch may not execute in the loop pre-transformation. If a branch may
// not execute and could cause UB, it would always cause UB if it is hoisted outside
// of the loop. Insert a freeze to prevent this case.
// 3. The branch condition may be poison or undef
static bool shouldInsertFreeze(Loop &L, Instruction &TI, DominatorTree &DT,
                               AssumptionCache &AC) {
  assert(isa<BranchInst>(TI) || isa<SwitchInst>(TI));
  if (!FreezeLoopUnswitchCond)
    return false;

  ICFLoopSafetyInfo SafetyInfo;
  SafetyInfo.computeLoopSafetyInfo(&L);
  if (SafetyInfo.isGuaranteedToExecute(TI, &DT, &L))
    return false;

  Value *Cond;
  if (BranchInst *BI = dyn_cast<BranchInst>(&TI))
    Cond = skipTrivialSelect(BI->getCondition());
  else
    Cond = skipTrivialSelect(cast<SwitchInst>(&TI)->getCondition());
  return !isGuaranteedNotToBeUndefOrPoison(
      Cond, &AC, L.getLoopPreheader()->getTerminator(), &DT);
}

static bool unswitchBestCondition(Loop &L, DominatorTree &DT, LoopInfo &LI,
                                  AssumptionCache &AC, AAResults &AA,
                                  TargetTransformInfo &TTI, ScalarEvolution *SE,
                                  MemorySSAUpdater *MSSAU,
                                  LPMUpdater &LoopUpdater) {
  // Collect all invariant conditions within this loop (as opposed to an inner
  // loop which would be handled when visiting that inner loop).
  SmallVector<NonTrivialUnswitchCandidate, 4> UnswitchCandidates;
  IVConditionInfo PartialIVInfo;
  Instruction *PartialIVCondBranch = nullptr;
  collectUnswitchCandidates(UnswitchCandidates, PartialIVInfo,
                            PartialIVCondBranch, L, LI, AA, MSSAU);
  if (!findOptionMDForLoop(&L, "llvm.loop.unswitch.injection.disable"))
    collectUnswitchCandidatesWithInjections(UnswitchCandidates, PartialIVInfo,
                                            PartialIVCondBranch, L, DT, LI, AA,
                                            MSSAU);
  // If we didn't find any candidates, we're done.
  if (UnswitchCandidates.empty())
    return false;

  LLVM_DEBUG(
      dbgs() << "Considering " << UnswitchCandidates.size()
             << " non-trivial loop invariant conditions for unswitching.\n");

  NonTrivialUnswitchCandidate Best = findBestNonTrivialUnswitchCandidate(
      UnswitchCandidates, L, DT, LI, AC, TTI, PartialIVInfo);

  assert(Best.TI && "Failed to find loop unswitch candidate");
  assert(Best.Cost && "Failed to compute cost");

  if (*Best.Cost >= UnswitchThreshold) {
    LLVM_DEBUG(dbgs() << "Cannot unswitch, lowest cost found: " << *Best.Cost
                      << "\n");
    return false;
  }

  bool InjectedCondition = false;
  if (Best.hasPendingInjection()) {
    Best = injectPendingInvariantConditions(Best, L, DT, LI, AC, MSSAU);
    InjectedCondition = true;
  }
  assert(!Best.hasPendingInjection() &&
         "All injections should have been done by now!");

  if (Best.TI != PartialIVCondBranch)
    PartialIVInfo.InstToDuplicate.clear();

  bool InsertFreeze;
  if (auto *SI = dyn_cast<SelectInst>(Best.TI)) {
    // If the best candidate is a select, turn it into a branch. Select
    // instructions with a poison conditional do not propagate poison, but
    // branching on poison causes UB. Insert a freeze on the select
    // conditional to prevent UB after turning the select into a branch.
    InsertFreeze = !isGuaranteedNotToBeUndefOrPoison(
        SI->getCondition(), &AC, L.getLoopPreheader()->getTerminator(), &DT);
    Best.TI = turnSelectIntoBranch(SI, DT, LI, MSSAU, &AC);
  } else {
    // If the best candidate is a guard, turn it into a branch.
    if (isGuard(Best.TI))
      Best.TI =
          turnGuardIntoBranch(cast<IntrinsicInst>(Best.TI), L, DT, LI, MSSAU);
    InsertFreeze = shouldInsertFreeze(L, *Best.TI, DT, AC);
  }

  LLVM_DEBUG(dbgs() << "  Unswitching non-trivial (cost = " << Best.Cost
                    << ") terminator: " << *Best.TI << "\n");
  unswitchNontrivialInvariants(L, *Best.TI, Best.Invariants, PartialIVInfo, DT,
                               LI, AC, SE, MSSAU, LoopUpdater, InsertFreeze,
                               InjectedCondition);
  return true;
}

/// Unswitch control flow predicated on loop invariant conditions.
///
/// This first hoists all branches or switches which are trivial (IE, do not
/// require duplicating any part of the loop) out of the loop body. It then
/// looks at other loop invariant control flows and tries to unswitch those as
/// well by cloning the loop if the result is small enough.
///
/// The `DT`, `LI`, `AC`, `AA`, `TTI` parameters are required analyses that are
/// also updated based on the unswitch. The `MSSA` analysis is also updated if
/// valid (i.e. its use is enabled).
///
/// If either `NonTrivial` is true or the flag `EnableNonTrivialUnswitch` is
/// true, we will attempt to do non-trivial unswitching as well as trivial
/// unswitching.
///
/// The `postUnswitch` function will be run after unswitching is complete
/// with information on whether or not the provided loop remains a loop and
/// a list of new sibling loops created.
///
/// If `SE` is non-null, we will update that analysis based on the unswitching
/// done.
static bool unswitchLoop(Loop &L, DominatorTree &DT, LoopInfo &LI,
                         AssumptionCache &AC, AAResults &AA,
                         TargetTransformInfo &TTI, bool Trivial,
                         bool NonTrivial, ScalarEvolution *SE,
                         MemorySSAUpdater *MSSAU, ProfileSummaryInfo *PSI,
                         BlockFrequencyInfo *BFI, LPMUpdater &LoopUpdater) {
  assert(L.isRecursivelyLCSSAForm(DT, LI) &&
         "Loops must be in LCSSA form before unswitching.");

  // Must be in loop simplified form: we need a preheader and dedicated exits.
  if (!L.isLoopSimplifyForm())
    return false;

  // Try trivial unswitch first before loop over other basic blocks in the loop.
  if (Trivial && unswitchAllTrivialConditions(L, DT, LI, SE, MSSAU)) {
    // If we unswitched successfully we will want to clean up the loop before
    // processing it further so just mark it as unswitched and return.
    postUnswitch(L, LoopUpdater, L.getName(),
                 /*CurrentLoopValid*/ true, /*PartiallyInvariant*/ false,
                 /*InjectedCondition*/ false, {});
    return true;
  }

  const Function *F = L.getHeader()->getParent();

  // Check whether we should continue with non-trivial conditions.
  // EnableNonTrivialUnswitch: Global variable that forces non-trivial
  //                           unswitching for testing and debugging.
  // NonTrivial: Parameter that enables non-trivial unswitching for this
  //             invocation of the transform. But this should be allowed only
  //             for targets without branch divergence.
  //
  // FIXME: If divergence analysis becomes available to a loop
  // transform, we should allow unswitching for non-trivial uniform
  // branches even on targets that have divergence.
  // https://bugs.llvm.org/show_bug.cgi?id=48819
  bool ContinueWithNonTrivial =
      EnableNonTrivialUnswitch || (NonTrivial && !TTI.hasBranchDivergence(F));
  if (!ContinueWithNonTrivial)
    return false;

  // Skip non-trivial unswitching for optsize functions.
  if (F->hasOptSize())
    return false;

  // Returns true if Loop L's loop nest is cold, i.e. if the headers of L,
  // of the loops L is nested in, and of the loops nested in L are all cold.
  auto IsLoopNestCold = [&](const Loop *L) {
    // Check L and all of its parent loops.
    auto *Parent = L;
    while (Parent) {
      if (!PSI->isColdBlock(Parent->getHeader(), BFI))
        return false;
      Parent = Parent->getParentLoop();
    }
    // Next check all loops nested within L.
    SmallVector<const Loop *, 4> Worklist;
    Worklist.insert(Worklist.end(), L->getSubLoops().begin(),
                    L->getSubLoops().end());
    while (!Worklist.empty()) {
      auto *CurLoop = Worklist.pop_back_val();
      if (!PSI->isColdBlock(CurLoop->getHeader(), BFI))
        return false;
      Worklist.insert(Worklist.end(), CurLoop->getSubLoops().begin(),
                      CurLoop->getSubLoops().end());
    }
    return true;
  };

  // Skip cold loops in cold loop nests, as unswitching them brings little
  // benefit but increases the code size
  if (PSI && PSI->hasProfileSummary() && BFI && IsLoopNestCold(&L)) {
    LLVM_DEBUG(dbgs() << " Skip cold loop: " << L << "\n");
    return false;
  }

  // Perform legality checks.
  if (!isSafeForNoNTrivialUnswitching(L, LI))
    return false;

  // For non-trivial unswitching, because it often creates new loops, we rely on
  // the pass manager to iterate on the loops rather than trying to immediately
  // reach a fixed point. There is no substantial advantage to iterating
  // internally, and if any of the new loops are simplified enough to contain
  // trivial unswitching we want to prefer those.

  // Try to unswitch the best invariant condition. We prefer this full unswitch to
  // a partial unswitch when possible below the threshold.
  if (unswitchBestCondition(L, DT, LI, AC, AA, TTI, SE, MSSAU, LoopUpdater))
    return true;

  // No other opportunities to unswitch.
  return false;
}

PreservedAnalyses SimpleLoopUnswitchPass::run(Loop &L, LoopAnalysisManager &AM,
                                              LoopStandardAnalysisResults &AR,
                                              LPMUpdater &U) {
  Function &F = *L.getHeader()->getParent();
  (void)F;
  ProfileSummaryInfo *PSI = nullptr;
  if (auto OuterProxy =
          AM.getResult<FunctionAnalysisManagerLoopProxy>(L, AR)
              .getCachedResult<ModuleAnalysisManagerFunctionProxy>(F))
    PSI = OuterProxy->getCachedResult<ProfileSummaryAnalysis>(*F.getParent());
  LLVM_DEBUG(dbgs() << "Unswitching loop in " << F.getName() << ": " << L
                    << "\n");

  std::optional<MemorySSAUpdater> MSSAU;
  if (AR.MSSA) {
    MSSAU = MemorySSAUpdater(AR.MSSA);
    if (VerifyMemorySSA)
      AR.MSSA->verifyMemorySSA();
  }
  if (!unswitchLoop(L, AR.DT, AR.LI, AR.AC, AR.AA, AR.TTI, Trivial, NonTrivial,
                    &AR.SE, MSSAU ? &*MSSAU : nullptr, PSI, AR.BFI, U))
    return PreservedAnalyses::all();

  if (AR.MSSA && VerifyMemorySSA)
    AR.MSSA->verifyMemorySSA();

  // Historically this pass has had issues with the dominator tree so verify it
  // in asserts builds.
  assert(AR.DT.verify(DominatorTree::VerificationLevel::Fast));

  auto PA = getLoopPassPreservedAnalyses();
  if (AR.MSSA)
    PA.preserve<MemorySSAAnalysis>();
  return PA;
}

void SimpleLoopUnswitchPass::printPipeline(
    raw_ostream &OS, function_ref<StringRef(StringRef)> MapClassName2PassName) {
  static_cast<PassInfoMixin<SimpleLoopUnswitchPass> *>(this)->printPipeline(
      OS, MapClassName2PassName);

  OS << '<';
  OS << (NonTrivial ? "" : "no-") << "nontrivial;";
  OS << (Trivial ? "" : "no-") << "trivial";
  OS << '>';
}
