//===----------------- LoopRotationUtils.cpp -----------------------------===//
//
// 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 provides utilities to convert a loop into a loop with bottom test.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/Utils/LoopRotationUtils.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/AssumptionCache.h"
#include "llvm/Analysis/CodeMetrics.h"
#include "llvm/Analysis/DomTreeUpdater.h"
#include "llvm/Analysis/InstructionSimplify.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/MemorySSA.h"
#include "llvm/Analysis/MemorySSAUpdater.h"
#include "llvm/Analysis/ScalarEvolution.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/IR/CFG.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/MDBuilder.h"
#include "llvm/IR/ProfDataUtils.h"
#include "llvm/Support/Debug.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/SSAUpdater.h"
#include "llvm/Transforms/Utils/ValueMapper.h"
using namespace llvm;

#define DEBUG_TYPE "loop-rotate"

STATISTIC(NumNotRotatedDueToHeaderSize,
          "Number of loops not rotated due to the header size");
STATISTIC(NumInstrsHoisted,
          "Number of instructions hoisted into loop preheader");
STATISTIC(NumInstrsDuplicated,
          "Number of instructions cloned into loop preheader");

// Probability that a rotated loop has zero trip count / is never entered.
static constexpr uint32_t ZeroTripCountWeights[] = {1, 127};

namespace {
/// A simple loop rotation transformation.
class LoopRotate {
  const unsigned MaxHeaderSize;
  LoopInfo *LI;
  const TargetTransformInfo *TTI;
  AssumptionCache *AC;
  DominatorTree *DT;
  ScalarEvolution *SE;
  MemorySSAUpdater *MSSAU;
  const SimplifyQuery &SQ;
  bool RotationOnly;
  bool IsUtilMode;
  bool PrepareForLTO;
  bool CheckExitCount;

public:
  LoopRotate(unsigned MaxHeaderSize, LoopInfo *LI,
             const TargetTransformInfo *TTI, AssumptionCache *AC,
             DominatorTree *DT, ScalarEvolution *SE, MemorySSAUpdater *MSSAU,
             const SimplifyQuery &SQ, bool RotationOnly, bool IsUtilMode,
             bool PrepareForLTO, bool CheckExitCount)
      : MaxHeaderSize(MaxHeaderSize), LI(LI), TTI(TTI), AC(AC), DT(DT), SE(SE),
        MSSAU(MSSAU), SQ(SQ), RotationOnly(RotationOnly),
        IsUtilMode(IsUtilMode), PrepareForLTO(PrepareForLTO),
        CheckExitCount(CheckExitCount) {}
  bool processLoop(Loop *L);

private:
  bool rotateLoop(Loop *L, bool SimplifiedLatch);
  bool simplifyLoopLatch(Loop *L);
};
} // end anonymous namespace

/// Insert (K, V) pair into the ValueToValueMap, and verify the key did not
/// previously exist in the map, and the value was inserted.
static void InsertNewValueIntoMap(ValueToValueMapTy &VM, Value *K, Value *V) {
  bool Inserted = VM.insert({K, V}).second;
  assert(Inserted);
  (void)Inserted;
}
/// RewriteUsesOfClonedInstructions - We just cloned the instructions from the
/// old header into the preheader.  If there were uses of the values produced by
/// these instruction that were outside of the loop, we have to insert PHI nodes
/// to merge the two values.  Do this now.
static void RewriteUsesOfClonedInstructions(BasicBlock *OrigHeader,
                                            BasicBlock *OrigPreheader,
                                            ValueToValueMapTy &ValueMap,
                                            ScalarEvolution *SE,
                                SmallVectorImpl<PHINode*> *InsertedPHIs) {
  // Remove PHI node entries that are no longer live.
  BasicBlock::iterator I, E = OrigHeader->end();
  for (I = OrigHeader->begin(); PHINode *PN = dyn_cast<PHINode>(I); ++I)
    PN->removeIncomingValue(OrigPreheader);

  // Now fix up users of the instructions in OrigHeader, inserting PHI nodes
  // as necessary.
  SSAUpdater SSA(InsertedPHIs);
  for (I = OrigHeader->begin(); I != E; ++I) {
    Value *OrigHeaderVal = &*I;

    // If there are no uses of the value (e.g. because it returns void), there
    // is nothing to rewrite.
    if (OrigHeaderVal->use_empty())
      continue;

    Value *OrigPreHeaderVal = ValueMap.lookup(OrigHeaderVal);

    // The value now exits in two versions: the initial value in the preheader
    // and the loop "next" value in the original header.
    SSA.Initialize(OrigHeaderVal->getType(), OrigHeaderVal->getName());
    // Force re-computation of OrigHeaderVal, as some users now need to use the
    // new PHI node.
    if (SE)
      SE->forgetValue(OrigHeaderVal);
    SSA.AddAvailableValue(OrigHeader, OrigHeaderVal);
    SSA.AddAvailableValue(OrigPreheader, OrigPreHeaderVal);

    // Visit each use of the OrigHeader instruction.
    for (Use &U : llvm::make_early_inc_range(OrigHeaderVal->uses())) {
      // SSAUpdater can't handle a non-PHI use in the same block as an
      // earlier def. We can easily handle those cases manually.
      Instruction *UserInst = cast<Instruction>(U.getUser());
      if (!isa<PHINode>(UserInst)) {
        BasicBlock *UserBB = UserInst->getParent();

        // The original users in the OrigHeader are already using the
        // original definitions.
        if (UserBB == OrigHeader)
          continue;

        // Users in the OrigPreHeader need to use the value to which the
        // original definitions are mapped.
        if (UserBB == OrigPreheader) {
          U = OrigPreHeaderVal;
          continue;
        }
      }

      // Anything else can be handled by SSAUpdater.
      SSA.RewriteUse(U);
    }

    // Replace MetadataAsValue(ValueAsMetadata(OrigHeaderVal)) uses in debug
    // intrinsics.
    SmallVector<DbgVariableRecord *, 1> DbgVariableRecords;
    llvm::findDbgValues(OrigHeaderVal, DbgVariableRecords);

    for (DbgVariableRecord *DVR : DbgVariableRecords) {
      // The original users in the OrigHeader are already using the original
      // definitions.
      BasicBlock *UserBB = DVR->getMarker()->getParent();
      if (UserBB == OrigHeader)
        continue;

      // Users in the OrigPreHeader need to use the value to which the
      // original definitions are mapped and anything else can be handled by
      // the SSAUpdater. To avoid adding PHINodes, check if the value is
      // available in UserBB, if not substitute poison.
      Value *NewVal;
      if (UserBB == OrigPreheader)
        NewVal = OrigPreHeaderVal;
      else if (SSA.HasValueForBlock(UserBB))
        NewVal = SSA.GetValueInMiddleOfBlock(UserBB);
      else
        NewVal = PoisonValue::get(OrigHeaderVal->getType());
      DVR->replaceVariableLocationOp(OrigHeaderVal, NewVal);
    }
  }
}

