//===-- 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>
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)) {
            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);
  }
}

// Loops containing convergent instructions that are uncontrolled or controlled
// from outside the loop must have a count that divides their TripMultiple.
LLVM_ATTRIBUTE_USED
static bool canHaveUnrollRemainder(const Loop *L) {
  if (getLoopConvergenceHeart(L))
    return false;

  // Check for uncontrolled convergent operations.
  for (auto &BB : L->blocks()) {
    for (auto &I : *BB) {
      if (isa<ConvergenceControlInst>(I))
        return true;
      if (auto *CB = dyn_cast<CallBase>(&I))
        if (CB->isConvergent())
          return CB->getConvergenceControlToken();
    }
  }
  return true;
}

// 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, this function just quickly hacks a few of their probabilities to
// restore the original total loop body frequency.  Otherwise, it determines
// 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 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:
  // - 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 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.
  // - For n <= 2, we can use simple formulas to solve the above polynomial
  //   equations exactly for p without performing a search.

  // When iterating for a solution, we stop early if we find probabilities
  // that produce a Freq whose 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 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;
    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);
    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.
  if (CondLatches.size() == 1) {
    SetAllProbs(ComputeProbForLinear());
  } else if (CondLatches.size() == 2) {
    SetAllProbs(ComputeProbForQuadratic());
  } else {
    // The polynomial is too complex for a simple formula, so 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) < FreqPrec)
        break;
    }
  }

  // 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);
  std::vector<BasicBlock *> OriginalLoopBlocks = L->getBlocks();

  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();

  // 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 (!I.isDebugOrPseudoInst())
          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) {
      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 : OriginalLoopBlocks) {
      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, 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(*DT);

  // 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 (const MDOperand &MDO : llvm::drop_begin(LoopID->operands())) {
    MDNode *MD = dyn_cast<MDNode>(MDO);
    if (!MD)
      continue;

    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();
  // Skip unsupported reductions.
  // TODO: Handle any-of and find-last reductions.
  if (RecurrenceDescriptor::isAnyOfRecurrenceKind(RK) ||
      RecurrenceDescriptor::isFindRecurrenceKind(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;
}
