//===-- UnrollLoop.cpp - Loop unrolling utilities -------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// This file implements some loop unrolling utilities. It does not define any
// actual pass or policy, but provides a single function to perform loop
// unrolling.
//
// The process of unrolling can produce extraneous basic blocks linked with
// unconditional branches.  This will be corrected in the future.
//
//===----------------------------------------------------------------------===//

#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/ScopedHashTable.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/AssumptionCache.h"
#include "llvm/Analysis/DomTreeUpdater.h"
#include "llvm/Analysis/InstructionSimplify.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/LoopIterator.h"
#include "llvm/Analysis/MemorySSA.h"
#include "llvm/Analysis/OptimizationRemarkEmitter.h"
#include "llvm/Analysis/ScalarEvolution.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/CFG.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/PatternMatch.h"
#include "llvm/IR/Use.h"
#include "llvm/IR/User.h"
#include "llvm/IR/ValueHandle.h"
#include "llvm/IR/ValueMap.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/GenericDomTree.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/Transforms/Utils/LoopSimplify.h"
#include "llvm/Transforms/Utils/LoopUtils.h"
#include "llvm/Transforms/Utils/SimplifyIndVar.h"
#include "llvm/Transforms/Utils/UnrollLoop.h"
#include "llvm/Transforms/Utils/ValueMapper.h"
#include <assert.h>
#include <cmath>
#include <numeric>
#include <vector>

namespace llvm {
class DataLayout;
class Value;
} // namespace llvm

using namespace llvm;

#define DEBUG_TYPE "loop-unroll"

// TODO: Should these be here or in LoopUnroll?
STATISTIC(NumCompletelyUnrolled, "Number of loops completely unrolled");
STATISTIC(NumUnrolled, "Number of loops unrolled (completely or otherwise)");
STATISTIC(NumUnrolledNotLatch, "Number of loops unrolled without a conditional "
                               "latch (completely or otherwise)");

static cl::opt<bool>
UnrollRuntimeEpilog("unroll-runtime-epilog", cl::init(false), cl::Hidden,
                    cl::desc("Allow runtime unrolled loops to be unrolled "
                             "with epilog instead of prolog."));

static cl::opt<bool> UnrollUniformWeights(
    "unroll-uniform-weights", cl::init(false), cl::Hidden,
    cl::desc("If new branch weights must be found, work harder to keep them "
             "uniform."));

static cl::opt<bool>
UnrollVerifyDomtree("unroll-verify-domtree", cl::Hidden,
                    cl::desc("Verify domtree after unrolling"),
#ifdef EXPENSIVE_CHECKS
    cl::init(true)
#else
    cl::init(false)
#endif
                    );

static cl::opt<bool>
UnrollVerifyLoopInfo("unroll-verify-loopinfo", cl::Hidden,
                    cl::desc("Verify loopinfo after unrolling"),
#ifdef EXPENSIVE_CHECKS
    cl::init(true)
#else
    cl::init(false)
#endif
                    );

static cl::opt<bool> UnrollAddParallelReductions(
    "unroll-add-parallel-reductions", cl::init(false), cl::Hidden,
    cl::desc("Allow unrolling to add parallel reduction phis."));

/// Check if unrolling created a situation where we need to insert phi nodes to
/// preserve LCSSA form.
/// \param Blocks is a vector of basic blocks representing unrolled loop.
/// \param L is the outer loop.
/// It's possible that some of the blocks are in L, and some are not. In this
/// case, if there is a use is outside L, and definition is inside L, we need to
/// insert a phi-node, otherwise LCSSA will be broken.
/// The function is just a helper function for llvm::UnrollLoop that returns
/// true if this situation occurs, indicating that LCSSA needs to be fixed.
static bool needToInsertPhisForLCSSA(Loop *L,
                                     const std::vector<BasicBlock *> &Blocks,
                                     LoopInfo *LI) {
  for (BasicBlock *BB : Blocks) {
    if (LI->getLoopFor(BB) == L)
      continue;
    for (Instruction &I : *BB) {
      for (Use &U : I.operands()) {
        if (const auto *Def = dyn_cast<Instruction>(U)) {
          Loop *DefLoop = LI->getLoopFor(Def->getParent());
          if (!DefLoop)
            continue;
          if (DefLoop->contains(L))
            return true;
        }
      }
    }
  }
  return false;
}

/// Adds ClonedBB to LoopInfo, creates a new loop for ClonedBB if necessary
/// and adds a mapping from the original loop to the new loop to NewLoops.
/// Returns nullptr if no new loop was created and a pointer to the
/// original loop OriginalBB was part of otherwise.
const Loop* llvm::addClonedBlockToLoopInfo(BasicBlock *OriginalBB,
                                           BasicBlock *ClonedBB, LoopInfo *LI,
                                           NewLoopsMap &NewLoops) {
  // Figure out which loop New is in.
  const Loop *OldLoop = LI->getLoopFor(OriginalBB);
  assert(OldLoop && "Should (at least) be in the loop being unrolled!");

  Loop *&NewLoop = NewLoops[OldLoop];
  if (!NewLoop) {
    // Found a new sub-loop.
    assert(OriginalBB == OldLoop->getHeader() &&
           "Header should be first in RPO");

    NewLoop = LI->AllocateLoop();
    Loop *NewLoopParent = NewLoops.lookup(OldLoop->getParentLoop());

    if (NewLoopParent)
      NewLoopParent->addChildLoop(NewLoop);
    else
      LI->addTopLevelLoop(NewLoop);

    NewLoop->addBasicBlockToLoop(ClonedBB, *LI);
    return OldLoop;
  } else {
    NewLoop->addBasicBlockToLoop(ClonedBB, *LI);
    return nullptr;
  }
}

/// The function chooses which type of unroll (epilog or prolog) is more
/// profitabale.
/// Epilog unroll is more profitable when there is PHI that starts from
/// constant.  In this case epilog will leave PHI start from constant,
/// but prolog will convert it to non-constant.
///
/// loop:
///   PN = PHI [I, Latch], [CI, PreHeader]
///   I = foo(PN)
///   ...
///
/// Epilog unroll case.
/// loop:
///   PN = PHI [I2, Latch], [CI, PreHeader]
///   I1 = foo(PN)
///   I2 = foo(I1)
///   ...
/// Prolog unroll case.
///   NewPN = PHI [PrologI, Prolog], [CI, PreHeader]
/// loop:
///   PN = PHI [I2, Latch], [NewPN, PreHeader]
///   I1 = foo(PN)
///   I2 = foo(I1)
///   ...
///
static bool isEpilogProfitable(Loop *L) {
  BasicBlock *PreHeader = L->getLoopPreheader();
  BasicBlock *Header = L->getHeader();
  assert(PreHeader && Header);
  for (const PHINode &PN : Header->phis()) {
    if (isa<ConstantInt>(PN.getIncomingValueForBlock(PreHeader)))
      return true;
  }
  return false;
}

struct LoadValue {
  Instruction *DefI = nullptr;
  unsigned Generation = 0;
  LoadValue() = default;
  LoadValue(Instruction *Inst, unsigned Generation)
      : DefI(Inst), Generation(Generation) {}
};

class StackNode {
  ScopedHashTable<const SCEV *, LoadValue>::ScopeTy LoadScope;
  unsigned CurrentGeneration;
  unsigned ChildGeneration;
  DomTreeNode *Node;
  DomTreeNode::const_iterator ChildIter;
  DomTreeNode::const_iterator EndIter;
  bool Processed = false;

public:
  StackNode(ScopedHashTable<const SCEV *, LoadValue> &AvailableLoads,
            unsigned cg, DomTreeNode *N, DomTreeNode::const_iterator Child,
            DomTreeNode::const_iterator End)
      : LoadScope(AvailableLoads), CurrentGeneration(cg), ChildGeneration(cg),
        Node(N), ChildIter(Child), EndIter(End) {}
  // Accessors.
  unsigned currentGeneration() const { return CurrentGeneration; }
  unsigned childGeneration() const { return ChildGeneration; }
  void childGeneration(unsigned generation) { ChildGeneration = generation; }
  DomTreeNode *node() { return Node; }
  DomTreeNode::const_iterator childIter() const { return ChildIter; }

  DomTreeNode *nextChild() {
    DomTreeNode *Child = *ChildIter;
    ++ChildIter;
    return Child;
  }

  DomTreeNode::const_iterator end() const { return EndIter; }
  bool isProcessed() const { return Processed; }
  void process() { Processed = true; }
};

Value *getMatchingValue(LoadValue LV, LoadInst *LI, unsigned CurrentGeneration,
                        BatchAAResults &BAA,
                        function_ref<MemorySSA *()> GetMSSA) {
  if (!LV.DefI)
    return nullptr;
  if (LV.DefI->getType() != LI->getType())
    return nullptr;
  if (LV.Generation != CurrentGeneration) {
    MemorySSA *MSSA = GetMSSA();
    if (!MSSA)
      return nullptr;
    auto *EarlierMA = MSSA->getMemoryAccess(LV.DefI);
    MemoryAccess *LaterDef =
        MSSA->getWalker()->getClobberingMemoryAccess(LI, BAA);
    if (!MSSA->dominates(LaterDef, EarlierMA))
      return nullptr;
  }
  return LV.DefI;
}