// Assuming both header and latch are exiting, check if rotating is profitable:
// either a header phi becomes dead, or rotating makes the latch exit count
// computable (enabling downstream optimizations like unrolling/vectorization).
static bool profitableToRotateLoopExitingLatch(Loop *L, ScalarEvolution *SE) {
  BasicBlock *Header = L->getHeader();
  BasicBlock *Latch = L->getLoopLatch();
  CondBrInst *BI = dyn_cast<CondBrInst>(Header->getTerminator());
  BasicBlock *HeaderExit = BI->getSuccessor(0);
  if (L->contains(HeaderExit))
    HeaderExit = BI->getSuccessor(1);

  for (auto &Phi : Header->phis()) {
    // Look for uses of this phi in the loop/via exits other than the header.
    if (llvm::any_of(Phi.users(), [HeaderExit](const User *U) {
          return cast<Instruction>(U)->getParent() != HeaderExit;
        }))
      continue;
    return true;
  }

  // Check if rotating would make the latch exit count computable, enabling
  // optimizations like runtime unrolling and vectorization.
  if (SE && isa<SCEVCouldNotCompute>(SE->getExitCount(L, Latch)) &&
      !isa<SCEVCouldNotCompute>(SE->getExitCount(L, Header)))
    return true;

  return false;
}

static void updateBranchWeights(CondBrInst &PreHeaderBI, CondBrInst &LoopBI,
                                bool HasConditionalPreHeader,
                                bool SuccsSwapped) {
  MDNode *WeightMD = getBranchWeightMDNode(PreHeaderBI);
  if (WeightMD == nullptr)
    return;

  // LoopBI should currently be a clone of PreHeaderBI with the same
  // metadata. But we double check to make sure we don't have a degenerate case
  // where instsimplify changed the instructions.
  if (WeightMD != getBranchWeightMDNode(LoopBI))
    return;

  SmallVector<uint32_t, 2> Weights;
  extractFromBranchWeightMD32(WeightMD, Weights);
  if (Weights.size() != 2)
    return;
  uint32_t OrigLoopExitWeight = Weights[0];
  uint32_t OrigLoopBackedgeWeight = Weights[1];

  if (SuccsSwapped)
    std::swap(OrigLoopExitWeight, OrigLoopBackedgeWeight);

  // Update branch weights. Consider the following edge-counts:
  //
  //    |  |--------             |
  //    V  V       |             V
  //   Br i1 ...   |            Br i1 ...
  //   |       |   |            |     |
  //  x|      y|   |  becomes:  |   y0|  |-----
  //   V       V   |            |     V  V    |
  // Exit    Loop  |            |    Loop     |
  //           |   |            |   Br i1 ... |
  //           -----            |   |      |  |
  //                          x0| x1|   y1 |  |
  //                            V   V      ----
  //                            Exit
  //
  // The following must hold:
  //  -  x == x0 + x1        # counts to "exit" must stay the same.
  //  - y0 == x - x0 == x1   # how often loop was entered at all.
  //  - y1 == y - y0         # How often loop was repeated (after first iter.).
  //
  // We cannot generally deduce how often we had a zero-trip count loop so we
  // have to make a guess for how to distribute x among the new x0 and x1.

  uint32_t ExitWeight0;    // aka x0
  uint32_t ExitWeight1;    // aka x1
  uint32_t EnterWeight;    // aka y0
  uint32_t LoopBackWeight; // aka y1
  if (OrigLoopExitWeight > 0 && OrigLoopBackedgeWeight > 0) {
    ExitWeight0 = 0;
    if (HasConditionalPreHeader) {
      // Here we cannot know how many 0-trip count loops we have, so we guess:
      if (OrigLoopBackedgeWeight >= OrigLoopExitWeight) {
        // If the loop count is bigger than the exit count then we set
        // probabilities as if 0-trip count nearly never happens.
        ExitWeight0 = ZeroTripCountWeights[0];
        // Scale up counts if necessary so we can match `ZeroTripCountWeights`
        // for the `ExitWeight0`:`ExitWeight1` (aka `x0`:`x1` ratio`) ratio.
        while (OrigLoopExitWeight < ZeroTripCountWeights[1] + ExitWeight0) {
          // ... but don't overflow.
          uint32_t const HighBit = uint32_t{1} << (sizeof(uint32_t) * 8 - 1);
          if ((OrigLoopBackedgeWeight & HighBit) != 0 ||
              (OrigLoopExitWeight & HighBit) != 0)
            break;
          OrigLoopBackedgeWeight <<= 1;
          OrigLoopExitWeight <<= 1;
        }
      } else {
        // If there's a higher exit-count than backedge-count then we set
        // probabilities as if there are only 0-trip and 1-trip cases.
        ExitWeight0 = OrigLoopExitWeight - OrigLoopBackedgeWeight;
      }
    } else {
      // Theoretically, if the loop body must be executed at least once, the
      // backedge count must be not less than exit count. However the branch
      // weight collected by sampling-based PGO may be not very accurate due to
      // sampling. Therefore this workaround is required here to avoid underflow
      // of unsigned in following update of branch weight.
      if (OrigLoopExitWeight > OrigLoopBackedgeWeight)
        OrigLoopBackedgeWeight = OrigLoopExitWeight;
    }
    assert(OrigLoopExitWeight >= ExitWeight0 && "Bad branch weight");
    ExitWeight1 = OrigLoopExitWeight - ExitWeight0;
    EnterWeight = ExitWeight1;
    assert(OrigLoopBackedgeWeight >= EnterWeight && "Bad branch weight");
    LoopBackWeight = OrigLoopBackedgeWeight - EnterWeight;
  } else if (OrigLoopExitWeight == 0) {
    if (OrigLoopBackedgeWeight == 0) {
      // degenerate case... keep everything zero...
      ExitWeight0 = 0;
      ExitWeight1 = 0;
      EnterWeight = 0;
      LoopBackWeight = 0;
    } else {
      // Special case "LoopExitWeight == 0" weights which behaves like an
      // endless where we don't want loop-enttry (y0) to be the same as
      // loop-exit (x1).
      ExitWeight0 = 0;
      ExitWeight1 = 0;
      EnterWeight = 1;
      LoopBackWeight = OrigLoopBackedgeWeight;
    }
  } else {
    // loop is never entered.
    assert(OrigLoopBackedgeWeight == 0 && "remaining case is backedge zero");
    ExitWeight0 = 1;
    ExitWeight1 = 1;
    EnterWeight = 0;
    LoopBackWeight = 0;
  }

  const uint32_t LoopBIWeights[] = {
      SuccsSwapped ? LoopBackWeight : ExitWeight1,
      SuccsSwapped ? ExitWeight1 : LoopBackWeight,
  };
  setBranchWeights(LoopBI, LoopBIWeights, /*IsExpected=*/false);
  if (HasConditionalPreHeader) {
    const uint32_t PreHeaderBIWeights[] = {
        SuccsSwapped ? EnterWeight : ExitWeight0,
        SuccsSwapped ? ExitWeight0 : EnterWeight,
    };
    setBranchWeights(PreHeaderBI, PreHeaderBIWeights, /*IsExpected=*/false);
  }
}