void loadCSE(Loop *L, DominatorTree &DT, ScalarEvolution &SE, LoopInfo &LI,
             BatchAAResults &BAA, function_ref<MemorySSA *()> GetMSSA) {
  ScopedHashTable<const SCEV *, LoadValue> AvailableLoads;
  SmallVector<std::unique_ptr<StackNode>> NodesToProcess;
  DomTreeNode *HeaderD = DT.getNode(L->getHeader());
  NodesToProcess.emplace_back(new StackNode(AvailableLoads, 0, HeaderD,
                                            HeaderD->begin(), HeaderD->end()));

  unsigned CurrentGeneration = 0;
  while (!NodesToProcess.empty()) {
    StackNode *NodeToProcess = &*NodesToProcess.back();

    CurrentGeneration = NodeToProcess->currentGeneration();

    if (!NodeToProcess->isProcessed()) {
      // Process the node.

      // If this block has a single predecessor, then the predecessor is the
      // parent
      // of the domtree node and all of the live out memory values are still
      // current in this block.  If this block has multiple predecessors, then
      // they could have invalidated the live-out memory values of our parent
      // value.  For now, just be conservative and invalidate memory if this
      // block has multiple predecessors.
      if (!NodeToProcess->node()->getBlock()->getSinglePredecessor())
        ++CurrentGeneration;
      for (auto &I : make_early_inc_range(*NodeToProcess->node()->getBlock())) {

        auto *Load = dyn_cast<LoadInst>(&I);
        if (!Load || !Load->isSimple()) {
          if (I.mayWriteToMemory())
            CurrentGeneration++;
          continue;
        }

        const SCEV *PtrSCEV = SE.getSCEV(Load->getPointerOperand());
        LoadValue LV = AvailableLoads.lookup(PtrSCEV);
        if (Value *M =
                getMatchingValue(LV, Load, CurrentGeneration, BAA, GetMSSA)) {
          if (LI.replacementPreservesLCSSAForm(Load, M)) {
            combineMetadataForCSE(cast<Instruction>(M), Load,
                                  /*DoesKMove=*/false);
            Load->replaceAllUsesWith(M);
            Load->eraseFromParent();
          }
        } else {
          AvailableLoads.insert(PtrSCEV, LoadValue(Load, CurrentGeneration));
        }
      }
      NodeToProcess->childGeneration(CurrentGeneration);
      NodeToProcess->process();
    } else if (NodeToProcess->childIter() != NodeToProcess->end()) {
      // Push the next child onto the stack.
      DomTreeNode *Child = NodeToProcess->nextChild();
      if (!L->contains(Child->getBlock()))
        continue;
      NodesToProcess.emplace_back(
          new StackNode(AvailableLoads, NodeToProcess->childGeneration(), Child,
                        Child->begin(), Child->end()));
    } else {
      // It has been processed, and there are no more children to process,
      // so delete it and pop it off the stack.
      NodesToProcess.pop_back();
    }
  }
}

/// Perform some cleanup and simplifications on loops after unrolling. It is
/// useful to simplify the IV's in the new loop, as well as do a quick
/// simplify/dce pass of the instructions.
void llvm::simplifyLoopAfterUnroll(Loop *L, bool SimplifyIVs, LoopInfo *LI,
                                   ScalarEvolution *SE, DominatorTree *DT,
                                   AssumptionCache *AC,
                                   const TargetTransformInfo *TTI,
                                   ArrayRef<BasicBlock *> Blocks,
                                   AAResults *AA) {
  using namespace llvm::PatternMatch;

  // Simplify any new induction variables in the partially unrolled loop.
  if (SE && SimplifyIVs) {
    SmallVector<WeakTrackingVH, 16> DeadInsts;
    simplifyLoopIVs(L, SE, DT, LI, TTI, DeadInsts);

    // Aggressively clean up dead instructions that simplifyLoopIVs already
    // identified. Any remaining should be cleaned up below.
    while (!DeadInsts.empty()) {
      Value *V = DeadInsts.pop_back_val();
      if (Instruction *Inst = dyn_cast_or_null<Instruction>(V))
        RecursivelyDeleteTriviallyDeadInstructions(Inst);
    }

    if (AA) {
      std::unique_ptr<MemorySSA> MSSA = nullptr;
      BatchAAResults BAA(*AA);
      loadCSE(L, *DT, *SE, *LI, BAA, [L, AA, DT, &MSSA]() -> MemorySSA * {
        if (!MSSA)
          MSSA.reset(new MemorySSA(*L, AA, DT));
        return &*MSSA;
      });
    }
  }

  // At this point, the code is well formed.  Perform constprop, instsimplify,
  // and dce.
  SmallVector<WeakTrackingVH, 16> DeadInsts;
  for (BasicBlock *BB : Blocks) {
    // Remove repeated debug instructions after loop unrolling.
    if (BB->getParent()->getSubprogram())
      RemoveRedundantDbgInstrs(BB);

    for (Instruction &Inst : llvm::make_early_inc_range(*BB)) {
      if (Value *V = simplifyInstruction(
              &Inst, {BB->getDataLayout(), nullptr, DT, AC}))
        if (LI->replacementPreservesLCSSAForm(&Inst, V))
          Inst.replaceAllUsesWith(V);
      if (isInstructionTriviallyDead(&Inst))
        DeadInsts.emplace_back(&Inst);

      // Fold ((add X, C1), C2) to (add X, C1+C2). This is very common in
      // unrolled loops, and handling this early allows following code to
      // identify the IV as a "simple recurrence" without first folding away
      // a long chain of adds.
      {
        Value *X;
        const APInt *C1, *C2;
        if (match(&Inst, m_Add(m_Add(m_Value(X), m_APInt(C1)), m_APInt(C2)))) {
          auto *InnerI = dyn_cast<Instruction>(Inst.getOperand(0));
          auto *InnerOBO = cast<OverflowingBinaryOperator>(Inst.getOperand(0));
          bool SignedOverflow;
          APInt NewC = C1->sadd_ov(*C2, SignedOverflow);
          Inst.setOperand(0, X);
          Inst.setOperand(1, ConstantInt::get(Inst.getType(), NewC));
          Inst.setHasNoUnsignedWrap(Inst.hasNoUnsignedWrap() &&
                                    InnerOBO->hasNoUnsignedWrap());
          Inst.setHasNoSignedWrap(Inst.hasNoSignedWrap() &&
                                  InnerOBO->hasNoSignedWrap() &&
                                  !SignedOverflow);
          if (InnerI && isInstructionTriviallyDead(InnerI))
            DeadInsts.emplace_back(InnerI);
        }
      }
    }
    // We can't do recursive deletion until we're done iterating, as we might
    // have a phi which (potentially indirectly) uses instructions later in
    // the block we're iterating through.
    RecursivelyDeleteTriviallyDeadInstructions(DeadInsts);
  }
}