/// Rotate loop LP. Return true if the loop is rotated.
///
/// \param SimplifiedLatch is true if the latch was just folded into the final
/// loop exit. In this case we may want to rotate even though the new latch is
/// now an exiting branch. This rotation would have happened had the latch not
/// been simplified. However, if SimplifiedLatch is false, then we avoid
/// rotating loops in which the latch exits to avoid excessive or endless
/// rotation. LoopRotate should be repeatable and converge to a canonical
/// form. This property is satisfied because simplifying the loop latch can only
/// happen once across multiple invocations of the LoopRotate pass.
bool LoopRotate::rotateLoop(Loop *L, bool SimplifiedLatch) {
  // If the loop has only one block then there is not much to rotate.
  if (L->getBlocks().size() == 1)
    return false;

  bool Rotated = false;
  BasicBlock *OrigHeader = L->getHeader();
  BasicBlock *OrigLatch = L->getLoopLatch();

  CondBrInst *BI = dyn_cast<CondBrInst>(OrigHeader->getTerminator());
  if (!BI)
    return Rotated;

  // If the loop header is not one of the loop exiting blocks then
  // either this loop is already rotated or it is not
  // suitable for loop rotation transformations.
  if (!L->isLoopExiting(OrigHeader))
    return Rotated;

  // If the loop latch already contains a branch that leaves the loop then the
  // loop is already rotated.
  if (!OrigLatch)
    return Rotated;

  // Rotate if the loop latch was just simplified. Or if it makes the loop exit
  // count computable. Or if we think it will be profitable.
  if (L->isLoopExiting(OrigLatch) && !SimplifiedLatch && IsUtilMode == false &&
      !profitableToRotateLoopExitingLatch(L, CheckExitCount ? SE : nullptr))
    return Rotated;

  // Check size of original header and reject loop if it is very big or we can't
  // duplicate blocks inside it.
  {
    SmallPtrSet<const Value *, 32> EphValues;
    CodeMetrics::collectEphemeralValues(L, AC, EphValues);

    CodeMetrics Metrics;
    Metrics.analyzeBasicBlock(OrigHeader, *TTI, EphValues, PrepareForLTO);
    if (Metrics.notDuplicatable) {
      LLVM_DEBUG(
          dbgs() << "LoopRotation: NOT rotating - contains non-duplicatable"
                 << " instructions: ";
          L->dump());
      return Rotated;
    }
    if (Metrics.Convergence != ConvergenceKind::None) {
      LLVM_DEBUG(dbgs() << "LoopRotation: NOT rotating - contains convergent "
                           "instructions: ";
                 L->dump());
      return Rotated;
    }
    if (!Metrics.NumInsts.isValid()) {
      LLVM_DEBUG(dbgs() << "LoopRotation: NOT rotating - contains instructions"
                           " with invalid cost: ";
                 L->dump());
      return Rotated;
    }
    if (Metrics.NumInsts > MaxHeaderSize) {
      LLVM_DEBUG(dbgs() << "LoopRotation: NOT rotating - contains "
                        << Metrics.NumInsts
                        << " instructions, which is more than the threshold ("
                        << MaxHeaderSize << " instructions): ";
                 L->dump());
      ++NumNotRotatedDueToHeaderSize;
      return Rotated;
    }

    // When preparing for LTO, avoid rotating loops with calls that could be
    // inlined during the LTO stage.
    if (PrepareForLTO && Metrics.NumInlineCandidates > 0)
      return Rotated;
  }

  // Now, this loop is suitable for rotation.
  BasicBlock *OrigPreheader = L->getLoopPreheader();

  // If the loop could not be converted to canonical form, it must have an
  // indirectbr in it, just give up.
  if (!OrigPreheader || !L->hasDedicatedExits())
    return Rotated;

  // Anything ScalarEvolution may know about this loop or the PHI nodes
  // in its header will soon be invalidated. We should also invalidate
  // all outer loops because insertion and deletion of blocks that happens
  // during the rotation may violate invariants related to backedge taken
  // infos in them.
  if (SE) {
    SE->forgetTopmostLoop(L);
    // We may hoist some instructions out of loop. In case if they were cached
    // as "loop variant" or "loop computable", these caches must be dropped.
    // We also may fold basic blocks, so cached block dispositions also need
    // to be dropped.
    SE->forgetBlockAndLoopDispositions();
  }

  LLVM_DEBUG(dbgs() << "LoopRotation: rotating "; L->dump());
  if (MSSAU && VerifyMemorySSA)
    MSSAU->getMemorySSA()->verifyMemorySSA();

  // Find new Loop header. NewHeader is a Header's one and only successor
  // that is inside loop.  Header's other successor is outside the
  // loop.  Otherwise loop is not suitable for rotation.
  BasicBlock *Exit = BI->getSuccessor(0);
  BasicBlock *NewHeader = BI->getSuccessor(1);
  bool BISuccsSwapped = L->contains(Exit);
  if (BISuccsSwapped)
    std::swap(Exit, NewHeader);
  assert(NewHeader && "Unable to determine new loop header");
  assert(L->contains(NewHeader) && !L->contains(Exit) &&
         "Unable to determine loop header and exit blocks");

  // This code assumes that the new header has exactly one predecessor.
  // Remove any single-entry PHI nodes in it.
  assert(NewHeader->getSinglePredecessor() &&
         "New header doesn't have one pred!");
  FoldSingleEntryPHINodes(NewHeader);

  // Begin by walking OrigHeader and populating ValueMap with an entry for
  // each Instruction.
  BasicBlock::iterator I = OrigHeader->begin(), E = OrigHeader->end();
  ValueToValueMapTy ValueMap, ValueMapMSSA;

  // For PHI nodes, the value available in OldPreHeader is just the
  // incoming value from OldPreHeader.
  for (; PHINode *PN = dyn_cast<PHINode>(I); ++I)
    InsertNewValueIntoMap(ValueMap, PN,
                          PN->getIncomingValueForBlock(OrigPreheader));

  // For the rest of the instructions, either hoist to the OrigPreheader if
  // possible or create a clone in the OldPreHeader if not.
  Instruction *LoopEntryBranch = OrigPreheader->getTerminator();

  // Record all debug records preceding LoopEntryBranch to avoid
  // duplication.
  using DbgHash =
      std::pair<std::pair<hash_code, DILocalVariable *>, DIExpression *>;
  auto makeHash = [](const DbgVariableRecord *D) -> DbgHash {
    auto VarLocOps = D->location_ops();
    return {{hash_combine_range(VarLocOps), D->getVariable()},
            D->getExpression()};
  };

  SmallDenseSet<DbgHash, 8> DbgRecords;
  // Build DbgVariableRecord hashes for DbgVariableRecords attached to the
  // terminator.
  for (const DbgVariableRecord &DVR :
       filterDbgVars(OrigPreheader->getTerminator()->getDbgRecordRange()))
    DbgRecords.insert(makeHash(&DVR));

  // Remember the local noalias scope declarations in the header. After the
  // rotation, they must be duplicated and the scope must be cloned. This
  // avoids unwanted interaction across iterations.
  SmallVector<NoAliasScopeDeclInst *, 6> NoAliasDeclInstructions;
  for (Instruction &I : *OrigHeader)
    if (auto *Decl = dyn_cast<NoAliasScopeDeclInst>(&I))
      NoAliasDeclInstructions.push_back(Decl);

  Module *M = OrigHeader->getModule();

  // Track the next DbgRecord to clone. If we have a sequence where an
  // instruction is hoisted instead of being cloned:
  //    DbgRecord blah
  //    %foo = add i32 0, 0
  //    DbgRecord xyzzy
  //    %bar = call i32 @foobar()
  // where %foo is hoisted, then the DbgRecord "blah" will be seen twice, once
  // attached to %foo, then when %foo his hoisted it will "fall down" onto the
  // function call:
  //    DbgRecord blah
  //    DbgRecord xyzzy
  //    %bar = call i32 @foobar()
  // causing it to appear attached to the call too.
  //
  // To avoid this, cloneDebugInfoFrom takes an optional "start cloning from
  // here" position to account for this behaviour. We point it at any
  // DbgRecords on the next instruction, here labelled xyzzy, before we hoist
  // %foo. Later, we only only clone DbgRecords from that position (xyzzy)
  // onwards, which avoids cloning DbgRecord "blah" multiple times. (Stored as
  // a range because it gives us a natural way of testing whether
  //  there were DbgRecords on the next instruction before we hoisted things).
  iterator_range<DbgRecord::self_iterator> NextDbgInsts =
      (I != E) ? I->getDbgRecordRange() : DbgMarker::getEmptyDbgRecordRange();

  while (I != E) {
    Instruction *Inst = &*I++;

    // If the instruction's operands are invariant and it doesn't read or write
    // memory, then it is safe to hoist.  Doing this doesn't change the order of
    // execution in the preheader, but does prevent the instruction from
    // executing in each iteration of the loop.  This means it is safe to hoist
    // something that might trap, but isn't safe to hoist something that reads
    // memory (without proving that the loop doesn't write).
    if (L->hasLoopInvariantOperands(Inst) && !Inst->mayReadFromMemory() &&
        !Inst->mayWriteToMemory() && !Inst->isTerminator() &&
        !isa<AllocaInst>(Inst) &&
        // It is not safe to hoist the value of these instructions in
        // coroutines, as the addresses of otherwise eligible variables (e.g.
        // thread-local variables and errno) may change if the coroutine is
        // resumed in a different thread.Therefore, we disable this
        // optimization for correctness. However, this may block other correct
        // optimizations.
        // FIXME: This should be reverted once we have a better model for
        // memory access in coroutines.
        !Inst->getFunction()->isPresplitCoroutine()) {

      if (!NextDbgInsts.empty()) {
        auto DbgValueRange =
            LoopEntryBranch->cloneDebugInfoFrom(Inst, NextDbgInsts.begin());
        RemapDbgRecordRange(M, DbgValueRange, ValueMap,
                            RF_NoModuleLevelChanges | RF_IgnoreMissingLocals);
        // Erase anything we've seen before.
        for (DbgVariableRecord &DVR :
             make_early_inc_range(filterDbgVars(DbgValueRange)))
          if (DbgRecords.count(makeHash(&DVR)))
            DVR.eraseFromParent();
      }

      NextDbgInsts = I->getDbgRecordRange();

      Inst->moveBefore(LoopEntryBranch->getIterator());

      ++NumInstrsHoisted;
      continue;
    }

    // Otherwise, create a duplicate of the instruction.
    Instruction *C = Inst->clone();
    if (const DebugLoc &DL = C->getDebugLoc())
      mapAtomInstance(DL, ValueMap);

    C->insertBefore(LoopEntryBranch->getIterator());

    ++NumInstrsDuplicated;

    if (!NextDbgInsts.empty()) {
      auto Range = C->cloneDebugInfoFrom(Inst, NextDbgInsts.begin());
      RemapDbgRecordRange(M, Range, ValueMap,
                          RF_NoModuleLevelChanges | RF_IgnoreMissingLocals);
      NextDbgInsts = DbgMarker::getEmptyDbgRecordRange();
      // Erase anything we've seen before.
      for (DbgVariableRecord &DVR : make_early_inc_range(filterDbgVars(Range)))
        if (DbgRecords.count(makeHash(&DVR)))
          DVR.eraseFromParent();
    }

    // Eagerly remap the operands of the instruction.
    RemapInstruction(C, ValueMap,
                     RF_NoModuleLevelChanges | RF_IgnoreMissingLocals);

    // With the operands remapped, see if the instruction constant folds or is
    // otherwise simplifyable.  This commonly occurs because the entry from PHI
    // nodes allows icmps and other instructions to fold.
    Value *V = simplifyInstruction(C, SQ);
    if (V && LI->replacementPreservesLCSSAForm(C, V)) {
      // If so, then delete the temporary instruction and stick the folded value
      // in the map.
      InsertNewValueIntoMap(ValueMap, Inst, V);
      if (!C->mayHaveSideEffects()) {
        C->eraseFromParent();
        C = nullptr;
      }
    } else {
      InsertNewValueIntoMap(ValueMap, Inst, C);
    }
    if (C) {
      // Otherwise, stick the new instruction into the new block!
      C->setName(Inst->getName());

      if (auto *II = dyn_cast<AssumeInst>(C))
        AC->registerAssumption(II);
      // MemorySSA cares whether the cloned instruction was inserted or not, and
      // not whether it can be remapped to a simplified value.
      if (MSSAU)
        InsertNewValueIntoMap(ValueMapMSSA, Inst, C);
    }
  }

  if (!NoAliasDeclInstructions.empty()) {
    // There are noalias scope declarations:
    // (general):
    // Original:    OrigPre              { OrigHeader NewHeader ... Latch }
    // after:      (OrigPre+OrigHeader') { NewHeader ... Latch OrigHeader }
    //
    // with D: llvm.experimental.noalias.scope.decl,
    //      U: !noalias or !alias.scope depending on D
    //       ... { D U1 U2 }   can transform into:
    // (0) : ... { D U1 U2 }        // no relevant rotation for this part
    // (1) : ... D' { U1 U2 D }     // D is part of OrigHeader
    // (2) : ... D' U1' { U2 D U1 } // D, U1 are part of OrigHeader
    //
    // We now want to transform:
    // (1) -> : ... D' { D U1 U2 D'' }
    // (2) -> : ... D' U1' { D U2 D'' U1'' }
    // D: original llvm.experimental.noalias.scope.decl
    // D', U1': duplicate with replaced scopes
    // D'', U1'': different duplicate with replaced scopes
    // This ensures a safe fallback to 'may_alias' introduced by the rotate,
    // as U1'' and U1' scopes will not be compatible wrt to the local restrict

    // Clone the llvm.experimental.noalias.decl again for the NewHeader.
    BasicBlock::iterator NewHeaderInsertionPoint =
        NewHeader->getFirstNonPHIIt();
    for (NoAliasScopeDeclInst *NAD : NoAliasDeclInstructions) {
      LLVM_DEBUG(dbgs() << "  Cloning llvm.experimental.noalias.scope.decl:"
                        << *NAD << "\n");
      Instruction *NewNAD = NAD->clone();
      NewNAD->insertBefore(*NewHeader, NewHeaderInsertionPoint);
    }

    // Scopes must now be duplicated, once for OrigHeader and once for
    // OrigPreHeader'.
    {
      auto &Context = NewHeader->getContext();

      SmallVector<MDNode *, 8> NoAliasDeclScopes;
      for (NoAliasScopeDeclInst *NAD : NoAliasDeclInstructions)
        NoAliasDeclScopes.push_back(NAD->getScopeList());

      LLVM_DEBUG(dbgs() << "  Updating OrigHeader scopes\n");
      cloneAndAdaptNoAliasScopes(NoAliasDeclScopes, {OrigHeader}, Context,
                                 "h.rot");
      LLVM_DEBUG(OrigHeader->dump());

      // Keep the compile time impact low by only adapting the inserted block
      // of instructions in the OrigPreHeader. This might result in slightly
      // more aliasing between these instructions and those that were already
      // present, but it will be much faster when the original PreHeader is
      // large.
      LLVM_DEBUG(dbgs() << "  Updating part of OrigPreheader scopes\n");
      auto *FirstDecl =
          cast<Instruction>(ValueMap[*NoAliasDeclInstructions.begin()]);
      auto *LastInst = &OrigPreheader->back();
      cloneAndAdaptNoAliasScopes(NoAliasDeclScopes, FirstDecl, LastInst,
                                 Context, "pre.rot");
      LLVM_DEBUG(OrigPreheader->dump());

      LLVM_DEBUG(dbgs() << "  Updated NewHeader:\n");
      LLVM_DEBUG(NewHeader->dump());
    }
  }

  // Along with all the other instructions, we just cloned OrigHeader's
  // terminator into OrigPreHeader. Fix up the PHI nodes in each of OrigHeader's
  // successors by duplicating their incoming values for OrigHeader.
  for (BasicBlock *SuccBB : successors(OrigHeader))
    for (BasicBlock::iterator BI = SuccBB->begin();
         PHINode *PN = dyn_cast<PHINode>(BI); ++BI)
      PN->addIncoming(PN->getIncomingValueForBlock(OrigHeader), OrigPreheader);

  // Now that OrigPreHeader has a clone of OrigHeader's terminator, remove
  // OrigPreHeader's old terminator (the original branch into the loop), and
  // remove the corresponding incoming values from the PHI nodes in OrigHeader.
  LoopEntryBranch->eraseFromParent();
  OrigPreheader->flushTerminatorDbgRecords();

  // Update MemorySSA before the rewrite call below changes the 1:1
  // instruction:cloned_instruction_or_value mapping.
  if (MSSAU) {
    InsertNewValueIntoMap(ValueMapMSSA, OrigHeader, OrigPreheader);
    MSSAU->updateForClonedBlockIntoPred(OrigHeader, OrigPreheader,
                                        ValueMapMSSA);
  }

  SmallVector<PHINode *, 2> InsertedPHIs;
  // If there were any uses of instructions in the duplicated block outside the
  // loop, update them, inserting PHI nodes as required
  RewriteUsesOfClonedInstructions(OrigHeader, OrigPreheader, ValueMap, SE,
                                  &InsertedPHIs);

  // Attach debug records to the new phis if that phi uses a value that
  // previously had debug metadata attached. This keeps the debug info
  // up-to-date in the loop body.
  if (!InsertedPHIs.empty())
    insertDebugValuesForPHIs(OrigHeader, InsertedPHIs);

  // NewHeader is now the header of the loop.
  L->moveToHeader(NewHeader);
  assert(L->getHeader() == NewHeader && "Latch block is our new header");

  // Inform DT about changes to the CFG.
  if (DT) {
    // The OrigPreheader branches to the NewHeader and Exit now. Then, inform
    // the DT about the removed edge to the OrigHeader (that got removed).
    SmallVector<DominatorTree::UpdateType, 3> Updates = {
        {DominatorTree::Insert, OrigPreheader, Exit},
        {DominatorTree::Insert, OrigPreheader, NewHeader},
        {DominatorTree::Delete, OrigPreheader, OrigHeader}};

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

  // At this point, we've finished our major CFG changes.  As part of cloning
  // the loop into the preheader we've simplified instructions and the
  // duplicated conditional branch may now be branching on a constant.  If it is
  // branching on a constant and if that constant means that we enter the loop,
  // then we fold away the cond branch to an uncond branch.  This simplifies the
  // loop in cases important for nested loops, and it also means we don't have
  // to split as many edges.
  CondBrInst *PHBI = cast<CondBrInst>(OrigPreheader->getTerminator());
  const Value *Cond = PHBI->getCondition();
  const bool HasConditionalPreHeader =
      !isa<ConstantInt>(Cond) ||
      PHBI->getSuccessor(cast<ConstantInt>(Cond)->isZero()) != NewHeader;

  updateBranchWeights(*PHBI, *BI, HasConditionalPreHeader, BISuccsSwapped);

  if (HasConditionalPreHeader) {
    // The conditional branch can't be folded, handle the general case.
    // Split edges as necessary to preserve LoopSimplify form.

    // Right now OrigPreHeader has two successors, NewHeader and ExitBlock, and
    // thus is not a preheader anymore.
    // Split the edge to form a real preheader.
    BasicBlock *NewPH = SplitCriticalEdge(
        OrigPreheader, NewHeader,
        CriticalEdgeSplittingOptions(DT, LI, MSSAU).setPreserveLCSSA());
    NewPH->setName(NewHeader->getName() + ".lr.ph");

    // Preserve canonical loop form, which means that 'Exit' should have only
    // one predecessor. Note that Exit could be an exit block for multiple
    // nested loops, causing both of the edges to now be critical and need to
    // be split.
    SmallVector<BasicBlock *, 4> ExitPreds(predecessors(Exit));
    bool SplitLatchEdge = false;
    for (BasicBlock *ExitPred : ExitPreds) {
      // We only need to split loop exit edges.
      Loop *PredLoop = LI->getLoopFor(ExitPred);
      if (!PredLoop || PredLoop->contains(Exit) ||
          isa<IndirectBrInst>(ExitPred->getTerminator()))
        continue;
      SplitLatchEdge |= L->getLoopLatch() == ExitPred;
      BasicBlock *ExitSplit = SplitCriticalEdge(
          ExitPred, Exit,
          CriticalEdgeSplittingOptions(DT, LI, MSSAU).setPreserveLCSSA());
      ExitSplit->moveBefore(Exit);
    }
    assert(SplitLatchEdge &&
           "Despite splitting all preds, failed to split latch exit?");
    (void)SplitLatchEdge;
  } else {
    // We can fold the conditional branch in the preheader, this makes things
    // simpler. The first step is to remove the extra edge to the Exit block.
    Exit->removePredecessor(OrigPreheader, true /*preserve LCSSA*/);
    UncondBrInst *NewBI = UncondBrInst::Create(NewHeader, PHBI->getIterator());
    NewBI->setDebugLoc(PHBI->getDebugLoc());
    PHBI->eraseFromParent();

    // With our CFG finalized, update DomTree if it is available.
    if (DT)
      DT->deleteEdge(OrigPreheader, Exit);

    // Update MSSA too, if available.
    if (MSSAU)
      MSSAU->removeEdge(OrigPreheader, Exit);
  }

  assert(L->getLoopPreheader() && "Invalid loop preheader after loop rotation");
  assert(L->getLoopLatch() && "Invalid loop latch after loop rotation");

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

  // Now that the CFG and DomTree are in a consistent state again, try to merge
  // the OrigHeader block into OrigLatch.  This will succeed if they are
  // connected by an unconditional branch.  This is just a cleanup so the
  // emitted code isn't too gross in this common case.
  DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Eager);
  BasicBlock *PredBB = OrigHeader->getUniquePredecessor();
  bool DidMerge = MergeBlockIntoPredecessor(OrigHeader, &DTU, LI, MSSAU);
  if (DidMerge)
    RemoveRedundantDbgInstrs(PredBB);

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

  LLVM_DEBUG(dbgs() << "LoopRotation: into "; L->dump());

  return true;
}

/// Determine whether the instructions in this range may be safely and cheaply
/// speculated. This is not an important enough situation to develop complex
/// heuristics. We handle a single arithmetic instruction along with any type
/// conversions.
static bool shouldSpeculateInstrs(BasicBlock::iterator Begin,
                                  BasicBlock::iterator End, Loop *L) {
  bool seenIncrement = false;
  bool MultiExitLoop = false;

  if (!L->getExitingBlock())
    MultiExitLoop = true;

  for (BasicBlock::iterator I = Begin; I != End; ++I) {

    if (!isSafeToSpeculativelyExecute(&*I))
      return false;

    switch (I->getOpcode()) {
    default:
      return false;
    case Instruction::GetElementPtr:
      // GEPs are cheap if all indices are constant.
      if (!cast<GEPOperator>(I)->hasAllConstantIndices())
        return false;
      // fall-thru to increment case
      [[fallthrough]];
    case Instruction::Add:
    case Instruction::Sub:
    case Instruction::And:
    case Instruction::Or:
    case Instruction::Xor:
    case Instruction::Shl:
    case Instruction::LShr:
    case Instruction::AShr: {
      Value *IVOpnd =
          !isa<Constant>(I->getOperand(0))
              ? I->getOperand(0)
              : !isa<Constant>(I->getOperand(1)) ? I->getOperand(1) : nullptr;
      if (!IVOpnd)
        return false;

      // If increment operand is used outside of the loop, this speculation
      // could cause extra live range interference.
      if (MultiExitLoop) {
        for (User *UseI : IVOpnd->users()) {
          auto *UserInst = cast<Instruction>(UseI);
          if (!L->contains(UserInst))
            return false;
        }
      }

      if (seenIncrement)
        return false;
      seenIncrement = true;
      break;
    }
    case Instruction::Trunc:
    case Instruction::ZExt:
    case Instruction::SExt:
      // ignore type conversions
      break;
    }
  }
  return true;
}