// If LoopUnroll has proven OriginalLoopProb is incorrect for some iterations
// of the original loop, adjust latch probabilities in the unrolled loop to
// maintain the original total frequency of the original loop body.
//
// OriginalLoopProb is practical but imprecise
// -------------------------------------------
//
// The latch branch weights that LLVM originally adds to a loop encode one latch
// probability, OriginalLoopProb, applied uniformly across the loop's infinite
// set of theoretically possible iterations.  While this uniform latch
// probability serves as a practical statistic summarizing the trip counts
// observed during profiling, it is imprecise.  Specifically, unless it is zero,
// it is impossible for it to be the actual probability observed at every
// individual iteration.  To see why, consider that the only way to actually
// observe at run time that the latch probability remains non-zero is to profile
// at least one loop execution that has an infinite number of iterations.  I do
// not know how to profile an infinite number of loop iterations, and most loops
// I work with are always finite.
//
// LoopUnroll proves OriginalLoopProb is incorrect
// ------------------------------------------------
//
// LoopUnroll reorganizes the original loop so that loop iterations are no
// longer all implemented by the same code, and then it analyzes some of those
// loop iteration implementations independently of others.  In particular, it
// converts some of their conditional latches to unconditional.  That is, by
// examining code structure without any profile data, LoopUnroll proves that the
// actual latch probability at the end of such an iteration is either 1 or 0.
// When an individual iteration's actual latch probability is 1 or 0, that means
// it always behaves the same, so it is impossible to observe it as having any
// other probability.  The original uniform latch probability is rarely 1 or 0
// because, when applied to all possible iterations, that would yield an
// estimated trip count of infinity or 1, respectively.
//
// Thus, the new probabilities of 1 or 0 are proven corrections to
// OriginalLoopProb for individual iterations in the original loop.  However,
// LoopUnroll often is able to perform these corrections for only some
// iterations, leaving other iterations with OriginalLoopProb, and thus
// corrupting the aggregate effect on the total frequency of the original loop
// body.
//
// Adjusting latch probabilities
// -----------------------------
//
// This function ensures that the total frequency of the original loop body,
// summed across all its occurrences in the unrolled loop after the
// aforementioned latch conversions, is the same as in the original loop.  To do
// so, it adjusts probabilities on the remaining conditional latches.  However,
// it cannot derive the new probabilities directly from the original uniform
// latch probability because the latter has been proven incorrect for some
// original loop iterations.
//
// There are often many sets of latch probabilities that can produce the
// original total loop body frequency.  If there are many remaining conditional
// latches and !UnrollUniformWeights, this function just quickly hacks a few of
// their probabilities to restore the original total loop body frequency.
// Otherwise, it tries harder to determine less arbitrary probabilities.
static void fixProbContradiction(Loop *L, UnrollLoopOptions ULO,
                                 OptimizationRemarkEmitter *ORE,
                                 BranchProbability OriginalLoopProb,
                                 bool CompletelyUnroll,
                                 std::vector<unsigned> &IterCounts,
                                 const std::vector<BasicBlock *> &CondLatches,
                                 std::vector<BasicBlock *> &CondLatchNexts) {
  // Runtime unrolling is handled later in LoopUnroll not here.
  //
  // There are two scenarios in which LoopUnroll sets ProbUpdateRequired to true
  // because it needs to update probabilities that were originally
  // OriginalLoopProb, but only in one scenario has LoopUnroll proven
  // OriginalLoopProb incorrect for iterations within the original loop:
  // - If ULO.Runtime, LoopUnroll adds new guards that enforce new reaching
  //   conditions for new loop iteration implementations (e.g., one unrolled
  //   loop iteration executes only if at least ULO.Count original loop
  //   iterations remain).  Those reaching conditions dictate how conditional
  //   latches can be converted to unconditional (e.g., within an unrolled loop
  //   iteration, there is no need to recheck the number of remaining original
  //   loop iterations).  None of this reorganization alters the set of possible
  //   original loop iteration counts or proves OriginalLoopProb incorrect for
  //   any of the original loop iterations.  Thus, LoopUnroll derives
  //   probabilities for the new guards and latches directly from
  //   OriginalLoopProb based on the probabilities that their reaching
  //   conditions would occur in the original loop.  Doing so maintains the
  //   total frequency of the original loop body.
  // - If !ULO.Runtime, LoopUnroll initially adds new loop iteration
  //   implementations, which have the same latch probabilities as in the
  //   original loop because there are no new guards that change their reaching
  //   conditions.  Sometimes, LoopUnroll is then done, and so does not set
  //   ProbUpdateRequired to true.  Other times, LoopUnroll then proves that
  //   some latches are unconditional, directly contradicting OriginalLoopProb
  //   for the corresponding original loop iterations.  That reduces the set of
  //   possible original loop iteration counts, possibly producing a finite set
  //   if it manages to eliminate the backedge.  LoopUnroll has to choose a new
  //   set of latch probabilities that produce the same total loop body
  //   frequency.
  //
  // This function addresses the second scenario only.
  if (ULO.Runtime)
    return;

  // If CondLatches.empty(), there are no latch branches with probabilities we
  // can adjust.  That should mean that the actual trip count is always exactly
  // the number of remaining unrolled iterations, and so OriginalLoopProb should
  // have yielded that trip count as the original loop body frequency.  Of
  // course, OriginalLoopProb could be based on inaccurate profile data, but
  // there is nothing we can do about that here.
  if (CondLatches.empty())
    return;

  // If the original latch probability is 1, the original frequency is infinity.
  // Leaving all remaining probabilities set to 1 might or might not get us
  // there (e.g., a completely unrolled loop cannot be infinite), but it is the
  // closest we can come.
  assert(!OriginalLoopProb.isUnknown() &&
         "Expected to have loop probability to fix");
  if (OriginalLoopProb.isOne())
    return;

  // FreqDesired is the frequency implied by the original loop probability.
  double FreqDesired = 1 / (1 - OriginalLoopProb.toDouble());

  // Get the probability at CondLatches[I].
  auto GetProb = [&](unsigned I) {
    CondBrInst *B = cast<CondBrInst>(CondLatches[I]->getTerminator());
    bool FirstTargetIsNext = B->getSuccessor(0) == CondLatchNexts[I];
    return getBranchProbability(B, FirstTargetIsNext).toDouble();
  };

  // Set the probability at CondLatches[I] to Prob.
  auto SetProb = [&](unsigned I, double Prob) {
    CondBrInst *B = cast<CondBrInst>(CondLatches[I]->getTerminator());
    bool FirstTargetIsNext = B->getSuccessor(0) == CondLatchNexts[I];
    setBranchProbability(B, BranchProbability::getBranchProbability(Prob),
                         FirstTargetIsNext);
  };

  // Set all probabilities in CondLatches to Prob.
  auto SetAllProbs = [&](double Prob) {
    for (unsigned I = 0, E = CondLatches.size(); I < E; ++I)
      SetProb(I, Prob);
  };

  // If UnrollUniformWeights or n <= 2, we choose the simplest probability model
  // we can think of: every remaining conditional branch instruction has the
  // same probability, Prob, of continuing to the next iteration.  This model
  // has several helpful properties:
  // - There is only one search parameter, Prob.
  // - We have no reason to think one latch branch's probability should be
  //   higher or lower than another, and so this model makes them all the same.
  //   In the worst cases, we thus avoid setting just some probabilities to 0 or
  //   1, which can unrealistically make some code appear unreachable.  There
  //   are cases where they *all* must become 0 or 1 to achieve the total
  //   frequency of original loop body, and our model does permit that.
  // - The frequency, FreqOne, of the original loop body in a single iteration
  //   of the unrolled loop is computed by a simple polynomial, where p=Prob,
  //   n=CondLatches.size(), and c_i=IterCounts[i]:
  //
  //     FreqOne = Sum(i=0..n)(c_i * p^i)
  //
  // - If the backedge has been eliminated:
  //   - FreqOne is the total frequency of the original loop body in the
  //     unrolled loop.
  //   - If Prob == 1, the total frequency of the original loop body is exactly
  //     the number of remaining loop iterations, as expected because every
  //     remaining loop iteration always then executes.
  // - If the backedge remains:
  //   - Sum(i=0..inf)(FreqOne * p^(n*i)) = FreqOne / (1 - p^n) is the total
  //     frequency of the original loop body in the unrolled loop, regardless of
  //     whether the backedge is conditional or unconditional.
  //   - As Prob approaches 1, the total frequency of the original loop body
  //     approaches infinity, as expected because the loop approaches never
  //     exiting.
  // - For n <= 2, we can use simple formulas to solve the above polynomial
  //   equations exactly for p without performing a search.
  // - For n > 2, evaluating each point in the search space, using ComputeFreq
  //   below, requires about as few instructions as we could hope for.  That is,
  //   the probability is constant across the conditional branches, so the only
  //   computation is across conditional branches and any backedge, as required
  //   for any model for Prob.
  // - Prob == 1 produces the maximum possible total frequency for the original
  //   loop body, as described above.  Prob == 0 produces the minimum, 0.
  //   Increasing or decreasing Prob monotonically increases or decreases the
  //   frequency, respectively.  Thus, for every possible frequency, there
  //   exists some Prob that can produce it, and we can easily use bisection to
  //   search the problem space.

  // When iterating for a solution, we stop early if we find probabilities
  // that produce a Freq whose relative difference from FreqDesired is small
  // (FreqPrec).  Otherwise, we expect to compute a solution at least that
  // accurate (but surely far more accurate).
  const double FreqPrec = 1e-6;

  // Compute the new frequency produced by using Prob throughout CondLatches.
  auto ComputeFreq = [&](double Prob) {
    double ProbReaching = 1;        // p^0
    double FreqOne = IterCounts[0]; // c_0*p^0
    for (unsigned I = 0, E = CondLatches.size(); I < E; ++I) {
      ProbReaching *= Prob;                        // p^(I+1)
      FreqOne += IterCounts[I + 1] * ProbReaching; // c_(I+1)*p^(I+1)
    }
    double ProbReachingBackedge = CompletelyUnroll ? 0 : ProbReaching;
    assert(FreqOne > 0 && "Expected at least one iteration before first latch");
    if (ProbReachingBackedge == 1)
      return std::numeric_limits<double>::infinity();
    return FreqOne / (1 - ProbReachingBackedge);
  };

  // Compute the probability that, used at CondLaches[0] where
  // CondLatches.size() == 1, gets as close as possible to FreqDesired.
  auto ComputeProbForLinear = [&]() {
    // The polynomial is linear (0 = A*p + B), so just solve it.
    double A = IterCounts[1] + (CompletelyUnroll ? 0 : FreqDesired);
    double B = IterCounts[0] - FreqDesired;
    assert(A > 0 && "Expected iterations after last conditional latch");
    double Prob = -B / A;
    // If it computes an invalid Prob, FreqDesired is impossibly low or high.
    // Otherwise, Prob should produce nearly FreqDesired.
    assert((Prob < 0 || Prob > 1 ||
            fabs(ComputeFreq(Prob) - FreqDesired) / FreqDesired < FreqPrec) &&
           "Expected accurate frequency when linear case is possible");
    Prob = std::max(Prob, 0.);
    Prob = std::min(Prob, 1.);
    return Prob;
  };

  // Compute the probability that, used throughout CondLatches where
  // CondLatches.size() == 2, gets as close as possible to FreqDesired.
  auto ComputeProbForQuadratic = [&]() {
    // The polynomial is quadratic (0 = A*p^2 + B*p + C), so just solve it.
    double A = IterCounts[2] + (CompletelyUnroll ? 0 : FreqDesired);
    double B = IterCounts[1];
    double C = IterCounts[0] - FreqDesired;
    assert(A > 0 && "Expected iterations after last conditional latch");
    double Prob = (-B + sqrt(B * B - 4 * A * C)) / (2 * A);
    // If it computes an invalid Prob, FreqDesired is impossibly low or high.
    // Otherwise, Prob should produce nearly FreqDesired.
    assert((Prob < 0 || Prob > 1 ||
            fabs(ComputeFreq(Prob) - FreqDesired) / FreqDesired < FreqPrec) &&
           "Expected accurate frequency when quadratic case is possible");
    Prob = std::max(Prob, 0.);
    Prob = std::min(Prob, 1.);
    return Prob;
  };

  // Adjust the probability at CondLatches[ComputeIdx] to get as close as
  // possible to FreqDesired without replacing probabilities elsewhere in
  // CondLatches.  Return the new total frequency.
  //
  // Given a CondLatches index I, then for a single unrolled loop iteration:
  // - ProbBefore or ProbAfter is the probability that control flow can pass
  //   through every CondLatches[J] for J < I or J > I, respectively.
  // - FreqBefore or FreqAfter is the total frequency accumulated before or
  //   after CondLatches[I], respectively, while the probability at
  //   CondLatches[I] is treated as 1.
  //
  // If ComputeIdx == 0, then ComputeProb will set those values for I == 0 and
  // ignore the current values.  If ComputeIdx > 0, then it expects those values
  // to already be set for I == ComputeIdx - 1, and it will set them for I ==
  // ComputeIdx.
  auto AdjustProb = [&](unsigned ComputeIdx, double &ProbBefore,
                        double &ProbAfter, double &FreqBefore,
                        double &FreqAfter) {
    assert(ComputeIdx < CondLatches.size() &&
           "Expected valid CondLatches index");

    // Compute or update ProbBefore, ProbAfter, FreqBefore, and FreqAfter.
    auto ComputeAfter = [&]() {
      ProbAfter = 1;
      FreqAfter = IterCounts[ComputeIdx + 1];
      for (unsigned I = ComputeIdx + 1, E = CondLatches.size(); I < E; ++I) {
        double Prob = GetProb(I);
        ProbAfter *= Prob;
        // After Prob == 0, ProbAfter and FreqAfter won't change, so save time.
        if (Prob == 0)
          break;
        FreqAfter += IterCounts[I + 1] * ProbAfter;
      }
    };
    if (ComputeIdx == 0) {
      ProbBefore = 1;
      FreqBefore = IterCounts[0];
      ComputeAfter();
    } else {
      // Rather than iterating all of CondLatches again, we fix up the
      // previously computed values.
      double ProbOld = GetProb(ComputeIdx);
      if (ProbOld > 0) {
        FreqAfter -= IterCounts[ComputeIdx] * ProbBefore;
        ProbAfter /= ProbOld;
        FreqAfter /= ProbOld;
      } else {
        // We cannot divide out the old zero probability.  We short-circuited
        // the iteration at that zero in the previous ComputeAfter call, so now
        // we pick up where we left off.
        ComputeAfter();
      }
      ProbBefore *= GetProb(ComputeIdx - 1);
      FreqBefore += IterCounts[ComputeIdx] * ProbBefore;
    }

    // Compute the required probability, and limit it to a valid probability (0
    // <= p <= 1).  See the FreqCompute formula below for how to derive the
    // ProbCompute formula.
    double ProbReachingBackedge = CompletelyUnroll ? 0 : ProbBefore * ProbAfter;
    double ProbComputeNumerator = FreqDesired - FreqBefore;
    double ProbComputeDenominator =
        FreqAfter + FreqDesired * ProbReachingBackedge;
    double ProbCompute = -1; // Init expected to be unused.
    if (ProbComputeNumerator <= 0) {
      // FreqBefore has already reached or surpassed FreqDesired, so add no more
      // frequency.  It is possible that ProbComputeDenominator == 0 here
      // because some latch probability (maybe the original) was set to zero, so
      // this check avoids setting ProbCompute=1 (in the else if below) and
      // division by zero where the numerator <= 0 (in the else below).
      ProbCompute = 0;
    } else if (ProbComputeDenominator == 0) {
      // Analytically, this case seems impossible.  It would occur if either:
      // - Both FreqAfter and FreqDesired are zero.  But the latter would cause
      //   ProbComputeNumerator < 0, which we catch above, and FreqDesired
      //   should always be >= 1 anyway.
      // - There are no iterations after CondLatches[ComputeIdx], not even via
      //   a backedge, so that both FreqAfter and ProbReachingBackedge are zero.
      //   But iterations should exist after even the last conditional latch.
      // - Some latch probability (maybe the original) was set to zero so that
      //   both FreqAfter and ProbReachingBackedge are zero.  But that should
      //   not have happened because, according to the above
      //   ProbComputeNumerator check, we have not yet reached FreqDesired
      //   (which, if the original latch probability is zero, is just 1 and thus
      //   always reached or surpassed).
      //
      // Numerically, perhaps this case is possible.  We interpret it to mean we
      // need more frequency (ProbComputeNumerator > 0) but have no way to get
      // any (ProbComputeDenominator is analytically too small to distinguish it
      // from 0 in floating point), suggesting infinite probability is needed,
      // but 1 is the maximum valid probability and thus the best we can do.
      //
      // TODO: Cover this case in the test suite if you can.
      ProbCompute = 1;
    } else {
      ProbCompute = ProbComputeNumerator / ProbComputeDenominator;
      ProbCompute = std::max(ProbCompute, 0.);
      ProbCompute = std::min(ProbCompute, 1.);
    }
    SetProb(ComputeIdx, ProbCompute);

    // Compute the resulting total frequency.
    double FreqCompute = -1; // Init expected to be unused.
    if (ProbReachingBackedge * ProbCompute == 1) {
      // Analytically, this case seems impossible.  It requires that there is a
      // backedge and that FreqDesired == infinity so that every conditional
      // latch's probability had to be set to 1.  But FreqDesired == infinity
      // means OriginalLoopProb.isOne(), which we guarded against earlier.
      //
      // Numerically, perhaps this case is possible.  We interpret it to mean
      // that analytically the probability has to be so near 1 that, in floating
      // point, the frequency is computed as infinite.
      //
      // TODO: Cover this case in the test suite if you can.
      FreqCompute = std::numeric_limits<double>::infinity();
      if (ORE) {
        ORE->emit([&]() {
          return OptimizationRemark(DEBUG_TYPE, "InfiniteFrequency",
                                    L->getStartLoc(), L->getHeader());
        });
      }
    } else {
      assert(FreqBefore > 0 &&
             "Expected at least one iteration before first latch");
      // In this equation, if we replace the left-hand side with FreqDesired and
      // then solve for ProbCompute, we get the ProbCompute formula above.
      FreqCompute = (FreqBefore + FreqAfter * ProbCompute) /
                    (1 - ProbReachingBackedge * ProbCompute);
    }
    assert(FreqCompute > 0 && "Expected valid frequency");
    return FreqCompute;
  };

  // Determine and set branch weights.
  //
  // Prob < 0 and Prob > 1 cannot be represented as branch weights.  We might
  // compute such a Prob if FreqDesired is impossible (e.g., due to inaccurate
  // profile data) for the maximum trip count we have determined when completely
  // unrolling.  In that case, so just go with whichever is closest.
  if (CondLatches.size() == 1) {
    SetAllProbs(ComputeProbForLinear());
  } else if (CondLatches.size() == 2) {
    SetAllProbs(ComputeProbForQuadratic());
  } else if (!UnrollUniformWeights) {
    // The polynomial is too complex for a simple formula, and the quick and
    // dirty fix has been selected.  Adjust probabilities starting from the
    // first latch, which has the most influence on the total frequency, so
    // starting there should minimize the number of latches that have to be
    // visited.  We do have to iterate because the first latch alone might not
    // be enough.  For example, we might need to set all probabilities to 1 if
    // the frequency is the unroll factor.
    double ProbBefore = -1, ProbAfter = -1; // Inits expected to be unused.
    double FreqBefore = -1, FreqAfter = -1; // Inits expected to be unused.
    for (unsigned I = 0; I != CondLatches.size(); ++I) {
      double Freq = AdjustProb(I, ProbBefore, ProbAfter, FreqBefore, FreqAfter);
      if (fabs(Freq - FreqDesired) / FreqDesired < FreqPrec)
        break;
    }
  } else {
    // The polynomial is too complex for a simple formula, and uniform branch
    // weights have been selected, so bisect.
    double ProbMin = -1, ProbMax = -1; // Inits expected to be unused.
    double ProbPrev = -1;              // Inits expected to be unused.
    auto TryProb = [&](double Prob) {
      ProbPrev = Prob;
      double FreqDelta = ComputeFreq(Prob) - FreqDesired;
      if (fabs(FreqDelta) / FreqDesired < FreqPrec)
        return 0;
      if (FreqDelta < 0) {
        ProbMin = Prob;
        return -1;
      }
      ProbMax = Prob;
      return 1;
    };
    // If Prob == 0 is too small and Prob == 1 is too large, bisect between
    // them.  Accuracy (relative difference) is controlled by FreqPrec above.
    // However, to place a hard upper limit on the search time, we stop
    // bisecting when Prob stops changing (ProbDelta) by much (ProbPrec).  In
    // this case, we compute an absolute difference not a relative difference,
    // which could produce more search time for smaller probabilities.
    if (TryProb(0.) < 0 && TryProb(1.) > 0) {
      assert(ProbMin == 0 && ProbMax == 1 &&
             "expected probability bounds to be initialized");
      const double ProbPrec = 1e-12;
      double Prob, ProbDelta;
      do {
        Prob = (ProbMin + ProbMax) / 2;
        ProbDelta = Prob - ProbPrev;
      } while (TryProb(Prob) != 0 && fabs(ProbDelta) > ProbPrec);
    }
    SetAllProbs(ProbPrev);
  }

  // FIXME: We have not considered non-latch loop exits:
  // - Their original probabilities are not considered in our calculation of
  //   FreqDesired.
  // - Their probabilities are not considered in our probability model used to
  //   determine new probabilities for remaining conditional branches.
  // - If they are conditional and LoopUnroll converts them to unconditional,
  //   LoopUnroll has proven their original probabilities are incorrect for some
  //   original loop iterations, but that does not cause ProbUpdateRequired to
  //   be set to true.
  //
  // To adjust FreqDesired and our probability model correctly for a non-latch
  // loop exit, we would need to compute the original probability that the exit
  // is reached from the loop header (in contrast, we currently assume that
  // probability is 1 in the case of a latch exit) and the probability that the
  // exit is taken if it is conditional (use the branch's old or new weights for
  // FreqDesired or the probability model, respectively).  Does computing the
  // reaching probability require a CFG traversal, or is there some existing
  // library that can do it?  Prior discussions suggest some such libraries are
  // difficult to use within LoopUnroll:
  // <https://github.com/llvm/llvm-project/pull/164799#issuecomment-3438681519>.
  // For now, we just let our corrected probabilities be less accurate in that
  // scenario.  Alternatively, we could refuse to correct probabilities at all
  // in that scenario, but that seems worse.
}