/// Fold the loop tail into the loop exit by speculating the loop tail
/// instructions. Typically, this is a single post-increment. In the case of a
/// simple 2-block loop, hoisting the increment can be much better than
/// duplicating the entire loop header. In the case of loops with early exits,
/// rotation will not work anyway, but simplifyLoopLatch will put the loop in
/// canonical form so downstream passes can handle it.
///
/// I don't believe this invalidates SCEV.
bool LoopRotate::simplifyLoopLatch(Loop *L) {
  BasicBlock *Latch = L->getLoopLatch();
  if (!Latch || Latch->hasAddressTaken())
    return false;

  UncondBrInst *Jmp = dyn_cast<UncondBrInst>(Latch->getTerminator());
  if (!Jmp)
    return false;

  BasicBlock *LastExit = Latch->getSinglePredecessor();
  if (!LastExit || !L->isLoopExiting(LastExit))
    return false;

  if (!isa<UncondBrInst, CondBrInst>(LastExit->getTerminator()))
    return false;

  if (!shouldSpeculateInstrs(Latch->begin(), Jmp->getIterator(), L))
    return false;

  LLVM_DEBUG(dbgs() << "Folding loop latch " << Latch->getName() << " into "
                    << LastExit->getName() << "\n");

  DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Eager);
  MergeBlockIntoPredecessor(Latch, &DTU, LI, MSSAU, nullptr,
                            /*PredecessorWithTwoSuccessors=*/true);

    if (SE) {
      // Merging blocks may remove blocks reference in the block disposition cache. Clear the cache.
      SE->forgetBlockAndLoopDispositions();
    }

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

  return true;
}