/// Unroll the given loop by Count. The loop must be in LCSSA form.  Unrolling
/// can only fail when the loop's latch block is not terminated by a conditional
/// branch instruction. However, if the trip count (and multiple) are not known,
/// loop unrolling will mostly produce more code that is no faster.
///
/// If Runtime is true then UnrollLoop will try to insert a prologue or
/// epilogue that ensures the latch has a trip multiple of Count. UnrollLoop
/// will not runtime-unroll the loop if computing the run-time trip count will
/// be expensive and AllowExpensiveTripCount is false.
///
/// The LoopInfo Analysis that is passed will be kept consistent.
///
/// This utility preserves LoopInfo. It will also preserve ScalarEvolution and
/// DominatorTree if they are non-null.
///
/// If RemainderLoop is non-null, it will receive the remainder loop (if
/// required and not fully unrolled).
LoopUnrollResult
llvm::UnrollLoop(Loop *L, UnrollLoopOptions ULO, LoopInfo *LI,
                 ScalarEvolution *SE, DominatorTree *DT, AssumptionCache *AC,
                 const TargetTransformInfo *TTI, OptimizationRemarkEmitter *ORE,
                 bool PreserveLCSSA, Loop **RemainderLoop, AAResults *AA) {
  assert(DT && "DomTree is required");

  if (!L->getLoopPreheader()) {
    LLVM_DEBUG(dbgs() << "  Can't unroll; loop preheader-insertion failed.\n");
    return LoopUnrollResult::Unmodified;
  }

  if (!L->getLoopLatch()) {
    LLVM_DEBUG(dbgs() << "  Can't unroll; loop exit-block-insertion failed.\n");
    return LoopUnrollResult::Unmodified;
  }

  // Loops with indirectbr cannot be cloned.
  if (!L->isSafeToClone()) {
    LLVM_DEBUG(dbgs() << "  Can't unroll; Loop body cannot be cloned.\n");
    return LoopUnrollResult::Unmodified;
  }

  if (L->getHeader()->hasAddressTaken()) {
    // The loop-rotate pass can be helpful to avoid this in many cases.
    LLVM_DEBUG(
        dbgs() << "  Won't unroll loop: address of header block is taken.\n");
    return LoopUnrollResult::Unmodified;
  }

  assert(ULO.Count > 0);

  // All these values should be taken only after peeling because they might have
  // changed.
  BasicBlock *Preheader = L->getLoopPreheader();
  BasicBlock *Header = L->getHeader();
  BasicBlock *LatchBlock = L->getLoopLatch();
  SmallVector<BasicBlock *, 4> ExitBlocks;
  L->getExitBlocks(ExitBlocks);

  const unsigned MaxTripCount = SE->getSmallConstantMaxTripCount(L);
  const bool MaxOrZero = SE->isBackedgeTakenCountMaxOrZero(L);
  std::optional<unsigned> OriginalTripCount =
      llvm::getLoopEstimatedTripCount(L);
  BranchProbability OriginalLoopProb = llvm::getLoopProbability(L);

  // Effectively "DCE" unrolled iterations that are beyond the max tripcount
  // and will never be executed.
  if (MaxTripCount && ULO.Count > MaxTripCount)
    ULO.Count = MaxTripCount;

  struct ExitInfo {
    unsigned TripCount;
    unsigned TripMultiple;
    unsigned BreakoutTrip;
    bool ExitOnTrue;
    BasicBlock *FirstExitingBlock = nullptr;
    SmallVector<BasicBlock *> ExitingBlocks;
  };
  MapVector<BasicBlock *, ExitInfo> ExitInfos;
  SmallVector<BasicBlock *, 4> ExitingBlocks;
  L->getExitingBlocks(ExitingBlocks);
  for (auto *ExitingBlock : ExitingBlocks) {
    // The folding code is not prepared to deal with non-branch instructions
    // right now.
    auto *BI = dyn_cast<CondBrInst>(ExitingBlock->getTerminator());
    if (!BI)
      continue;

    ExitInfo &Info = ExitInfos[ExitingBlock];
    Info.TripCount = SE->getSmallConstantTripCount(L, ExitingBlock);
    Info.TripMultiple = SE->getSmallConstantTripMultiple(L, ExitingBlock);
    if (Info.TripCount != 0) {
      Info.BreakoutTrip = Info.TripCount % ULO.Count;
      Info.TripMultiple = 0;
    } else {
      Info.BreakoutTrip = Info.TripMultiple =
          (unsigned)std::gcd(ULO.Count, Info.TripMultiple);
    }
    Info.ExitOnTrue = !L->contains(BI->getSuccessor(0));
    Info.ExitingBlocks.push_back(ExitingBlock);
    LLVM_DEBUG(dbgs() << "  Exiting block %" << ExitingBlock->getName()
                      << ": TripCount=" << Info.TripCount
                      << ", TripMultiple=" << Info.TripMultiple
                      << ", BreakoutTrip=" << Info.BreakoutTrip << "\n");
  }

  // Are we eliminating the loop control altogether?  Note that we can know
  // we're eliminating the backedge without knowing exactly which iteration
  // of the unrolled body exits.
  const bool CompletelyUnroll = ULO.Count == MaxTripCount;

  const bool PreserveOnlyFirst = CompletelyUnroll && MaxOrZero;

  // There's no point in performing runtime unrolling if this unroll count
  // results in a full unroll.
  if (CompletelyUnroll)
    ULO.Runtime = false;

  // Go through all exits of L and see if there are any phi-nodes there. We just
  // conservatively assume that they're inserted to preserve LCSSA form, which
  // means that complete unrolling might break this form. We need to either fix
  // it in-place after the transformation, or entirely rebuild LCSSA. TODO: For
  // now we just recompute LCSSA for the outer loop, but it should be possible
  // to fix it in-place.
  bool NeedToFixLCSSA =
      PreserveLCSSA && CompletelyUnroll &&
      any_of(ExitBlocks,
             [](const BasicBlock *BB) { return isa<PHINode>(BB->begin()); });

  // The current loop unroll pass can unroll loops that have
  // (1) single latch; and
  // (2a) latch is unconditional; or
  // (2b) latch is conditional and is an exiting block
  // FIXME: The implementation can be extended to work with more complicated
  // cases, e.g. loops with multiple latches.
  Instruction *LatchTerm = LatchBlock->getTerminator();

  // A conditional branch which exits the loop, which can be optimized to an
  // unconditional branch in the unrolled loop in some cases.
  bool LatchIsExiting = L->isLoopExiting(LatchBlock);
  if (!isa<UncondBrInst>(LatchTerm) &&
      !(isa<CondBrInst>(LatchTerm) && LatchIsExiting)) {
    LLVM_DEBUG(
        dbgs() << "Can't unroll; a conditional latch must exit the loop");
    return LoopUnrollResult::Unmodified;
  }

  bool EpilogProfitability =
      UnrollRuntimeEpilog.getNumOccurrences() ? UnrollRuntimeEpilog
                                              : isEpilogProfitable(L);

  if (ULO.Runtime &&
      !UnrollRuntimeLoopRemainder(
          L, ULO.Count, ULO.AllowExpensiveTripCount, EpilogProfitability,
          ULO.UnrollRemainder, ULO.ForgetAllSCEV, LI, SE, DT, AC, TTI,
          PreserveLCSSA, ULO.SCEVExpansionBudget, ULO.RuntimeUnrollMultiExit,
          RemainderLoop, OriginalTripCount, OriginalLoopProb)) {
    if (ULO.Force)
      ULO.Runtime = false;
    else {
      LLVM_DEBUG(dbgs() << "Won't unroll; remainder loop could not be "
                           "generated when assuming runtime trip count\n");
      return LoopUnrollResult::Unmodified;
    }
  }

  using namespace ore;

  // Determine whether this loop originated from the vectorizer so we can
  // produce more informative remarks.
  StringRef LoopKind = getLoopVectorizeKindPrefix(L);

  // Report the unrolling decision.
  if (CompletelyUnroll) {
    LLVM_DEBUG(dbgs() << "COMPLETELY UNROLLING loop %" << Header->getName()
                      << " with trip count " << ULO.Count << "!\n");
    if (ORE)
      ORE->emit([&]() {
        return OptimizationRemark(DEBUG_TYPE, "FullyUnrolled", L->getStartLoc(),
                                  L->getHeader())
               << "completely unrolled " + LoopKind.str() + "loop with "
               << NV("UnrollCount", ULO.Count) << " iterations";
      });
  } else {
    LLVM_DEBUG({
      dbgs() << "UNROLLING loop %" << Header->getName() << " by " << ULO.Count;
      if (ULO.Runtime) {
        dbgs() << " with run-time trip count";
        if (ULO.UnrollRemainder)
          dbgs() << " (remainder unrolled)";
      }
      dbgs() << "!\n";
    });

    if (ORE)
      ORE->emit([&]() {
        OptimizationRemark Diag(DEBUG_TYPE, "PartialUnrolled", L->getStartLoc(),
                                L->getHeader());
        Diag << "unrolled " + LoopKind.str() + "loop by a factor of "
             << NV("UnrollCount", ULO.Count);
        if (ULO.Runtime)
          Diag << " with run-time trip count"
               << (ULO.UnrollRemainder ? " (remainder unrolled)" : "");
        return Diag;
      });
  }

  // We are going to make changes to this loop. SCEV may be keeping cached info
  // about it, in particular about backedge taken count. The changes we make
  // are guaranteed to invalidate this information for our loop. It is tempting
  // to only invalidate the loop being unrolled, but it is incorrect as long as
  // all exiting branches from all inner loops have impact on the outer loops,
  // and if something changes inside them then any of outer loops may also
  // change. When we forget outermost loop, we also forget all contained loops
  // and this is what we need here.
  if (SE) {
    if (ULO.ForgetAllSCEV)
      SE->forgetAllLoops();
    else {
      SE->forgetTopmostLoop(L);
      SE->forgetBlockAndLoopDispositions();
    }
  }

  if (!LatchIsExiting)
    ++NumUnrolledNotLatch;

  // For the first iteration of the loop, we should use the precloned values for
  // PHI nodes.  Insert associations now.
  ValueToValueMapTy LastValueMap;
  std::vector<PHINode*> OrigPHINode;
  for (BasicBlock::iterator I = Header->begin(); isa<PHINode>(I); ++I) {
    OrigPHINode.push_back(cast<PHINode>(I));
  }

  // Collect phi nodes for reductions for which we can introduce multiple
  // parallel reduction phis and compute the final reduction result after the
  // loop. This requires a single exit block after unrolling. This is ensured by
  // restricting to single-block loops where the unrolled iterations are known
  // to not exit.
  DenseMap<PHINode *, RecurrenceDescriptor> Reductions;
  bool CanAddAdditionalAccumulators =
      (UnrollAddParallelReductions.getNumOccurrences() > 0
           ? UnrollAddParallelReductions
           : ULO.AddAdditionalAccumulators) &&
      !CompletelyUnroll && L->getNumBlocks() == 1 &&
      (ULO.Runtime ||
       (ExitInfos.contains(Header) && ((ExitInfos[Header].TripCount != 0 &&
                                        ExitInfos[Header].BreakoutTrip == 0))));

  // Limit parallelizing reductions to unroll counts of 4 or less for now.
  // TODO: The number of parallel reductions should depend on the number of
  // execution units. We also don't have to add a parallel reduction phi per
  // unrolled iteration, but could for example add a parallel phi for every 2
  // unrolled iterations.
  if (CanAddAdditionalAccumulators && ULO.Count <= 4) {
    for (PHINode &Phi : Header->phis()) {
      auto RdxDesc = canParallelizeReductionWhenUnrolling(Phi, L, SE);
      if (!RdxDesc)
        continue;

      // Only handle duplicate phis for a single reduction for now.
      // TODO: Handle any number of reductions
      if (!Reductions.empty())
        continue;

      Reductions[&Phi] = *RdxDesc;
    }
  }

  std::vector<BasicBlock *> Headers;
  std::vector<BasicBlock *> Latches;
  Headers.push_back(Header);
  Latches.push_back(LatchBlock);

  // The current on-the-fly SSA update requires blocks to be processed in
  // reverse postorder so that LastValueMap contains the correct value at each
  // exit.
  LoopBlocksDFS DFS(L);
  DFS.perform(LI);

  // Stash the DFS iterators before adding blocks to the loop.
  LoopBlocksDFS::RPOIterator BlockBegin = DFS.beginRPO();
  LoopBlocksDFS::RPOIterator BlockEnd = DFS.endRPO();

  std::vector<BasicBlock*> UnrolledLoopBlocks = L->getBlocks();

  // Snapshot the blocks to be cloned after remainder generation, which may
  // delete blocks from L, but before cloning adds new blocks to L.
  const std::vector<BasicBlock *> PostRemainderLoopBlocks = L->getBlocks();

  // Loop Unrolling might create new loops. While we do preserve LoopInfo, we
  // might break loop-simplified form for these loops (as they, e.g., would
  // share the same exit blocks). We'll keep track of loops for which we can
  // break this so that later we can re-simplify them.
  SmallSetVector<Loop *, 4> LoopsToSimplify;
  LoopsToSimplify.insert_range(*L);

  // When a FSDiscriminator is enabled, we don't need to add the multiply
  // factors to the discriminators.
  if (Header->getParent()->shouldEmitDebugInfoForProfiling() &&
      !EnableFSDiscriminator)
    for (BasicBlock *BB : L->getBlocks())
      for (Instruction &I : *BB)
        if (!isa<PseudoProbeInst>(I))
          if (const DILocation *DIL = I.getDebugLoc()) {
            auto NewDIL = DIL->cloneByMultiplyingDuplicationFactor(ULO.Count);
            if (NewDIL)
              I.setDebugLoc(*NewDIL);
            else
              LLVM_DEBUG(dbgs()
                         << "Failed to create new discriminator: "
                         << DIL->getFilename() << " Line: " << DIL->getLine());
          }

  // Identify what noalias metadata is inside the loop: if it is inside the
  // loop, the associated metadata must be cloned for each iteration.
  SmallVector<MDNode *, 6> LoopLocalNoAliasDeclScopes;
  identifyNoAliasScopesToClone(L->getBlocks(), LoopLocalNoAliasDeclScopes);

  // We place the unrolled iterations immediately after the original loop
  // latch.  This is a reasonable default placement if we don't have block
  // frequencies, and if we do, well the layout will be adjusted later.
  auto BlockInsertPt = std::next(LatchBlock->getIterator());
  SmallVector<Instruction *> PartialReductions;
  for (unsigned It = 1; It != ULO.Count; ++It) {
    SmallVector<BasicBlock *, 8> NewBlocks;
    SmallDenseMap<const Loop *, Loop *, 4> NewLoops;
    NewLoops[L] = L;

    for (LoopBlocksDFS::RPOIterator BB = BlockBegin; BB != BlockEnd; ++BB) {
      ValueToValueMapTy VMap;
      BasicBlock *New = CloneBasicBlock(*BB, VMap, "." + Twine(It));
      Header->getParent()->insert(BlockInsertPt, New);

      assert((*BB != Header || LI->getLoopFor(*BB) == L) &&
             "Header should not be in a sub-loop");
      // Tell LI about New.
      const Loop *OldLoop = addClonedBlockToLoopInfo(*BB, New, LI, NewLoops);
      if (OldLoop)
        LoopsToSimplify.insert(NewLoops[OldLoop]);

      if (*BB == Header) {
        // Loop over all of the PHI nodes in the block, changing them to use
        // the incoming values from the previous block.
        for (PHINode *OrigPHI : OrigPHINode) {
          PHINode *NewPHI = cast<PHINode>(VMap[OrigPHI]);
          Value *InVal = NewPHI->getIncomingValueForBlock(LatchBlock);

          // Use cloned phis as parallel phis for partial reductions, which will
          // get combined to the final reduction result after the loop.
          if (Reductions.contains(OrigPHI)) {
            // Collect partial  reduction results.
            if (PartialReductions.empty())
              PartialReductions.push_back(cast<Instruction>(InVal));
            PartialReductions.push_back(cast<Instruction>(VMap[InVal]));

            // Update the start value for the cloned phis to use the identity
            // value for the reduction.
            const RecurrenceDescriptor &RdxDesc = Reductions[OrigPHI];
            NewPHI->setIncomingValueForBlock(
                L->getLoopPreheader(),
                getRecurrenceIdentity(RdxDesc.getRecurrenceKind(),
                                      OrigPHI->getType(),
                                      RdxDesc.getFastMathFlags()));

            // Update NewPHI to use the cloned value for the iteration and move
            // to header.
            NewPHI->replaceUsesOfWith(InVal, VMap[InVal]);
            NewPHI->moveBefore(OrigPHI->getIterator());
            continue;
          }

          if (Instruction *InValI = dyn_cast<Instruction>(InVal))
            if (It > 1 && L->contains(InValI))
              InVal = LastValueMap[InValI];
          VMap[OrigPHI] = InVal;
          NewPHI->eraseFromParent();
        }

        // Eliminate copies of the loop heart intrinsic, if any.
        if (ULO.Heart) {
          auto it = VMap.find(ULO.Heart);
          assert(it != VMap.end());
          Instruction *heartCopy = cast<Instruction>(it->second);
          heartCopy->eraseFromParent();
          VMap.erase(it);
        }
      }

      // Remap source location atom instance. Do this now, rather than
      // when we remap instructions, because remap is called once we've
      // cloned all blocks (all the clones would get the same atom
      // number).
      if (!VMap.AtomMap.empty())
        for (Instruction &I : *New)
          RemapSourceAtom(&I, VMap);

      // Update our running map of newest clones
      LastValueMap[*BB] = New;
      for (ValueToValueMapTy::iterator VI = VMap.begin(), VE = VMap.end();
           VI != VE; ++VI)
        LastValueMap[VI->first] = VI->second;

      // Add phi entries for newly created values to all exit blocks.
      for (BasicBlock *Succ : successors(*BB)) {
        if (L->contains(Succ))
          continue;
        for (PHINode &PHI : Succ->phis()) {
          Value *Incoming = PHI.getIncomingValueForBlock(*BB);
          ValueToValueMapTy::iterator It = LastValueMap.find(Incoming);
          if (It != LastValueMap.end())
            Incoming = It->second;
          PHI.addIncoming(Incoming, New);
          SE->forgetLcssaPhiWithNewPredecessor(L, &PHI);
        }
      }
      // Keep track of new headers and latches as we create them, so that
      // we can insert the proper branches later.
      if (*BB == Header)
        Headers.push_back(New);
      if (*BB == LatchBlock)
        Latches.push_back(New);

      // Keep track of the exiting block and its successor block contained in
      // the loop for the current iteration.
      auto ExitInfoIt = ExitInfos.find(*BB);
      if (ExitInfoIt != ExitInfos.end())
        ExitInfoIt->second.ExitingBlocks.push_back(New);

      NewBlocks.push_back(New);
      UnrolledLoopBlocks.push_back(New);

      // Update DomTree: since we just copy the loop body, and each copy has a
      // dedicated entry block (copy of the header block), this header's copy
      // dominates all copied blocks. That means, dominance relations in the
      // copied body are the same as in the original body.
      if (*BB == Header)
        DT->addNewBlock(New, Latches[It - 1]);
      else {
        auto BBDomNode = DT->getNode(*BB);
        auto BBIDom = BBDomNode->getIDom();
        BasicBlock *OriginalBBIDom = BBIDom->getBlock();
        DT->addNewBlock(
            New, cast<BasicBlock>(LastValueMap[cast<Value>(OriginalBBIDom)]));
      }
    }

    // Remap all instructions in the most recent iteration.
    // Key Instructions: Nothing to do - we've already remapped the atoms.
    remapInstructionsInBlocks(NewBlocks, LastValueMap);
    for (BasicBlock *NewBlock : NewBlocks)
      for (Instruction &I : *NewBlock)
        if (auto *II = dyn_cast<AssumeInst>(&I))
          AC->registerAssumption(II);

    {
      // Identify what other metadata depends on the cloned version. After
      // cloning, replace the metadata with the corrected version for both
      // memory instructions and noalias intrinsics.
      std::string ext = (Twine("It") + Twine(It)).str();
      cloneAndAdaptNoAliasScopes(LoopLocalNoAliasDeclScopes, NewBlocks,
                                 Header->getContext(), ext);
    }
  }

  // Loop over the PHI nodes in the original block, setting incoming values.
  for (PHINode *PN : OrigPHINode) {
    if (CompletelyUnroll) {
      // The RAUW below disconnects the original PHI from its users.
      // Invalidate cached SCEVs while the def-use chain is still intact.
      if (SE)
        SE->forgetValue(PN);
      PN->replaceAllUsesWith(PN->getIncomingValueForBlock(Preheader));
      PN->eraseFromParent();
    } else if (ULO.Count > 1) {
      if (Reductions.contains(PN))
        continue;

      Value *InVal = PN->removeIncomingValue(LatchBlock, false);
      // If this value was defined in the loop, take the value defined by the
      // last iteration of the loop.
      if (Instruction *InValI = dyn_cast<Instruction>(InVal)) {
        if (L->contains(InValI))
          InVal = LastValueMap[InVal];
      }
      assert(Latches.back() == LastValueMap[LatchBlock] && "bad last latch");
      PN->addIncoming(InVal, Latches.back());
    }
  }

  // Connect latches of the unrolled iterations to the headers of the next
  // iteration. Currently they point to the header of the same iteration.
  for (unsigned i = 0, e = Latches.size(); i != e; ++i) {
    unsigned j = (i + 1) % e;
    Latches[i]->getTerminator()->replaceSuccessorWith(Headers[i], Headers[j]);
  }

  // Remove loop metadata copied from the original loop latch to branches that
  // are no longer latches.
  for (unsigned I = 0, E = Latches.size() - (CompletelyUnroll ? 0 : 1); I < E;
       ++I)
    Latches[I]->getTerminator()->setMetadata(LLVMContext::MD_loop, nullptr);

  // Update dominators of blocks we might reach through exits.
  // Immediate dominator of such block might change, because we add more
  // routes which can lead to the exit: we can now reach it from the copied
  // iterations too.
  if (ULO.Count > 1) {
    for (auto *BB : PostRemainderLoopBlocks) {
      auto *BBDomNode = DT->getNode(BB);
      SmallVector<BasicBlock *, 16> ChildrenToUpdate;
      for (auto *ChildDomNode : BBDomNode->children()) {
        auto *ChildBB = ChildDomNode->getBlock();
        if (!L->contains(ChildBB))
          ChildrenToUpdate.push_back(ChildBB);
      }
      // The new idom of the block will be the nearest common dominator
      // of all copies of the previous idom. This is equivalent to the
      // nearest common dominator of the previous idom and the first latch,
      // which dominates all copies of the previous idom.
      BasicBlock *NewIDom = DT->findNearestCommonDominator(BB, LatchBlock);
      for (auto *ChildBB : ChildrenToUpdate)
        DT->changeImmediateDominator(ChildBB, NewIDom);
    }
  }

  assert(!UnrollVerifyDomtree ||
         DT->verify(DominatorTree::VerificationLevel::Fast));

  SmallVector<DominatorTree::UpdateType> DTUpdates;
  auto SetDest = [&](BasicBlock *Src, bool WillExit, bool ExitOnTrue) {
    auto *Term = cast<CondBrInst>(Src->getTerminator());
    const unsigned Idx = ExitOnTrue ^ WillExit;
    BasicBlock *Dest = Term->getSuccessor(Idx);
    BasicBlock *DeadSucc = Term->getSuccessor(1-Idx);

    // Remove predecessors from all non-Dest successors.
    DeadSucc->removePredecessor(Src, /* KeepOneInputPHIs */ true);

    // Replace the conditional branch with an unconditional one.
    auto *BI = UncondBrInst::Create(Dest, Term->getIterator());
    BI->setDebugLoc(Term->getDebugLoc());
    Term->eraseFromParent();

    DTUpdates.emplace_back(DominatorTree::Delete, Src, DeadSucc);
  };

  auto WillExit = [&](const ExitInfo &Info, unsigned i, unsigned j,
                      bool IsLatch) -> std::optional<bool> {
    if (CompletelyUnroll) {
      if (PreserveOnlyFirst) {
        if (i == 0)
          return std::nullopt;
        return j == 0;
      }
      // Complete (but possibly inexact) unrolling
      if (j == 0)
        return true;
      if (Info.TripCount && j != Info.TripCount)
        return false;
      return std::nullopt;
    }

    if (ULO.Runtime) {
      // If runtime unrolling inserts a prologue, information about non-latch
      // exits may be stale.
      if (IsLatch && j != 0)
        return false;
      return std::nullopt;
    }

    if (j != Info.BreakoutTrip &&
        (Info.TripMultiple == 0 || j % Info.TripMultiple != 0)) {
      // If we know the trip count or a multiple of it, we can safely use an
      // unconditional branch for some iterations.
      return false;
    }
    return std::nullopt;
  };

  // Fold branches for iterations where we know that they will exit or not
  // exit.  In the case of an iteration's latch, if we thus find
  // *OriginalLoopProb is incorrect, set ProbUpdateRequired to true.
  bool ProbUpdateRequired = false;
  for (auto &Pair : ExitInfos) {
    ExitInfo &Info = Pair.second;
    for (unsigned i = 0, e = Info.ExitingBlocks.size(); i != e; ++i) {
      // The branch destination.
      unsigned j = (i + 1) % e;
      bool IsLatch = Pair.first == LatchBlock;
      std::optional<bool> KnownWillExit = WillExit(Info, i, j, IsLatch);
      if (!KnownWillExit) {
        if (!Info.FirstExitingBlock)
          Info.FirstExitingBlock = Info.ExitingBlocks[i];
        continue;
      }

      // We don't fold known-exiting branches for non-latch exits here,
      // because this ensures that both all loop blocks and all exit blocks
      // remain reachable in the CFG.
      // TODO: We could fold these branches, but it would require much more
      // sophisticated updates to LoopInfo.
      if (*KnownWillExit && !IsLatch) {
        if (!Info.FirstExitingBlock)
          Info.FirstExitingBlock = Info.ExitingBlocks[i];
        continue;
      }

      // For a latch, record any OriginalLoopProb contradiction.
      if (!OriginalLoopProb.isUnknown() && IsLatch) {
        BranchProbability ActualProb = *KnownWillExit
                                           ? BranchProbability::getZero()
                                           : BranchProbability::getOne();
        ProbUpdateRequired |= OriginalLoopProb != ActualProb;
      }

      SetDest(Info.ExitingBlocks[i], *KnownWillExit, Info.ExitOnTrue);
    }
  }

  DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy);
  DomTreeUpdater *DTUToUse = &DTU;
  if (ExitingBlocks.size() == 1 && ExitInfos.size() == 1) {
    // Manually update the DT if there's a single exiting node. In that case
    // there's a single exit node and it is sufficient to update the nodes
    // immediately dominated by the original exiting block. They will become
    // dominated by the first exiting block that leaves the loop after
    // unrolling. Note that the CFG inside the loop does not change, so there's
    // no need to update the DT inside the unrolled loop.
    DTUToUse = nullptr;
    auto &[OriginalExit, Info] = *ExitInfos.begin();
    if (!Info.FirstExitingBlock)
      Info.FirstExitingBlock = Info.ExitingBlocks.back();
    for (auto *C : to_vector(DT->getNode(OriginalExit)->children())) {
      if (L->contains(C->getBlock()))
        continue;
      C->setIDom(DT->getNode(Info.FirstExitingBlock));
    }
  } else {
    DTU.applyUpdates(DTUpdates);
  }

  // When completely unrolling, the last latch becomes unreachable.
  if (!LatchIsExiting && CompletelyUnroll) {
    // There is no need to update the DT here, because there must be a unique
    // latch. Hence if the latch is not exiting it must directly branch back to
    // the original loop header and does not dominate any nodes.
    assert(LatchBlock->getSingleSuccessor() && "Loop with multiple latches?");
    changeToUnreachable(Latches.back()->getTerminator(), PreserveLCSSA);
  }

  // After merging adjacent blocks in Latches below:
  // - CondLatches will list the blocks from Latches that are still terminated
  //   with conditional branches.
  // - For 1 <= I < CondLatches.size(), IterCounts[I] will store the number of
  //   the original loop iterations through which control flows from
  //   CondLatches[I-1] to CondLatches[I].
  // - For I == 0 or I == CondLatches.size(), IterCounts[I] will store the
  //   number of the original loop iterations through which control can flow
  //   before CondLatches.front() or after CondLatches.back(), respectively,
  //   without taking the unrolled loop's backedge, if any.
  // - CondLatchNexts[I] will store the CondLatches[I] branch target for the
  //   next of the original loop's iterations (as opposed to the exit target).
  assert(ULO.Count == Latches.size() &&
         "Expected one latch block per unrolled iteration");
  std::vector<unsigned> IterCounts(1, 0);
  std::vector<BasicBlock *> CondLatches;
  std::vector<BasicBlock *> CondLatchNexts;
  IterCounts.reserve(Latches.size() + 1);
  CondLatches.reserve(Latches.size());
  CondLatchNexts.reserve(Latches.size());

  // Merge adjacent basic blocks, if possible.
  for (auto [I, Latch] : enumerate(Latches)) {
    ++IterCounts.back();
    assert((isa<UncondBrInst, CondBrInst>(Latch->getTerminator()) ||
            (CompletelyUnroll && !LatchIsExiting && Latch == Latches.back())) &&
           "Need a branch as terminator, except when fully unrolling with "
           "unconditional latch");
    if (auto *Term = dyn_cast<UncondBrInst>(Latch->getTerminator())) {
      BasicBlock *Dest = Term->getSuccessor();
      BasicBlock *Fold = Dest->getUniquePredecessor();
      if (MergeBlockIntoPredecessor(Dest, /*DTU=*/DTUToUse, LI,
                                    /*MSSAU=*/nullptr, /*MemDep=*/nullptr,
                                    /*PredecessorWithTwoSuccessors=*/false,
                                    DTUToUse ? nullptr : DT)) {
        // Dest has been folded into Fold. Update our worklists accordingly.
        llvm::replace(Latches, Dest, Fold);
        llvm::erase(UnrolledLoopBlocks, Dest);
      }
    } else if (isa<CondBrInst>(Latch->getTerminator())) {
      IterCounts.push_back(0);
      CondLatches.push_back(Latch);
      CondLatchNexts.push_back(Headers[(I + 1) % Latches.size()]);
    }
  }

  // Fix probabilities we contradicted above.
  if (ProbUpdateRequired) {
    fixProbContradiction(L, ULO, ORE, OriginalLoopProb, CompletelyUnroll,
                         IterCounts, CondLatches, CondLatchNexts);
  }

  // If there are partial reductions, create code in the exit block to compute
  // the final result and update users of the final result.
  if (!PartialReductions.empty()) {
    BasicBlock *ExitBlock = L->getExitBlock();
    assert(ExitBlock &&
           "Can only introduce parallel reduction phis with single exit block");
    assert(Reductions.size() == 1 &&
           "currently only a single reduction is supported");
    Value *FinalRdxValue = PartialReductions.back();
    Value *RdxResult = nullptr;
    for (PHINode &Phi : ExitBlock->phis()) {
      if (Phi.getIncomingValueForBlock(L->getLoopLatch()) != FinalRdxValue)
        continue;
      if (!RdxResult) {
        RdxResult = PartialReductions.front();
        IRBuilder Builder(ExitBlock->getFirstNonPHIIt());
        Builder.setFastMathFlags(Reductions.begin()->second.getFastMathFlags());
        RecurKind RK = Reductions.begin()->second.getRecurrenceKind();
        for (Instruction *RdxPart : drop_begin(PartialReductions)) {
          if (RecurrenceDescriptor::isMinMaxRecurrenceKind(RK))
            RdxResult = createMinMaxOp(Builder, RK, RdxResult, RdxPart);
          else
            RdxResult = Builder.CreateBinOp(
                (Instruction::BinaryOps)RecurrenceDescriptor::getOpcode(RK),
                RdxPart, RdxResult, "bin.rdx");
        }
        NeedToFixLCSSA = true;
        for (Instruction *RdxPart : PartialReductions)
          RdxPart->dropPoisonGeneratingFlags();
      }

      Phi.replaceAllUsesWith(RdxResult);
    }
  }

  if (DTUToUse) {
    // Apply updates to the DomTree.
    DT = &DTU.getDomTree();
  }
  assert(!UnrollVerifyDomtree ||
         DT->verify(DominatorTree::VerificationLevel::Fast));

  Loop *OuterL = L->getParentLoop();
  std::vector<BasicBlock *> Blocks;
  // Update LoopInfo if the loop is completely removed.
  if (CompletelyUnroll) {
    Blocks = L->getBlocks();
    LI->erase(L);
    // We shouldn't try to use `L` anymore.
    L = nullptr;
  }

  // At this point, the code is well formed.  We now simplify the unrolled loop,
  // doing constant propagation and dead code elimination as we go.
  simplifyLoopAfterUnroll(
      L, !CompletelyUnroll && ULO.Count > 1, LI, SE, DT, AC, TTI,
      CompletelyUnroll ? ArrayRef<BasicBlock *>(Blocks) : L->getBlocks(), AA);

  NumCompletelyUnrolled += CompletelyUnroll;
  ++NumUnrolled;

  if (!CompletelyUnroll) {
    // Update metadata for the loop's branch weights and estimated trip count:
    // - If ULO.Runtime, UnrollRuntimeLoopRemainder sets the guard branch
    //   weights, latch branch weights, and estimated trip count of the
    //   remainder loop it creates.  It also sets the branch weights for the
    //   unrolled loop guard it creates.  The branch weights for the unrolled
    //   loop latch are adjusted below.  FIXME: Handle prologue loops.
    // - Otherwise, if unrolled loop iteration latches become unconditional,
    //   branch weights are adjusted by the fixProbContradiction call above.
    // - Otherwise, the original loop's branch weights are correct for the
    //   unrolled loop, so do not adjust them.
    // - In all cases, the unrolled loop's estimated trip count is set below.
    //
    // As an example of the last case, consider what happens if the unroll count
    // is 4 for a loop with an estimated trip count of 10 when we do not create
    // a remainder loop and all iterations' latches remain conditional.  Each
    // unrolled iteration's latch still has the same probability of exiting the
    // loop as it did when in the original loop, and thus it should still have
    // the same branch weights.  Each unrolled iteration's non-zero probability
    // of exiting already appropriately reduces the probability of reaching the
    // remaining iterations just as it did in the original loop.  Trying to also
    // adjust the branch weights of the final unrolled iteration's latch (i.e.,
    // the backedge for the unrolled loop as a whole) to reflect its new trip
    // count of 3 will erroneously further reduce its block frequencies.
    // However, in case an analysis later needs to estimate the trip count of
    // the unrolled loop as a whole without considering the branch weights for
    // each unrolled iteration's latch within it, we store the new trip count as
    // separate metadata.
    if (!OriginalLoopProb.isUnknown() && ULO.Runtime && EpilogProfitability) {
      assert((CondLatches.size() == 1 &&
              (ProbUpdateRequired || OriginalLoopProb.isOne())) &&
             "Expected ULO.Runtime to give unrolled loop 1 conditional latch, "
             "the backedge, requiring a probability update unless infinite");
      // Where p is always the probability of executing at least 1 more
      // iteration, the probability for at least n more iterations is p^n.
      setLoopProbability(L, OriginalLoopProb.pow(ULO.Count));
    }
    if (OriginalTripCount) {
      unsigned NewTripCount = *OriginalTripCount / ULO.Count;
      if (!ULO.Runtime && *OriginalTripCount % ULO.Count)
        ++NewTripCount;
      setLoopEstimatedTripCount(L, NewTripCount);
    }
  }

  // LoopInfo should not be valid, confirm that.
  if (UnrollVerifyLoopInfo)
    LI->verify();

  // After complete unrolling most of the blocks should be contained in OuterL.
  // However, some of them might happen to be out of OuterL (e.g. if they
  // precede a loop exit). In this case we might need to insert PHI nodes in
  // order to preserve LCSSA form.
  // We don't need to check this if we already know that we need to fix LCSSA
  // form.
  // TODO: For now we just recompute LCSSA for the outer loop in this case, but
  // it should be possible to fix it in-place.
  if (PreserveLCSSA && OuterL && CompletelyUnroll && !NeedToFixLCSSA)
    NeedToFixLCSSA |= ::needToInsertPhisForLCSSA(OuterL, UnrolledLoopBlocks, LI);

  // Make sure that loop-simplify form is preserved. We want to simplify
  // at least one layer outside of the loop that was unrolled so that any
  // changes to the parent loop exposed by the unrolling are considered.
  if (OuterL) {
    // OuterL includes all loops for which we can break loop-simplify, so
    // it's sufficient to simplify only it (it'll recursively simplify inner
    // loops too).
    if (NeedToFixLCSSA) {
      // LCSSA must be performed on the outermost affected loop. The unrolled
      // loop's last loop latch is guaranteed to be in the outermost loop
      // after LoopInfo's been updated by LoopInfo::erase.
      Loop *LatchLoop = LI->getLoopFor(Latches.back());
      Loop *FixLCSSALoop = OuterL;
      if (!FixLCSSALoop->contains(LatchLoop))
        while (FixLCSSALoop->getParentLoop() != LatchLoop)
          FixLCSSALoop = FixLCSSALoop->getParentLoop();

      formLCSSARecursively(*FixLCSSALoop, *DT, LI, SE);
    } else if (PreserveLCSSA) {
      assert(OuterL->isLCSSAForm(*DT) &&
             "Loops should be in LCSSA form after loop-unroll.");
    }

    // TODO: That potentially might be compile-time expensive. We should try
    // to fix the loop-simplified form incrementally.
    simplifyLoop(OuterL, DT, LI, SE, AC, nullptr, PreserveLCSSA);
  } else {
    // Simplify loops for which we might've broken loop-simplify form.
    for (Loop *SubLoop : LoopsToSimplify)
      simplifyLoop(SubLoop, DT, LI, SE, AC, nullptr, PreserveLCSSA);
  }

  return CompletelyUnroll ? LoopUnrollResult::FullyUnrolled
                          : LoopUnrollResult::PartiallyUnrolled;
}

/// Given an llvm.loop loop id metadata node, returns the loop hint metadata
/// node with the given name (for example, "llvm.loop.unroll.count"). If no
/// such metadata node exists, then nullptr is returned.
MDNode *llvm::GetUnrollMetadata(MDNode *LoopID, StringRef Name) {
  // First operand should refer to the loop id itself.
  assert(LoopID->getNumOperands() > 0 && "requires at least one operand");
  assert(LoopID->getOperand(0) == LoopID && "invalid loop id");

  for (MDNode *MD :
       make_isa_range<MDNode>(llvm::drop_begin(LoopID->operands()))) {
    MDString *S = dyn_cast<MDString>(MD->getOperand(0));
    if (!S)
      continue;

    if (Name == S->getString())
      return MD;
  }
  return nullptr;
}

// Returns the loop hint metadata node with the given name (for example,
// "llvm.loop.unroll.count").  If no such metadata node exists, then nullptr is
// returned.
MDNode *llvm::getUnrollMetadataForLoop(const Loop *L, StringRef Name) {
  if (MDNode *LoopID = L->getLoopID())
    return GetUnrollMetadata(LoopID, Name);
  return nullptr;
}

std::optional<RecurrenceDescriptor>
llvm::canParallelizeReductionWhenUnrolling(PHINode &Phi, Loop *L,
                                           ScalarEvolution *SE) {
  RecurrenceDescriptor RdxDesc;
  if (!RecurrenceDescriptor::isReductionPHI(&Phi, L, RdxDesc,
                                            /*DemandedBits=*/nullptr,
                                            /*AC=*/nullptr, /*DT=*/nullptr, SE))
    return std::nullopt;
  if (RdxDesc.hasUsesOutsideReductionChain())
    return std::nullopt;
  RecurKind RK = RdxDesc.getRecurrenceKind();
  static const auto ValidRKs = {
      RecurKind::Add,         RecurKind::Mul,      RecurKind::Or,
      RecurKind::And,         RecurKind::Xor,      RecurKind::SMin,
      RecurKind::SMax,        RecurKind::UMin,     RecurKind::UMax,
      RecurKind::FAdd,        RecurKind::FMul,     RecurKind::FMin,
      RecurKind::FMax,        RecurKind::FMinNum,  RecurKind::FMaxNum,
      RecurKind::FMinimum,    RecurKind::FMaximum, RecurKind::FMinimumNum,
      RecurKind::FMaximumNum, RecurKind::FMulAdd};
  // Skip unsupported reductions, including sub, any-of and find-last.
  // TODO: Handle sub, any-of and find-last reductions.
  if (!any_of(ValidRKs, equal_to(RK)))
    return std::nullopt;

  if (RdxDesc.hasExactFPMath())
    return std::nullopt;

  if (RdxDesc.IntermediateStore)
    return std::nullopt;

  BasicBlock *Latch = L->getLoopLatch();
  if (!Latch)
    return std::nullopt;
  Instruction *LatchInst =
      cast<Instruction>(Phi.getIncomingValueForBlock(Latch));
  // Don't unroll reductions with constant ops; those can be folded to a
  // single induction update. For calls (e.g. fmuladd or min/max
  // intrinsics), the called function is itself a Constant operand and is
  // not a reduction operand, so restrict the check to the argument list.
  auto Ops = isa<CallBase>(LatchInst) ? cast<CallBase>(LatchInst)->args()
                                      : LatchInst->operands();
  if (any_of(Ops, IsaPred<Constant>))
    return std::nullopt;

  if (!is_contained(LatchInst->operands(), &Phi))
    return std::nullopt;

  return RdxDesc;
}