/// Rotate \c L, and return true if any modification was made.
bool LoopRotate::processLoop(Loop *L) {
  // Save the loop metadata.
  MDNode *LoopMD = L->getLoopID();

  bool SimplifiedLatch = false;

  // Simplify the loop latch before attempting to rotate the header
  // upward. Rotation may not be needed if the loop tail can be folded into the
  // loop exit.
  if (!RotationOnly)
    SimplifiedLatch = simplifyLoopLatch(L);

  bool MadeChange = rotateLoop(L, SimplifiedLatch);
  assert((!MadeChange || L->isLoopExiting(L->getLoopLatch())) &&
         "Loop latch should be exiting after loop-rotate.");

  // Restore the loop metadata.
  // NB! We presume LoopRotation DOESN'T ADD its own metadata.
  if ((MadeChange || SimplifiedLatch) && LoopMD)
    L->setLoopID(LoopMD);

  return MadeChange || SimplifiedLatch;
}


/// The utility to convert a loop into a loop with bottom test.
bool llvm::LoopRotation(Loop *L, LoopInfo *LI, const TargetTransformInfo *TTI,
                        AssumptionCache *AC, DominatorTree *DT,
                        ScalarEvolution *SE, MemorySSAUpdater *MSSAU,
                        const SimplifyQuery &SQ, bool RotationOnly = true,
                        unsigned Threshold = unsigned(-1),
                        bool IsUtilMode = true, bool PrepareForLTO,
                        bool CheckExitCount) {
  LoopRotate LR(Threshold, LI, TTI, AC, DT, SE, MSSAU, SQ, RotationOnly,
                IsUtilMode, PrepareForLTO, CheckExitCount);
  return LR.processLoop(L);
}
